summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/link.c8
-rw-r--r--src/main_menu.c1662
-rw-r--r--src/menu.c1003
-rw-r--r--src/pokemon.c607
-rw-r--r--src/text.c2
-rw-r--r--src/text_window.c196
6 files changed, 3473 insertions, 5 deletions
diff --git a/src/link.c b/src/link.c
index a5d848b83..13fcf8c05 100644
--- a/src/link.c
+++ b/src/link.c
@@ -27,7 +27,7 @@ struct LinkTestBGInfo
u32 dummy_C;
};
-extern void sub_8071C4C(const struct WindowConfig *);
+extern void InitMenuWindow(const struct WindowConfig *);
extern void sub_80516C4(u8, u16);
extern u8 unk_2000000[];
@@ -237,7 +237,7 @@ static void LinkTestScreen(void)
ResetTasks();
SetVBlankCallback(VBlankCB_LinkTest);
SetUpWindowConfig(&gWindowConfig_81E6CE4);
- sub_8071C4C(&gWindowConfig_81E6CE4);
+ InitMenuWindow(&gWindowConfig_81E6CE4);
ResetBlockSend();
gLinkType = 0x1111;
OpenLink();
@@ -1224,8 +1224,8 @@ void CB2_LinkError(void)
ResetTasks();
SetVBlankCallback(VBlankCB_LinkTest);
SetUpWindowConfig(&gWindowConfig_81E7198);
- sub_8071C4C(&gWindowConfig_81E7198);
- sub_8071EF4();
+ InitMenuWindow(&gWindowConfig_81E7198);
+ MenuZeroFillScreen();
REG_BLDALPHA = 0;
REG_BG0VOFS = 0;
REG_BG0HOFS = 0;
diff --git a/src/main_menu.c b/src/main_menu.c
new file mode 100644
index 000000000..559bf5a0a
--- /dev/null
+++ b/src/main_menu.c
@@ -0,0 +1,1662 @@
+#include "global.h"
+#include "text.h"
+#include "sprite.h"
+#include "task.h"
+#include "main.h"
+#include "rtc.h"
+#include "songs.h"
+#include "palette.h"
+#include "string_util.h"
+#include "species.h"
+
+extern u8 MenuUpdateWindowText(void);
+extern void MenuPrint(u8 *, u8, u8);
+extern void CB2_ContinueSavedGame(void);
+extern void CB2_InitMysteryEventMenu(void);
+extern void CB2_InitOptionMenu(void);
+extern void CB2_InitTitleScreen(void);
+extern void FormatPlayTime(u8 *str, u16 hours, u16 minutes, bool16 colon);
+extern u8 *sub_8072C74(u8 *, u8 *, u8, u8);
+extern u16 GetPokedexSeenCount(void);
+extern u8 *sub_8072C14(u8 *, s32, u8, u8);
+extern u8 sub_80729D8(u8 *, u8, u16, u8);
+extern u8 GetBadgeCount(void);
+extern void Task_Birch1(u8);
+void MenuPrintMessage(const u8 *string, u8 a, u8 b);
+u8 MenuUpdateWindowText_OverrideLineLength(u8 a);
+void sub_8072DEC(void);
+u8 sub_8075374(void);
+void MenuSetText(u32);
+void cry_related(u16, u8);
+void audio_play(u8 a);
+void MenuZeroFillWindowRect(u8 a, u8 b, u8 c, u8 d);
+u8 GetMenuCursorPos(void);
+void DoNamingScreen(u8 r0, struct SaveBlock2 *r1, u16 r2, u16 r3, u8 s0, MainCallback s4);
+void DisplayYesNoMenu(u8 r0, u8 r1, u32 r2);
+s8 ProcessMenuInputNoWrap_(void);
+void c2_load_new_map_2(void);
+void LZ77UnCompVram(const void *src, void *dest);
+void InitMenuWindow(const struct WindowConfig *);
+void CB2_MainMenu(void);
+void VBlankCB_MainMenu(void);
+void DecompressPicFromTable_2(const struct SpriteSheet *, u8, u8, void *, void *, u32);
+void LoadCompressedObjectPalette(const struct SpritePalette *);
+void gpu_pal_obj_decompress_and_apply(u16, u8);
+u8 AddNewGameBirchObject(u8, u8, u8);
+u8 sub_80859BC(u8, u16, u16, u8, void *);
+void MenuDrawTextWindow(u8 a, u8 b, u8 c, u8 d);
+
+extern struct PaletteFadeControl gPaletteFade;
+extern u8 gSaveFileDeletedMessage[];
+extern u8 gSaveFileCorruptMessage[];
+extern u8 gBoardNotInstalledMessage[];
+extern u8 gBatteryDryMessage[];
+extern u16 gSaveFileStatus;
+extern u8 gMainMenuString_Continue[];
+extern u8 gMainMenuString_NewGame[];
+extern u8 gMainMenuString_MysteryEvents[];
+extern u8 gMainMenuString_Option[];
+extern u8 gMainMenuString_Player[];
+extern u8 gMainMenuString_Time[];
+extern u8 gMainMenuString_Pokedex[];
+extern u8 gMainMenuString_Badges[];
+
+void CB2_MainMenu(void);
+void VBlankCB_MainMenu(void);
+void CB2_InitMainMenu(void);
+static void sub_80096FC(void);
+static u32 InitMainMenu(bool8 a1);
+static void Task_CheckSave(u8 taskId);
+static void Task_WaitForSaveErrorAck(u8 taskId);
+static void Task_CheckRtc(u8 taskId);
+static void Task_WaitForRtcErrorAck(u8 taskId);
+static void Task_DrawMainMenu(u8 taskId);
+static void Task_HighlightCurrentMenuItem(u8 taskId);
+static bool8 MainMenuProcessKeyInput(u8 taskId);
+static void Task_MainMenuProcessKeyInput(u8 taskId);
+static void MainMenuPressedA(u8 taskId);
+static void MainMenuPressedB(u8 taskId);
+static void HighlightCurrentMenuItem(u8, u8);
+static void PrintMainMenuItem(u8 *text, u8, u8);
+static void PrintSaveFileInfo(void);
+static void PrintPlayerName(void);
+static void PrintPlayTime(void);
+static void PrintPokedexCount(void);
+static void PrintBadgeCount(void);
+
+extern u16 gMainMenuPalette[];
+
+void CB2_MainMenu(void)
+{
+ RunTasks();
+ AnimateSprites();
+ BuildOamBuffer();
+ UpdatePaletteFade();
+}
+
+void VBlankCB_MainMenu(void)
+{
+ LoadOam();
+ ProcessSpriteCopyRequests();
+ TransferPlttBuffer();
+}
+
+void CB2_InitMainMenu(void)
+{
+ InitMainMenu(FALSE);
+}
+
+static void sub_80096FC(void)
+{
+ InitMainMenu(TRUE);
+}
+
+u32 InitMainMenu(u8 a1)
+{
+ u16 savedIme;
+ u8 taskId;
+
+ SetVBlankCallback(NULL);
+
+ REG_DISPCNT = 0;
+ REG_BG2CNT = 0;
+ REG_BG1CNT = 0;
+ REG_BG0CNT = 0;
+ REG_BG2HOFS = 0;
+ REG_BG2VOFS = 0;
+ REG_BG1HOFS = 0;
+ REG_BG1VOFS = 0;
+ REG_BG0HOFS = 0;
+ REG_BG0VOFS = 0;
+
+ DmaFill16(3, 0, (void *)VRAM, VRAM_SIZE);
+ DmaFill32(3, 0, (void *)OAM, OAM_SIZE);
+ DmaFill16(3, 0, (void *)(PLTT + 2), PLTT_SIZE - 2);
+
+ ResetPaletteFade();
+ LoadPalette(gMainMenuPalette, 0, 32);
+ remove_some_task();
+ ResetTasks();
+ ResetSpriteData();
+ FreeAllSpritePalettes();
+ SetUpWindowConfig(&gWindowConfig_81E6C3C);
+ InitMenuWindow(&gWindowConfig_81E6CE4);
+
+ if (a1)
+ BeginNormalPaletteFade(-1, 0, 0x10, 0, 0x0000); // fade to black
+ else
+ BeginNormalPaletteFade(-1, 0, 0x10, 0, 0xFFFF); // fade to white
+
+ REG_WIN0H = 0;
+ REG_WIN0V = 0;
+ REG_WININ = 0;
+ REG_WINOUT = 0;
+ REG_BLDCNT = 0;
+ REG_BLDALPHA = 0;
+ REG_BLDY = 0;
+
+ savedIme = REG_IME;
+ REG_IME = 0;
+ REG_IE |= INTR_FLAG_VBLANK;
+ REG_IME = savedIme;
+
+ SetVBlankCallback(VBlankCB_MainMenu);
+ SetMainCallback2(CB2_MainMenu);
+
+ REG_DISPCNT = DISPCNT_OBJ_1D_MAP
+ | DISPCNT_BG0_ON
+ | DISPCNT_OBJ_ON
+ | DISPCNT_WIN0_ON;
+
+ taskId = CreateTask(Task_CheckSave, 0);
+ gTasks[taskId].data[1] = 0;
+
+ return 0;
+}
+
+void Task_CheckSave(u8 taskId)
+{
+ if (gPaletteFade.active)
+ return;
+
+ REG_WIN0H = 0;
+ REG_WIN0V = 0;
+ REG_WININ = 0x1111;
+ REG_WINOUT = 49;
+ REG_BLDCNT = 241;
+ REG_BLDALPHA = 0;
+ REG_BLDY = 7;
+
+ switch (gSaveFileStatus)
+ {
+ case 1:
+ if (sub_806918C() == TRUE)
+ gTasks[taskId].data[0] = 2;
+ else
+ gTasks[taskId].data[0] = 1;
+
+ gTasks[taskId].func = Task_CheckRtc;
+ break;
+ case 2:
+ MenuDrawTextWindow(2, 14, 27, 19);
+ MenuPrintMessage(gSaveFileDeletedMessage, 3, 15);
+ REG_WIN0H = WIN_RANGE(17, 223);
+ REG_WIN0V = WIN_RANGE(113, 159);
+ gTasks[taskId].data[0] = 0;
+ gTasks[taskId].func = Task_WaitForSaveErrorAck;
+ break;
+ case 255:
+ MenuDrawTextWindow(2, 14, 27, 19);
+ MenuPrintMessage(gSaveFileCorruptMessage, 3, 15);
+ REG_WIN0H = WIN_RANGE(17, 223);
+ REG_WIN0V = WIN_RANGE(113, 159);
+ gTasks[taskId].data[0] = 1;
+ gTasks[taskId].func = Task_WaitForSaveErrorAck;
+
+ if (sub_806918C() == TRUE)
+ gTasks[taskId].data[0] = 2;
+ else
+ gTasks[taskId].data[0] = 1;
+ break;
+ case 0:
+ default:
+ gTasks[taskId].data[0] = 0;
+ gTasks[taskId].func = Task_CheckRtc;
+ break;
+ case 4:
+ MenuDrawTextWindow(2, 14, 27, 19);
+ MenuPrintMessage(gBoardNotInstalledMessage, 3, 15);
+ REG_WIN0H = WIN_RANGE(17, 223);
+ REG_WIN0V = WIN_RANGE(113, 159);
+ gTasks[taskId].data[0] = 0;
+ gTasks[taskId].func = Task_WaitForSaveErrorAck;
+ return;
+ }
+}
+
+void Task_WaitForSaveErrorAck(u8 taskId)
+{
+ if (MenuUpdateWindowText())
+ {
+ if (gMain.newKeys & A_BUTTON)
+ {
+ MenuZeroFillWindowRect(2, 14, 27, 19);
+ gTasks[taskId].func = Task_CheckRtc;
+ }
+ }
+}
+
+void Task_CheckRtc(u8 taskId)
+{
+ if (!gPaletteFade.active)
+ {
+ REG_WIN0H = 0;
+ REG_WIN0V = 0;
+ REG_WININ = 0x1111;
+ REG_WINOUT = 49;
+ REG_BLDCNT = 241;
+ REG_BLDALPHA = 0;
+ REG_BLDY = 7;
+
+ if (!(RtcGetErrorStatus() & RTC_ERR_FLAG_MASK))
+ {
+ gTasks[taskId].func = Task_DrawMainMenu;
+ }
+ else
+ {
+ MenuDrawTextWindow(2, 14, 27, 19);
+ MenuPrintMessage(gBatteryDryMessage, 3, 15);
+ REG_WIN0H = WIN_RANGE(17, 223);
+ REG_WIN0V = WIN_RANGE(113, 159);
+ gTasks[taskId].func = Task_WaitForRtcErrorAck;
+ }
+ }
+}
+
+void Task_WaitForRtcErrorAck(u8 taskId)
+{
+ if (MenuUpdateWindowText())
+ {
+ if ( gMain.newKeys & 1 )
+ {
+ MenuZeroFillWindowRect(2, 14, 27, 19);
+ gTasks[taskId].func = Task_DrawMainMenu;
+ }
+ }
+}
+
+void Task_DrawMainMenu(u8 taskId)
+{
+ u16 palette;
+
+ if (!gPaletteFade.active)
+ {
+ REG_WIN0H = 0;
+ REG_WIN0V = 0;
+ REG_WININ = 0x1111;
+ REG_WINOUT = 49;
+ REG_BLDCNT = 241;
+ REG_BLDALPHA = 0;
+ REG_BLDY = 7;
+
+ palette = RGB(0, 0, 0);
+ LoadPalette(&palette, 254, 2);
+
+ if (gSaveBlock2.playerGender == MALE)
+ {
+ palette = RGB(4, 16, 31);
+ LoadPalette(&palette, 241, 2);
+ }
+ else
+ {
+ palette = RGB(31, 3, 21);
+ LoadPalette(&palette, 241, 2);
+ }
+
+ switch (gTasks[taskId].data[0])
+ {
+ case 0:
+ default:
+ MenuDrawTextWindow(1, 0, 28, 3);
+ PrintMainMenuItem(gMainMenuString_NewGame, 2, 1);
+ MenuDrawTextWindow(1, 4, 28, 7);
+ PrintMainMenuItem(gMainMenuString_Option, 2, 5);
+ break;
+ case 1:
+ MenuDrawTextWindow(1, 0, 28, 7);
+ PrintMainMenuItem(gMainMenuString_Continue, 2, 1);
+ MenuDrawTextWindow(1, 8, 28, 11);
+ PrintMainMenuItem(gMainMenuString_NewGame, 2, 9);
+ MenuDrawTextWindow(1, 12, 28, 15);
+ PrintMainMenuItem(gMainMenuString_Option, 2, 13);
+ PrintSaveFileInfo();
+ break;
+ case 2:
+ MenuDrawTextWindow(1, 0, 28, 7);
+ PrintMainMenuItem(gMainMenuString_Continue, 2, 1);
+ MenuDrawTextWindow(1, 8, 28, 11);
+ PrintMainMenuItem(gMainMenuString_NewGame, 2, 9);
+ MenuDrawTextWindow(1, 12, 28, 15);
+ PrintMainMenuItem(gMainMenuString_MysteryEvents, 2, 13);
+ MenuDrawTextWindow(1, 16, 28, 19);
+ PrintMainMenuItem(gMainMenuString_Option, 2, 0x11);
+ PrintSaveFileInfo();
+ break;
+ }
+
+ gTasks[taskId].func = Task_HighlightCurrentMenuItem;
+ }
+}
+
+void Task_HighlightCurrentMenuItem(u8 taskId)
+{
+ HighlightCurrentMenuItem(gTasks[taskId].data[0], gTasks[taskId].data[1]);
+ gTasks[taskId].func = Task_MainMenuProcessKeyInput;
+}
+
+bool8 MainMenuProcessKeyInput(u8 taskId)
+{
+ if (gMain.newKeys & A_BUTTON)
+ {
+ audio_play(SE_SELECT);
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 0x10, 0x0000);
+ gTasks[taskId].func = MainMenuPressedA;
+ }
+ else if (gMain.newKeys & B_BUTTON)
+ {
+ audio_play(SE_SELECT);
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 0x10, 0xFFFF);
+ REG_WIN0H = WIN_RANGE(0, 240);
+ REG_WIN0V = WIN_RANGE(0, 160);
+ gTasks[taskId].func = MainMenuPressedB;
+ }
+ else
+ {
+ s32 menuItemCount;
+
+ switch (gTasks[taskId].data[0])
+ {
+ case 0:
+ default:
+ menuItemCount = 2;
+ break;
+ case 1:
+ menuItemCount = 3;
+ break;
+ case 2:
+ menuItemCount = 4;
+ break;
+ }
+
+ if (gMain.newKeys & DPAD_UP)
+ {
+ if (gTasks[taskId].data[1] > 0)
+ {
+ gTasks[taskId].data[1]--;
+ return TRUE;
+ }
+ }
+ if (gMain.newKeys & DPAD_DOWN)
+ {
+ if (gTasks[taskId].data[1] < menuItemCount - 1)
+ {
+ gTasks[taskId].data[1]++;
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+void Task_MainMenuProcessKeyInput(u8 taskId)
+{
+ bool8 currentMenuItemChanged = MainMenuProcessKeyInput(taskId);
+ if (currentMenuItemChanged)
+ gTasks[taskId].func = Task_HighlightCurrentMenuItem;
+}
+
+void MainMenuPressedA(u8 taskId)
+{
+ enum
+ {
+ NEW_GAME,
+ CONTINUE,
+ OPTION,
+ MYSTERY_EVENTS,
+ } action;
+
+ if (gPaletteFade.active)
+ return;
+
+ switch (gTasks[taskId].data[0])
+ {
+ case 0:
+ default:
+ switch (gTasks[taskId].data[1])
+ {
+ case 0:
+ default:
+ action = NEW_GAME;
+ break;
+ case 1:
+ action = OPTION;
+ break;
+ }
+ break;
+ case 1:
+ switch (gTasks[taskId].data[1])
+ {
+ case 0:
+ default:
+ action = CONTINUE;
+ break;
+ case 1:
+ action = NEW_GAME;
+ break;
+ case 2:
+ action = OPTION;
+ break;
+ }
+ break;
+ case 2:
+ switch (gTasks[taskId].data[1])
+ {
+ case 0:
+ default:
+ action = CONTINUE;
+ break;
+ case 1:
+ action = NEW_GAME;
+ break;
+ case 2:
+ action = MYSTERY_EVENTS;
+ break;
+ case 3:
+ action = OPTION;
+ break;
+ }
+ break;
+ }
+
+ switch ((int)action)
+ {
+ case NEW_GAME:
+ default:
+ gPlttBufferUnfaded[0] = 0;
+ gPlttBufferFaded[0] = 0;
+ gTasks[taskId].func = Task_Birch1;
+ break;
+ case CONTINUE:
+ gPlttBufferUnfaded[0] = 0;
+ gPlttBufferFaded[0] = 0;
+ SetMainCallback2(CB2_ContinueSavedGame);
+ DestroyTask(taskId);
+ break;
+ case OPTION:
+ gMain.field_8 = (u32)sub_80096FC;
+ SetMainCallback2(CB2_InitOptionMenu);
+ DestroyTask(taskId);
+ break;
+ case MYSTERY_EVENTS:
+ SetMainCallback2(CB2_InitMysteryEventMenu);
+ DestroyTask(taskId);
+ break;
+ }
+}
+
+void MainMenuPressedB(u8 taskId)
+{
+ if (!gPaletteFade.active)
+ {
+ SetMainCallback2(CB2_InitTitleScreen);
+ DestroyTask(taskId);
+ }
+}
+
+void HighlightCurrentMenuItem(u8 layout, u8 menuItem)
+{
+ REG_WIN0H = WIN_RANGE(9, 231);
+
+ switch (layout)
+ {
+ case 0:
+ default:
+ switch (menuItem)
+ {
+ case 0:
+ default:
+ REG_WIN0V = WIN_RANGE(1, 31);
+ break;
+ case 1:
+ REG_WIN0V = WIN_RANGE(33, 63);
+ break;
+ }
+ break;
+ case 1:
+ switch (menuItem)
+ {
+ case 0:
+ default:
+ REG_WIN0V = WIN_RANGE(1, 63);
+ break;
+ case 1:
+ REG_WIN0V = WIN_RANGE(65, 95);
+ break;
+ case 2:
+ REG_WIN0V = WIN_RANGE(97, 127);
+ break;
+ }
+ break;
+ case 2:
+ switch (menuItem)
+ {
+ case 0:
+ default:
+ REG_WIN0V = WIN_RANGE(1, 63);
+ break;
+ case 1:
+ REG_WIN0V = WIN_RANGE(65, 95);
+ break;
+ case 2:
+ REG_WIN0V = WIN_RANGE(97, 127);
+ break;
+ case 3:
+ REG_WIN0V = WIN_RANGE(129, 159);
+ break;
+ }
+ break;
+ }
+}
+
+void PrintMainMenuItem(u8 *text, u8 left, u8 top)
+{
+ u8 i;
+ u8 buffer[32];
+
+ buffer[0] = 0xFC;
+ buffer[1] = 1;
+ buffer[2] = 14;
+
+ for (i = 0; i < 26; i++)
+ buffer[3 + i] = text[i];
+
+ buffer[29] = EOS;
+
+ MenuPrint(buffer, left, top);
+}
+
+void PrintSaveFileInfo(void)
+{
+ PrintPlayerName();
+ PrintPokedexCount();
+ PrintPlayTime();
+ PrintBadgeCount();
+}
+
+void PrintPlayerName(void)
+{
+ MenuPrint(gMainMenuString_Player, 2, 3);
+ MenuPrint(gSaveBlock2.playerName, 9, 3);
+}
+
+void PrintPlayTime(void)
+{
+ u8 playTime[16];
+ u8 alignedPlayTime[32];
+
+ MenuPrint(gMainMenuString_Time, 16, 3);
+ FormatPlayTime(playTime, gSaveBlock2.playTimeHours, gSaveBlock2.playTimeMinutes, 1);
+ sub_8072C74(alignedPlayTime, playTime, 48, 1);
+ MenuPrint(alignedPlayTime, 22, 3);
+}
+
+void PrintPokedexCount(void)
+{
+ u8 buffer[16];
+
+ MenuPrint(gMainMenuString_Pokedex, 2, 5);
+ sub_8072C14(buffer, GetPokedexSeenCount(), 18, 0);
+ MenuPrint(buffer, 9, 5);
+}
+
+void PrintBadgeCount(void)
+{
+ u8 buffer[16];
+
+ MenuPrint(gMainMenuString_Badges, 16, 5);
+ ConvertIntToDecimalString(buffer, GetBadgeCount());
+ sub_80729D8(buffer, 205, 40, 1);
+}
+
+//Text Strings
+extern const u8 gUnknown_081C6D78[]; //Hi! Sorry to keep you waiting!...
+extern const u8 gUnknown_081C6DF8[];
+extern const u8 gUnknown_081C6E1A[];
+extern const u8 gUnknown_081C6FCB[];
+extern const u8 gUnknown_081C6FD8[];
+extern const u8 gUnknown_081C6FFA[];
+extern u8 gUnknown_081C7017[];
+extern u8 gUnknown_081C7025[];
+extern u8 gUnknown_081C7074[];
+
+struct MonCoords
+{
+ u8 x, y;
+};
+
+extern const struct MonCoords gMonFrontPicCoords[];
+extern const struct SpriteSheet gMonFrontPicTable[];
+extern const struct SpritePalette gMonPaletteTable[];
+extern struct SpriteTemplate gUnknown_02024E8C;
+extern void * const gUnknown_081FAF4C[];
+extern u16 gUnknown_081E795C[];
+extern u8 * const gUnknown_081E79B0[][2];
+extern u8 * const gUnknown_081E79C0[][2];
+extern u8 * const gUnknown_081E79E8[][2];
+
+extern const u8 gUnknown_081E764C[];
+extern const u8 gUnknown_081E768C[];
+extern const u8 gUnknown_081E7834[];
+extern const u8 gUnknown_081E796C[];
+extern const u8 gUnknown_0840DFF7[];
+
+extern u8 gSpriteAffineAnimTable_81E79AC[];
+
+extern struct Sprite gSprites[];
+extern u8 gStringVar4[];
+
+extern u8 unk_2000000[];
+
+void task_new_game_prof_birch_speech_2(u8 taskId);
+void task_new_game_prof_birch_speech_3(u8 taskId);
+void task_new_game_prof_birch_speech_4(u8 taskId);
+void task_new_game_prof_birch_speech_5(u8 taskId);
+void task_new_game_prof_birch_speech_6(u8 taskId);
+void task_new_game_prof_birch_speech_7(u8 taskId);
+void task_new_game_prof_birch_speech_8(u8 taskId);
+void task_new_game_prof_birch_speech_9(u8 taskId);
+void task_new_game_prof_birch_speech_10(u8 taskId);
+void task_new_game_prof_birch_speech_11(u8 taskId);
+void task_new_game_prof_birch_speech_12(u8 taskId);
+void task_new_game_prof_birch_speech_13(u8 taskId);
+void task_new_game_prof_birch_speech_14(u8 taskId);
+void task_new_game_prof_birch_speech_15(u8 taskId);
+void task_new_game_prof_birch_speech_16(u8 taskId);
+void task_new_game_prof_birch_speech_17(u8 taskId);
+void task_new_game_prof_birch_speech_18(u8 taskId);
+void sub_800A974(u8 taskId);
+void Task_800A9B4(u8 taskId);
+void sub_800A9EC(u8 taskId);
+void sub_800AAAC(u8 taskId);
+void task_new_game_prof_birch_speech_part2_1(u8 taskId);
+void sub_800AB38(u8 taskId);
+void task_new_game_prof_birch_speech_part2_4(u8 taskId);
+void sub_800AC20(u8 taskId);
+void task_new_game_prof_birch_speech_part2_6(u8 taskId);
+void task_new_game_prof_birch_speech_part2_7(u8 taskId);
+void task_new_game_prof_birch_speech_part2_8(u8 taskId);
+void task_new_game_prof_birch_speech_part2_9(u8 taskId);
+void task_new_game_prof_birch_speech_part2_10(u8 taskId);
+void sub_800AFC0(u8 taskId);
+void sub_800B034(u8 taskId);
+void new_game_prof_birch_speech_part2_start();
+void nullsub_34(struct Sprite *sprite);
+void sub_800B240(struct Sprite *sprite);
+u8 CreateAzurillSprite(u8, u8);
+void AddBirchSpeechObjects(u8);
+void sub_800B3EC(u8);
+void sub_800B458(u8, u8);
+void sub_800B4C8(u8);
+void sub_800B534(u8 taskId, u8 a);
+void sub_800B5A8(u8);
+void sub_800B614(u8, u8);
+void sub_800B654(u8);
+void sub_800B6C0(u8 taskId, u8 a);
+void CreateGenderMenu(u8 left, u8 top);
+s8 GenderMenuProcessInput(void);
+void CreateNameMenu(u8 a, u8 b);
+s8 NameMenuProcessInput(void);
+void set_default_player_name(u8 a);
+
+void Task_Birch1(u8 taskId)
+{
+ SetUpWindowConfig(&gWindowConfig_81E6C3C);
+ InitMenuWindow(&gWindowConfig_81E6CE4);
+ REG_WIN0H = 0;
+ REG_WIN0V = 0;
+ REG_WININ = 0;
+ REG_WINOUT = 0;
+ REG_BLDCNT = 0;
+ REG_BLDALPHA = 0;
+ REG_BLDY = 0;
+ LZ77UnCompVram(gUnknown_081E768C, (void *)BG_VRAM);
+ LZ77UnCompVram(gUnknown_081E7834, (void *)(BG_VRAM + 0x3800));
+ LoadPalette(gUnknown_081E764C, 0, 0x40);
+ LoadPalette(gUnknown_081E796C, 1, 0x10);
+ remove_some_task();
+ ResetSpriteData();
+ FreeAllSpritePalettes();
+ AddBirchSpeechObjects(taskId);
+ BeginNormalPaletteFade(-1, 0, 0x10, 0, 0);
+ REG_BG1CNT = 0x00000703;
+ REG_DISPCNT = DISPCNT_BG0_ON | DISPCNT_BG1_ON | DISPCNT_OBJ_ON | DISPCNT_OBJ_1D_MAP;
+ gTasks[taskId].data[4] = 0;
+ gTasks[taskId].func = task_new_game_prof_birch_speech_2;
+ gTasks[taskId].data[2] = 0xFF;
+ gTasks[taskId].data[3] = 0xFF;
+ gTasks[taskId].data[7] = 0xD8;
+
+ sub_8075474(BGM_DOORO_X4);
+}
+
+void task_new_game_prof_birch_speech_2(u8 taskId)
+{
+ struct Task *tasks = gTasks;
+ struct Task *task = &tasks[taskId];
+
+ if (task->data[7] != 0)
+ {
+ task->data[7]--;
+ }
+ else
+ {
+ u8 spriteId = task->data[8];
+ struct Sprite *sprites = gSprites;
+ struct Sprite *sprite = &sprites[spriteId];
+ sprite->pos1.x = 0x88;
+ sprite->pos1.y = 0x3C;
+ sprite->invisible = 0;
+ sprite->oam.objMode = 1;
+ sub_800B534(taskId, 0xA);
+ sub_800B6C0(taskId, 0x14);
+ task->data[7] = 0x50;
+ task->func = task_new_game_prof_birch_speech_3;
+ }
+}
+
+void task_new_game_prof_birch_speech_3(u8 taskId)
+{
+ struct Task *tasks = gTasks;
+ struct Task *task = &tasks[taskId];
+
+ if (task->data[5] != 0)
+ {
+ struct Sprite *sprites = gSprites;
+ struct Sprite *sprite = &sprites[task->data[8]];
+
+ sprite->oam.objMode = 0;
+ if (task->data[7])
+ {
+ task->data[7]--;
+ }
+ else
+ {
+ MenuDrawTextWindow(0x2, 0xD, 0x1B, 0x12);
+ MenuPrintMessage(gUnknown_081C6D78, 3, 14);
+ task->func = task_new_game_prof_birch_speech_4;
+ }
+ }
+}
+
+void task_new_game_prof_birch_speech_4(u8 taskId)
+{
+ if (!gPaletteFade.active && MenuUpdateWindowText_OverrideLineLength(24))
+ {
+ gTasks[taskId].func = task_new_game_prof_birch_speech_5;
+ MenuPrintMessage(gUnknown_081C6DF8, 3, 14);
+ }
+}
+
+void task_new_game_prof_birch_speech_5(u8 taskId)
+{
+ if (MenuUpdateWindowText_OverrideLineLength(24))
+ gTasks[taskId].func = task_new_game_prof_birch_speech_6;
+}
+
+void task_new_game_prof_birch_speech_6(u8 taskId)
+{
+ struct Task *tasks = gTasks;
+ struct Task *task = &tasks[taskId];
+ u8 data = task->data[9];
+ struct Sprite *sprites = gSprites;
+ struct Sprite *sprite = &sprites[data];
+
+ sprite->pos1.x = 0x68;
+ sprite->pos1.y = 0x48;
+ sprite->invisible = 0;
+ sprite->data0 = 0;
+ CreatePokeballSprite(data, sprite->oam.paletteNum, 0x70, 0x3A, 0, 0, 0x20, 0x0000FFFF);
+ task->func = task_new_game_prof_birch_speech_7;
+ task->data[7] = 0;
+}
+
+void task_new_game_prof_birch_speech_7(u8 taskId)
+{
+ struct Task *tasks;
+ struct Task *task;
+
+ if (sub_8075374())
+ {
+ struct Task *tasks = gTasks;
+ struct Task *task = &tasks[taskId];
+
+ if (task->data[7] > 0x5F)
+ {
+ MenuSetText((u32)&gUnknown_0840DFF7);
+ task->func = task_new_game_prof_birch_speech_8;
+ }
+ }
+
+ tasks = gTasks;
+ task = &tasks[taskId];
+
+ if (task->data[7] < 0x4000)
+ {
+ task->data[7]++;
+ if (task->data[7] == 0x20)
+ {
+ cry_related(SPECIES_AZURILL, 0);
+ }
+ }
+}
+
+void task_new_game_prof_birch_speech_8(u8 taskId)
+{
+ if (MenuUpdateWindowText_OverrideLineLength(24))
+ {
+ MenuPrintMessage(gUnknown_081C6E1A, 3, 14);
+ gTasks[taskId].func = task_new_game_prof_birch_speech_9;
+ }
+}
+
+void task_new_game_prof_birch_speech_9(u8 taskId)
+{
+ if (MenuUpdateWindowText_OverrideLineLength(24))
+ {
+ MenuDrawTextWindow(0x2, 0xD, 0x1B, 0x12);
+ MenuPrintMessage(gUnknown_081C6FCB, 3, 14);
+ gTasks[taskId].func = task_new_game_prof_birch_speech_10;
+ }
+}
+
+void task_new_game_prof_birch_speech_10(u8 taskId)
+{
+ if (MenuUpdateWindowText_OverrideLineLength(24))
+ {
+ struct Sprite *sprites = gSprites;
+ struct Task *tasks = gTasks;
+ struct Task *task = &tasks[taskId];
+ struct Sprite *sprite = &sprites[task->data[8]];
+ struct Sprite *sprite2;
+
+ sprite->oam.objMode = 1;
+ sprite2 = &sprites[task->data[9]];
+ sprite2->oam.objMode = 1;
+ sub_800B458(taskId, 0x2);
+ sub_800B614(taskId, 0x1);
+ task->data[7] = 0x40;
+ task->func = task_new_game_prof_birch_speech_11;
+ }
+}
+
+void task_new_game_prof_birch_speech_11(u8 taskId)
+{
+ struct Task *tasks = gTasks;
+ struct Task *task = &tasks[taskId];
+
+ if (task->data[4] != -0x3C)
+ {
+ task->data[4] -= 2;
+ REG_BG1HOFS = task->data[4];
+ }
+ else
+ {
+ task->data[4] = 0x0000ffc4;
+ task->func = task_new_game_prof_birch_speech_12;
+ }
+}
+
+void task_new_game_prof_birch_speech_12(u8 taskId)
+{
+ if (gTasks[taskId].data[5])
+ {
+ gSprites[gTasks[taskId].data[8]].invisible = 1;
+ gSprites[gTasks[taskId].data[9]].invisible = 1;
+
+ if (gTasks[taskId].data[7])
+ {
+ gTasks[taskId].data[7]--;
+ }
+ else
+ {
+ u8 data10 = gTasks[taskId].data[10];
+
+ gSprites[data10].pos1.x = 0xB4;
+ gSprites[data10].pos1.y = 0x3C;
+ gSprites[data10].invisible = 0;
+ gSprites[data10].oam.objMode = 1;
+ gTasks[taskId].data[2] = data10;
+ gTasks[taskId].data[6] = 0;
+ sub_800B534(taskId, 2);
+ sub_800B6C0(taskId, 1);
+ gTasks[taskId].func = task_new_game_prof_birch_speech_13;
+ }
+ }
+}
+
+void task_new_game_prof_birch_speech_13(u8 taskId)
+{
+ struct Task *tasks = gTasks;
+ struct Task *task = &tasks[taskId];
+
+ if (task->data[5])
+ {
+ struct Sprite *sprites = gSprites;
+ struct Sprite *sprite = &sprites[task->data[2]];
+
+ sprite->oam.objMode = 0;
+ task->func = task_new_game_prof_birch_speech_14;
+ }
+}
+
+void task_new_game_prof_birch_speech_14(u8 taskId)
+{
+ MenuDrawTextWindow(2, 0xD, 0x1B, 0x12);
+ MenuPrintMessage(gUnknown_081C6FD8, 3, 14);
+ gTasks[taskId].func = task_new_game_prof_birch_speech_15;
+}
+
+void task_new_game_prof_birch_speech_15(u8 taskId)
+{
+ if (MenuUpdateWindowText_OverrideLineLength(24))
+ {
+ CreateGenderMenu(2, 4);
+ gTasks[taskId].func = task_new_game_prof_birch_speech_16;
+ }
+}
+
+void task_new_game_prof_birch_speech_16(u8 taskId)
+{
+ u8 cursorPos;
+
+ switch (GenderMenuProcessInput())
+ {
+ case MALE:
+ sub_8072DEC();
+ audio_play(SE_SELECT);
+ gSaveBlock2.playerGender = MALE;
+ MenuZeroFillWindowRect(2, 4, 8, 9);
+ gTasks[taskId].func = sub_800A974;
+ break;
+ case FEMALE:
+ sub_8072DEC();
+ audio_play(SE_SELECT);
+ gSaveBlock2.playerGender = FEMALE;
+ MenuZeroFillWindowRect(2, 4, 8, 9);
+ gTasks[taskId].func = sub_800A974;
+ break;
+ }
+
+ cursorPos = GetMenuCursorPos();
+
+ if (cursorPos != gTasks[taskId].data[6])
+ {
+ gTasks[taskId].data[6] = cursorPos;
+ gSprites[gTasks[taskId].data[2]].oam.objMode = 1;
+ sub_800B458(taskId, 0);
+ gTasks[taskId].func = task_new_game_prof_birch_speech_17;
+ }
+}
+
+void task_new_game_prof_birch_speech_17(u8 taskId)
+{
+ u8 spriteId = gTasks[taskId].data[2];
+
+ if (gTasks[taskId].data[5] == 0)
+ {
+ gSprites[spriteId].pos1.x += 4;
+ }
+ else
+ {
+ gSprites[spriteId].invisible = 1;
+ if (gTasks[taskId].data[6])
+ {
+ spriteId = gTasks[taskId].data[11];
+ }
+ else
+ {
+ spriteId = gTasks[taskId].data[10];
+ }
+
+ gSprites[spriteId].pos1.x = 0xF0;
+ gSprites[spriteId].pos1.y = 0x3C;
+ gSprites[spriteId].invisible = 0;
+ gTasks[taskId].data[2] = spriteId;
+ gSprites[spriteId].oam.objMode = 1;
+ sub_800B534(taskId, 0);
+ gTasks[taskId].func = task_new_game_prof_birch_speech_18;
+ }
+}
+
+void task_new_game_prof_birch_speech_18(u8 taskId)
+{
+ u8 spriteId = gTasks[taskId].data[2];
+
+ if (gSprites[spriteId].pos1.x > 0xB4)
+ {
+ gSprites[spriteId].pos1.x -= 4;
+ }
+ else
+ {
+ gSprites[spriteId].pos1.x = 0xB4;
+ if (gTasks[taskId].data[5])
+ {
+ gSprites[spriteId].oam.objMode = 0;
+ gTasks[taskId].func = task_new_game_prof_birch_speech_16;
+ }
+ }
+}
+
+void sub_800A974(u8 taskId)
+{
+ MenuDrawTextWindow(2, 13, 27, 18);
+ MenuPrintMessage(gUnknown_081C6FFA, 3, 14);
+ gTasks[taskId].func = Task_800A9B4;
+}
+
+void Task_800A9B4(u8 taskId)
+{
+ if (MenuUpdateWindowText_OverrideLineLength(24))
+ {
+ CreateNameMenu(2, 1);
+ gTasks[taskId].func = sub_800A9EC;
+ }
+}
+
+void sub_800A9EC(u8 taskId)
+{
+ s8 n = NameMenuProcessInput();
+
+ switch (n)
+ {
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ sub_8072DEC();
+ audio_play(SE_SELECT);
+ MenuZeroFillWindowRect(2, 1, 22, 12);
+ set_default_player_name(n);
+ gTasks[taskId].func = task_new_game_prof_birch_speech_part2_1;
+ break;
+ case 0:
+ audio_play(SE_SELECT);
+ BeginNormalPaletteFade(-1, 0, 0, 16, 0);
+ gTasks[taskId].func = sub_800AAAC;
+ break;
+ case -1:
+ sub_8072DEC();
+ audio_play(SE_SELECT);
+ MenuZeroFillWindowRect(2, 1, 22, 12);
+ gTasks[taskId].func = task_new_game_prof_birch_speech_14;
+ break;
+ }
+}
+
+void sub_800AAAC(u8 taskId)
+{
+ if (!gPaletteFade.active)
+ {
+ set_default_player_name(1);
+ DoNamingScreen(0, &gSaveBlock2, gSaveBlock2.playerGender, 0, 0, new_game_prof_birch_speech_part2_start);
+ }
+}
+
+void task_new_game_prof_birch_speech_part2_1(u8 taskId)
+{
+ MenuDrawTextWindow(2, 13, 27, 18);
+ StringExpandPlaceholders(gStringVar4, gUnknown_081C7017);
+ MenuPrintMessage(gStringVar4, 3, 14);
+ gTasks[taskId].func = sub_800AB38;
+}
+
+void sub_800AB38(u8 taskId)
+{
+ if (MenuUpdateWindowText_OverrideLineLength(24))
+ {
+ DisplayYesNoMenu(2, 1, 1);
+ gTasks[taskId].func = task_new_game_prof_birch_speech_part2_4;
+ }
+}
+
+void task_new_game_prof_birch_speech_part2_4(u8 taskId)
+{
+ switch (ProcessMenuInputNoWrap_())
+ {
+ case 0:
+ audio_play(SE_SELECT);
+ MenuZeroFillWindowRect(2, 1, 8, 7);
+ gSprites[gTasks[taskId].data[2]].oam.objMode = ST_OAM_OBJ_BLEND;
+ sub_800B458(taskId, 2);
+ sub_800B614(taskId, 1);
+ gTasks[taskId].func = sub_800AC20;
+ break;
+ case -1:
+ case 1:
+ audio_play(SE_SELECT);
+ MenuZeroFillWindowRect(2, 1, 8, 7);
+ gTasks[taskId].func = task_new_game_prof_birch_speech_14;
+ break;
+ }
+}
+
+void sub_800AC20(u8 taskId)
+{
+ if (gTasks[taskId].data[4])
+ {
+ gTasks[taskId].data[4] += 2;
+ REG_BG1HOFS = gTasks[taskId].data[4];
+ }
+ else
+ {
+ gTasks[taskId].func = task_new_game_prof_birch_speech_part2_6;
+ }
+}
+
+void task_new_game_prof_birch_speech_part2_6(u8 taskId)
+{
+ if (gTasks[taskId].data[5])
+ {
+ s16 spriteId;
+
+ spriteId = gTasks[taskId].data[10];
+ gSprites[spriteId].invisible = 1;
+
+ spriteId = gTasks[taskId].data[11];
+ gSprites[spriteId].invisible = 1;
+
+ spriteId = (u8)gTasks[taskId].data[8];
+ gSprites[spriteId].pos1.x = 0x88;
+ gSprites[spriteId].pos1.y = 0x40;
+ gSprites[spriteId].invisible = 0;
+ gSprites[spriteId].oam.objMode = 1;
+
+ spriteId = (u8)gTasks[taskId].data[9];
+ gSprites[spriteId].pos1.x = 0x68;
+ gSprites[spriteId].pos1.y = 0x48;
+ gSprites[spriteId].invisible = 0;
+ gSprites[spriteId].oam.objMode = 1;
+
+ sub_800B534(taskId, 2);
+ sub_800B6C0(taskId, 1);
+ MenuDrawTextWindow(2, 13, 27, 18);
+ StringExpandPlaceholders(gStringVar4, gUnknown_081C7025);
+ MenuPrintMessage(gStringVar4, 3, 14);
+ gTasks[taskId].func = task_new_game_prof_birch_speech_part2_7;
+ }
+}
+
+void task_new_game_prof_birch_speech_part2_7(u8 taskId)
+{
+ if (gTasks[taskId].data[5])
+ {
+ s16 spriteId;
+
+ spriteId = gTasks[taskId].data[8];
+ gSprites[spriteId].oam.objMode = 0;
+
+ spriteId = gTasks[taskId].data[9];
+ gSprites[spriteId].oam.objMode = 0;
+
+ if (MenuUpdateWindowText_OverrideLineLength(24))
+ {
+ spriteId = gTasks[taskId].data[8];
+ gSprites[spriteId].oam.objMode = 1;
+
+ spriteId = gTasks[taskId].data[9];
+ gSprites[spriteId].oam.objMode = 1;
+
+ sub_800B458(taskId, 2);
+ sub_800B614(taskId, 1);
+ gTasks[taskId].data[7] = 0x40;
+ gTasks[taskId].func = task_new_game_prof_birch_speech_part2_8;
+ }
+ }
+}
+
+void task_new_game_prof_birch_speech_part2_8(u8 taskId)
+{
+ if (gTasks[taskId].data[5])
+ {
+ s16 spriteId;
+
+ spriteId = gTasks[taskId].data[8];
+ gSprites[spriteId].invisible = 1;
+
+ spriteId = gTasks[taskId].data[9];
+ gSprites[spriteId].invisible = 1;
+
+ if (gTasks[taskId].data[7])
+ {
+ gTasks[taskId].data[7]--;
+ }
+ else
+ {
+ u8 spriteId;
+
+ if (gSaveBlock2.playerGender)
+ spriteId = (u8)gTasks[taskId].data[11];
+ else
+ spriteId = (u8)gTasks[taskId].data[10];
+
+ gSprites[spriteId].pos1.x = 0x78;
+ gSprites[spriteId].pos1.y = 0x3C;
+ gSprites[spriteId].invisible = 0;
+ gSprites[spriteId].oam.objMode = 1;
+ gTasks[taskId].data[2] = spriteId;
+
+ sub_800B534(taskId, 2);
+ sub_800B6C0(taskId, 1);
+ MenuDrawTextWindow(2, 13, 27, 18);
+ MenuPrintMessage(gUnknown_081C7074, 3, 14);
+ gTasks[taskId].func = task_new_game_prof_birch_speech_part2_9;
+ }
+ }
+}
+
+void task_new_game_prof_birch_speech_part2_9(u8 taskId)
+{
+ if (gTasks[taskId].data[5])
+ {
+ s16 spriteId;
+
+ spriteId = gTasks[taskId].data[2];
+ gSprites[spriteId].oam.objMode = 0;
+
+ if (MenuUpdateWindowText_OverrideLineLength(24))
+ {
+ u8 spriteId;
+
+ spriteId = gTasks[taskId].data[2];
+ gSprites[spriteId].oam.affineMode = 1;
+ gSprites[spriteId].affineAnims = (union AffineAnimCmd **)gSpriteAffineAnimTable_81E79AC;
+ InitSpriteAffineAnim(&gSprites[spriteId]);
+ StartSpriteAffineAnim(&gSprites[spriteId], 0);
+ gSprites[spriteId].callback = sub_800B240;
+ BeginNormalPaletteFade(0x0000ffff, 0, 0, 0x10, 0);
+ play_sound_effect(4);
+ gTasks[taskId].func = task_new_game_prof_birch_speech_part2_10;
+ }
+ }
+}
+
+void task_new_game_prof_birch_speech_part2_10(u8 taskId)
+{
+ u8 spriteId = gTasks[taskId].data[2];
+
+ if (gSprites[spriteId].affineAnimEnded)
+ gTasks[taskId].func = sub_800AFC0;
+}
+
+void sub_800AFC0(u8 taskId)
+{
+ if (!gPaletteFade.active)
+ {
+ u8 spriteId = gTasks[taskId].data[2];
+ gSprites[spriteId].callback = nullsub_34;
+ REG_DISPCNT = 4160;
+ BeginNormalPaletteFade(0xFFFF0000, 0, 0, 0x10, 0xFFFF);
+ gTasks[taskId].func = sub_800B034;
+ }
+}
+
+void sub_800B034(u8 taskId)
+{
+ if (!gPaletteFade.active)
+ {
+ SetMainCallback2(c2_load_new_map_2);
+ DestroyTask(taskId);
+ }
+}
+
+// CB2
+void new_game_prof_birch_speech_part2_start()
+{
+ u8 taskId;
+ u8 spriteId;
+ u16 savedIme;
+
+ SetVBlankCallback(NULL);
+
+ REG_DISPCNT = 0;
+ REG_BG2CNT = 0;
+ REG_BG1CNT = 0;
+ REG_BG0CNT = 0;
+ REG_BG2HOFS = 0;
+ REG_BG2VOFS = 0;
+ REG_BG1HOFS = 0;
+ REG_BG1VOFS = 0;
+ REG_BG0HOFS = 0;
+ REG_BG0VOFS = 0;
+
+ DmaFill16(3, 0, (void *)VRAM, VRAM_SIZE);
+ DmaFill32(3, 0, (void *)OAM, OAM_SIZE);
+ DmaFill16(3, 0, (void *)PLTT, PLTT_SIZE);
+
+ ResetPaletteFade();
+
+ LZ77UnCompVram(gUnknown_081E768C, (void *)BG_VRAM);
+ LZ77UnCompVram(gUnknown_081E7834, (void *)(BG_VRAM + 0x3800));
+
+ LoadPalette(gUnknown_081E764C, 0, 0x40);
+
+ ResetTasks();
+
+ taskId = CreateTask(task_new_game_prof_birch_speech_part2_1, 0);
+
+ gTasks[taskId].data[4] = -60;
+
+ remove_some_task();
+ ResetSpriteData();
+ FreeAllSpritePalettes();
+ AddBirchSpeechObjects(taskId);
+
+ SetUpWindowConfig(&gWindowConfig_81E6C3C);
+ InitMenuWindow(&gWindowConfig_81E6CE4);
+
+ if (gSaveBlock2.playerGender != MALE)
+ {
+ gTasks[taskId].data[6] = FEMALE;
+ spriteId = gTasks[taskId].data[11];
+ }
+ else
+ {
+ gTasks[taskId].data[6] = MALE;
+ spriteId = gTasks[taskId].data[10];
+ }
+
+ gSprites[spriteId].pos1.x = 180;
+ gSprites[spriteId].pos1.y = 60;
+ gSprites[spriteId].invisible = 0;
+
+ gTasks[taskId].data[2] = spriteId;
+
+ REG_BG1HOFS = -60;
+
+ BeginNormalPaletteFade(0xFFFFFFFFu, 0, 0x10, 0, 0);
+
+ REG_WIN0H = 0;
+ REG_WIN0V = 0;
+ REG_WININ = 0;
+ REG_WINOUT = 0;
+ REG_BLDCNT = 0;
+ REG_BLDALPHA = 0;
+ REG_BLDY = 0;
+
+ savedIme = REG_IME;
+ REG_IME = 0;
+ REG_IE |= INTR_FLAG_VBLANK;
+ REG_IME = savedIme;
+
+ SetVBlankCallback(VBlankCB_MainMenu);
+ SetMainCallback2(CB2_MainMenu);
+ REG_BG1CNT = 1795;
+ REG_DISPCNT = 4928;
+}
+
+void nullsub_34(struct Sprite *sprite)
+{
+}
+
+void sub_800B240(struct Sprite *sprite)
+{
+ u32 y = (sprite->pos1.y << 16) + sprite->data0 + 0xC000;
+ sprite->pos1.y = y >> 16;
+ sprite->data0 = y;
+}
+
+u8 CreateAzurillSprite(u8 a1, u8 a2)
+{
+ DecompressPicFromTable_2(
+ &gMonFrontPicTable[SPECIES_AZURILL],
+ gMonFrontPicCoords[SPECIES_AZURILL].x,
+ gMonFrontPicCoords[SPECIES_AZURILL].y,
+ gUnknown_081FAF4C[0],
+ gUnknown_081FAF4C[1],
+ SPECIES_AZURILL);
+ LoadCompressedObjectPalette(&gMonPaletteTable[SPECIES_AZURILL]);
+ gpu_pal_obj_decompress_and_apply(SPECIES_AZURILL, 1);
+ return CreateSprite(&gUnknown_02024E8C, a1, a2, 0);
+}
+
+void AddBirchSpeechObjects(u8 taskId)
+{
+ u8 spriteId;
+
+ spriteId = AddNewGameBirchObject(136, 60, 1);
+ gSprites[spriteId].callback = nullsub_34;
+ gSprites[spriteId].oam.priority = 0;
+ gSprites[spriteId].invisible = 1;
+ gTasks[taskId].data[8] = spriteId;
+
+ spriteId = CreateAzurillSprite(0x68, 0x48);
+ gSprites[spriteId].callback = nullsub_34;
+ gSprites[spriteId].oam.priority = 0;
+ gSprites[spriteId].invisible = 1;
+ gTasks[taskId].data[9] = spriteId;
+
+ spriteId = sub_80859BC(0, 120, 60, 0, unk_2000000);
+ gSprites[spriteId].callback = nullsub_34;
+ gSprites[spriteId].invisible = 1;
+ gSprites[spriteId].oam.priority = 0;
+ gTasks[taskId].data[10] = spriteId;
+
+ spriteId = sub_80859BC(1, 120, 60, 0, unk_2000000 + 0x800);
+ gSprites[spriteId].callback = nullsub_34;
+ gSprites[spriteId].invisible = 1;
+ gSprites[spriteId].oam.priority = 0;
+ gTasks[taskId].data[11] = spriteId;
+}
+
+void sub_800B3EC(u8 taskId)
+{
+ if (gTasks[taskId].data[1] == 0)
+ {
+ gTasks[gTasks[taskId].data[0]].data[5] = 1;
+ DestroyTask(taskId);
+ }
+ else
+ {
+ if (gTasks[taskId].data[4])
+ {
+ gTasks[taskId].data[4]--;
+ }
+ else
+ {
+ gTasks[taskId].data[4] = gTasks[taskId].data[3];
+ gTasks[taskId].data[1]--;
+ gTasks[taskId].data[2]++;
+ REG_BLDALPHA = gTasks[taskId].data[1] + (gTasks[taskId].data[2] * 256);
+ }
+ }
+}
+
+void sub_800B458(u8 taskId, u8 a2)
+{
+ u8 newTaskId;
+
+ REG_BLDCNT = 592;
+ REG_BLDALPHA = 16;
+ REG_BLDY = 0;
+ gTasks[taskId].data[5] = 0;
+ newTaskId = CreateTask(sub_800B3EC, 0);
+
+ gTasks[newTaskId].data[0] = taskId;
+ gTasks[newTaskId].data[1] = 16;
+ gTasks[newTaskId].data[2] = 0;
+ gTasks[newTaskId].data[3] = a2;
+ gTasks[newTaskId].data[4] = a2;
+}
+
+void sub_800B4C8(u8 taskId)
+{
+ if (gTasks[taskId].data[1] == 16)
+ {
+ gTasks[gTasks[taskId].data[0]].data[5] = 1;
+ DestroyTask(taskId);
+ }
+ else if (gTasks[taskId].data[4])
+ {
+ gTasks[taskId].data[4]--;
+ }
+ else
+ {
+ gTasks[taskId].data[4] = gTasks[taskId].data[3];
+ gTasks[taskId].data[1]++;
+ gTasks[taskId].data[2]--;
+ REG_BLDALPHA = gTasks[taskId].data[1] + (gTasks[taskId].data[2] * 256);
+ }
+}
+
+void sub_800B534(u8 taskId, u8 a2)
+{
+ u8 newTaskId;
+
+ REG_BLDCNT = 592;
+ REG_BLDALPHA = 4096;
+ REG_BLDY = 0;
+ gTasks[taskId].data[5] = 0;
+ newTaskId = CreateTask(sub_800B4C8, 0);
+
+ gTasks[newTaskId].data[0] = taskId;
+ gTasks[newTaskId].data[1] = 0;
+ gTasks[newTaskId].data[2] = 16;
+ gTasks[newTaskId].data[3] = a2;
+ gTasks[newTaskId].data[4] = a2;
+}
+
+void sub_800B5A8(u8 taskId)
+{
+ if (gTasks[taskId].data[2])
+ {
+ gTasks[taskId].data[2]--;
+ }
+ else
+ {
+ if (gTasks[taskId].data[1] == 8)
+ {
+ DestroyTask(taskId);
+ }
+ else if (gTasks[taskId].data[4])
+ {
+ gTasks[taskId].data[4]--;
+ }
+ else
+ {
+ gTasks[taskId].data[4] = gTasks[taskId].data[3];
+ gTasks[taskId].data[1]++;
+ LoadPalette(&gUnknown_081E795C[gTasks[taskId].data[1]], 1, 0x10);
+ }
+ }
+}
+
+void sub_800B614(u8 a1, u8 a2)
+{
+ u8 newTaskId = CreateTask(sub_800B5A8, 0);
+ gTasks[newTaskId].data[0] = a1;
+ gTasks[newTaskId].data[1] = 0;
+ gTasks[newTaskId].data[2] = 8;
+ gTasks[newTaskId].data[3] = a2;
+ gTasks[newTaskId].data[4] = a2;
+}
+
+void sub_800B654(u8 taskId)
+{
+ if (gTasks[taskId].data[2])
+ {
+ gTasks[taskId].data[2]--;
+ }
+ else
+ {
+ if (gTasks[taskId].data[1] == 0)
+ {
+ DestroyTask(taskId);
+ }
+ else
+ {
+ if (gTasks[taskId].data[4])
+ {
+ gTasks[taskId].data[4]--;
+ }
+ else
+ {
+ gTasks[taskId].data[4] = gTasks[taskId].data[3];
+ gTasks[taskId].data[1]--;
+ LoadPalette(&gUnknown_081E795C[gTasks[taskId].data[1]], 1, 0x10);
+ }
+ }
+ }
+}
+
+void sub_800B6C0(u8 a1, u8 a2)
+{
+ u8 newTaskId = CreateTask(sub_800B654, 0);
+ gTasks[newTaskId].data[0] = a1;
+ gTasks[newTaskId].data[1] = 8;
+ gTasks[newTaskId].data[2] = 8;
+ gTasks[newTaskId].data[3] = a2;
+ gTasks[newTaskId].data[4] = a2;
+}
+
+void CreateGenderMenu(u8 left, u8 top)
+{
+ u8 menuLeft, menuTop;
+ MenuDrawTextWindow(left, top, left + 6, top + 5);
+ menuLeft = left + 1;
+ menuTop = top + 1;
+ PrintMenuItems(menuLeft, menuTop, 2, gUnknown_081E79B0);
+ InitMenu(0, menuLeft, menuTop, 2, 0, 5);
+}
+
+s8 GenderMenuProcessInput(void)
+{
+ return ProcessMenuInputNoWrap();
+}
+
+void CreateNameMenu(u8 left, u8 top)
+{
+ MenuDrawTextWindow(left, top, left + 10, top + 11);
+
+ if (gSaveBlock2.playerGender == MALE)
+ {
+ PrintMenuItems((u8)(left + 1), (u8)(top + 1), 5, gUnknown_081E79C0);
+ }
+ else
+ {
+ PrintMenuItems((u8)(left + 1), (u8)(top + 1), 5, gUnknown_081E79E8);
+ }
+
+ InitMenu(0, (u8)(left + 1), (u8)(top + 1), 5, 0, 9);
+}
+
+s8 NameMenuProcessInput(void)
+{
+ return ProcessMenuInput();
+}
+
+void set_default_player_name(u8 index)
+{
+ u8 i;
+ u8 *name;
+
+ if (gSaveBlock2.playerGender == MALE)
+ name = gUnknown_081E79C0[index][0];
+ else
+ name = gUnknown_081E79E8[index][0];
+
+ for (i = 0; i < 7; i++)
+ gSaveBlock2.playerName[i] = name[i];
+
+ gSaveBlock2.playerName[i] = EOS;
+}
diff --git a/src/menu.c b/src/menu.c
new file mode 100644
index 000000000..b101165f2
--- /dev/null
+++ b/src/menu.c
@@ -0,0 +1,1003 @@
+#include "global.h"
+#include "main.h"
+#include "text.h"
+#include "songs.h"
+#include "text_window.h"
+
+struct Menu
+{
+ u8 left;
+ u8 top;
+ s8 cursorPos;
+ s8 minCursorPos;
+ s8 maxCursorPos;
+ u8 width;
+ u8 height;
+ u8 menu_field_7;
+ u8 columnXCoords[8];
+};
+
+void InitMenuWindow(struct WindowConfig *);
+void MultistepInitMenuWindowBegin(struct WindowConfig *);
+void MultistepInitMenuWindowInternal(struct WindowConfig *, u16);
+bool32 MultistepInitMenuWindowContinue(void);
+void InitMenuWindowInternal(struct WindowConfig *, u16);
+void unref_sub_8071DA4(struct WindowConfig *, u16);
+void MenuLoadTextWindowGraphics_OverrideFrameType(u8);
+void MenuLoadTextWindowGraphics(void);
+void BasicInitMenuWindow(struct WindowConfig *);
+void MenuPrint(u8 *, u8, u8);
+void MenuZeroFillWindowRect(u8, u8, u8, u8);
+void MenuFillWindowRectWithBlankTile(u8, u8, u8, u8);
+void MenuZeroFillScreen(void);
+void MenuDrawTextWindow(u8, u8, u8, u8);
+void sub_8071F40(u8 *);
+void sub_8071F60(u8, u8, u8, u8);
+u16 unref_sub_8071F98(u8, u8);
+void unref_sub_8071FBC(u16, u8, u8, u8, u8);
+void MenuDisplayMessageBox(void);
+void MenuPrintMessage(u8 *, u8, u8);
+void sub_8072044(u8 *);
+void MenuSetText(u8 *);
+u8 MenuUpdateWindowText(void);
+u8 unref_sub_8072098(void);
+void sub_80720B0(void);
+u8 MoveMenuCursor(s8);
+u8 MoveMenuCursorNoWrap(s8);
+u8 GetMenuCursorPos(void);
+s8 ProcessMenuInput(void);
+s8 ProcessMenuInputNoWrap(void);
+u8 MoveMenuCursor3(s8);
+u8 MoveMenuCursor4(s8);
+bool8 sub_80723D4(void);
+u8 sub_8072484(u8, u8, u8, u8, u8, u8, u32);
+u8 sub_80724F4(u8, u8, u8, u8*[][2], u8);
+void sub_8072620(u8, u8, u8, u8*[][2], u8);
+void sub_807274C(u8, u8, u8, u8, u8*[][2], u8, u32);
+s8 sub_80727CC(void);
+u8 sub_807288C(u8);
+void PrintMenuItems(u8, u8, u8, u8*[][2]);
+void PrintMenuItemsReordered(u8, u8, u8, u8*[][2], u8*);
+void InitYesNoMenu(u8, u8, u8);
+void DisplayYesNoMenu(u8, u8, u32);
+s8 ProcessMenuInputNoWrap_(void);
+u8 sub_80729D8(u8 *, u8, u16, u8);
+u8 sub_8072A18(u8 *, u8, u16, u8, u32);
+u8 unref_sub_8072A5C(u8 *, u8 *, u8, u16, u8, u32);
+int sub_8072AB0(u8 *, u8, u16, u8, u8, u32);
+void sub_8072B4C(u8 *, u8, u8);
+void sub_8072B80(u8 *, u8, u8, u8 *);
+void sub_8072BD8(u8 *, u8, u8, u16);
+u8 *sub_8072C14(u8 *, s32, u8, u8);
+u8 *sub_8072C44(u8 *, s32, u8, u8);
+u8 *sub_8072C74(u8 *, u8 *, u8, u8);
+u8 sub_8072CA4(u8 *s);
+u8 sub_8072CBC(void);
+void sub_8072CD4(u8 *, u8 *, u8 *);
+u32 MenuUpdateWindowText_OverrideLineLength(u8);
+struct Window * unref_sub_8072D0C(void);
+void sub_8072D18(u8, u8);
+u8 InitMenu(u8, u8, u8, u8, u8, u8);
+void RedrawMenuCursor(u8, u8);
+void unref_sub_8072DC0(void);
+void sub_8072DCC(u8);
+void sub_8072DDC(u8);
+void sub_8072DEC(void);
+
+extern void sub_814A5C0(u8, u16, u8, u16, u8);
+extern void sub_814A880(u8, u8);
+extern void sub_814A904(void);
+extern void sub_814A958(u8);
+extern void sub_814A7FC(void);
+
+static struct Menu gMenu;
+
+extern struct Window gMenuWindow;
+extern struct Window *gMenuWindowPtr;
+extern u8 gMenuMultistepInitState;
+extern u16 gMenuTextTileOffset;
+extern u16 gMenuTextWindowTileOffset;
+extern u16 gMenuTextWindowContentTileOffset;
+extern u16 gMenuMessageBoxContentTileOffset;
+
+extern const u8 *gUnknown_08376D74[][2];
+
+void InitMenuWindow(struct WindowConfig *winConfig)
+{
+ InitMenuWindowInternal(winConfig, 1);
+}
+
+void MultistepInitMenuWindowBegin(struct WindowConfig *winConfig)
+{
+ MultistepInitMenuWindowInternal(winConfig, 1);
+}
+
+void MultistepInitMenuWindowInternal(struct WindowConfig *winConfig, u16 tileOffset)
+{
+ gMenuMultistepInitState = 0;
+ gMenuTextTileOffset = tileOffset;
+ gMenuWindowPtr = &gMenuWindow;
+ InitWindowFromConfig(&gMenuWindow, winConfig);
+}
+
+bool32 MultistepInitMenuWindowContinue(void)
+{
+ switch (gMenuMultistepInitState)
+ {
+ case 0:
+ gMenuMultistepInitState++;
+ return 0;
+ case 1:
+ gMenuTextWindowTileOffset = MultistepInitWindowTileData(gMenuWindowPtr, gMenuTextTileOffset);
+ goto next;
+ case 2:
+ if (!MultistepLoadFont())
+ goto fail;
+ goto next;
+ case 3:
+ gMenuTextWindowContentTileOffset = SetTextWindowBaseTileNum(gMenuTextWindowTileOffset);
+ next:
+ gMenuMultistepInitState++;
+ return 0;
+ case 4:
+ LoadTextWindowGraphics(gMenuWindowPtr);
+ gMenuMessageBoxContentTileOffset = SetMessageBoxBaseTileNum(gMenuTextWindowContentTileOffset);
+ return 1;
+ default:
+ fail:
+ return 0;
+ }
+}
+
+void InitMenuWindowInternal(struct WindowConfig *winConfig, u16 tileOffset)
+{
+ gMenuWindowPtr = &gMenuWindow;
+ InitWindowFromConfig(&gMenuWindow, winConfig);
+ gMenuTextTileOffset = tileOffset;
+ gMenuTextWindowTileOffset = InitWindowTileData(gMenuWindowPtr, gMenuTextTileOffset);
+ gMenuTextWindowContentTileOffset = SetTextWindowBaseTileNum(gMenuTextWindowTileOffset);
+ LoadTextWindowGraphics(gMenuWindowPtr);
+ gMenuMessageBoxContentTileOffset = SetMessageBoxBaseTileNum(gMenuTextWindowContentTileOffset);
+}
+
+void unref_sub_8071DA4(struct WindowConfig *winConfig, u16 tileOffset)
+{
+ gMenuWindowPtr = &gMenuWindow;
+ InitWindowFromConfig(&gMenuWindow, winConfig);
+ gMenuTextWindowTileOffset = tileOffset;
+ gMenuTextWindowContentTileOffset = SetTextWindowBaseTileNum(gMenuTextWindowTileOffset);
+ LoadTextWindowGraphics(gMenuWindowPtr);
+ gMenuTextTileOffset = SetMessageBoxBaseTileNum(gMenuTextWindowContentTileOffset);
+ gMenuMessageBoxContentTileOffset = InitWindowTileData(gMenuWindowPtr, gMenuTextTileOffset);
+}
+
+void MenuLoadTextWindowGraphics_OverrideFrameType(u8 frameType)
+{
+ LoadTextWindowGraphics_OverrideFrameType(gMenuWindowPtr, frameType);
+}
+
+void MenuLoadTextWindowGraphics(void)
+{
+ LoadTextWindowGraphics(gMenuWindowPtr);
+}
+
+void BasicInitMenuWindow(struct WindowConfig *winConfig)
+{
+ InitWindowFromConfig(gMenuWindowPtr, winConfig);
+ gMenuWindowPtr->tileDataStartOffset = gMenuTextTileOffset;
+}
+
+void MenuPrint(u8 *str, u8 left, u8 top)
+{
+ sub_8003460(gMenuWindowPtr, str, gMenuTextTileOffset, left, top);
+}
+
+void MenuZeroFillWindowRect(u8 a1, u8 a2, u8 a3, u8 a4)
+{
+ ZeroFillWindowRect(gMenuWindowPtr, a1, a2, a3, a4);
+}
+
+void MenuFillWindowRectWithBlankTile(u8 left, u8 top, u8 right, u8 bottom)
+{
+ FillWindowRectWithBlankTile(gMenuWindowPtr, left, top, right, bottom);
+}
+
+void MenuZeroFillScreen(void)
+{
+ MenuZeroFillWindowRect(0, 0, 29, 19);
+}
+
+void MenuDrawTextWindow(u8 left, u8 top, u8 right, u8 bottom)
+{
+ DrawTextWindow(gMenuWindowPtr, left, top, right, bottom);
+}
+
+void sub_8071F40(u8 *str)
+{
+ MenuDrawTextWindow(2, 14, 28, 19);
+ MenuPrint(str, 3, 15);
+}
+
+void sub_8071F60(u8 a1, u8 a2, u8 a3, u8 a4)
+{
+ sub_8003490(gMenuWindowPtr, a1, gMenuTextTileOffset, a2, a3);
+}
+
+u16 unref_sub_8071F98(u8 x, u8 y)
+{
+ return GetWindowTilemapEntry(gMenuWindowPtr, x, y);
+}
+
+void unref_sub_8071FBC(u16 a1, u8 a2, u8 a3, u8 a4, u8 a5)
+{
+ DrawWindowRect(gMenuWindowPtr, a1, a2, a3, a4, a5);
+}
+
+void MenuDisplayMessageBox(void)
+{
+ DisplayMessageBox(gMenuWindowPtr);
+}
+
+void MenuPrintMessage(u8 *str, u8 left, u8 top)
+{
+ sub_8002EB0(gMenuWindowPtr, str, gMenuTextTileOffset, left, top);
+}
+
+void sub_8072044(u8 *str)
+{
+ sub_8002EB0(gMenuWindowPtr, str, gMenuTextTileOffset, 2, 15);
+}
+
+void MenuSetText(u8 *str)
+{
+ sub_8002E90(gMenuWindowPtr, str);
+}
+
+u8 MenuUpdateWindowText(void)
+{
+ return sub_80035AC(gMenuWindowPtr);
+}
+
+u8 unref_sub_8072098(void)
+{
+ return sub_8003418(gMenuWindowPtr);
+}
+
+void sub_80720B0(void)
+{
+ ClearWindowTextLines(gMenuWindowPtr);
+}
+
+u8 MoveMenuCursor(s8 delta)
+{
+ s32 newPos = gMenu.cursorPos + delta;
+
+ if (newPos < gMenu.minCursorPos)
+ gMenu.cursorPos = gMenu.maxCursorPos;
+ else if (newPos > gMenu.maxCursorPos)
+ gMenu.cursorPos = gMenu.minCursorPos;
+ else
+ gMenu.cursorPos += delta;
+
+ RedrawMenuCursor(gMenu.left, 2 * gMenu.cursorPos + gMenu.top);
+ return gMenu.cursorPos;
+}
+
+u8 MoveMenuCursorNoWrap(s8 delta)
+{
+ s32 newPos = gMenu.cursorPos + delta;
+
+ if (newPos < gMenu.minCursorPos)
+ gMenu.cursorPos = gMenu.minCursorPos;
+ else if (newPos > gMenu.maxCursorPos)
+ gMenu.cursorPos = gMenu.maxCursorPos;
+ else
+ gMenu.cursorPos += delta;
+
+ RedrawMenuCursor(gMenu.left, 2 * gMenu.cursorPos + gMenu.top);
+ return gMenu.cursorPos;
+}
+
+u8 GetMenuCursorPos(void)
+{
+ return gMenu.cursorPos;
+}
+
+s8 ProcessMenuInput(void)
+{
+ if (gMain.newKeys & A_BUTTON)
+ {
+ audio_play(SE_SELECT);
+ if (gMenu.menu_field_7)
+ sub_8072DEC();
+ return gMenu.cursorPos;
+ }
+
+ if (gMain.newKeys & B_BUTTON)
+ {
+ if (gMenu.menu_field_7)
+ sub_8072DEC();
+ return -1;
+ }
+
+ if (gMain.newKeys & DPAD_UP)
+ {
+ audio_play(SE_SELECT);
+ MoveMenuCursor(-1);
+ return -2;
+ }
+ else if (gMain.newKeys & DPAD_DOWN)
+ {
+ audio_play(SE_SELECT);
+ MoveMenuCursor(1);
+ return -2;
+ }
+
+ return -2;
+}
+
+s8 ProcessMenuInputNoWrap(void)
+{
+ u8 cursorPos = gMenu.cursorPos;
+
+ if (gMain.newKeys & A_BUTTON)
+ {
+ audio_play(SE_SELECT);
+ if (gMenu.menu_field_7)
+ sub_8072DEC();
+ return gMenu.cursorPos;
+ }
+
+ if (gMain.newKeys & B_BUTTON)
+ {
+ if (gMenu.menu_field_7)
+ sub_8072DEC();
+ return -1;
+ }
+
+ if (gMain.newKeys & DPAD_UP)
+ {
+ if (cursorPos != MoveMenuCursorNoWrap(-1))
+ audio_play(SE_SELECT);
+ return -2;
+ }
+ else if (gMain.newKeys & DPAD_DOWN)
+ {
+ if (cursorPos != MoveMenuCursorNoWrap(1))
+ audio_play(SE_SELECT);
+ return -2;
+ }
+
+ MoveMenuCursorNoWrap(0);
+ return -2;
+}
+
+u8 MoveMenuCursor3(s8 delta)
+{
+ u8 menuHeight = (gMenu.maxCursorPos + 1) >> 1;
+ s32 newPos = gMenu.cursorPos + delta;
+
+ if (newPos < gMenu.minCursorPos)
+ gMenu.cursorPos = gMenu.maxCursorPos;
+ else if (newPos > gMenu.maxCursorPos)
+ gMenu.cursorPos = gMenu.minCursorPos;
+ else
+ gMenu.cursorPos += delta;
+
+ RedrawMenuCursor(
+ 6 * (gMenu.cursorPos / menuHeight) + gMenu.left,
+ 2 * (gMenu.cursorPos % menuHeight) + gMenu.top);
+
+ return gMenu.cursorPos;
+}
+
+u8 MoveMenuCursor4(s8 delta)
+{
+ if (gMenu.cursorPos + delta <= gMenu.maxCursorPos)
+ {
+ if (sub_80723D4() == TRUE)
+ return gMenu.cursorPos;
+ }
+ else
+ {
+ return gMenu.cursorPos;
+ }
+
+ gMenu.cursorPos += delta;
+
+ if ((gMenu.maxCursorPos + 1) / gMenu.width == 0)
+ RedrawMenuCursor(
+ gMenu.left + gMenu.columnXCoords[gMenu.cursorPos % gMenu.width],
+ 2 * ((gMenu.cursorPos / gMenu.width) % gMenu.height) + gMenu.top);
+ else
+ RedrawMenuCursor(
+ gMenu.left + gMenu.columnXCoords[gMenu.cursorPos % gMenu.width],
+ 2 * (gMenu.cursorPos / gMenu.width) + gMenu.top);
+
+ return gMenu.cursorPos;
+}
+
+bool8 sub_80723D4(void)
+{
+ if ((gMain.newKeys & DPAD_UP) && gMenu.cursorPos < gMenu.width)
+ return TRUE;
+
+ if ((gMain.newKeys & DPAD_DOWN) && gMenu.cursorPos >= (gMenu.maxCursorPos + 1) - gMenu.width)
+ return TRUE;
+
+ if ((gMain.newKeys & DPAD_LEFT)
+ && ((gMenu.cursorPos - (gMenu.cursorPos % gMenu.width)) % gMenu.width == 1 // always false
+ || gMenu.cursorPos == 0
+ || gMenu.cursorPos % gMenu.width == 0))
+ return TRUE;
+
+ if ((gMain.newKeys & DPAD_RIGHT) && gMenu.cursorPos % gMenu.width == gMenu.width - 1)
+ return TRUE;
+
+ return FALSE;
+}
+
+u8 sub_8072484(u8 a1, u8 a2, u8 menuItemCount, u8 a4, u8 width, u8 a6, u32 a7)
+{
+ u8 v7;
+
+ gMenu.width = width;
+ gMenu.height = menuItemCount / width;
+ InitMenu(0, a1, a2, menuItemCount, a4, a6);
+ v7 = 0;
+ if (a7)
+ v7 = -1;
+ gMenu.menu_field_7 = v7;
+ return a4;
+}
+
+#ifdef NONMATCHING
+u8 sub_80724F4(u8 left, u8 top, u8 menuItemCount, u8 *menuItems[][2], u8 columnCount)
+{
+ u8 i;
+ u8 maxWidth;
+ s32 height;
+
+ for (i = 0; i < 7; i++)
+ gMenu.columnXCoords[i] = 0;
+
+ maxWidth = 0;
+ for (i = 0; i < menuItemCount; i++)
+ {
+ u8 width = (sub_8072CA4(menuItems[i][0]) + 7) / 8;
+
+ if (width > maxWidth)
+ maxWidth = width;
+ }
+
+ for (i = 1; i <= columnCount; i++)
+ gMenu.columnXCoords[i] = maxWidth;
+
+ for (i = 1; i <= columnCount; i++)
+ gMenu.columnXCoords[i] += 1 + gMenu.columnXCoords[i - 1];
+
+ gMenu.columnXCoords[columnCount]--;
+
+ if (!((menuItemCount / 2) < columnCount || (menuItemCount % 2 != 0))
+ || columnCount == 1
+ || columnCount == menuItemCount)
+ {
+ height = 2 * (menuItemCount / columnCount) + 1;
+ }
+ else
+ {
+ height = 2 * ((menuItemCount / columnCount) + 1) + 1;
+ }
+
+ {
+ u8 right;
+ u8 bottom;
+ u32 totalWidth;
+ register s32 val asm("r1");
+
+ val = (s8)top + height;
+ bottom = val;
+
+ totalWidth = (gMenu.columnXCoords[columnCount] + 1);
+ right = left + totalWidth;
+
+ MenuDrawTextWindow(left, top, right, bottom);
+ }
+
+ return maxWidth;
+}
+#else
+__attribute__((naked))
+u8 sub_80724F4(u8 left, u8 top, u8 menuItemCount, u8 *menuItems[][2], u8 columnCount)
+{
+ asm("push {r4-r7,lr}\n\
+ mov r7, r10\n\
+ mov r6, r9\n\
+ mov r5, r8\n\
+ push {r5-r7}\n\
+ sub sp, #0xC\n\
+ mov r8, r3\n\
+ ldr r3, [sp, #0x2C]\n\
+ lsl r0, #24\n\
+ lsr r0, #24\n\
+ str r0, [sp]\n\
+ lsl r1, #24\n\
+ lsr r1, #24\n\
+ str r1, [sp, #0x4]\n\
+ lsl r2, #24\n\
+ lsr r6, r2, #24\n\
+ lsl r3, #24\n\
+ lsr r5, r3, #24\n\
+ movs r4, #0\n\
+ ldr r0, _080725D4\n\
+ mov r9, r0\n\
+ mov r1, r9\n\
+ add r1, #0x8\n\
+ movs r2, #0\n\
+_08072524:\n\
+ add r0, r4, r1\n\
+ strb r2, [r0]\n\
+ add r0, r4, #0x1\n\
+ lsl r0, #24\n\
+ lsr r4, r0, #24\n\
+ cmp r4, #0x6\n\
+ bls _08072524\n\
+ movs r7, #0\n\
+ movs r4, #0\n\
+ lsr r2, r6, #1\n\
+ mov r10, r2\n\
+ ldr r0, [sp, #0x4]\n\
+ lsl r0, #24\n\
+ str r0, [sp, #0x8]\n\
+ cmp r7, r6\n\
+ bcs _08072566\n\
+_08072544:\n\
+ lsl r0, r4, #3\n\
+ add r0, r8\n\
+ ldr r0, [r0]\n\
+ bl sub_8072CA4\n\
+ lsl r0, #24\n\
+ lsr r0, #24\n\
+ add r1, r0, #0x7\n\
+ lsr r0, r1, #3\n\
+ cmp r0, r7\n\
+ bls _0807255C\n\
+ add r7, r0, #0\n\
+_0807255C:\n\
+ add r0, r4, #0x1\n\
+ lsl r0, #24\n\
+ lsr r4, r0, #24\n\
+ cmp r4, r6\n\
+ bcc _08072544\n\
+_08072566:\n\
+ movs r4, #0x1\n\
+ ldr r2, _080725D4\n\
+ mov r9, r2\n\
+ cmp r4, r5\n\
+ bhi _08072582\n\
+ mov r1, r9\n\
+ add r1, #0x8\n\
+_08072574:\n\
+ add r0, r4, r1\n\
+ strb r7, [r0]\n\
+ add r0, r4, #0x1\n\
+ lsl r0, #24\n\
+ lsr r4, r0, #24\n\
+ cmp r4, r5\n\
+ bls _08072574\n\
+_08072582:\n\
+ movs r4, #0x1\n\
+ cmp r4, r5\n\
+ bhi _080725A4\n\
+ ldr r3, _080725D8\n\
+_0807258A:\n\
+ add r2, r4, r3\n\
+ ldrb r1, [r2]\n\
+ sub r0, r4, #0x1\n\
+ add r0, r3\n\
+ add r1, #0x1\n\
+ ldrb r0, [r0]\n\
+ add r1, r0\n\
+ strb r1, [r2]\n\
+ add r0, r4, #0x1\n\
+ lsl r0, #24\n\
+ lsr r4, r0, #24\n\
+ cmp r4, r5\n\
+ bls _0807258A\n\
+_080725A4:\n\
+ mov r1, r9\n\
+ add r1, #0x8\n\
+ add r1, r5, r1\n\
+ ldrb r0, [r1]\n\
+ sub r0, #0x1\n\
+ strb r0, [r1]\n\
+ cmp r10, r5\n\
+ bcc _080725BC\n\
+ movs r0, #0x1\n\
+ and r0, r6\n\
+ cmp r0, #0\n\
+ beq _080725C4\n\
+_080725BC:\n\
+ cmp r5, #0x1\n\
+ beq _080725C4\n\
+ cmp r5, r6\n\
+ bne _080725DC\n\
+_080725C4:\n\
+ add r0, r6, #0\n\
+ add r1, r5, #0\n\
+ bl __udivsi3\n\
+ lsl r0, #24\n\
+ lsr r0, #23\n\
+ add r0, #0x1\n\
+ b _080725EA\n\
+ .align 2, 0\n\
+_080725D4: .4byte 0x030006b0\n\
+_080725D8: .4byte 0x030006b8\n\
+_080725DC:\n\
+ add r0, r6, #0\n\
+ add r1, r5, #0\n\
+ bl __udivsi3\n\
+ lsl r0, #24\n\
+ lsr r0, #23\n\
+ add r0, #0x3\n\
+_080725EA:\n\
+ ldr r2, [sp, #0x8]\n\
+ asr r1, r2, #24\n\
+ add r1, r0\n\
+ lsl r1, #24\n\
+ lsr r3, r1, #24\n\
+ mov r0, r9\n\
+ add r0, #0x8\n\
+ add r0, r5, r0\n\
+ ldrb r2, [r0]\n\
+ add r2, #0x1\n\
+ ldr r0, [sp]\n\
+ add r2, r0, r2\n\
+ lsl r2, #24\n\
+ lsr r2, #24\n\
+ ldr r1, [sp, #0x4]\n\
+ bl MenuDrawTextWindow\n\
+ add r0, r7, #0\n\
+ add sp, #0xC\n\
+ pop {r3-r5}\n\
+ mov r8, r3\n\
+ mov r9, r4\n\
+ mov r10, r5\n\
+ pop {r4-r7}\n\
+ pop {r1}\n\
+ bx r1\n");
+}
+#endif // NONMATCHING
+
+void sub_8072620(u8 left, u8 top, u8 menuItemCount, u8 *menuItems[][2], u8 columnCount)
+{
+ u8 i;
+ u8 maxWidth;
+
+ for (i = 0; i < 7; i++)
+ gMenu.columnXCoords[i] = 0;
+
+ maxWidth = 0;
+ for (i = 0; i < menuItemCount; i++)
+ {
+ u8 width = (sub_8072CA4(menuItems[i][0]) + 7) / 8;
+
+ if (width > maxWidth)
+ maxWidth = width;
+ }
+
+ for (i = 1; i <= columnCount; i++)
+ gMenu.columnXCoords[i] = maxWidth;
+
+ for (i = 1; i <= columnCount; i++)
+ gMenu.columnXCoords[i] += 1 + gMenu.columnXCoords[i - 1];
+
+ gMenu.columnXCoords[columnCount]--;
+
+ for (i = 0; i < columnCount; i++)
+ {
+ u8 row = 0;
+ u8 j;
+ for (j = 0; i + j < menuItemCount; j += columnCount, row++)
+ MenuPrint(menuItems[i + j][0], left + gMenu.columnXCoords[i % columnCount], top + 2 * row);
+ }
+}
+
+void sub_807274C(u8 left, u8 top, u8 menuItemCount, u8 a4, u8 *menuItems[][2], u8 columnCount, u32 a7)
+{
+ u8 maxWidth = sub_80724F4(left, top, menuItemCount, menuItems, columnCount);
+
+ sub_8072484(left + 1, top + 1, menuItemCount, a4, columnCount, maxWidth, a7);
+ sub_8072620(left + 1, top + 1, menuItemCount, menuItems, columnCount);
+}
+
+s8 sub_80727CC(void)
+{
+ if (gMain.newKeys & A_BUTTON)
+ {
+ if (gMenu.menu_field_7)
+ sub_8072DEC();
+ audio_play(SE_SELECT);
+ return GetMenuCursorPos();
+ }
+
+ if (gMain.newKeys & B_BUTTON)
+ {
+ if (gMenu.menu_field_7)
+ sub_8072DEC();
+ return -1;
+ }
+
+ if (gMain.newKeys & DPAD_UP)
+ {
+ audio_play(SE_SELECT);
+ MoveMenuCursor4(-gMenu.width);
+ return -2;
+ }
+ else if (gMain.newKeys & DPAD_DOWN)
+ {
+ audio_play(SE_SELECT);
+ MoveMenuCursor4(gMenu.width);
+ return -2;
+ }
+ else if (gMain.newKeys & DPAD_LEFT)
+ {
+ audio_play(SE_SELECT);
+ MoveMenuCursor4(-1);
+ return -2;
+ }
+ else if (gMain.newKeys & DPAD_RIGHT)
+ {
+ audio_play(SE_SELECT);
+ MoveMenuCursor4(1);
+ return -2;
+ }
+
+ return -2;
+}
+
+u8 sub_807288C(u8 column)
+{
+ return gMenu.columnXCoords[column];
+}
+
+void PrintMenuItems(u8 left, u8 top, u8 menuItemCount, u8 *menuItems[][2])
+{
+ u8 i;
+
+ for (i = 0; i < menuItemCount; i++)
+ MenuPrint(menuItems[i][0], left, top + 2 * i);
+}
+
+void PrintMenuItemsReordered(u8 left, u8 top, u8 menuItemCount, u8 *menuItems[][2], u8 *order)
+{
+ u8 i;
+
+ for (i = 0; i < menuItemCount; i++)
+ MenuPrint(menuItems[order[i]][0], left, top + 2 * i);
+}
+
+void InitYesNoMenu(u8 left, u8 top, u8 a3)
+{
+ PrintMenuItems(left + 1, top + 1, 2, (void *)gUnknown_08376D74);
+ InitMenu(0, left + 1, top + 1, 2, 0, a3);
+}
+
+void DisplayYesNoMenu(u8 left, u8 top, u32 a3)
+{
+ MenuDrawTextWindow(left, top, left + 6, top + 5);
+ InitYesNoMenu(left, top, 5);
+ gMenu.menu_field_7 = a3 ? -1 : 0;
+}
+
+s8 ProcessMenuInputNoWrap_(void)
+{
+ return ProcessMenuInputNoWrap();
+}
+
+u8 sub_80729D8(u8 *text, u8 left, u16 top, u8 a4)
+{
+ return sub_8004D04(gMenuWindowPtr, text, gMenuTextTileOffset, left, top, a4);
+}
+
+u8 sub_8072A18(u8 *text, u8 left, u16 top, u8 width, u32 a5)
+{
+ return sub_8004FD0(gMenuWindowPtr, 0, text, gMenuTextTileOffset, left, top, width, a5);
+}
+
+u8 unref_sub_8072A5C(u8 *dest, u8 *src, u8 left, u16 top, u8 width, u32 a6)
+{
+ return sub_8004FD0(gMenuWindowPtr, dest, src, gMenuTextTileOffset, left, top, width, a6);
+}
+
+__attribute__((naked))
+int sub_8072AB0(u8 *str, u8 left, u16 top, u8 width, u8 height, u32 a6)
+{
+ asm("push {r4-r7,lr}\n\
+ mov r7, r9\n\
+ mov r6, r8\n\
+ push {r6,r7}\n\
+ sub sp, #0x10\n\
+ mov r9, r0\n\
+ add r4, r1, #0\n\
+ add r5, r2, #0\n\
+ ldr r0, [sp, #0x2C]\n\
+ ldr r2, [sp, #0x30]\n\
+ lsl r4, #24\n\
+ lsr r1, r4, #24\n\
+ mov r12, r1\n\
+ lsl r5, #16\n\
+ lsr r7, r5, #16\n\
+ lsl r3, #24\n\
+ lsr r6, r3, #24\n\
+ lsl r0, #24\n\
+ lsr r0, #24\n\
+ mov r8, r0\n\
+ ldr r0, _08072B44\n\
+ ldr r0, [r0]\n\
+ ldr r1, _08072B48\n\
+ ldrh r3, [r1]\n\
+ mov r1, r12\n\
+ str r1, [sp]\n\
+ str r7, [sp, #0x4]\n\
+ str r6, [sp, #0x8]\n\
+ str r2, [sp, #0xC]\n\
+ movs r1, #0\n\
+ mov r2, r9\n\
+ bl sub_8004FD0\n\
+ add r1, r0, #0\n\
+ lsl r1, #24\n\
+ lsr r2, r1, #24\n\
+ lsr r4, #27\n\
+ mov r12, r4\n\
+ lsr r7, r5, #19\n\
+ add r1, r6, #0x7\n\
+ lsr r6, r1, #3\n\
+ mov r1, r8\n\
+ add r1, #0x7\n\
+ asr r1, #3\n\
+ lsl r1, #24\n\
+ lsr r1, #24\n\
+ mov r8, r1\n\
+ cmp r2, r8\n\
+ bcs _08072B34\n\
+ lsl r1, r2, #1\n\
+ add r1, r7, r1\n\
+ lsl r1, #24\n\
+ lsr r1, #24\n\
+ mov r0, r12\n\
+ add r2, r0, r6\n\
+ sub r2, #0x1\n\
+ lsl r2, #24\n\
+ lsr r2, #24\n\
+ mov r0, r8\n\
+ add r3, r0, r7\n\
+ sub r3, #0x1\n\
+ lsl r3, #24\n\
+ lsr r3, #24\n\
+ mov r0, r12\n\
+ bl MenuFillWindowRectWithBlankTile\n\
+_08072B34:\n\
+ add sp, #0x10\n\
+ pop {r3,r4}\n\
+ mov r8, r3\n\
+ mov r9, r4\n\
+ pop {r4-r7}\n\
+ pop {r1}\n\
+ bx r1\n\
+ .align 2, 0\n\
+_08072B44: .4byte 0x0202e9c8\n\
+_08072B48: .4byte 0x0202e9ce\n");
+}
+
+void sub_8072B4C(u8 *str, u8 left, u8 top)
+{
+ sub_8004D38(gMenuWindowPtr, str, gMenuTextTileOffset, left, top);
+}
+
+void sub_8072B80(u8 *a1, u8 a2, u8 a3, u8 *a4)
+{
+ u8 buffer[64];
+ u8 width = GetStringWidth(gMenuWindowPtr, a4);
+ AlignString(gMenuWindowPtr, buffer, a1, width, 1);
+ sub_8003460(gMenuWindowPtr, buffer, gMenuTextTileOffset, a2, a3);
+}
+
+void sub_8072BD8(u8 *a1, u8 a2, u8 a3, u16 a4)
+{
+ sub_8004DB0(gMenuWindowPtr, a1, gMenuTextTileOffset, a2, a3, a4);
+}
+
+u8 *sub_8072C14(u8 *a1, s32 a2, u8 a3, u8 a4)
+{
+ return AlignInt1(gMenuWindowPtr, a1, a2, a3, a4);
+}
+
+u8 *sub_8072C44(u8 *a1, s32 a2, u8 a3, u8 a4)
+{
+ return AlignInt2(gMenuWindowPtr, a1, a2, a3, a4);
+}
+
+u8 *sub_8072C74(u8 *a1, u8 *a2, u8 a3, u8 a4)
+{
+ return AlignString(gMenuWindowPtr, a1, a2, a3, a4);
+}
+
+u8 sub_8072CA4(u8 *str)
+{
+ return GetStringWidth(gMenuWindowPtr, str);
+}
+
+u8 sub_8072CBC()
+{
+ return sub_8004E24(gMenuWindowPtr);
+}
+
+void sub_8072CD4(u8 *a1, u8 *a2, u8 *a3)
+{
+ sub_8004E28(gMenuWindowPtr, a1, a2, a3);
+}
+
+u32 MenuUpdateWindowText_OverrideLineLength(u8 lineLength)
+{
+ return sub_80037C8(gMenuWindowPtr, lineLength);
+}
+
+struct Window *unref_sub_8072D0C(void)
+{
+ return gMenuWindowPtr;
+}
+
+void sub_8072D18(u8 a1, u8 a2)
+{
+ sub_814A5C0(a1, 0xFFFF, 12, 11679, 8 * a2);
+}
+
+u8 InitMenu(u8 a1, u8 left, u8 top, u8 numChoices, u8 cursorPos, u8 a6)
+{
+ s32 pos;
+
+ if (a6)
+ sub_8072D18(a1, a6);
+
+ gMenu.left = left - 1;
+ gMenu.top = top;
+ gMenu.minCursorPos = 0;
+ gMenu.maxCursorPos = numChoices - 1;
+ gMenu.menu_field_7 = 0;
+
+ pos = cursorPos;
+
+ if (pos < 0 || pos > gMenu.maxCursorPos)
+ pos = 0;
+
+ gMenu.cursorPos = pos;
+ MoveMenuCursor(0);
+
+ return pos;
+}
+
+void RedrawMenuCursor(u8 a1, u8 a2)
+{
+ sub_814A880((a1 + 1) * 8, 8 * a2);
+}
+
+void unref_sub_8072DC0()
+{
+ sub_814A904();
+}
+
+void sub_8072DCC(u8 a1)
+{
+ sub_814A958(a1);
+}
+
+void sub_8072DDC(u8 a1)
+{
+ sub_8072DCC(8 * a1);
+}
+
+void sub_8072DEC(void)
+{
+ sub_814A7FC();
+}
diff --git a/src/pokemon.c b/src/pokemon.c
new file mode 100644
index 000000000..a2c98a71b
--- /dev/null
+++ b/src/pokemon.c
@@ -0,0 +1,607 @@
+#include "global.h"
+#include "text.h"
+#include "string_util.h"
+#include "pokemon.h"
+
+struct PokemonSubstruct0
+{
+ u16 species;
+ u16 heldItem;
+ u32 experience;
+ u8 ppBonuses;
+ u8 friendship;
+};
+
+struct PokemonSubstruct1
+{
+ u16 moves[4];
+ u8 pp[4];
+};
+
+struct PokemonSubstruct2
+{
+ u8 hpEV;
+ u8 attackEV;
+ u8 defenseEV;
+ u8 speedEV;
+ u8 spAttackEV;
+ u8 spDefenseEV;
+ u8 cool;
+ u8 beauty;
+ u8 cute;
+ u8 smart;
+ u8 tough;
+ u8 sheen;
+};
+
+struct PokemonSubstruct3
+{
+ u8 pokerus;
+ u8 metLocation;
+
+ u16 metLevel:7;
+ u16 metGame:4;
+ u16 pokeball:4;
+ u16 otGender:1;
+
+ u32 hpIV:5;
+ u32 attackIV:5;
+ u32 defenseIV:5;
+ u32 speedIV:5;
+ u32 spAttackIV:5;
+ u32 spDefenseIV:5;
+ u32 isEgg:1;
+ u32 altAbility:1;
+
+ u32 coolRibbon:3;
+ u32 beautyRibbon:3;
+ u32 cuteRibbon:3;
+ u32 smartRibbon:3;
+ u32 toughRibbon:3;
+ u32 championRibbon:1;
+ u32 winningRibbon:1;
+ u32 victoryRibbon:1;
+ u32 artistRibbon:1;
+ u32 effortRibbon:1;
+ u32 giftRibbon1:1;
+ u32 giftRibbon2:1;
+ u32 giftRibbon3:1;
+ u32 giftRibbon4:1;
+ u32 giftRibbon5:1;
+ u32 giftRibbon6:1;
+ u32 giftRibbon7:1;
+ u32 fatefulEncounter:5; // unused in Ruby/Sapphire, but the high bit must be set for Mew/Deoxys to obey in FR/LG/Emerald
+};
+
+union PokemonSubstruct
+{
+ struct PokemonSubstruct0 type0;
+ struct PokemonSubstruct1 type1;
+ struct PokemonSubstruct2 type2;
+ struct PokemonSubstruct3 type3;
+};
+
+struct BoxPokemon
+{
+ u32 personality;
+ u32 otId;
+ u8 nickname[10];
+ u8 language;
+ u8 isBadEgg:1;
+ u8 sanity2:1;
+ u8 sanity3:1;
+ u8 unused:5;
+ u8 otName[7];
+ u8 markings;
+ u16 checksum;
+ u16 unknown;
+
+ union
+ {
+ u32 raw[12];
+ union PokemonSubstruct substructs[4];
+ } secure;
+};
+
+struct Pokemon
+{
+ struct BoxPokemon box;
+ u32 status;
+ u8 level;
+ u8 pokerus;
+ u16 hp;
+ u16 maxHP;
+ u16 attack;
+ u16 defense;
+ u16 speed;
+ u16 spAttack;
+ u16 spDefense;
+};
+
+void ZeroPokemonBoxData(struct BoxPokemon *mon);
+
+u16 pokemon_calc_checksum(struct Pokemon *mon);
+
+void EncryptMon(struct Pokemon *mon);
+void DecryptMon(struct Pokemon *mon);
+union PokemonSubstruct *GetSubstruct(struct Pokemon *mon, u32 personality, u8 substructType);
+u32 GetMonData(struct Pokemon *mon, s32 field, u8 *data);
+u32 GetMonBoxData(struct Pokemon *mon, s32 field, u8 *data);
+
+extern u8 gBadEggNickname[];
+extern u8 gEggNickname[];
+extern u32 gBitTable[];
+
+/*
+void ZeroPokemonBoxData(struct BoxPokemon *mon)
+{
+ u8 *raw = (u8 *)mon;
+ u32 i;
+ for (i = 0; i < sizeof(struct BoxPokemon); i++)
+ raw[i] = 0;
+}
+*/
+
+void EncryptMon(struct Pokemon *mon)
+{
+ u32 i;
+ for (i = 0; i < 12; i++)
+ {
+ mon->box.secure.raw[i] ^= mon->box.personality;
+ mon->box.secure.raw[i] ^= mon->box.otId;
+ }
+}
+
+void DecryptMon(struct Pokemon *mon)
+{
+ u32 i;
+ for (i = 0; i < 12; i++)
+ {
+ mon->box.secure.raw[i] ^= mon->box.otId;
+ mon->box.secure.raw[i] ^= mon->box.personality;
+ }
+}
+
+#define SUBSTRUCT_CASE(n, v1, v2, v3, v4) \
+case n: \
+ switch (substructType) \
+ { \
+ case 0: \
+ substruct = &substructs ## n [v1]; \
+ break; \
+ case 1: \
+ substruct = &substructs ## n [v2]; \
+ break; \
+ case 2: \
+ substruct = &substructs ## n [v3]; \
+ break; \
+ case 3: \
+ substruct = &substructs ## n [v4]; \
+ break; \
+ } \
+ break;
+
+union PokemonSubstruct *GetSubstruct(struct Pokemon *mon, u32 personality, u8 substructType)
+{
+ union PokemonSubstruct *substruct = NULL;
+
+ union PokemonSubstruct *substructs0 = mon->box.secure.substructs;
+ union PokemonSubstruct *substructs1 = mon->box.secure.substructs;
+ union PokemonSubstruct *substructs2 = mon->box.secure.substructs;
+ union PokemonSubstruct *substructs3 = mon->box.secure.substructs;
+ union PokemonSubstruct *substructs4 = mon->box.secure.substructs;
+ union PokemonSubstruct *substructs5 = mon->box.secure.substructs;
+ union PokemonSubstruct *substructs6 = mon->box.secure.substructs;
+ union PokemonSubstruct *substructs7 = mon->box.secure.substructs;
+ union PokemonSubstruct *substructs8 = mon->box.secure.substructs;
+ union PokemonSubstruct *substructs9 = mon->box.secure.substructs;
+ union PokemonSubstruct *substructs10 = mon->box.secure.substructs;
+ union PokemonSubstruct *substructs11 = mon->box.secure.substructs;
+ union PokemonSubstruct *substructs12 = mon->box.secure.substructs;
+ union PokemonSubstruct *substructs13 = mon->box.secure.substructs;
+ union PokemonSubstruct *substructs14 = mon->box.secure.substructs;
+ union PokemonSubstruct *substructs15 = mon->box.secure.substructs;
+ union PokemonSubstruct *substructs16 = mon->box.secure.substructs;
+ union PokemonSubstruct *substructs17 = mon->box.secure.substructs;
+ union PokemonSubstruct *substructs18 = mon->box.secure.substructs;
+ union PokemonSubstruct *substructs19 = mon->box.secure.substructs;
+ union PokemonSubstruct *substructs20 = mon->box.secure.substructs;
+ union PokemonSubstruct *substructs21 = mon->box.secure.substructs;
+ union PokemonSubstruct *substructs22 = mon->box.secure.substructs;
+ union PokemonSubstruct *substructs23 = mon->box.secure.substructs;
+
+ switch (personality % 24)
+ {
+ SUBSTRUCT_CASE( 0,0,1,2,3)
+ SUBSTRUCT_CASE( 1,0,1,3,2)
+ SUBSTRUCT_CASE( 2,0,2,1,3)
+ SUBSTRUCT_CASE( 3,0,3,1,2)
+ SUBSTRUCT_CASE( 4,0,2,3,1)
+ SUBSTRUCT_CASE( 5,0,3,2,1)
+ SUBSTRUCT_CASE( 6,1,0,2,3)
+ SUBSTRUCT_CASE( 7,1,0,3,2)
+ SUBSTRUCT_CASE( 8,2,0,1,3)
+ SUBSTRUCT_CASE( 9,3,0,1,2)
+ SUBSTRUCT_CASE(10,2,0,3,1)
+ SUBSTRUCT_CASE(11,3,0,2,1)
+ SUBSTRUCT_CASE(12,1,2,0,3)
+ SUBSTRUCT_CASE(13,1,3,0,2)
+ SUBSTRUCT_CASE(14,2,1,0,3)
+ SUBSTRUCT_CASE(15,3,1,0,2)
+ SUBSTRUCT_CASE(16,2,3,0,1)
+ SUBSTRUCT_CASE(17,3,2,0,1)
+ SUBSTRUCT_CASE(18,1,2,3,0)
+ SUBSTRUCT_CASE(19,1,3,2,0)
+ SUBSTRUCT_CASE(20,2,1,3,0)
+ SUBSTRUCT_CASE(21,3,1,2,0)
+ SUBSTRUCT_CASE(22,2,3,1,0)
+ SUBSTRUCT_CASE(23,3,2,1,0)
+ }
+
+ return substruct;
+}
+
+u32 GetMonData(struct Pokemon *mon, s32 field, u8 *data)
+{
+ switch (field)
+ {
+ case MON_DATA_STATUS:
+ return mon->status;
+ case MON_DATA_LEVEL:
+ return mon->level;
+ case MON_DATA_HP:
+ return mon->hp;
+ case MON_DATA_MAX_HP:
+ return mon->maxHP;
+ case MON_DATA_ATK:
+ return mon->attack;
+ case MON_DATA_DEF:
+ return mon->defense;
+ case MON_DATA_SPD:
+ return mon->speed;
+ case MON_DATA_SPATK:
+ return mon->spAttack;
+ case MON_DATA_SPDEF:
+ return mon->spDefense;
+ case MON_DATA_64:
+ return mon->pokerus;
+ default:
+ return GetMonBoxData(mon, field, data);
+ }
+}
+
+u32 GetMonBoxData(struct Pokemon *mon, s32 field, u8 *data)
+{
+ u32 retVal = 0;
+ struct PokemonSubstruct0 *substruct0 = NULL;
+ struct PokemonSubstruct1 *substruct1 = NULL;
+ struct PokemonSubstruct2 *substruct2 = NULL;
+ struct PokemonSubstruct3 *substruct3 = NULL;
+
+ if (field > MON_DATA_10)
+ {
+ substruct0 = &(GetSubstruct(mon, mon->box.personality, 0)->type0);
+ substruct1 = &(GetSubstruct(mon, mon->box.personality, 1)->type1);
+ substruct2 = &(GetSubstruct(mon, mon->box.personality, 2)->type2);
+ substruct3 = &(GetSubstruct(mon, mon->box.personality, 3)->type3);
+
+ DecryptMon(mon);
+
+ if (pokemon_calc_checksum(mon) != mon->box.checksum)
+ {
+ mon->box.isBadEgg = 1;
+ mon->box.sanity3 = 1;
+ substruct3->isEgg = 1;
+ }
+ }
+
+ switch (field)
+ {
+ case MON_DATA_PERSONALITY:
+ retVal = mon->box.personality;
+ break;
+ case MON_DATA_OT_ID:
+ retVal = mon->box.otId;
+ break;
+ case MON_DATA_NICKNAME:
+ {
+ if (mon->box.isBadEgg)
+ {
+ StringCopy(data, gBadEggNickname);
+ retVal = StringLength(data);
+ }
+ else if (mon->box.sanity3)
+ {
+ StringCopy(data, gEggNickname);
+ retVal = StringLength(data);
+ }
+ else
+ {
+ retVal = 0;
+
+ while (retVal < 10 && mon->box.nickname[retVal] != EOS)
+ {
+ data[retVal] = mon->box.nickname[retVal];
+ retVal++;
+ }
+
+ data[retVal] = EOS;
+ ConvertInternationalString(data, mon->box.language);
+ retVal = StringLength(data);
+ }
+ break;
+ }
+ case MON_DATA_LANGUAGE:
+ retVal = mon->box.language;
+ break;
+ case MON_DATA_SANITY_BIT1:
+ retVal = mon->box.isBadEgg;
+ break;
+ case MON_DATA_SANITY_BIT2:
+ retVal = mon->box.sanity2;
+ break;
+ case MON_DATA_SANITY_BIT3:
+ retVal = mon->box.sanity3;
+ break;
+ case MON_DATA_OT_NAME:
+ {
+ retVal = 0;
+
+ while (retVal < 7 && mon->box.otName[retVal] != EOS)
+ {
+ data[retVal] = mon->box.otName[retVal];
+ retVal++;
+ }
+
+ data[retVal] = EOS;
+ break;
+ }
+ case MON_DATA_MARKINGS:
+ retVal = mon->box.markings;
+ break;
+ case MON_DATA_CHECKSUM:
+ retVal = mon->box.checksum;
+ break;
+ case MON_DATA_10:
+ retVal = mon->box.unknown;
+ break;
+ case MON_DATA_SPECIES:
+ retVal = mon->box.isBadEgg ? 412 : substruct0->species;
+ break;
+ case MON_DATA_HELD_ITEM:
+ retVal = substruct0->heldItem;
+ break;
+ case MON_DATA_EXP:
+ retVal = substruct0->experience;
+ break;
+ case MON_DATA_PP_BONUSES:
+ retVal = substruct0->ppBonuses;
+ break;
+ case MON_DATA_FRIENDSHIP:
+ retVal = substruct0->friendship;
+ break;
+ case MON_DATA_MOVE1:
+ case MON_DATA_MOVE2:
+ case MON_DATA_MOVE3:
+ case MON_DATA_MOVE4:
+ retVal = substruct1->moves[field - MON_DATA_MOVE1];
+ break;
+ case MON_DATA_PP1:
+ case MON_DATA_PP2:
+ case MON_DATA_PP3:
+ case MON_DATA_PP4:
+ retVal = substruct1->pp[field - MON_DATA_PP1];
+ break;
+ case MON_DATA_HP_EV:
+ retVal = substruct2->hpEV;
+ break;
+ case MON_DATA_ATK_EV:
+ retVal = substruct2->attackEV;
+ break;
+ case MON_DATA_DEF_EV:
+ retVal = substruct2->defenseEV;
+ break;
+ case MON_DATA_SPD_EV:
+ retVal = substruct2->speedEV;
+ break;
+ case MON_DATA_SPATK_EV:
+ retVal = substruct2->spAttackEV;
+ break;
+ case MON_DATA_SPDEF_EV:
+ retVal = substruct2->spDefenseEV;
+ break;
+ case MON_DATA_COOL:
+ retVal = substruct2->cool;
+ break;
+ case MON_DATA_BEAUTY:
+ retVal = substruct2->beauty;
+ break;
+ case MON_DATA_CUTE:
+ retVal = substruct2->cute;
+ break;
+ case MON_DATA_SMART:
+ retVal = substruct2->smart;
+ break;
+ case MON_DATA_TOUGH:
+ retVal = substruct2->tough;
+ break;
+ case MON_DATA_SHEEN:
+ retVal = substruct2->sheen;
+ break;
+ case MON_DATA_POKERUS:
+ retVal = substruct3->pokerus;
+ break;
+ case MON_DATA_MET_LOCATION:
+ retVal = substruct3->metLocation;
+ break;
+ case MON_DATA_MET_LEVEL:
+ retVal = substruct3->metLevel;
+ break;
+ case MON_DATA_MET_GAME:
+ retVal = substruct3->metGame;
+ break;
+ case MON_DATA_POKEBALL:
+ retVal = substruct3->pokeball;
+ break;
+ case MON_DATA_OT_GENDER:
+ retVal = substruct3->otGender;
+ break;
+ case MON_DATA_HP_IV:
+ retVal = substruct3->hpIV;
+ break;
+ case MON_DATA_ATK_IV:
+ retVal = substruct3->attackIV;
+ break;
+ case MON_DATA_DEF_IV:
+ retVal = substruct3->defenseIV;
+ break;
+ case MON_DATA_SPD_IV:
+ retVal = substruct3->speedIV;
+ break;
+ case MON_DATA_SPATK_IV:
+ retVal = substruct3->spAttackIV;
+ break;
+ case MON_DATA_SPDEF_IV:
+ retVal = substruct3->spDefenseIV;
+ break;
+ case MON_DATA_IS_EGG:
+ retVal = substruct3->isEgg;
+ break;
+ case MON_DATA_ALT_ABILITY:
+ retVal = substruct3->altAbility;
+ break;
+ case MON_DATA_COOL_RIBBON:
+ retVal = substruct3->coolRibbon;
+ break;
+ case MON_DATA_BEAUTY_RIBBON:
+ retVal = substruct3->beautyRibbon;
+ break;
+ case MON_DATA_CUTE_RIBBON:
+ retVal = substruct3->cuteRibbon;
+ break;
+ case MON_DATA_SMART_RIBBON:
+ retVal = substruct3->smartRibbon;
+ break;
+ case MON_DATA_TOUGH_RIBBON:
+ retVal = substruct3->toughRibbon;
+ break;
+ case MON_DATA_CHAMPION_RIBBON:
+ retVal = substruct3->championRibbon;
+ break;
+ case MON_DATA_WINNING_RIBBON:
+ retVal = substruct3->winningRibbon;
+ break;
+ case MON_DATA_VICTORY_RIBBON:
+ retVal = substruct3->victoryRibbon;
+ break;
+ case MON_DATA_ARTIST_RIBBON:
+ retVal = substruct3->artistRibbon;
+ break;
+ case MON_DATA_EFFORT_RIBBON:
+ retVal = substruct3->effortRibbon;
+ break;
+ case MON_DATA_GIFT_RIBBON_1:
+ retVal = substruct3->giftRibbon1;
+ break;
+ case MON_DATA_GIFT_RIBBON_2:
+ retVal = substruct3->giftRibbon2;
+ break;
+ case MON_DATA_GIFT_RIBBON_3:
+ retVal = substruct3->giftRibbon3;
+ break;
+ case MON_DATA_GIFT_RIBBON_4:
+ retVal = substruct3->giftRibbon4;
+ break;
+ case MON_DATA_GIFT_RIBBON_5:
+ retVal = substruct3->giftRibbon5;
+ break;
+ case MON_DATA_GIFT_RIBBON_6:
+ retVal = substruct3->giftRibbon6;
+ break;
+ case MON_DATA_GIFT_RIBBON_7:
+ retVal = substruct3->giftRibbon7;
+ break;
+ case MON_DATA_FATEFUL_ENCOUNTER:
+ retVal = substruct3->fatefulEncounter;
+ break;
+ case MON_DATA_SPECIES2:
+ retVal = substruct0->species;
+ if (substruct0->species && (substruct3->isEgg || mon->box.isBadEgg))
+ retVal = 412;
+ break;
+ case MON_DATA_IVS:
+ retVal = substruct3->hpIV | (substruct3->attackIV << 5) | (substruct3->defenseIV << 10) | (substruct3->speedIV << 15) | (substruct3->spAttackIV << 20) | (substruct3->spDefenseIV << 25);
+ break;
+ case MON_DATA_KNOWN_MOVES:
+ if (substruct0->species && !substruct3->isEgg)
+ {
+ u16 *moves = (u16 *)data;
+ s32 i = 0;
+
+ while (moves[i] != 355)
+ {
+ u16 move = moves[i];
+ if (substruct1->moves[0] == move
+ || substruct1->moves[1] == move
+ || substruct1->moves[2] == move
+ || substruct1->moves[3] == move)
+ retVal |= gBitTable[i];
+ i++;
+ }
+ }
+ break;
+ case MON_DATA_RIBBON_COUNT:
+ retVal = 0;
+ if (substruct0->species && !substruct3->isEgg)
+ {
+ retVal += substruct3->coolRibbon;
+ retVal += substruct3->beautyRibbon;
+ retVal += substruct3->cuteRibbon;
+ retVal += substruct3->smartRibbon;
+ retVal += substruct3->toughRibbon;
+ retVal += substruct3->championRibbon;
+ retVal += substruct3->winningRibbon;
+ retVal += substruct3->victoryRibbon;
+ retVal += substruct3->artistRibbon;
+ retVal += substruct3->effortRibbon;
+ retVal += substruct3->giftRibbon1;
+ retVal += substruct3->giftRibbon2;
+ retVal += substruct3->giftRibbon3;
+ retVal += substruct3->giftRibbon4;
+ retVal += substruct3->giftRibbon5;
+ retVal += substruct3->giftRibbon6;
+ retVal += substruct3->giftRibbon7;
+ }
+ break;
+ case MON_DATA_RIBBONS:
+ retVal = 0;
+ if (substruct0->species && !substruct3->isEgg)
+ {
+ retVal = substruct3->championRibbon
+ | (substruct3->coolRibbon << 1)
+ | (substruct3->beautyRibbon << 4)
+ | (substruct3->cuteRibbon << 7)
+ | (substruct3->smartRibbon << 10)
+ | (substruct3->toughRibbon << 13)
+ | (substruct3->winningRibbon << 16)
+ | (substruct3->victoryRibbon << 17)
+ | (substruct3->artistRibbon << 18)
+ | (substruct3->effortRibbon << 19)
+ | (substruct3->giftRibbon1 << 20)
+ | (substruct3->giftRibbon2 << 21)
+ | (substruct3->giftRibbon3 << 22)
+ | (substruct3->giftRibbon4 << 23)
+ | (substruct3->giftRibbon5 << 24)
+ | (substruct3->giftRibbon6 << 25)
+ | (substruct3->giftRibbon7 << 26);
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (field > MON_DATA_10)
+ EncryptMon(mon);
+
+ return retVal;
+}
diff --git a/src/text.c b/src/text.c
index 372d3e7e2..64a302fed 100644
--- a/src/text.c
+++ b/src/text.c
@@ -2523,7 +2523,7 @@ u8 sub_80037A0(struct Window *win)
return retVal;
}
-u8 sub_80037C8(struct Window *win, u8 lineLength)
+u32 sub_80037C8(struct Window *win, u8 lineLength)
{
u8 retVal;
diff --git a/src/text_window.c b/src/text_window.c
new file mode 100644
index 000000000..ab14fe1fb
--- /dev/null
+++ b/src/text_window.c
@@ -0,0 +1,196 @@
+#include "global.h"
+#include "main.h"
+#include "text.h"
+#include "text_window.h"
+
+u16 SetTextWindowBaseTileNum(u16);
+void LoadTextWindowGraphics(struct Window *);
+void LoadTextWindowGraphics_OverridePalSlot(struct Window *, u8);
+void LoadTextWindowGraphics_OverrideFrameType(struct Window *, u8);
+void DrawTextWindow(struct Window *win, u8 left, u8 top, u8 right, u8 bottom);
+const struct FrameGraphics *GetTextWindowFrameGraphics(u8 frameType);
+static void LoadTextWindowTiles(u8, void *);
+static void LoadTextWindowPalette(u8, u8);
+static void DrawTextWindowInternal(u16 *dest, u16 baseTileNum, u8 left, u8 top, u8 right, u8 bottom);
+u16 SetMessageBoxBaseTileNum(u16);
+void unref_sub_80651DC(struct Window *, u8 *);
+void DisplayMessageBox(struct Window *);
+static u16 GetMessageBoxTilemapEntry(u16 tilemapEntry, u8 x, u8 y, u8 width, u8 height);
+static void DrawMessageBox(struct Window *win, u8 left, u8 top, u8 width, u8 height);
+void DrawStandardMessageBox(struct Window *win);
+void LoadMessageBoxTiles(struct Window *win);
+void sub_806536C(struct Window *win);
+
+static u16 sTextWindowBaseTileNum;
+static u16 sMessageBoxBaseTileNum;
+
+struct FrameGraphics
+{
+ u8 *tiles;
+ u16 *palette;
+};
+
+extern const struct FrameGraphics gUnknown_083761F0[20];
+
+extern const u16 gMessageBoxTilemap[5][7];
+extern const u8 gMessageBox_Gfx[];
+
+u16 SetTextWindowBaseTileNum(u16 baseTileNum)
+{
+ sTextWindowBaseTileNum = baseTileNum;
+ return baseTileNum + 9;
+}
+
+void LoadTextWindowGraphics(struct Window *win)
+{
+ u8 *tileData = win->config->tileData + TILE_SIZE_4BPP * sTextWindowBaseTileNum;
+ LoadTextWindowTiles(gSaveBlock2.optionsWindowFrameType, tileData);
+ LoadTextWindowPalette(gSaveBlock2.optionsWindowFrameType, 0xE);
+}
+
+void LoadTextWindowGraphics_OverridePalSlot(struct Window *win, u8 palSlot)
+{
+ u8 *tileData = win->config->tileData + TILE_SIZE_4BPP * sTextWindowBaseTileNum;
+ LoadTextWindowTiles(gSaveBlock2.optionsWindowFrameType, tileData);
+ LoadTextWindowPalette(gSaveBlock2.optionsWindowFrameType, palSlot);
+}
+
+void LoadTextWindowGraphics_OverrideFrameType(struct Window *win, u8 frameType)
+{
+ u8 *tileData = win->config->tileData + TILE_SIZE_4BPP * sTextWindowBaseTileNum;
+ LoadTextWindowTiles(frameType, tileData);
+ LoadTextWindowPalette(frameType, 0xE);
+}
+
+void DrawTextWindow(struct Window *win, u8 left, u8 top, u8 right, u8 bottom)
+{
+ DrawTextWindowInternal(win->config->tilemap, sTextWindowBaseTileNum, left, top, right, bottom);
+}
+
+const struct FrameGraphics *GetTextWindowFrameGraphics(u8 frameType)
+{
+ if (frameType > 19)
+ return &gUnknown_083761F0[0];
+ else
+ return &gUnknown_083761F0[frameType];
+}
+
+static void LoadTextWindowTiles(u8 frameType, void *dest)
+{
+ const struct FrameGraphics *frameGraphics = GetTextWindowFrameGraphics(frameType);
+ CpuFastCopy(frameGraphics->tiles, dest, 9 * TILE_SIZE_4BPP);
+}
+
+static void LoadTextWindowPalette(u8 frameType, u8 palSlot)
+{
+ const struct FrameGraphics *frameGraphics = GetTextWindowFrameGraphics(frameType);
+ LoadPalette(frameGraphics->palette, 16 * palSlot, 0x20);
+}
+
+static void DrawTextWindowInternal(u16 *dest, u16 baseTileNum, u8 left, u8 top, u8 right, u8 bottom)
+{
+ u8 x, y;
+ u8 startX, endX;
+ u8 startY, endY;
+
+ startX = (left < right) ? left : right;
+ endX = (right > left) ? right : left;
+
+ startY = (top < bottom) ? top : bottom;
+ endY = (bottom > top) ? bottom : top;
+
+ dest[32 * startY + startX] = baseTileNum | 0xE000;
+
+ for (x = startX + 1; x < endX; x++)
+ dest[32 * startY + x] = (baseTileNum + 1) | 0xE000;
+
+ dest[32 * startY + endX] = (baseTileNum + 2) | 0xE000;
+
+ for (y = startY + 1; y < endY; y++)
+ {
+ dest[32 * y + startX] = (baseTileNum + 3) | 0xE000;
+
+ for (x = startX + 1; x < endX; x++)
+ dest[32 * y + x] = (baseTileNum + 4) | 0xE000;
+
+ dest[32 * y + endX] = (baseTileNum + 5) | 0xE000;
+ }
+
+ dest[32 * endY + startX] = (baseTileNum + 6) | 0xE000;
+
+ for (x = startX + 1; x < endX; x++)
+ dest[32 * endY + x] = (baseTileNum + 7) | 0xE000;
+
+ dest[32 * endY + endX] = (baseTileNum + 8) | 0xE000;
+}
+
+u16 SetMessageBoxBaseTileNum(u16 baseTileNum)
+{
+ sMessageBoxBaseTileNum = baseTileNum;
+ return baseTileNum + 14;
+}
+
+void unref_sub_80651DC(struct Window *win, u8 *text)
+{
+ sub_8002EB0(win, text, sMessageBoxBaseTileNum + 14, 2, 15);
+}
+
+void DisplayMessageBox(struct Window *win)
+{
+ LoadMessageBoxTiles(win);
+ DrawStandardMessageBox(win);
+}
+
+static u16 GetMessageBoxTilemapEntry(u16 baseTilemapEntry, u8 x, u8 y, u8 width, u8 height)
+{
+ u16 tilemapEntry = 9;
+
+ if (y >= height)
+ y = y - height + 3;
+ else if (y > 1)
+ y = 2;
+
+ if (x >= width + 2)
+ x = x - (width + 2) + 4;
+ else if (x > 2)
+ x = 3;
+
+ if (x <= 6 && y <= 4)
+ tilemapEntry = gMessageBoxTilemap[y][x];
+
+ tilemapEntry += baseTilemapEntry;
+
+ return tilemapEntry;
+}
+
+static void DrawMessageBox(struct Window *win, u8 left, u8 top, u8 width, u8 height)
+{
+ u8 i, j;
+ u16 tilemapEntry = (win->paletteNum << 12) | sMessageBoxBaseTileNum;
+ u16 *tilemap = win->config->tilemap;
+
+ for (i = 0; i < height + 2; i++)
+ for (j = 0; j < width + 6; j++)
+ tilemap[(left + j) + 32 * (top + i)] = (win->paletteNum << 12) | GetMessageBoxTilemapEntry(tilemapEntry, j, i, width, height);
+}
+
+void DrawStandardMessageBox(struct Window *win)
+{
+ DrawMessageBox(win, 0, 14, 26, 4);
+}
+
+void LoadMessageBoxTiles(struct Window *win)
+{
+ u8 *tileData = win->config->tileData;
+ CpuFastCopy(gMessageBox_Gfx, tileData + 32 * sMessageBoxBaseTileNum, 14 * TILE_SIZE_4BPP);
+}
+
+void sub_806536C(struct Window *win)
+{
+ u8 i;
+ u16 *tilemap = win->config->tilemap + 0x1C0;
+ u16 tilemapEntry = win->paletteNum << 12;
+
+ for (i = 0; i < 0xC0; i++)
+ tilemap[i] = tilemapEntry;
+}