papermario/src/msg.c

1115 lines
39 KiB
C

#include "common.h"
#include "ld_addrs.h"
// todo consider symbol
#define MSG_ROM_START 0x1B83000
extern s32 D_802EF0D0;
s32 D_8014C280[] = { 0x028001E0, 0x01FF0000, 0x028001E0, 0x01FF0000, };
s32 MessagePlural = 0x53FD0000;
s16 MessageSingular = 0xF0FD;
s16 gNextMessageBuffer = 0;
s32 D_8014C298[] = { 0xFFF00009, 0x00000000, 0x00000000, 0xFFFFFFFF, 0x00100009, 0x00000000, 0x04000000, 0xFFFFFFFF, 0xFFF0FFF7, 0x00000000, 0x00000240, 0xFFFFFFFF, 0x0010FFF7, 0x00000000, 0x04000240, 0xFFFFFFFF, };
Gfx D_8014C2D8[] = {
gsDPSetCycleType(G_CYC_2CYCLE),
gsSPClearGeometryMode(G_CULL_BOTH | G_LIGHTING),
gsSPSetGeometryMode(G_SHADE | G_SHADING_SMOOTH),
gsDPSetColorDither(G_CD_DISABLE),
gsDPSetAlphaDither(G_AD_DISABLE),
gsDPSetAlphaCompare(G_AC_NONE),
gsSPTexture(-1, -1, 0, G_TX_RENDERTILE, G_ON),
gsDPSetTexturePersp(G_TP_PERSP),
gsDPSetTextureLUT(G_TT_NONE),
gsDPSetTextureFilter(G_TF_AVERAGE),
gsDPSetRenderMode(IM_RD | CVG_DST_SAVE | ZMODE_XLU | FORCE_BL | G_RM_PASS, IM_RD | CVG_DST_SAVE | ZMODE_XLU |
FORCE_BL | GBL_c2(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA)),
gsDPSetCombineLERP(TEXEL0, 0, PRIMITIVE, 0, 0, 0, 0, TEXEL1, 0, 0, 0, COMBINED, 0, 0, 0, COMBINED),
gsSPEndDisplayList(),
};
MessageNumber gMsgNumbers[] = {
{
.rasters = &D_802EF0D0,
.texSize = 128,
.texWidth = 16,
.texHeight = 16,
.digitWidth = {11, 8, 11, 11, 11, 11, 11, 11, 11, 11},
.fixedWidth = 11
},{
.rasters = &D_802EF0D0,
.texSize = 128,
.texWidth = 16,
.texHeight = 16,
.digitWidth = {9, 8, 9, 9, 9, 9, 9, 9, 9, 9},
.fixedWidth = 9
}
};
Gfx D_8014C368[] = {
gsDPPipeSync(),
gsDPSetCycleType(G_CYC_1CYCLE),
gsDPSetTextureFilter(G_TF_POINT),
gsDPSetTexturePersp(G_TP_NONE),
gsDPSetColorDither(G_CD_DISABLE),
gsDPSetAlphaDither(G_AD_DISABLE),
gsDPSetCombineKey(G_CK_NONE),
gsDPSetAlphaCompare(G_AC_NONE),
gsDPSetTextureLUT(G_TT_RGBA16),
gsSPTexture(-1, -1, 0, G_TX_RENDERTILE, G_ON),
gsSPEndDisplayList(),
};
s32 D_8014C3C0[] = { 0x00010000, 0x00000000, 0x00000000, 0xFFFFF8FF, 0x00200000, 0x00000000, 0x04000000, 0xFFFFF8FF, 0x0001FFC0, 0x00000000, 0x00000800, 0xBFB8B0FF, 0x0020FFC0, 0x00000000, 0x04000800, 0xBFB8B0FF, };
s32 D_8014C400[] = { 0x00200000, 0x00000000, 0x00000000, 0xFFFFF8FF, 0x00E10000, 0x00000000, 0x01000000, 0xFFFFF8FF, 0x0020FFC0, 0x00000000, 0x00000800, 0xBFB8B0FF, 0x00E1FFC0, 0x00000000, 0x01000800, 0xBFB8B0FF, };
s32 D_8014C440[] = { 0x00E10000, 0x00000000, 0x00000000, 0xFFFFF8FF, 0x01000000, 0x00000000, 0x04000000, 0xFFFFF8FF, 0x00E1FFC0, 0x00000000, 0x00000800, 0xBFB8B0FF, 0x0100FFC0, 0x00000000, 0x04000800, 0xBFB8B0FF, };
s32 D_8014C480[] = { 0xFFF1001E, 0x00000000, 0x00000000, 0xBFB8B0FF, 0x000F001E, 0x00000000, 0x01E00000, 0xBFB8B0FF, 0xFFFF0000, 0x00000000, 0x000001E0, 0xBFB8B0FF, 0x00010000, 0x00000000, 0x01E001E0, 0xBFB8B0FF, };
s32 D_8014C4C0[] = { 0xFFF1001E, 0x00000000, 0x00000000, 0xBFB8B0FF, 0x000F001E, 0x00000000, 0x01E00000, 0xBFB8B0FF, 0xFFFF0000, 0x00000000, 0x000001E0, 0xBFB8B0FF, 0x00010000, 0x00000000, 0x01E001E0, 0xBFB8B0FF, };
Gfx D_8014C500[] = {
gsDPSetCycleType(G_CYC_1CYCLE),
gsDPSetRenderMode(G_RM_TEX_EDGE, G_RM_TEX_EDGE2),
gsDPSetCombineMode(G_CC_DECALRGBA, G_CC_DECALRGBA),
gsDPSetTextureFilter(G_TF_AVERAGE),
gsSPTexture(-1, -1, 0, G_TX_RENDERTILE, G_ON),
gsDPSetTexturePersp(G_TP_NONE),
gsDPSetColorDither(G_CD_DISABLE),
gsDPSetAlphaDither(G_AD_DISABLE),
gsDPSetTextureLOD(G_TL_TILE),
gsDPSetTextureLUT(G_TT_RGBA16),
gsDPSetTextureDetail(G_TD_CLAMP),
gsDPSetTextureConvert(G_TC_FILT),
gsDPSetCombineKey(G_CK_NONE),
gsDPSetAlphaCompare(G_AC_NONE),
gsDPNoOp(),
gsSPEndDisplayList(),
};
u8 D_8014C580[] = { 50, 80, 100, 105, 100, 0, 0, 0 };
u8 D_8014C588[] = { 105, 100, 77, 57, 40, 27, 16, 8, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
// BSS
extern s32 gMsgBGScrollAmtX;
extern u16 gMsgGlobalWaveCounter;
extern s32 gMsgVarImages; // message images?
extern s32 gMsgBGScrollAmtY;
extern s32 D_80151338;
extern char gMessageBuffers[][1024];
extern u8 gMessageMsgVars[3][32];
extern s16 D_80155C98;
extern Matrix4s gMessageWindowProjMatrix[2];
extern MessageDrawState* gMessageDrawStatePtr;
// another file?
extern s32 D_802ED550;
extern s32 D_802ED670;
extern s32 D_802ED970;
extern s32 D_802EE8D0;
extern MessageCharset* gMsgCharsets[5];
extern s32 D_802F39D0;
extern s32* D_802F4560;
void load_font(s32 font);
s32 _update_message(MessagePrintState*);
void appendGfx_message(MessagePrintState*, s16, s16, u16, u16, u16, u8);
void appendGfx_msg_prim_rect(u8 r, u8 g, u8 b, u8 a, u16 ulX, u16 ulY, u16 lrX, u16 lrY);
void get_msg_properties(s32 msgID, s32* height, s32* width, s32* maxLineChars, s32* numLines,
s32* maxLinesPerPage, s32* arg6, s32 charset);
void clear_character_set(void) {
D_80155C98 = -1;
}
void clear_printers(void) {
s32 i;
for (i = 0; i < ARRAY_COUNT(gMessagePrinters); i++) {
initialize_printer(&gMessagePrinters[i], 0, 0);
}
gMsgBGScrollAmtX = 0;
gMsgBGScrollAmtY = 0;
for (i = 0; i < ARRAY_COUNT(gMessageMsgVars); i++) {
gMessageMsgVars[i][0] = 0;
}
D_80151338 = 0;
gMsgGlobalWaveCounter = 0;
load_font(0);
}
void load_font_data(Addr offset, u16 size, void* dest) {
u8* base = charset_ROM_START + (s32) offset;
dma_copy(base, base + size, dest);
}
void load_font(s32 font) {
if (font != D_80155C98) {
if (font == 0) {
load_font_data(charset_standard_OFFSET, 0x5100, &D_802EE8D0);
load_font_data(charset_standard_pal_OFFSET, 0x500, &D_802F4560);
} else if (font == 1) {
load_font_data(charset_title_OFFSET, 0xF60, &D_802ED970);
load_font_data(charset_subtitle_OFFSET, 0xB88, &D_802F39D0);
load_font_data(charset_credits_pal_OFFSET, 0x80, &D_802F4560);
}
}
}
void update_messages(void) {
s32 i;
gMsgGlobalWaveCounter++;
if (gMsgGlobalWaveCounter >= 360) {
gMsgGlobalWaveCounter = 0;
}
for (i = 0; i < ARRAY_COUNT(gMessagePrinters); i++) {
if (gMessagePrinters[i].stateFlags & 2) {
_update_message(&gMessagePrinters[i]);
}
}
gMsgBGScrollAmtX += 12;
gMsgBGScrollAmtY -= 12;
if (gMsgBGScrollAmtX >= 2048) {
gMsgBGScrollAmtX -= 2048;
}
if (gMsgBGScrollAmtY < 0) {
gMsgBGScrollAmtY += 2048;
}
}
#ifdef NON_MATCHING
s32 _update_message(MessagePrintState* printer) {
GameStatus* temp_v0_5;
f32 temp_f4;
s32 temp_a1_3;
s32 temp_v0_2;
u8 temp_v1_2;
s32 phi_a3;
s32 phi_a0;
u8 phi_v0;
s32 phi_a0_2;
MessagePrintState* phi_a0_4;
s32 phi_a1_2;
s32 phi_s1;
u8 phi_a1_3;
s16 phi_v1;
s32 phi_a0_5;
printer->effectFrameCounter++;
if (printer->effectFrameCounter >= 3600) {
printer->effectFrameCounter = 0;
}
temp_f4 = (f32) ((((f64) (f32) printer->initOpenPos.x - 160.0) / 3.8) + 64.0);
if (temp_f4 < 5.0) {
temp_f4 = 5.0f;
} else if (temp_f4 > 122.0) {
temp_f4 = 122.0f;
}
if (temp_f4 >= 2.1474836e9f) {
printer->unk_51A = ((s8)(temp_f4 - 2.1474836e9f));
} else {
printer->unk_51A = temp_f4;
}
if (!(printer->stateFlags & 0x40)) {
if (!(printer->stateFlags & 0x30)) {
temp_v1_2 = printer->windowState;
if (temp_v1_2 != 7) {
if (temp_v1_2 < 8) {
if (temp_v1_2 != 5) {
phi_s1 = 0;
} else {
phi_a3 = 0x8000;
if (printer->stateFlags & 0x80000) {
phi_a3 = 0x8004;
}
if (((phi_a3 & gGameStatusPtr->pressedButtons)) || ((gGameStatusPtr->currentButtons & 0x4000) != 0)) {
printer->windowState = 4;
printer->currentPrintDelay = 0;
printer->stateFlags |= 0x4;
if ((gGameStatusPtr->pressedButtons & 0x8004) != 0) {
phi_s1 = 1;
sfx_play_sound_with_params(0xC9, 0, 0, 0);
} else {
if (printer->srcBuffer[printer->srcBufferPos] != 0xFD) {
printer->stateFlags |= 0x104;
if (printer->fontVariant == 0) {
if (printer->srcBuffer[printer->srcBufferPos] == 0xC3) {
phi_a0 = 0xCC;
} else {
block_29:
printer->stateFlags |= 0x184;
phi_a0 = 0xCC;
}
} else {
goto block_29;
}
sfx_play_sound_with_params(phi_a0, 0, 0, 0);
}
if ((printer->style - 1) < 4U) {
sfx_play_sound_with_params(0xC9, 0, 0, 0);
}
}
} else {
if ((gGameStatusPtr->pressedButtons & 0x2000) != 0) {
if (!(printer->stateFlags & 0x40000)) {
if (printer->currentLine != 0) {
printer->windowState = 0xB;
printer->unk_4CC = 0;
phi_v0 = printer->currentLine - 1;
phi_a0_2 = 0xCD;
block_44:
printer->unkArraySize = phi_v0;
temp_v0_2 = printer->curLinePos - printer->lineEndPos[phi_v0 & 0xFF];
if (temp_v0_2 < 0) {
temp_v0_2 = -temp_v0_2;
}
printer->unk_4C8 = temp_v0_2;
sfx_play_sound_with_params(phi_a0_2, 0, 0, 0);
}
}
}
}
}
} else if (temp_v1_2 != 8) {
if (temp_v1_2 == 0xC) {
if (gGameStatusPtr->pressedButtons & 0x4000) {
printer->windowState = 0xB;
printer->unk_4CC = 0;
phi_v0 = printer->currentLine;
phi_a0_2 = 0xCC;
goto block_44;
}
if (gGameStatusPtr->pressedButtons & 0x2000) {
if (printer->unkArraySize != 0) {
printer->windowState = 0xB;
printer->unk_4CC = 0;
phi_v0 = printer->unkArraySize - 1;
phi_a0_2 = 0xCD;
goto block_44;
}
} else {
if (gGameStatusPtr->pressedButtons & 0x8000) {
printer->windowState = 0xB;
printer->unk_4CC = 0;
phi_v0 = printer->unkArraySize + 1;
phi_a0_2 = 0xCE;
goto block_44;
}
}
}
} else {
block_65:
printer->unkCounter++;
if ((printer->unkCounter & 0xFF) >= 5U) {
printer->windowState = 7;
printer->currentOption = printer->targetOption;
printer->selectedOption = printer->targetOption;
}
}
} else {
if (gGameStatusPtr->pressedButtons & 0x8000) {
printer->madeChoice = 1;
printer->windowState = 4;
printer->unkCounter = 0;
printer->stateFlags |= 0x20000;
sfx_play_sound_with_params(0xC9, 0, 0, 0);
} else {
if ((printer->cancelOption != 0xFF) && (gGameStatusPtr->pressedButtons & 0x4000)) {
if (printer->cancelOption < printer->maxOption) {
printer->selectedOption = printer->cancelOption;
} else {
printer->selectedOption = printer->currentOption;
}
printer->madeChoice = 1;
printer->windowState = 4;
printer->unkCounter = 0;
printer->currentOption = printer->cancelOption;
printer->stateFlags |= 0x20000;
sfx_play_sound_with_params(0xCA, 0, 0, 0);
}
if (gGameStatusPtr->heldButtons & 0x20000) {
if (printer->currentOption != printer->maxOption - 1) {
printer->targetOption = printer->currentOption + 1;
printer->windowState = 8;
printer->unkCounter = 1;
sfx_play_sound_with_params(0xCA, 0, 0, 0);
}
} else if (gGameStatusPtr->heldButtons & 0x10000) {
if (printer->currentOption != 0) {
printer->targetOption = printer->currentOption - 1;
printer->windowState = 8;
printer->unkCounter = 1;
sfx_play_sound_with_params(0xCA, 0, 0, 0);
}
}
}
if (printer->windowState == 8) {
goto block_65;
}
}
} else {
if (!(printer->stateFlags & 0x20)) {
if (printer->windowState == 5) {
if ((gGameStatusPtr->pressedButtons & 0x8000) != 0) {
printer->windowState = 4;
printer->currentPrintDelay = 0;
printer->stateFlags |= 4;
}
}
}
}
if (printer->stateFlags & 4) {
phi_a1_2 = 0;
if ((gGameStatusPtr->currentButtons & 0x8000) == 0) {
printer->stateFlags &= ~0x4;
}
}
do {
temp_a1_3 = phi_a1_2 + 1;
if (printer->animTimers[0] > 0) {
printer->animTimers[0]--;
}
phi_a0_4 += 2;
phi_a1_2 = temp_a1_3;
} while ((temp_a1_3 < 4) != 0);
switch (printer->windowState) {
case 1:
block_84:
block_85:
if (printer->windowState == 1) {
printer->windowState = 4;
phi_a1_3 = printer->charsPerChunk;
printer->currentPrintDelay = 0;
} else {
if (printer->stateFlags & 0x100) {
phi_a1_3 = 0xC;
printer->currentPrintDelay = 0;
}
phi_a1_3 = printer->charsPerChunk;
if (!(printer->stateFlags & 0x4)) {
if (!(printer->stateFlags & 0x30)) {
if (gGameStatusPtr->currentButtons & 0x8000) {
phi_a1_3 = 6;
printer->currentPrintDelay = 0;
}
}
}
}
if ((printer->currentPrintDelay == 0) || (printer->currentPrintDelay--, (printer->currentPrintDelay == 0))) {
msg_copy_to_print_buffer(printer, phi_a1_3, 0);
}
goto block_135;
case 4:
temp_v0_5 = gGameStatusPtr;
if ((temp_v0_5->pressedButtons & 0x8000) | (temp_v0_5->currentButtons & 0x4000)) {
if (!(printer->stateFlags & 0x30) && ((phi_s1 & 0xFF) == 0)) {
printer->stateFlags |= 0x100;
goto block_84;
}
}
goto block_85;
case 6:
if ((gGameStatusPtr->pressedButtons & 0xC000) != 0) {
if (!(printer->stateFlags & 0x30)) {
printer->stateFlags |= 0x100;
}
}
printer->curLinePos += printer->unk_464;
if ((printer->stateFlags & 0x100) || ((!(printer->stateFlags & 0x14)) && ((gGameStatusPtr->currentButtons & 0x8000) != 0))) {
printer->curLinePos += 6;
}
if (printer->curLinePos >= printer->nextLinePos) {
printer->windowState = 4;
printer->curLinePos = printer->nextLinePos;
printer->stateFlags |= 4;
if (((printer->style - 7) < 2U) || (printer->srcBuffer[printer->srcBufferPos] == 0xF1)) {
printer->currentPrintDelay = 0;
} else {
printer->currentPrintDelay = 5;
}
printer->lineEndPos[printer->currentLine] = printer->unk_462;
}
goto block_135;
case 11:
printer->unk_4CC++;
phi_v1 = printer->curLinePos - printer->lineEndPos[printer->unkArraySize];
if (phi_v1 < 0) {
phi_v1 = -phi_v1;
}
if (printer->unk_4C8 < 0x11U) {
if (phi_v1 < 0xF) {
phi_a0_5 = 2;
if (!(phi_v1 < 9)) {
phi_a0_5 = 3;
}
} else {
phi_a0_5 = 4;
}
} else if (phi_v1 > 96) {
phi_a0_5 = 10;
} else if (phi_v1 > 48) {
phi_a0_5 = 9;
} else if (phi_v1 >= 24) {
phi_a0_5 = 7;
} else if (phi_v1 >= 16) {
phi_a0_5 = 5;
} else {
if (phi_v1 >= 8) {
phi_a0_5 = 4;
}
phi_a0_5 = 2;
if (!(phi_v1 < 5)) {
phi_a0_5 = 3;
}
}
printer->unk_4CA = phi_a0_5;
if (printer->lineEndPos[printer->unkArraySize] >= printer->curLinePos) {
printer->curLinePos += phi_a0_5;
if (printer->curLinePos >= printer->lineEndPos[printer->unkArraySize]) {
printer->curLinePos = printer->lineEndPos[printer->unkArraySize];
printer->windowState = 0xC;
if (printer->unkArraySize == printer->currentLine) {
printer->windowState = 5;
printer->rewindArrowAnimState = 0;
printer->rewindArrowBlinkCounter = 0;
}
}
} else {
printer->curLinePos -= phi_a0_5;
if (printer->lineEndPos[printer->unkArraySize] >= printer->curLinePos) {
printer->curLinePos = printer->lineEndPos[printer->unkArraySize];
printer->windowState = 0xC;
}
}
default:
block_135:
if (printer->stateFlags & 1) {
printer->windowState = 0;
printer->stateFlags = 0;
if (printer->letterBackgroundImg != NULL) {
general_heap_free(printer->letterBackgroundImg);
}
if (printer->letterBackgroundPal != NULL) {
general_heap_free(printer->letterBackgroundPal);
}
if (printer->letterContentImg != NULL) {
general_heap_free(printer->letterContentImg);
}
if (printer->letterContentPal != NULL) {
general_heap_free(printer->letterContentPal);
}
if (printer->closedWritebackBool != NULL) {
*printer->closedWritebackBool = 1;
printer->closedWritebackBool = NULL;
}
}
}
}
return printer->windowState;
}
#else
INCLUDE_ASM(s32, "msg", _update_message, MessagePrintState* msgPrintState);
#endif
void render_messages(void) {
Matrix4s* matrix = &gMessageWindowProjMatrix[gCurrentDisplayContextIndex];
s32 i;
for (i = 0; i < ARRAY_COUNT(gMessagePrinters); i++) {
if (gMessagePrinters[i].stateFlags & 0x2) {
gSPViewport(gMasterGfxPos++, D_8014C280);
guOrtho(matrix, 0.0f, 319.0f, -240.0f, 0.0f, -500.0f, 500.0f, 1.0f);
gSPMatrix(gMasterGfxPos++, OS_K0_TO_PHYSICAL(matrix), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION);
gDPPipeSync(gMasterGfxPos++);
gDPSetCycleType(gMasterGfxPos++, G_CYC_1CYCLE);
gSPClearGeometryMode(gMasterGfxPos++, G_SHADE | G_CULL_BOTH | G_FOG | G_LIGHTING | G_TEXTURE_GEN |
G_TEXTURE_GEN_LINEAR | G_LOD | G_SHADING_SMOOTH);
gSPSetGeometryMode(gMasterGfxPos++, G_SHADE | G_SHADING_SMOOTH);
break;
}
}
for (i = 0; i < ARRAY_COUNT(gMessagePrinters); i++) {
if (gMessagePrinters[i].stateFlags & 0x2) {
draw_message_window(&gMessagePrinters[i]);
if (gMessagePrinters[i].windowState == 5) {
if (!(gMessagePrinters[i].stateFlags & 0x8000) && !(gMessagePrinters[i].stateFlags & 0x40)) {
msg_update_rewind_arrow(i);
}
} else if (gMessagePrinters[i].windowState == 0xC) {
msg_draw_rewind_arrow(i);
} else if (gMessagePrinters[i].windowState == 7 || gMessagePrinters[i].windowState == 8 ||
gMessagePrinters[i].stateFlags & 0x10000 || gMessagePrinters[i].stateFlags & 0x20000) {
msg_draw_choice_pointer(&gMessagePrinters[i]);
}
}
}
}
void msg_play_speech_sound(MessagePrintState* printer, u8 character) {
f32 volTemp;
s16 volume;
s32 pitchShift;
s32 flag = 1;
s32 hundred = 100;
if (printer->stateFlags & 0x800000 && !(printer->delayFlags & 6) && printer->volume != 0) {
volTemp = (f32)printer->volume / 100.0;
pitchShift = ((character % 20) * 10) + (printer->speechVolumePitch - hundred);
volume = ((rand_int(15) + 78) * volTemp);
if (volume > 255) {
volume = 255;
}
if (character & flag) {
sfx_play_sound_with_params(printer->speedSoundIDA, volume, printer->speechPan, pitchShift);
} else {
sfx_play_sound_with_params(printer->speedSoundIDB, volume, printer->speechPan, pitchShift);
}
}
}
INCLUDE_ASM(s32, "msg", msg_copy_to_print_buffer);
void initialize_printer(MessagePrintState* printer, s32 arg1, s32 arg2) {
s32 i;
printer->printBufferSize = ARRAY_COUNT(printer->printBuffer);
printer->printBuffer[0] = 0xFB; // next (TODO: make enum for this)
printer->printDelayTime = 1;
printer->charsPerChunk = 1;
printer->unk_464 = 6;
printer->srcBuffer = NULL;
printer->msgID = 0;
printer->currentPrintDelay = 0;
printer->windowOffsetPos.x = 0;
printer->windowOffsetPos.y = 0;
printer->windowBasePos.x = 0;
printer->windowBasePos.y = 0;
printer->rewindArrowAnimState = 0;
printer->rewindArrowBlinkCounter = 0;
printer->rewindArrowPos.x = 0;
printer->rewindArrowPos.y = 0;
printer->currentLine = 0;
printer->unkArraySize = 0;
printer->maxOption = 0;
printer->madeChoice = 0;
printer->currentOption = 0;
printer->selectedOption = 0;
printer->cancelOption = -1;
printer->windowState = 0;
printer->stateFlags = 0;
printer->delayFlags = 0;
printer->closedWritebackBool = NULL;
printer->printBufferPos = 0;
printer->srcBufferPos = 0;
printer->font = 0;
printer->fontVariant = 0;
printer->effectFrameCounter = 0;
printer->curLinePos = 0;
printer->unk_46C = 0;
printer->lineCount = 0;
for (i = 0; i < ARRAY_COUNT(printer->animTimers); i++) {
printer->currentAnimFrame[i] = 0;
printer->animTimers[i] = -1;
}
printer->initOpenPos.x = 160;
printer->initOpenPos.y = 40;
printer->speechSoundType = -1;
printer->speechPan = 64;
printer->volume = 75;
printer->rewindArrowBlinkCounter = 0;
printer->style = 0;
printer->fadeInCounter = 0;
printer->openStartPos.x = 0;
printer->openStartPos.y = 0;
printer->fadeOutCounter = 0;
printer->windowSize.y = 0;
printer->windowSize.x = 0;
printer->speechVolumePitch = 0;
printer->speedSoundIDA = 0;
printer->speedSoundIDB = 0;
printer->varBufferReadPos = 0;
printer->currentImageIndex = 0;
printer->varImageScreenPos.x = 0;
printer->varImageScreenPos.y = 0;
printer->varImgHasBorder = 0;
printer->varImgFinalAlpha = 255;
printer->varImageDisplayState = 0;
printer->varImageFadeTimer = 0;
printer->letterBackgroundImg = NULL;
printer->letterBackgroundPal = NULL;
printer->letterContentImg = NULL;
printer->letterContentPal = NULL;
printer->sizeScale = 1.0f;
}
void dma_load_msg(u32 msgID, void* dest) {
u8* addr = (u8*) MSG_ROM_START + (msgID >> 14); // (msgID >> 16) * 4
u8* offset[2]; // start, end
dma_copy(addr, addr + 4, &offset[0]); // Load section offset
addr = MSG_ROM_START + offset[0] + (msgID & 0xFFFF) * 4;
dma_copy(addr, addr + 8, &offset); // Load message start and end offsets
// Load the msg data
dma_copy(MSG_ROM_START + offset[0], MSG_ROM_START + offset[1], dest);
}
s32* load_message_to_buffer(s32 msgID) {
s32* prevBufferPos;
dma_load_msg(msgID, &gMessageBuffers[gNextMessageBuffer]);
prevBufferPos = gMessageBuffers[gNextMessageBuffer];
gNextMessageBuffer++;
if (gNextMessageBuffer >= 2) {
gNextMessageBuffer = 0;
}
return prevBufferPos;
}
MessagePrintState* msg_get_printer_for_msg(s32 msgID, s32* donePrintingWriteback) {
return _msg_get_printer_for_msg(msgID, donePrintingWriteback, 0);
}
#ifdef NON_MATCHING
MessagePrintState* _msg_get_printer_for_msg(s32 msgID, s32* donePrintingWriteback, s32 arg2) {
if (msgID != 0) {
s8* srcBuffer = (s8*) msgID;
s32 i;
if (msgID >= 0) {
srcBuffer = load_message_to_buffer(srcBuffer);
}
for (i = 0; i < ARRAY_COUNT(gMessagePrinters); i++) {
MessagePrintState* printer = &gMessagePrinters[i];
if (!(printer->stateFlags & 2)) {
s32 height;
s32 width;
s32 maxLineChars;
s32 numLines;
s32 maxLinesPerPage;
initialize_printer(printer, 1, arg2);
printer->windowState = 1;
printer->srcBuffer = srcBuffer;
printer->msgID = msgID;
printer->stateFlags |= 2;
get_msg_properties(msgID, &height, &width, &maxLineChars, &numLines, &maxLinesPerPage, NULL, 0);
printer->msgHeight = height;
printer->msgWidth = width;
printer->maxLineChars = maxLineChars;
printer->numLines = numLines;
printer->maxLinesPerPage = maxLinesPerPage;
printer->closedWritebackBool = donePrintingWriteback;
if (donePrintingWriteback != NULL) {
*donePrintingWriteback = FALSE;
}
return printer;
}
}
}
return NULL;
}
#else
INCLUDE_ASM(MessagePrintState*, "msg", _msg_get_printer_for_msg, s32 msgID, s32* donePrintingWriteback, s32 arg2);
#endif
s32 msg_printer_load_msg(s32 msgID, MessagePrintState* printer) {
s32* buffer;
if (msgID >= 0) {
buffer = load_message_to_buffer(msgID);
} else {
buffer = (s32*) msgID;
}
printer->srcBuffer = buffer;
printer->srcBufferPos = 0;
printer->stateFlags &= ~0x40;
return 1;
}
void msg_printer_set_origin_pos(MessagePrintState* msgPrintState, s16 x, s16 y) {
msgPrintState->initOpenPos.x = x;
msgPrintState->initOpenPos.y = y;
if (msgPrintState->initOpenPos.x < 0) {
msgPrintState->initOpenPos.x = 0;
}
if (msgPrintState->initOpenPos.x > SCREEN_WIDTH) {
msgPrintState->initOpenPos.x = SCREEN_WIDTH;
}
if (msgPrintState->initOpenPos.y < 0) {
msgPrintState->initOpenPos.y = 0;
}
if (msgPrintState->initOpenPos.y > 220) {
msgPrintState->initOpenPos.y = 220;
}
}
s32 cancel_message(MessagePrintState* msgPrintState) {
if ((msgPrintState->stateFlags & 2) == 0) {
return 0;
}
msgPrintState->stateFlags |= 1;
return 1;
}
void set_message_images(s32* images) {
gMsgVarImages = images;
}
// loop crap
#ifdef NON_MATCHING
void set_message_msg(s32 msgID, s32 index) {
u8* buffer = msgID;
u8* mallocSpace = NULL;
u8* it;
s32 i;
s32 new_var;
if (msgID >= 0) {
buffer = general_heap_malloc(0x400);
dma_load_msg(msgID, buffer);
mallocSpace = buffer;
}
for (i = 0; i < ARRAY_COUNT(gMessageMsgVars[index]); i++) {
gMessageMsgVars[index][i] = buffer[i];
if (buffer[i] == 0xFD) {
break;
}
}
if (mallocSpace != NULL) {
general_heap_free(mallocSpace);
}
}
#else
INCLUDE_ASM(s32, "msg", set_message_msg);
#endif
void set_message_value(s32 value, s32 index) {
s8 strBuffer[ARRAY_COUNT(gMessageMsgVars[index])];
s8* bufferIt;
s32 i;
int_to_string(value, &strBuffer, 10);
for (i = 0, bufferIt = strBuffer; i < ARRAY_COUNT(gMessageMsgVars[index]) - 1; i++) {
s8 thisChar = bufferIt[i];
if (thisChar == 0) {
break;
}
gMessageMsgVars[index][i] = thisChar - 0x20;
}
gMessageMsgVars[index][i] = 0xFD;
}
void close_message(MessagePrintState* msgPrintState) {
msgPrintState->stateFlags &= ~0x40;
}
// so close, just some dumb control flow thing at the beginning
s32 msg_get_print_char_width(s32 character, s32 charset, s32 variation, f32 msgScale, s32 overrideCharWidth, u8 flags);
#ifdef NON_MATCHING
s32 msg_get_print_char_width(s32 character, s32 charset, s32 variation, f32 msgScale, s32 overrideCharWidth, u8 flags) {
u8* charWidthTable;
f32 baseWidth;
f64 charWidth;
f64 modifier;
if (character < 0xF0 || (character == 0xF7 || character == 0xF8 || character == 0xF9)) {
if (overrideCharWidth != 0) {
baseWidth = overrideCharWidth;
} else if (flags != 0 && gMsgCharsets[charset]->rasters[variation].charWidthTable != NULL &&
character != 0xF7 && character != 0xF8 && character != 0xF9) {
baseWidth = gMsgCharsets[charset]->rasters[variation].charWidthTable[character];
} else {
baseWidth = gMsgCharsets[charset]->rasters[variation].monospaceWidth;
}
if (character == 0xF7) {
charWidth = baseWidth * msgScale;
modifier = 0.6;
return charWidth * modifier;
}
if (character == 0xF8) {
charWidth = baseWidth * msgScale;
return charWidth;
}
if (character == 0xF9) {
charWidth = baseWidth * msgScale;
modifier = 0.5;
return charWidth * modifier;
}
if (character < 0xF0) {
return baseWidth * msgScale;
}
}
return 0;
}
#else
INCLUDE_ASM(s32, "msg", msg_get_print_char_width, s32 character, s32 charset, s32 variation, f32 msgScale, s32 overrideCharWidth, u8 flags);
#endif
s32 msg_get_draw_char_width(s32 character, s32 charset, s32 varaition, f32 msgScale, s32 overrideCharWidth, s32 flags);
INCLUDE_ASM(s32, "msg", msg_get_draw_char_width, s32 character, s32 charset, s32 varaition, f32 msgScale, s32 overrideCharWidth, s32 flags);
INCLUDE_ASM(void, "msg", get_msg_properties, s32 msgID, s32* height, s32* width, s32* maxLineChars, s32* numLines,
s32* maxLinesPerPage, s32* arg6, s32 charset);
s32 get_msg_width(s32 msgID, u16 charset) {
s32 width;
get_msg_properties(msgID, NULL, &width, NULL, NULL, NULL, NULL, charset);
return width;
}
s32 get_msg_lines(s32 msgID) {
s32 numLines;
get_msg_properties(msgID, NULL, NULL, NULL, &numLines, NULL, NULL, 0);
return numLines;
}
// some weird stacky msgIDy stuff
#ifdef NON_MATCHING
void draw_msg(s32 msgID, s32 posX, s32 posY, s32 opacity, s32 palette, u8 style) {
s32 width;
MessagePrintState stackPrinter;
MessagePrintState* printer;
u16 bufferPos;
s32* mallocSpace;
s32 charset;
s32 flags;
flags = 0;
bufferPos = 0;
mallocSpace = NULL;
charset = 0;
if (msgID != 0) {
if (style & 1) {
flags = 2;
charset = 1;
}
if (opacity < 0xFF) {
flags |= 1;
}
printer = &stackPrinter;
initialize_printer(printer, 1, 0);
if (msgID < 0) {
printer = (MessagePrintState*)msgID;
} else {
mallocSpace = general_heap_malloc(0x400);
dma_load_msg(msgID, mallocSpace);
printer->srcBuffer = mallocSpace;
get_msg_properties(msgID, 0, &width, 0, 0, 0, 0, charset);
printer->msgWidth = width;
}
if (palette >= 0) {
printer->printBuffer[bufferPos++] = 0xFF;
printer->printBuffer[bufferPos++] = 4;
printer->printBuffer[bufferPos++] = palette;
printer->printBufferPos += 3;
}
if (style & 2) {
printer->printBuffer[bufferPos++] = 0xFF;
printer->printBuffer[bufferPos++] = 0x1C;
printer->printBuffer[bufferPos++] = 8;
printer->printBufferPos += 3;
}
if (style & 4) {
printer->printBuffer[bufferPos++] = 0xFF;
printer->printBuffer[bufferPos++] = 0x1C;
printer->printBuffer[bufferPos++] = 9;
printer->printBufferPos += 3;
}
if (style & 8) {
printer->printBuffer[bufferPos++] = 0xFF;
printer->printBuffer[bufferPos++] = 0x1C;
printer->printBuffer[bufferPos++] = 0xE;
printer->printBufferPos += 3;
}
msg_copy_to_print_buffer(printer, 10000, 1);
appendGfx_message(printer, posX, posY, 0, 0, flags, opacity);
if (mallocSpace != NULL) {
general_heap_free(mallocSpace);
}
}
}
#else
INCLUDE_ASM(void, "msg", draw_msg, s32 msgID, s32 posX, s32 posY, s32 opacity, s32 palette, s32 style);
#endif
INCLUDE_ASM(s32, "msg", msg_update_rewind_arrow);
void msg_draw_rewind_arrow(s32 printerIndex) {
MessagePrintState* printer = &gMessagePrinters[printerIndex];
if (printer->rewindArrowBlinkCounter < 6) {
draw_ci_image_with_clipping(&D_802ED550, 0x18, 0x18, 2, 0, &D_802ED670, printer->rewindArrowPos.x,
printer->rewindArrowPos.y, 0xA, 0xA, 0x12C, 0xDC, 0xFF);
}
printer->rewindArrowBlinkCounter++;
if (printer->rewindArrowBlinkCounter >= 12) {
printer->rewindArrowBlinkCounter = 0;
}
}
INCLUDE_ASM(s32, "msg", msg_draw_choice_pointer);
INCLUDE_ASM(s32, "msg", draw_digit);
INCLUDE_ASM(void, "msg", draw_number, s32 value, s32 x, s32 y, s32 arg3, s32 palette, s32 opacity, s32 style);
void drawbox_message_delegate(MessagePrintState* printer) {
appendGfx_message(printer, 0, 0, 0, 0, 4, 0);
}
void draw_message_window(MessagePrintState* printer) {
f32 scale = 1.0f;
s32 rotZ = 0;
switch (printer->windowState) {
case 0xD:
scale = (f32)D_8014C580[printer->fadeInCounter] / 100.0;
rotZ = (4 - printer->fadeInCounter) * 3;
printer->fadeInCounter++;
if (D_8014C580[printer->fadeInCounter] == 0) {
printer->windowState = 4;
}
break;
case 0xE:
scale = (f32)D_8014C588[printer->fadeOutCounter] / 100.0;
rotZ = -printer->fadeOutCounter;
printer->fadeOutCounter++;
if (D_8014C588[printer->fadeOutCounter] == 0) {
printer->stateFlags |= 1;
}
break;
}
switch (printer->windowState) {
case 0xD:
case 0xE:
printer->windowBasePos.x = 160 - (printer->windowSize.x / 2);
printer->windowBasePos.y = 56;
draw_box(1, 0, printer->windowBasePos.x, 56, 0, printer->windowSize.x, printer->windowSize.y, 255, 0,
scale, scale, 0.0f, 0.0f, rotZ, drawbox_message_delegate, printer, NULL, SCREEN_WIDTH,
SCREEN_HEIGHT, NULL);
break;
default:
appendGfx_message(printer, printer->windowOffsetPos.x, printer->windowOffsetPos.y, printer->unk_46C,
printer->curLinePos, 4, 0);
break;
}
}
INCLUDE_ASM(void, "msg", appendGfx_message, MessagePrintState* printer, s16 arg1, s16 arg2, u16 arg3, u16 arg4, u16 arg5, u8 arg6);
void msg_reset_gfx_state(void) {
gDPPipeSync(gMasterGfxPos++);
gSPDisplayList(gMasterGfxPos++, D_8014C500);
}
INCLUDE_ASM(s32, "msg", msg_draw_char);
void msg_draw_prim_rect(u8 r, u8 g, u8 b, u8 a, s32 posX, s32 posY, s32 sizeX, s32 sizeY) {
u16 lrX = posX + sizeX;
u16 lrY = posY + sizeY;
appendGfx_msg_prim_rect(r, g, b, a, posX, posY, lrX, lrY);
}
void appendGfx_msg_prim_rect(u8 r, u8 g, u8 b, u8 a, u16 ulX, u16 ulY, u16 lrX, u16 lrY) {
gDPPipeSync(gMasterGfxPos++);
if (a == 255) {
gDPSetCombineLERP(gMasterGfxPos++, 0, 0, 0, PRIMITIVE, 0, 0, 0, 1, 0, 0, 0, PRIMITIVE, 0, 0, 0, 1);
} else {
gDPSetRenderMode(gMasterGfxPos++, G_RM_XLU_SURF, G_RM_XLU_SURF2);
gDPSetCombineMode(gMasterGfxPos++, G_CC_PRIMITIVE, G_CC_PRIMITIVE);
}
gDPSetPrimColor(gMasterGfxPos++, 0, 0, r, g, b, a);
gDPFillRectangle(gMasterGfxPos++, ulX, ulY, lrX, lrY);
gDPPipeSync(gMasterGfxPos++);
gDPSetRenderMode(gMasterGfxPos++, G_RM_TEX_EDGE, G_RM_TEX_EDGE2);
switch (gMessageDrawStatePtr->unk_29) {
case 0:
gDPSetCombineMode(gMasterGfxPos++, G_CC_DECALRGBA, G_CC_DECALRGBA);
break;
case 1:
gDPSetCombineMode(gMasterGfxPos++, G_CC_MODULATEIDECALA_PRIM, G_CC_MODULATEIDECALA_PRIM);
break;
default:
gDPSetCombineMode(gMasterGfxPos++, G_CC_DECALRGBA, G_CC_DECALRGBA);
break;
}
}
INCLUDE_ASM(s32, "msg", msg_draw_speech_bubble);
INCLUDE_ASM(s32, "msg", msg_draw_speech_arrow);
INCLUDE_ASM(s32, "msg", msg_draw_frame);
void msg_get_glyph(s32 font, s32 variation, s32 charIndex, s32 palette, MesasgeFontGlyphData* out);
INCLUDE_ASM(void, "msg", msg_get_glyph, s32 font, s32 variation, s32 charIndex, s32 palette, MesasgeFontGlyphData* out);