mirror of
https://github.com/pret/pmd-red.git
synced 2026-05-07 05:27:11 -05:00
847 lines
29 KiB
C
847 lines
29 KiB
C
#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);
|
|
}
|