#include "global.h" #include "globaldata.h" #include "constants/input.h" #include "bg_palette_buffer.h" #include "code_800D090.h" #include "music_util.h" #include "event_flag.h" #include "game_options.h" #include "input.h" #include "menu_input.h" #include "pokemon.h" #include "rescue_team_info.h" #include "sprite.h" #include "string_format.h" #include "text_1.h" #include "text_2.h" #include "text_3.h" static const MenuItem sYesNoMenuItems[] = { { _("*Yes"), 1 }, { _("No"), 0 }, { NULL, -1 } }; static const MenuItem sYesNoMenuItems_DefaultNo[] = { { _("Yes"), 1 }, { _("*No"), 0 }, { NULL, -1 } }; static const u32 gUnknown_80D48A0[3] = { 0x7, 0x2, 0x2 }; static const WindowTemplate sWinTemplateDummy = WIN_TEMPLATE_DUMMY; static const WindowTemplate sDialogueBoxWindowTemplate = { .flags = WINTEMPLATE_FLAG_NONE, .type = WINDOW_TYPE_0, .pos = { 2, 15 }, .width = 26, .height = 5, .totalHeight = 7, .unk12 = 0, .header = NULL, }; static const WindowTemplate sOnlyTextDialogueBoxWindowTemplate = { .flags = WINTEMPLATE_FLAG_NONE, .type = WINDOW_TYPE_ONLY_TEXT, .pos = { 2, 8 }, .width = 26, .height = 5, .totalHeight = 7, .unk12 = 0, .header = NULL, }; static void sub_8014A88(void); static bool8 sub_8014B94(void); static void nullsub_35(void); static bool8 AppendString(const u8 *, u8 **, u8 *, u16 r3); // 'd', 'v' and 'V' EWRAM_DATA s32 gFormatArgs[10] = {0}; // NDS=02134278 // 'i', apparently only i0 and i1 are actually used though it's yet to be verified EWRAM_DATA u8 gFormatBuffer_Items[4][FORMAT_BUFFER_LEN] = {0}; // NDS=02134450 // 'm' which probably stands for 'monster', available through m0 to m9 EWRAM_DATA u8 gFormatBuffer_Monsters[10][FORMAT_BUFFER_LEN] = {0}; // 'n' which probably stands for 'name', available through n0 to n9 EWRAM_DATA u8 gFormatBuffer_Names[10][FORMAT_BUFFER_LEN] = {0}; // Current textbox's speaker's name EWRAM_DATA u8 gSpeakerNameBuffer[FORMAT_BUFFER_LEN] = {0}; // NDS=02134400 // 'h' - Friend Area buffer. This buffer seems larger than others. It's possible it actually has the same length, but there were some unused buffers right after it. EWRAM_DATA u8 gFormatBuffer_FriendArea[FRIEND_AREA_BUFFER_LEN] = {0}; static EWRAM_DATA SpriteOAM sDialogueBoxArrowSprite = {0}; // 't' - team name. This buffer seems wastefully large, given team name can be max 10(or so) characters. static EWRAM_DATA u8 sFormatBuffer_TeamName[FORMAT_BUFFER_LEN] = {0}; static EWRAM_DATA s32 sAutoPressNewTextboxFrames = 0; static EWRAM_DATA s32 sAutoPressMidTextboxFrames = 0; static EWRAM_DATA s32 sAutoPressFramesEndMsg = 0; static EWRAM_DATA s32 sPrintStringState = 0; static EWRAM_DATA UnkDrawStringStruct sTextPrintStruct = {0}; static EWRAM_DATA u16 sStringFormatFlags = 0; static EWRAM_DATA s32 sAutoPressFrames = 0; static EWRAM_DATA s32 sDialoguePrintFrames = 0; static EWRAM_DATA s32 sTextPrintSpeed = 0; static EWRAM_DATA s32 sFramesBetweenCharPrints = 0; static EWRAM_DATA bool8 sInstantText = FALSE; static EWRAM_DATA u8 sArrowFrames = 0; static EWRAM_DATA const u8 *sCurrStr = NULL; #define DIALOGUE_TEXT_BUFFER_SIZE 1000 static EWRAM_DATA u8 sDialogueTextBuffer[DIALOGUE_TEXT_BUFFER_SIZE] = {0}; static EWRAM_DATA u8 sFormatBuffer_UnknownMonster[64] = {0}; static EWRAM_DATA MenuStruct gUnknown_202EBC0 = {0}; static EWRAM_DATA u32 gUnknown_202EC10 = 0; static EWRAM_DATA const MenuItem *sDialogueMenuItems = NULL; static EWRAM_DATA void *gUnknown_202EC18 = NULL; static EWRAM_DATA s32 gUnknown_202EC1C = 0; // Only read, but never written to. Possibly used in Blue? struct NeverWrittenToStruct202EC20 { WindowTemplate unk0; const u8 *unk18; }; static EWRAM_DATA struct NeverWrittenToStruct202EC20 *sNeverWrittenToUnknownStructPtr = NULL; static UNUSED EWRAM_DATA u8 sUnusedEwram1[4] = {0}; static EWRAM_DATA TouchScreenMenuInput sDialogueMenuTouchScreenInput = {0}; static EWRAM_INIT WindowTemplates sDialogueBoxWinTemplates = { .id = { [0] = { .flags = WINTEMPLATE_FLAG_NONE, .type = WINDOW_TYPE_0, .pos = { 2, 15 }, .width = 26, .height = 5, .totalHeight = 7, .unk12 = 0, .header = NULL, }, [1] = { .flags = WINTEMPLATE_FLAG_x40, .type = WINDOW_TYPE_7, .pos = { 0, 0 }, .width = 0, .height = 0, .totalHeight = 0, .unk12 = 0, .header = NULL, }, [2] = WIN_TEMPLATE_DUMMY, [3] = WIN_TEMPLATE_DUMMY, } }; enum { STATE_FINISHED, STATE_PRINT_CHAR, STATE_PRINT_CHAR_SOUND_WAIT, STATE_PRINT_FINISHED_MENU, STATE_4, STATE_5, STATE_PRINT_FINISHED, // These 3 are the same STATE_WAIT_FOR_BUTTON_MID_TEXTBOX, STATE_WAIT_FOR_BUTTON_NEW_TEXTBOX, STATE_WAIT_FOR_BUTTON_PRESS_END_MSG, }; void ResetDialogueBox(void) { sPrintStringState = STATE_FINISHED; sAutoPressNewTextboxFrames = 60; sAutoPressMidTextboxFrames = 60; sAutoPressFramesEndMsg = 0; } void SetDialogueBoxAutoPressFrames(s32 endMsgFrames, s32 midMsgFrames) { if (endMsgFrames < -1) { sAutoPressNewTextboxFrames = midMsgFrames; sAutoPressFramesEndMsg = -endMsgFrames; } else { sAutoPressNewTextboxFrames = endMsgFrames; sAutoPressFramesEndMsg = 0; } sAutoPressMidTextboxFrames = (midMsgFrames < 0 ) ? 0 : midMsgFrames; } void CreateDialogueBoxAndPortrait(const u8 *text, void *param_2, MonPortraitMsg *monPortraitPtr, u16 flags) { CreateMenuDialogueBoxAndPortrait(text, param_2, -1, NULL, NULL, 3, 0, monPortraitPtr, flags); } void CreateYesNoDialogueBoxAndPortrait_DefaultYes(const u8 *text, MonPortraitMsg *monPortraitPtr, u16 flags) { CreateMenuDialogueBoxAndPortrait(text, NULL, -1, sYesNoMenuItems, NULL, 3, 0, monPortraitPtr, flags | 0x300); } void CreateYesNoDialogueBoxAndPortrait_DefaultNo(const u8 *text, MonPortraitMsg *monPortraitPtr, u16 flags) { CreateMenuDialogueBoxAndPortrait(text, NULL, -1, sYesNoMenuItems_DefaultNo, NULL, 3, 0, monPortraitPtr, flags | 0x300); } #define TEXTBOX_LINE_HEIGHT 11 #define TEXTBOX_HEIGHT ((TEXTBOX_LINE_HEIGHT * 3) + 1) #define TEXTBOX_OUT_OF_SPACE(y)(y > TEXTBOX_HEIGHT) // arm9.bin::0201D700 void CreateMenuDialogueBoxAndPortrait(const u8 *text, void *a1, u32 r9, const MenuItem *menuItems, void *arg_0, u32 a5, u32 unknownUnused, MonPortraitMsg *monPortraitPtr, u16 flags) { bool8 portraitOn = FALSE; FormatString(text, sDialogueTextBuffer, sDialogueTextBuffer + DIALOGUE_TEXT_BUFFER_SIZE - 1, flags); sCurrStr = sDialogueTextBuffer; sTextPrintStruct.unk24 = a1; gUnknown_202EC10 = a5; sDialogueMenuItems = menuItems; gUnknown_202EC18 = arg_0; gUnknown_202EC1C = r9; ResetTouchScreenMenuInput(&sDialogueMenuTouchScreenInput); if (flags & STR_FORMAT_FLAG_ONLY_TEXT) { sDialogueBoxWinTemplates.id[0] = sOnlyTextDialogueBoxWindowTemplate; } else { sDialogueBoxWinTemplates.id[0] = sDialogueBoxWindowTemplate; } sDialogueBoxWinTemplates.id[1].width = 0; sDialogueBoxWinTemplates.id[1].height = 0; sDialogueBoxWinTemplates.id[1].totalHeight = 0; sDialogueBoxWinTemplates.id[1].flags = WINTEMPLATE_FLAG_x40; if (monPortraitPtr != NULL && monPortraitPtr->faceData != NULL && monPortraitPtr->faceData->sprites[monPortraitPtr->spriteId].gfx != 0) { s32 i; sDialogueBoxWinTemplates.id[1].pos.x = monPortraitPtr->pos.x; sDialogueBoxWinTemplates.id[1].pos.y = monPortraitPtr->pos.y; sDialogueBoxWinTemplates.id[1].width = 5; sDialogueBoxWinTemplates.id[1].height = 5; sDialogueBoxWinTemplates.id[1].totalHeight = 5; for (i = 0; i < 16; i++) { SetBGPaletteBufferColorArray(224 + i, &monPortraitPtr->faceData->sprites[monPortraitPtr->spriteId].pal[i]); } portraitOn = TRUE; if (monPortraitPtr->unkE) { sDialogueBoxWinTemplates.id[1].type = WINDOW_TYPE_7; } else { sDialogueBoxWinTemplates.id[1].type = WINDOW_TYPE_FILL_TRANSPARENT; } } sDialogueBoxWinTemplates.id[2] = sWinTemplateDummy; sDialogueBoxWinTemplates.id[3] = sWinTemplateDummy; ResetUnusedInputStruct(); ShowWindows(&sDialogueBoxWinTemplates, TRUE, TRUE); sTextPrintStruct.x = 4; sTextPrintStruct.y = 4; sTextPrintStruct.arrowSpritePosX = 112; sTextPrintStruct.arrowSpritePosY = (gWindows[0].y * 8) + TEXTBOX_HEIGHT; sTextPrintStruct.unk10 = 7; sTextPrintStruct.unk1C = 0; sTextPrintStruct.waitButtonPress = 0; SetCharacterMask((flags & STR_FORMAT_FLAG_ONLY_TEXT) ? 8 : 3); sPrintStringState = 1; sStringFormatFlags = flags; if (flags & STR_FORMAT_FLAG_INSTANT_TEXT) { sInstantText = TRUE; } else { sInstantText = FALSE; } if (flags & 0x400) { SetWindowBGColor(); } sTextPrintSpeed = 1; sFramesBetweenCharPrints = 1; UnpressButtons(); sArrowFrames = 0; sDialoguePrintFrames = 0; if (portraitOn) { const u8 *data = monPortraitPtr->faceData->sprites[monPortraitPtr->spriteId].gfx; sub_80073B8(1); if (!monPortraitPtr->flip) { DisplayMonPortraitSprite(1, data, 14); } else { DisplayMonPortraitSpriteFlipped(1, data, 14); } sub_80073E0(1); } } void sub_8014490(void) { sPrintStringState = STATE_FINISHED; gUnknown_202EC1C = 0; } s32 sub_80144A4(s32 *a0) { if (a0 != NULL) { *a0 = gUnknown_202EC1C; } return sPrintStringState; } // arm9.bin::0201CEB0 void DrawDialogueBoxString_Async(void) { bool8 keepLooping = TRUE; sDialoguePrintFrames++; while (keepLooping) { switch (sPrintStringState) { case STATE_FINISHED: { keepLooping = FALSE; } break; case STATE_PRINT_CHAR: { const u8 *str = sCurrStr; s32 txtSpeed; if (sInstantText) { txtSpeed = 99999; } else { txtSpeed = sTextPrintSpeed; } sTextPrintStruct.framesToWait = 0; sub_80073B8(0); while (txtSpeed > 0) { str = HandleSpecialCharFormat(str, &sTextPrintStruct); if (sTextPrintStruct.waitFrames) { break; } if (sTextPrintStruct.waitButtonPress) { if (TEXTBOX_OUT_OF_SPACE(sTextPrintStruct.y)) { sPrintStringState = STATE_WAIT_FOR_BUTTON_NEW_TEXTBOX; sAutoPressFrames = sAutoPressNewTextboxFrames; } else { sPrintStringState = STATE_WAIT_FOR_BUTTON_MID_TEXTBOX; sAutoPressFrames = sAutoPressMidTextboxFrames; } sArrowFrames = 0; break; } if (*str == '\0') { break; } if (*str == '\r' || *str == '\n') { sTextPrintStruct.x = 4; sTextPrintStruct.y += TEXTBOX_LINE_HEIGHT; str++; } else { u32 chr; str = GetNextCharFromStr(str, &chr); sTextPrintStruct.x += DrawCharOnWindow(sTextPrintStruct.x, sTextPrintStruct.y, chr, sTextPrintStruct.unk10, 0); sTextPrintStruct.framesToWait = sFramesBetweenCharPrints; } if (TEXTBOX_OUT_OF_SPACE(sTextPrintStruct.y)) { if (!(sStringFormatFlags & STR_FORMAT_FLAG_ONLY_TEXT)) { sTextPrintStruct.unk1C = 0; sTextPrintStruct.waitButtonPress = TRUE; sPrintStringState = STATE_WAIT_FOR_BUTTON_NEW_TEXTBOX; sArrowFrames = 0; sAutoPressFrames = sAutoPressNewTextboxFrames; break; } else { sTextPrintStruct.y = 4; } } txtSpeed--; } sub_80073E0(0); sCurrStr = str; ResetTouchScreenMenuInput(&sDialogueMenuTouchScreenInput); if (*sCurrStr == '\0') { if (sDialogueMenuItems != NULL) { sPrintStringState = STATE_PRINT_FINISHED_MENU; } else { sPrintStringState = STATE_PRINT_FINISHED; } keepLooping = FALSE; } else { sTextPrintStruct.currFrames = 0; if (sTextPrintStruct.waitButtonPress) { if (sPrintStringState == STATE_PRINT_CHAR) { sPrintStringState = 7; sArrowFrames = 0; sAutoPressFrames = sAutoPressNewTextboxFrames; } keepLooping = FALSE; } else { sPrintStringState = STATE_PRINT_CHAR_SOUND_WAIT; } } } break; case STATE_PRINT_CHAR_SOUND_WAIT: { if (sStringFormatFlags & STR_FORMAT_FLAG_DIALOGUE_SOUND) { PlayDialogueTextSound(); } if (!(sStringFormatFlags & 2)) { if (sStringFormatFlags & STR_FORMAT_FLAG_INSTANT_TEXT_ON_AB_PRESS && gRealInputs.pressed & AB_BUTTONS) { sInstantText = TRUE; sTextPrintStruct.currFrames = 99999; } } if (++sTextPrintStruct.currFrames > sTextPrintStruct.framesToWait) { sPrintStringState = STATE_PRINT_CHAR; sTextPrintStruct.waitFrames = FALSE; } else { keepLooping = FALSE; } } break; case STATE_PRINT_FINISHED: { if (sStringFormatFlags & STR_FORMAT_FLAG_WAIT_FOR_BUTTON_PRESS) { sPrintStringState = STATE_WAIT_FOR_BUTTON_PRESS_END_MSG; sArrowFrames = 0; if (sAutoPressFramesEndMsg > 0) { sAutoPressFrames = sAutoPressFramesEndMsg - sDialoguePrintFrames; if (sAutoPressFrames < 0) { sPrintStringState = 11; sAutoPressFrames = 0; } } else { sAutoPressFrames = sAutoPressNewTextboxFrames; } } else { sPrintStringState = 11; } } break; case STATE_WAIT_FOR_BUTTON_MID_TEXTBOX: case STATE_WAIT_FOR_BUTTON_NEW_TEXTBOX: case STATE_WAIT_FOR_BUTTON_PRESS_END_MSG: { bool8 buttonPress = FALSE; sTextPrintStruct.waitButtonPress = 0; GetTouchScreenMenuInput(&sDialogueMenuTouchScreenInput, 0); if (!(sStringFormatFlags & STR_FORMAT_FLAG_WAIT_FOR_BUTTON_PRESS_2)) { buttonPress = TRUE; } else { if (sStringFormatFlags & STR_FORMAT_FLAG_TIMED_AUTO_MSG_CLOSE) { if (sAutoPressFrames > 0) { sAutoPressFrames--; } else { buttonPress = TRUE; } } else if (gRealInputs.pressed & AB_BUTTONS || sDialogueMenuTouchScreenInput.a_button) { buttonPress = TRUE; } else if ((gRealInputs.held & (DPAD_ANY | B_BUTTON)) == B_BUTTON) { buttonPress = TRUE; } else if (sDialogueMenuTouchScreenInput.unk5) { buttonPress = TRUE; } } if (!buttonPress) { sArrowFrames++; if (!(sStringFormatFlags & STR_FORMAT_FLAG_TIMED_AUTO_MSG_CLOSE) && sArrowFrames & 8) { SpriteSetAffine1(&sDialogueBoxArrowSprite, 0); SpriteSetAffine2(&sDialogueBoxArrowSprite, 0); SpriteSetObjMode(&sDialogueBoxArrowSprite, 0); SpriteSetMosaic(&sDialogueBoxArrowSprite, 0); SpriteSetBpp(&sDialogueBoxArrowSprite, 0); SpriteSetShape(&sDialogueBoxArrowSprite, 1); SpriteSetMatrixNum(&sDialogueBoxArrowSprite, 0); SpriteSetSize(&sDialogueBoxArrowSprite, 0); SpriteSetTileNum(&sDialogueBoxArrowSprite, 0x3F0); SpriteSetPriority(&sDialogueBoxArrowSprite, 0); SpriteSetPalNum(&sDialogueBoxArrowSprite, 15); if (sStringFormatFlags & STR_FORMAT_FLAG_ONLY_TEXT) { SpriteSetY(&sDialogueBoxArrowSprite, 120); SpriteSetX(&sDialogueBoxArrowSprite, 112); } else { SpriteSetY(&sDialogueBoxArrowSprite, sTextPrintStruct.arrowSpritePosY + 1); SpriteSetX(&sDialogueBoxArrowSprite, sTextPrintStruct.arrowSpritePosX); } AddSprite(&sDialogueBoxArrowSprite, 256, NULL, NULL); } } else { if (*sCurrStr == '\0') { sPrintStringState = 11; } else if (sPrintStringState == 9) { sPrintStringState = 11; } else if (sPrintStringState == 8) { sTextPrintStruct.x = 4; if (TEXTBOX_OUT_OF_SPACE(sTextPrintStruct.y)) { sTextPrintStruct.y = 4; if (sStringFormatFlags & STR_FORMAT_FLAG_ONLY_TEXT) { CallPrepareTextbox_8008C54(0); sPrintStringState = STATE_PRINT_CHAR; } else if (sTextPrintStruct.unk1C != 0) { CallPrepareTextbox_8008C54(0); sPrintStringState = STATE_PRINT_CHAR; } else { sPrintStringState = 10; sTextPrintStruct.unk28 = 0; } } else { sPrintStringState = STATE_PRINT_CHAR; } } else { sPrintStringState = STATE_PRINT_CHAR; } sTextPrintStruct.arrowSpritePosX = 0x70; sTextPrintStruct.arrowSpritePosY = (gWindows[0].y * 8) + TEXTBOX_HEIGHT; } keepLooping = FALSE; } break; case 10: { sTextPrintStruct.unk28++; gIwramTextFunc3(0); if (sTextPrintStruct.unk28 > 17) { sPrintStringState = STATE_PRINT_CHAR; } keepLooping = FALSE; } break; case 11: { if (sStringFormatFlags & 0x200) { ResetUnusedInputStruct(); ShowWindows(NULL, TRUE, TRUE); sPrintStringState = STATE_FINISHED; } else { sPrintStringState = STATE_FINISHED; } keepLooping = FALSE; } break; case STATE_PRINT_FINISHED_MENU: { sub_8014A88(); sPrintStringState = 4; keepLooping = FALSE; } break; case 4: { if (sub_8014B94()) { sPrintStringState = 5; } keepLooping = FALSE; } break; case 5: { nullsub_35(); sPrintStringState = 11; } break; } } } static void sub_8014A88(void) { s32 r2, r1; u8 text[128]; const MenuItem *menuItem = sDialogueMenuItems; s32 r5 = 0; s32 r7 = 0; s32 i; for (i = 0; i < 10; menuItem++, i++) { s32 val; if (menuItem->text == NULL) break; r5 += 12; FormatString(menuItem->text, text, text + sizeof(text), 0); val = GetStringLineWidth(text); if (r7 < val) { r7 = val; } } r2 = r5 / 8; if (r5 % 8) r2++; sDialogueBoxWinTemplates.id[2].type = gUnknown_202EC10; r1 = r7 / 8; r1 += 2; sDialogueBoxWinTemplates.id[2].width = r1; sDialogueBoxWinTemplates.id[2].totalHeight = r2; sDialogueBoxWinTemplates.id[2].height = r2; sDialogueBoxWinTemplates.id[2].pos.x = 28 - r1; sDialogueBoxWinTemplates.id[2].pos.y = 14 - r2; sDialogueBoxWinTemplates.id[0].flags = WINTEMPLATE_FLAG_x80; sDialogueBoxWinTemplates.id[1].flags = WINTEMPLATE_FLAG_x40 | WINTEMPLATE_FLAG_x80; if (sNeverWrittenToUnknownStructPtr != NULL) { sDialogueBoxWinTemplates.id[3] = sNeverWrittenToUnknownStructPtr->unk0; } ResetUnusedInputStruct(); ShowWindows(&sDialogueBoxWinTemplates, TRUE, FALSE); sub_8012D60(&gUnknown_202EBC0, sDialogueMenuItems, gUnknown_80D48A0, gUnknown_202EC18, gUnknown_202EC1C, 2); if (sNeverWrittenToUnknownStructPtr != NULL) { sub_80073B8(3); PrintStringOnWindow(4, 2, sNeverWrittenToUnknownStructPtr->unk18, 3, 0); sub_80073E0(3); } } static bool8 sub_8014B94(void) { if (!sub_8012FD8(&gUnknown_202EBC0)) { sub_8013114(&gUnknown_202EBC0, &gUnknown_202EC1C); return TRUE; } else { return FALSE; } } static void UNUSED nullsub_35(void) { } // arm9.bin::0201C854 const u8 *FormatString(const u8 *str, u8 *dst, u8 *dstMax, u16 flags) { u8 txtArray[60]; bool8 r10 = TRUE; bool8 r9 = TRUE; dstMax--; while (TRUE) { u8 currChar = *str; if (currChar == '\0') break; if (currChar == '\r' || currChar == '\n') { if (flags & STR_FORMAT_FLAG_NEW_LINE_TERMINATES) break; r9 = TRUE; } else { if (r10) { r10 = FALSE; r9 = FALSE; if (flags & STR_FORMAT_FLAG_SPEAKER_NAME) { AppendString(gSpeakerNameBuffer, &dst, dstMax, flags); AppendString(": ", &dst, dstMax, flags); } } else if (r9) { r9 = FALSE; } } if (currChar == '#') { u8 chrPls1 = str[1]; if (chrPls1 == 'P' || chrPls1 == 'p') { r10 = TRUE; r9 = TRUE; } if (dst + 1 < dstMax) { *(dst++) = '#'; *(dst++) = chrPls1; } str += 2; } else if (currChar == '$') { const u8 *txtPtr = NULL; str++; switch (*str) { case 'i': str++; txtPtr = gFormatBuffer_Items[*str - '0']; str++; break; case 'm': str++; if (*str == 'm') { Pokemon *monStruct = GetLeaderMon2(); txtPtr = sFormatBuffer_UnknownMonster; PrintColoredPokeNameToBuffer(sFormatBuffer_UnknownMonster, monStruct, 0); } else { txtPtr = gFormatBuffer_Monsters[*str - '0']; str++; } break; case 'n': str++; txtPtr = gFormatBuffer_Names[*str - '0']; str++; break; case 't': str++; if (CheckQuest(QUEST_SET_TEAM_NAME)) { StrncpyTeamName(sFormatBuffer_TeamName); } else { InlineStrcpy(sFormatBuffer_TeamName, "????"); } txtPtr = sFormatBuffer_TeamName; break; case 'h': str++; txtPtr = gFormatBuffer_FriendArea; break; case 'd': str++; sprintfStatic(txtArray, "%d", gFormatArgs[*(str++) - '0']); txtPtr = txtArray; break; case 'v': { s32 a; u8 *unkTxtPtr; str++; a = gFormatArgs[*(str++) - '0']; sprintfStatic(txtArray, "%*d", *(str++) - '0', a); unkTxtPtr = txtArray; while (*unkTxtPtr != '\0') { if (*unkTxtPtr == ' ') { *unkTxtPtr = '`'; } unkTxtPtr++; } txtPtr = txtArray; } break; // the same as above except "%0*d" instead of "%*d" case 'V': { s32 a; u8 *unkTxtPtr; str++; a = gFormatArgs[*(str++) - '0']; sprintfStatic(txtArray, "%0*d", *(str++) - '0', a); unkTxtPtr = txtArray; while (*unkTxtPtr != '\0') { if (*unkTxtPtr == ' ') { *unkTxtPtr = '`'; } unkTxtPtr++; } txtPtr = txtArray; } break; case '$': txtPtr = "$"; break; case '-': str++; break; } if (txtPtr != NULL) { if (AppendString(txtPtr, &dst, dstMax, flags)) break; } } else if (currChar == 0x81 || currChar == 0x82 || currChar == 0x83 || currChar == 0x84 || currChar == 0x87) { if (dst < dstMax) { *(dst++) = currChar; } str++; if (*str == '\0') break; if (dst < dstMax) { *(dst++) = *str; } str++; } else { if (dst < dstMax) { *(dst++) = currChar; } str++; } } *dst = 0; if (*str == '\r') str++; if (*str == '\n') str++; return str; } static bool8 AppendString(const u8 *str, u8 **dstPtr, u8 *dstMax, u16 flags) { u8 *dst = *dstPtr; while (*str != '\0') { if (flags & STR_FORMAT_FLAG_NEW_LINE_TERMINATES && *str == '\r') { *dstPtr = dst; return TRUE; } if (dst < dstMax) { *dst = *str; dst++; } str++; } *dstPtr = dst; return FALSE; } #define FORMAT_STR_MAX_LEN 500 // arm9.bin::0201C7AC void PrintFormattedStringOnWindow(s32 x, s32 y, const u8 *str, u32 windowId, u32 terminatingChr) { u8 formattedString[FORMAT_STR_MAX_LEN]; FormatString(str, formattedString, formattedString + FORMAT_STR_MAX_LEN, 0); formattedString[FORMAT_STR_MAX_LEN - 1] = '\0'; PrintStringOnWindow(x, y, formattedString, windowId, terminatingChr); } // arm9.bin::0201C750 void PrintFormattedStringOnWindow2(s32 x, s32 y, const u8 *str, u32 windowId, u32 terminatingChr, s32 lineSpacing) { u8 formattedString[FORMAT_STR_MAX_LEN]; FormatString(str, formattedString, formattedString + FORMAT_STR_MAX_LEN, 0); formattedString[FORMAT_STR_MAX_LEN - 1] = '\0'; PrintStringOnWindow2(x, y, formattedString, windowId, terminatingChr, lineSpacing); }