diff options
author | huderlem <huderlem@gmail.com> | 2019-03-17 17:32:42 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-03-17 17:32:42 -0500 |
commit | 7154d2614d21c5a5931fc944e247059d49cda782 (patch) | |
tree | 414ed687f836521c1a966531e87122951c070083 /src | |
parent | 4ae8a52473a0e4842cf140bf0c59f0276125a896 (diff) | |
parent | e9a3cc6d51ce3818eed11de585f5084342450093 (diff) |
Merge pull request #595 from Phlosioneer/move-tutor
Move tutor
Diffstat (limited to 'src')
-rw-r--r-- | src/battle_pyramid_bag.c | 12 | ||||
-rw-r--r-- | src/battle_script_commands.c | 12 | ||||
-rw-r--r-- | src/decoration.c | 2 | ||||
-rw-r--r-- | src/egg_hatch.c | 2 | ||||
-rw-r--r-- | src/field_screen_effect.c | 26 | ||||
-rw-r--r-- | src/field_specials.c | 6 | ||||
-rwxr-xr-x | src/item_menu.c | 4 | ||||
-rw-r--r-- | src/learn_move.c | 833 | ||||
-rw-r--r-- | src/list_menu.c | 4 | ||||
-rw-r--r-- | src/menu_specialized.c | 2094 | ||||
-rw-r--r-- | src/move_relearner.c | 976 | ||||
-rw-r--r-- | src/overworld.c | 2 | ||||
-rwxr-xr-x | src/party_menu.c | 9 | ||||
-rw-r--r-- | src/player_pc.c | 8 | ||||
-rw-r--r-- | src/pokeblock.c | 10 | ||||
-rw-r--r-- | src/roulette.c | 2 | ||||
-rw-r--r-- | src/secret_base.c | 4 | ||||
-rwxr-xr-x | src/shop.c | 2 | ||||
-rw-r--r-- | src/strings.c | 30 | ||||
-rw-r--r-- | src/trade.c | 2 | ||||
-rw-r--r-- | src/use_pokeblock.c | 17 | ||||
-rw-r--r-- | src/walda_phrase.c | 2 |
22 files changed, 3148 insertions, 911 deletions
diff --git a/src/battle_pyramid_bag.c b/src/battle_pyramid_bag.c index 3b8cac14f..ee35ed45b 100644 --- a/src/battle_pyramid_bag.c +++ b/src/battle_pyramid_bag.c @@ -576,7 +576,7 @@ static void SetBagItemsListTemplate(void) } StringCopy(gPyramidBagResources->itemStrings[i], gText_CloseBag); gPyramidBagResources->bagListItems[i].name = gPyramidBagResources->itemStrings[i]; - gPyramidBagResources->bagListItems[i].id = LIST_B_PRESSED; + gPyramidBagResources->bagListItems[i].id = LIST_CANCEL; gMultiuseListMenuTemplate = gUnknown_0861F2C0; gMultiuseListMenuTemplate.totalItems = gPyramidBagResources->listMenuCount; gMultiuseListMenuTemplate.items = gPyramidBagResources->bagListItems; @@ -607,7 +607,7 @@ static void PyramidBagMoveCursorFunc(s32 itemIndex, bool8 onInit, struct ListMen if (gPyramidBagResources->unk814 == 0xFF) { sub_81C6FF8(gPyramidBagResources->unk815 ^ 1); - if (itemIndex != LIST_B_PRESSED) + if (itemIndex != LIST_CANCEL) ShowItemImage(gSaveBlock2Ptr->frontier.pyramidBag.itemId[gSaveBlock2Ptr->frontier.lvlMode][itemIndex], gPyramidBagResources->unk815); else ShowItemImage(0xFFFF, gPyramidBagResources->unk815); @@ -619,7 +619,7 @@ static void PyramidBagMoveCursorFunc(s32 itemIndex, bool8 onInit, struct ListMen static void PrintItemQuantity(u8 windowId, s32 itemIndex, u8 y) { s32 xAlign; - if (itemIndex == LIST_B_PRESSED) + if (itemIndex == LIST_CANCEL) return; if (gPyramidBagResources->unk814 != 0xFF) @@ -641,7 +641,7 @@ static void PrintItemQuantity(u8 windowId, s32 itemIndex, u8 y) static void PrintItemDescription(s32 listMenuId) { const u8 *desc; - if (listMenuId != LIST_B_PRESSED) + if (listMenuId != LIST_CANCEL) { desc = ItemId_GetDescription(gSaveBlock2Ptr->frontier.pyramidBag.itemId[gSaveBlock2Ptr->frontier.lvlMode][listMenuId]); } @@ -859,7 +859,7 @@ static void Task_HandlePyramidBagInput(u8 taskId) { case LIST_NOTHING_CHOSEN: break; - case LIST_B_PRESSED: + case LIST_CANCEL: PlaySE(SE_SELECT); gSpecialVar_ItemId = 0; sub_81C5B14(taskId); @@ -1293,7 +1293,7 @@ static void Task_ItemSwapHandleInput(u8 taskId) { case LIST_NOTHING_CHOSEN: break; - case LIST_B_PRESSED: + case LIST_CANCEL: PlaySE(SE_SELECT); if (gMain.newKeys & A_BUTTON) PerformItemSwap(taskId); diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 025d694e4..0eb6dfec0 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -49,14 +49,12 @@ #include "field_specials.h" #include "pokemon_summary_screen.h" #include "pokenav.h" +#include "menu_specialized.h" extern struct MusicPlayerInfo gMPlayInfo_BGM; extern const u8* const gBattleScriptsForMoveEffects[]; -// functions -extern void sub_81D388C(struct Pokemon* mon, void* statStoreLocation); // pokenav.s - #define DEFENDER_IS_PROTECTED ((gProtectStructs[gBattlerTarget].protected) && (gBattleMoves[gCurrentMove].flags & FLAG_PROTECT_AFFECTED)) // this file's functions @@ -6319,16 +6317,16 @@ static void sub_804F100(void) { struct StatsArray currentStats; - sub_81D388C(&gPlayerParty[gBattleStruct->expGetterMonId], ¤tStats); - sub_81D3640(0xD, gBattleResources->statsBeforeLvlUp, ¤tStats, 0xE, 0xD, 0xF); + GetMonLevelUpWindowStats(&gPlayerParty[gBattleStruct->expGetterMonId], ¤tStats); + DrawLevelUpWindowPg1(0xD, gBattleResources->statsBeforeLvlUp, ¤tStats, 0xE, 0xD, 0xF); } static void sub_804F144(void) { struct StatsArray currentStats; - sub_81D388C(&gPlayerParty[gBattleStruct->expGetterMonId], ¤tStats); - sub_81D3784(0xD, ¤tStats, 0xE, 0xD, 0xF); + GetMonLevelUpWindowStats(&gPlayerParty[gBattleStruct->expGetterMonId], ¤tStats); + DrawLevelUpWindowPg2(0xD, ¤tStats, 0xE, 0xD, 0xF); } static void sub_804F17C(void) diff --git a/src/decoration.c b/src/decoration.c index 47e3ae18c..3c8809c6a 100644 --- a/src/decoration.c +++ b/src/decoration.c @@ -941,7 +941,7 @@ void sub_812764C(u8 taskId) { case LIST_NOTHING_CHOSEN: break; - case LIST_B_PRESSED: + case LIST_CANCEL: PlaySE(SE_SELECT); SecretBasePC_SelectedDecorActions[data[11]][1](taskId); break; diff --git a/src/egg_hatch.c b/src/egg_hatch.c index 00b67a5d9..fc559e001 100644 --- a/src/egg_hatch.c +++ b/src/egg_hatch.c @@ -469,7 +469,7 @@ static void Task_EggHatch(u8 taskID) { CleanupOverworldWindowsAndTilemaps(); SetMainCallback2(CB2_EggHatch_0); - gFieldCallback = sub_80AF168; + gFieldCallback = FieldCallback_ReturnToEventScript2; DestroyTask(taskID); } } diff --git a/src/field_screen_effect.c b/src/field_screen_effect.c index b6dcf212c..5769f44af 100644 --- a/src/field_screen_effect.c +++ b/src/field_screen_effect.c @@ -44,7 +44,7 @@ static void task0A_fade_n_map_maybe(u8); static void sub_808115C(u8); static void palette_bg_faded_fill_white(void); static void sub_80AF438(u8); -static bool32 sub_80AF71C(void); +static bool32 WaitForWeatherFadeIn(void); static void task0A_mpl_807E31C(u8 taskId); static void sub_80AFA0C(u8 taskId); static void sub_80AFA88(u8 taskId); @@ -119,7 +119,7 @@ static void sub_80AF0F4(u8 arg) static void task0A_nop_for_a_while(u8 taskId) { - if (sub_80AF71C() == TRUE) + if (WaitForWeatherFadeIn() == TRUE) DestroyTask(taskId); } @@ -133,14 +133,14 @@ void sub_80AF128(void) static void task0A_asap_script_env_2_enable_and_set_ctx_running(u8 taskID) { - if (sub_80AF71C() == TRUE) + if (WaitForWeatherFadeIn() == TRUE) { DestroyTask(taskID); EnableBothScriptContexts(); } } -void sub_80AF168(void) +void FieldCallback_ReturnToEventScript2(void) { ScriptContext2_Enable(); Overworld_PlaySpecialMapMusic(); @@ -173,7 +173,7 @@ static void task_mpl_807DD60(u8 taskId) } break; case 2: - if (sub_80AF71C() == TRUE) + if (WaitForWeatherFadeIn() == TRUE) { ScriptContext2_Disable(); DestroyTask(taskId); @@ -213,7 +213,7 @@ static void sub_80AF234(u8 taskId) } break; case 2: - if (sub_80AF71C() == TRUE) + if (WaitForWeatherFadeIn() == TRUE) { sub_8009F18(); ScriptContext2_Disable(); @@ -333,7 +333,7 @@ static void sub_80AF438(u8 taskId) task->data[0] = 1; break; case 1: - if (sub_80AF71C()) + if (WaitForWeatherFadeIn()) { u8 eventObjId; sub_80AF0F4(1); @@ -381,7 +381,7 @@ static void task_map_chg_seq_0807E20C(u8 taskId) task->data[0] = 1; break; case 1: - if (sub_80AF71C()) + if (WaitForWeatherFadeIn()) { u8 eventObjId; sub_80AF0F4(1); @@ -414,7 +414,7 @@ static void task_map_chg_seq_0807E2CC(u8 taskId) gTasks[taskId].data[0]++; break; case 1: - if (sub_80AF71C()) + if (WaitForWeatherFadeIn()) { UnfreezeEventObjects(); ScriptContext2_Disable(); @@ -426,7 +426,7 @@ static void task_map_chg_seq_0807E2CC(u8 taskId) static void sub_80AF660(u8 taskId) { - if (sub_80AF71C() == TRUE) + if (WaitForWeatherFadeIn() == TRUE) { DestroyTask(taskId); CreateTask(sub_809FA34, 80); @@ -448,7 +448,7 @@ bool8 sub_80AF6A4(void) static void task_mpl_807E3C8(u8 taskId) { - if (sub_80AF71C() == 1) + if (WaitForWeatherFadeIn() == 1) { ScriptContext2_Disable(); DestroyTask(taskId); @@ -476,7 +476,7 @@ static bool32 PaletteFadeActive(void) return gPaletteFade.active; } -static bool32 sub_80AF71C(void) +static bool32 WaitForWeatherFadeIn(void) { if (IsWeatherNotFadingIn() == TRUE) return TRUE; @@ -1007,7 +1007,7 @@ static void task0A_mpl_807E31C(u8 taskId) gTasks[taskId].data[0]++; break; case 1: - if (sub_80AF71C() && sub_808D1B4() != TRUE) + if (WaitForWeatherFadeIn() && sub_808D1B4() != TRUE) { UnfreezeEventObjects(); ScriptContext2_Disable(); diff --git a/src/field_specials.c b/src/field_specials.c index 436b06f53..2ae494dad 100644 --- a/src/field_specials.c +++ b/src/field_specials.c @@ -2610,7 +2610,7 @@ static void sub_813A4EC(u8 taskId) { case LIST_NOTHING_CHOSEN: break; - case LIST_B_PRESSED: + case LIST_CANCEL: gSpecialVar_Result = 0x7F; PlaySE(SE_SELECT); sub_813A570(taskId); @@ -2690,10 +2690,10 @@ static void sub_813A664(u8 taskId) static void sub_813A694(u8 taskId) { static const struct ScrollArrowsTemplate gUnknown_085B3030 = { - .firstArrowType = 2, + .firstArrowType = SCROLL_ARROW_UP, .firstX = 0, .firstY = 0, - .secondArrowType = 3, + .secondArrowType = SCROLL_ARROW_DOWN, .secondX = 0, .secondY = 0, .fullyUpThreshold = 0, diff --git a/src/item_menu.c b/src/item_menu.c index 5738757bd..81bc120a8 100755 --- a/src/item_menu.c +++ b/src/item_menu.c @@ -1107,7 +1107,7 @@ void Task_BagMenu(u8 taskId) { case LIST_NOTHING_CHOSEN: break; - case LIST_B_PRESSED: + case LIST_CANCEL: if (gUnknown_0203CE58.location == 5) { PlaySE(SE_HAZURE); @@ -1323,7 +1323,7 @@ void sub_81AC3C0(u8 taskId) { case LIST_NOTHING_CHOSEN: break; - case LIST_B_PRESSED: + case LIST_CANCEL: PlaySE(SE_SELECT); if (gMain.newKeys & A_BUTTON) sub_81AC498(taskId); diff --git a/src/learn_move.c b/src/learn_move.c deleted file mode 100644 index 879acff6d..000000000 --- a/src/learn_move.c +++ /dev/null @@ -1,833 +0,0 @@ -#include "global.h" -#include "main.h" -#include "battle.h" -#include "bg.h" -#include "contest_effect.h" -#include "data2.h" -#include "event_data.h" -#include "field_screen_effect.h" -#include "gpu_regs.h" -#include "learn_move.h" -#include "list_menu.h" -#include "alloc.h" -#include "menu.h" -#include "menu_helpers.h" -#include "overworld.h" -#include "palette.h" -#include "pokemon_summary_screen.h" -#include "pokenav.h" -#include "script.h" -#include "sound.h" -#include "sprite.h" -#include "string_util.h" -#include "strings.h" -#include "task.h" -#include "constants/rgb.h" -#include "constants/songs.h" - -static EWRAM_DATA struct -{ - u8 state; - u8 spriteIds[16]; /*0x001*/ - u16 movesToLearn[4]; /*0x012*/ - u8 filler1A[0x44 - 0x1A]; /*0x01A*/ - u8 partyMon; /*0x044*/ - u8 moveSlot; /*0x045*/ - struct ListMenuItem menuItems[20]; /*0x048*/ - u8 fillerE8[0x110 - 0xE8]; /*0x0E8*/ - u8 numMenuChoices; /*0x110*/ - u8 numToShowAtOnce; /*0x111*/ - u8 listMenuTask; /*0x112*/ - u8 scrollArrowTaskId1; /*0x113*/ - u8 scrollArrowTaskId2; /*0x114*/ - u16 scrollOffset; /*0x116*/ -} *sLearnMoveStruct = {0}; - -static EWRAM_DATA struct { - u16 listOffset; - u16 listRow; - u8 showContestInfo; -} sLearnMoveStruct2 = {0}; - -const u16 gUnknown_085CE9F8[] = INCBIN_U16("graphics/interface/ui_learn_move.gbapal"); -const u8 gUnknown_085CEA18[] = INCBIN_U8("graphics/interface/ui_learn_move.4bpp"); - -const struct OamData gUnknown_085CEB98 = -{ - .y = 0, - .affineMode = 0, - .objMode = ST_OAM_OBJ_NORMAL, - .mosaic = 0, - .bpp = ST_OAM_4BPP, - .shape = ST_OAM_SQUARE, - .x = 0, - .matrixNum = 0, - .size = 0, - .tileNum = 0, - .priority = 0, - .paletteNum = 0, - .affineParam = 0, -}; - -const struct OamData gUnknown_085CEBA0 = -{ - .y = 0, - .affineMode = 0, - .objMode = ST_OAM_OBJ_NORMAL, - .mosaic = 0, - .bpp = ST_OAM_4BPP, - .shape = ST_OAM_V_RECTANGLE, - .x = 0, - .matrixNum = 0, - .size = 0, - .tileNum = 0, - .priority = 0, - .paletteNum = 0, - .affineParam = 0, -}; - -const struct OamData gUnknown_085CEBA8 = -{ - .y = 0, - .affineMode = 0, - .objMode = ST_OAM_OBJ_NORMAL, - .mosaic = 0, - .bpp = ST_OAM_4BPP, - .shape = ST_OAM_H_RECTANGLE, - .x = 0, - .matrixNum = 0, - .size = 0, - .tileNum = 0, - .priority = 0, - .paletteNum = 0, - .affineParam = 0, -}; - -const struct SpriteSheet gUnknown_085CEBB0 = -{ - .data = gUnknown_085CEA18, - .size = 0x180, - .tag = 5525 -}; - -const struct SpritePalette gUnknown_085CEBB8 = -{ - .data = gUnknown_085CE9F8, - .tag = 5526 -}; - -const struct ScrollArrowsTemplate gUnknown_085CEBC0 = -{ - .firstArrowType = 0, - .firstX = 27, - .firstY = 16, - .secondArrowType = 1, - .secondX = 117, - .secondY = 16, - .fullyUpThreshold = -1, - .fullyDownThreshold = -1, - .tileTag = 5325, - .palTag = 5325, - .palNum = 0, -}; - -const struct ScrollArrowsTemplate gUnknown_085CEBD0 = -{ - .firstArrowType = 2, - .firstX = 192, - .firstY = 8, - .secondArrowType = 3, - .secondX = 192, - .secondY = 104, - .fullyUpThreshold = 0, - .fullyDownThreshold = 0, - .tileTag = 5425, - .palTag = 5425, - .palNum = 0, -}; - -const union AnimCmd gUnknown_085CEBE0[] = -{ - ANIMCMD_FRAME(8, 5, FALSE, FALSE), - ANIMCMD_END -}; - -const union AnimCmd gUnknown_085CEBE8[] = -{ - ANIMCMD_FRAME(9, 5, FALSE, FALSE), - ANIMCMD_END -}; - -const union AnimCmd gUnknown_085CEBF0[] = -{ - ANIMCMD_FRAME(10, 5, FALSE, FALSE), - ANIMCMD_END -}; - -const union AnimCmd gUnknown_085CEBF8[] = -{ - ANIMCMD_FRAME(11, 5, FALSE, FALSE), - ANIMCMD_END -}; - -const union AnimCmd *const gUnknown_085CEC00[] = -{ - gUnknown_085CEBE0, - gUnknown_085CEBE8, - gUnknown_085CEBF0, - gUnknown_085CEBF8, -}; - -const struct SpriteTemplate gUnknown_085CEC10 = -{ - .tileTag = 5525, - .paletteTag = 5526, - .oam = &gUnknown_085CEB98, - .anims = gUnknown_085CEC00, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = SpriteCallbackDummy -}; - -const struct BgTemplate gUnknown_085CEC28[] = -{ - { - .bg = 0, - .charBaseIndex = 0, - .mapBaseIndex = 31, - .screenSize = 0, - .paletteMode = 0, - .priority = 0, - .baseTile = 0, - }, - { - .bg = 1, - .charBaseIndex = 0, - .mapBaseIndex = 30, - .screenSize = 0, - .paletteMode = 0, - .priority = 1, - .baseTile = 0, - }, -}; - -static void LearnMoveMain(void); -static void CreateMenuItemsList(void); -static void CreateHearts(void); -static void CB2_Main(void); -static void Task_WaitForFadeOut(u8 taskId); -static void CB2_InitLearnMove(void); -static void CB2_InitLearnMoveReturnFromSelectMove(void); -static void InitBGs(void); -static void AddScrollArrows(void); -static void HandleInput(u8); -static void ShowTeachMoveText(u8); -static s32 GetCurrentItemId(void); -static void FreeListMenuResources(void); -static void RemoveScrollArrows(void); -static void HideSpritesAndPrintTeachText(bool8); - -static void VBlankCB_LearnMove(void) -{ - LoadOam(); - ProcessSpriteCopyRequests(); - TransferPlttBuffer(); -} - -void TeachMoveTutorMove(void) -{ - ScriptContext2_Enable(); - CreateTask(Task_WaitForFadeOut, 0xA); - BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 0x10, 0); -} - -static void Task_WaitForFadeOut(u8 taskId) -{ - if (!gPaletteFade.active) - { - SetMainCallback2(CB2_InitLearnMove); - gFieldCallback = sub_80AF168; - DestroyTask(taskId); - } -} - -static void CB2_InitLearnMove(void) -{ - ResetSpriteData(); - FreeAllSpritePalettes(); - ResetTasks(); - clear_scheduled_bg_copies_to_vram(); - sLearnMoveStruct = AllocZeroed(sizeof(*sLearnMoveStruct)); - sLearnMoveStruct->partyMon = gSpecialVar_0x8004; - SetVBlankCallback(VBlankCB_LearnMove); - - InitBGs(); - sub_81D2824(0); - - sLearnMoveStruct2.listOffset = 0; - sLearnMoveStruct2.listRow = 0; - sLearnMoveStruct2.showContestInfo = FALSE; - - CreateMenuItemsList(); - - LoadSpriteSheet(&gUnknown_085CEBB0); - LoadSpritePalette(&gUnknown_085CEBB8); - CreateHearts(); - - sLearnMoveStruct->listMenuTask = ListMenuInit(&gMultiuseListMenuTemplate, sLearnMoveStruct2.listOffset, sLearnMoveStruct2.listRow); - FillPalette(RGB_BLACK, 0, 2); - SetMainCallback2(CB2_Main); -} - -static void CB2_InitLearnMoveReturnFromSelectMove(void) -{ - ResetSpriteData(); - FreeAllSpritePalettes(); - ResetTasks(); - clear_scheduled_bg_copies_to_vram(); - sLearnMoveStruct = AllocZeroed(sizeof(*sLearnMoveStruct)); - sLearnMoveStruct->state = 28; - sLearnMoveStruct->partyMon = gSpecialVar_0x8004; - sLearnMoveStruct->moveSlot = gSpecialVar_0x8005; - SetVBlankCallback(VBlankCB_LearnMove); - - InitBGs(); - sub_81D2824(sLearnMoveStruct2.showContestInfo); - CreateMenuItemsList(); - - LoadSpriteSheet(&gUnknown_085CEBB0); - LoadSpritePalette(&gUnknown_085CEBB8); - CreateHearts(); - - sLearnMoveStruct->listMenuTask = ListMenuInit(&gMultiuseListMenuTemplate, sLearnMoveStruct2.listOffset, sLearnMoveStruct2.listRow); - FillPalette(RGB_BLACK, 0, 2); - SetMainCallback2(CB2_Main); -} - -static void InitBGs(void) -{ - ResetVramOamAndBgCntRegs(); - ResetBgsAndClearDma3BusyFlags(0); - InitBgsFromTemplates(0, gUnknown_085CEC28, 2); - ResetAllBgsCoordinates(); - SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_MODE_0 | - DISPCNT_OBJ_1D_MAP | - DISPCNT_OBJ_ON); - ShowBg(0); - ShowBg(1); - SetGpuReg(REG_OFFSET_BLDCNT, 0); -} - -static void CB2_Main(void) -{ - LearnMoveMain(); - RunTasks(); - AnimateSprites(); - BuildOamBuffer(); - do_scheduled_bg_tilemap_copies_to_vram(); - UpdatePaletteFade(); -} - -static void sub_816084C(const u8 *src) -{ - StringExpandPlaceholders(gStringVar4, src); - sub_81D2BF4(gStringVar4); -} - -static void LearnMoveMain(void) -{ - switch (sLearnMoveStruct->state) - { - case 0: - sLearnMoveStruct->state++; - HideSpritesAndPrintTeachText(FALSE); - BeginNormalPaletteFade(0xFFFFFFFF, 0, 16, 0, RGB_BLACK); - break; - case 1: - if (!gPaletteFade.active) - { - sLearnMoveStruct->state = 4; - } - break; - case 2: - sLearnMoveStruct->state++; - break; - case 3: - HideSpritesAndPrintTeachText(FALSE); - sLearnMoveStruct->state++; - AddScrollArrows(); - break; - case 4: - HandleInput(FALSE); - return; - case 5: - ShowTeachMoveText(FALSE); - sLearnMoveStruct->state++; - AddScrollArrows(); - break; - case 6: - HandleInput(TRUE); - break; - case 8: - if (!sub_81D2C3C()) - { - sub_81D2C50(); - sLearnMoveStruct->state++; - } - break; - case 9: - { - s8 selection = Menu_ProcessInputNoWrapClearOnChoose(); - - if (selection == 0) - { - if (GiveMoveToMon(&gPlayerParty[sLearnMoveStruct->partyMon], GetCurrentItemId()) != 0xFFFF) - { - sub_816084C(gText_PkmnLearnedMove4); - gSpecialVar_0x8004 = 1; - sLearnMoveStruct->state = 31; - } - else - { - sLearnMoveStruct->state = 16; - } - } - else if (selection == -1 || selection == 1) - { - if (sLearnMoveStruct2.showContestInfo == FALSE) - { - sLearnMoveStruct->state = 3; - } - else if (sLearnMoveStruct2.showContestInfo == TRUE) - { - sLearnMoveStruct->state = 5; - } - } - } - break; - case 12: - if (!sub_81D2C3C()) - { - sub_81D2C50(); - sLearnMoveStruct->state++; - } - break; - case 13: - { - s8 selection = Menu_ProcessInputNoWrapClearOnChoose(); - - if (selection == 0) - { - gSpecialVar_0x8004 = selection; - sLearnMoveStruct->state = 14; - } - else if (selection == -1 || selection == 1) - { - if (sLearnMoveStruct2.showContestInfo == FALSE) - { - sLearnMoveStruct->state = 3; - } - else if (sLearnMoveStruct2.showContestInfo == TRUE) - { - sLearnMoveStruct->state = 5; - } - } - } - break; - case 16: - sub_816084C(gText_PkmnTryingToLearnMove); - sLearnMoveStruct->state++; - break; - case 17: - if (!sub_81D2C3C()) - { - sub_81D2C50(); - sLearnMoveStruct->state = 18; - } - break; - case 18: - { - s8 var = Menu_ProcessInputNoWrapClearOnChoose(); - - if (var == 0) - { - sub_816084C(gText_WhichMoveToForget2); - sLearnMoveStruct->state = 19; - } - else if (var == -1 || var == 1) - { - sLearnMoveStruct->state = 24; - } - } - break; - case 24: - StringCopy(gStringVar2, gMoveNames[GetCurrentItemId()]); - sub_816084C(gText_StopTryingToTeachMove); - sLearnMoveStruct->state++; - break; - case 25: - if (!sub_81D2C3C()) - { - sub_81D2C50(); - sLearnMoveStruct->state++; - } - break; - case 26: - { - s8 var = Menu_ProcessInputNoWrapClearOnChoose(); - - if (var == 0) - { - sLearnMoveStruct->state = 27; - } - else if (var == -1 || var == 1) - { - // What's the point? It gets set to 16, anyway. - if (sLearnMoveStruct2.showContestInfo == FALSE) - { - sLearnMoveStruct->state = 3; - } - else if (sLearnMoveStruct2.showContestInfo == TRUE) - { - sLearnMoveStruct->state = 5; - } - sLearnMoveStruct->state = 16; - } - } - break; - case 27: - if (!sub_81D2C3C()) - { - FillWindowPixelBuffer(3, PIXEL_FILL(1)); - if (sLearnMoveStruct2.showContestInfo == FALSE) - { - sLearnMoveStruct->state = 3; - } - else if (sLearnMoveStruct2.showContestInfo == TRUE) - { - sLearnMoveStruct->state = 5; - } - } - break; - case 19: - if (!sub_81D2C3C()) - { - sLearnMoveStruct->state = 20; - BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, RGB_BLACK); - } - break; - case 20: - if (!gPaletteFade.active) - { - ShowSelectMovePokemonSummaryScreen(gPlayerParty, sLearnMoveStruct->partyMon, gPlayerPartyCount - 1, CB2_InitLearnMoveReturnFromSelectMove, GetCurrentItemId()); - FreeListMenuResources(); - } - break; - case 21: - if (!sub_81D2C3C()) - { - sLearnMoveStruct->state = 14; - } - break; - case 22: - BeginNormalPaletteFade(0xFFFFFFFF, 0, 16, 0, RGB_BLACK); - break; - case 14: - BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, RGB_BLACK); - sLearnMoveStruct->state++; - break; - case 15: - if (!gPaletteFade.active) - { - FreeListMenuResources(); - SetMainCallback2(CB2_ReturnToField); - } - break; - case 28: - BeginNormalPaletteFade(0xFFFFFFFF, 0, 16, 0, RGB_BLACK); - sLearnMoveStruct->state++; - if (sLearnMoveStruct2.showContestInfo == FALSE) - { - HideSpritesAndPrintTeachText(TRUE); - } - else if (sLearnMoveStruct2.showContestInfo == TRUE) - { - ShowTeachMoveText(TRUE); - } - RemoveScrollArrows(); - CopyWindowToVram(3, 2); - break; - case 29: - if (!gPaletteFade.active) - { - if (sLearnMoveStruct->moveSlot == MAX_MON_MOVES) - { - sLearnMoveStruct->state = 24; - } - else - { - u16 moveId = GetMonData(&gPlayerParty[sLearnMoveStruct->partyMon], MON_DATA_MOVE1 + sLearnMoveStruct->moveSlot); - - StringCopy(gStringVar3, gMoveNames[moveId]); - RemoveMonPPBonus(&gPlayerParty[sLearnMoveStruct->partyMon], sLearnMoveStruct->moveSlot); - SetMonMoveSlot(&gPlayerParty[sLearnMoveStruct->partyMon], GetCurrentItemId(), sLearnMoveStruct->moveSlot); - StringCopy(gStringVar2, gMoveNames[GetCurrentItemId()]); - sub_816084C(gText_12AndPoof); - sLearnMoveStruct->state = 30; - gSpecialVar_0x8004 = 1; - } - } - break; - case 30: - if (!sub_81D2C3C()) - { - sub_816084C(gText_PkmnForgotMoveAndLearnedNew); - sLearnMoveStruct->state = 31; - PlayFanfare(MUS_FANFA1); - } - break; - case 31: - if (!sub_81D2C3C()) - { - PlayFanfare(MUS_FANFA1); - sLearnMoveStruct->state = 32; - } - break; - case 32: - if (IsFanfareTaskInactive()) - { - sLearnMoveStruct->state = 33; - } - break; - case 33: - if (gMain.newKeys & A_BUTTON) - { - PlaySE(SE_SELECT); - sLearnMoveStruct->state = 14; - } - break; - } -} - -static void FreeListMenuResources(void) -{ - RemoveScrollArrows(); - DestroyListMenuTask(sLearnMoveStruct->listMenuTask, &sLearnMoveStruct2.listOffset, &sLearnMoveStruct2.listRow); - FreeAllWindowBuffers(); - FREE_AND_SET_NULL(sLearnMoveStruct); - ResetSpriteData(); - FreeAllSpritePalettes(); -} - -static void HideSpritesAndPrintTeachText(bool8 a) -{ - s32 i; - - for (i = 0; i < 16; i++) - { - gSprites[sLearnMoveStruct->spriteIds[i]].invisible = TRUE; - } - - if (!a) - { - StringExpandPlaceholders(gStringVar4, gText_TeachWhichMoveToPkmn); - FillWindowPixelBuffer(3, PIXEL_FILL(1)); - AddTextPrinterParameterized(3, 1, gStringVar4, 0, 1, 0, NULL); - } -} - -static void HandleInput(bool8 showContest) -{ - s32 itemId = ListMenu_ProcessInput(sLearnMoveStruct->listMenuTask); - ListMenuGetScrollAndRow(sLearnMoveStruct->listMenuTask, &sLearnMoveStruct2.listOffset, &sLearnMoveStruct2.listRow); - - switch (itemId) - { - case LIST_NOTHING_CHOSEN: - if (!(gMain.newKeys & (DPAD_LEFT | DPAD_RIGHT)) && !GetLRKeysState()) - { - break; - } - - PlaySE(SE_SELECT); - - if (showContest == FALSE) - { - PutWindowTilemap(1); - sLearnMoveStruct->state = 5; - sLearnMoveStruct2.showContestInfo = TRUE; - } - else - { - PutWindowTilemap(0); - sLearnMoveStruct->state = 3; - sLearnMoveStruct2.showContestInfo = FALSE; - } - - schedule_bg_copy_tilemap_to_vram(1); - ShowHideHearts(GetCurrentItemId()); - break; - case LIST_B_PRESSED: - PlaySE(SE_SELECT); - RemoveScrollArrows(); - sLearnMoveStruct->state = 12; - StringExpandPlaceholders(gStringVar4, gText_GiveUpTeachingNewMove); - sub_81D2BF4(gStringVar4); - break; - default: - PlaySE(SE_SELECT); - RemoveScrollArrows(); - sLearnMoveStruct->state = 8; - StringCopy(gStringVar2, gMoveNames[itemId]); - StringExpandPlaceholders(gStringVar4, gText_TeachX); - sub_81D2BF4(gStringVar4); - break; - } -} - -static s32 GetCurrentItemId(void) -{ - return sLearnMoveStruct->menuItems[sLearnMoveStruct2.listRow + sLearnMoveStruct2.listOffset].id; -} - -static void ShowTeachMoveText(bool8 showContest) -{ - if (showContest == FALSE) - { - StringExpandPlaceholders(gStringVar4, gText_TeachWhichMoveToPkmn); - FillWindowPixelBuffer(3, PIXEL_FILL(1)); - AddTextPrinterParameterized(3, 1, gStringVar4, 0, 1, 0, NULL); - } -} - -static void CreateHearts(void) -{ - int i; - - sLearnMoveStruct->scrollArrowTaskId2 = -1; - sLearnMoveStruct->scrollArrowTaskId1 = -1; - AddScrollArrows(); - - for (i = 0; i < 8; i++) - { - sLearnMoveStruct->spriteIds[i] = CreateSprite(&gUnknown_085CEC10, (i - (i / 4) * 4) * 8 + 104, (i / 4) * 8 + 36, 0); - } - - for (i = 0; i < 8; i++) - { - sLearnMoveStruct->spriteIds[i + 8] = CreateSprite(&gUnknown_085CEC10, (i - (i / 4) * 4) * 8 + 104, (i / 4) * 8 + 52, 0); - StartSpriteAnim(&gSprites[sLearnMoveStruct->spriteIds[i + 8]], 2); - } - - for (i = 0; i < 16; i++) - { - gSprites[sLearnMoveStruct->spriteIds[i]].invisible = TRUE; - } -} - -static void AddScrollArrows(void) -{ - if (sLearnMoveStruct->scrollArrowTaskId2 == 0xFF) - { - sLearnMoveStruct->scrollArrowTaskId2 = AddScrollIndicatorArrowPair(&gUnknown_085CEBC0, &sLearnMoveStruct->scrollOffset); - } - - if (sLearnMoveStruct->scrollArrowTaskId1 == 0xFF) - { - gTempScrollArrowTemplate = gUnknown_085CEBD0; - gTempScrollArrowTemplate.fullyDownThreshold = sLearnMoveStruct->numMenuChoices - sLearnMoveStruct->numToShowAtOnce; - sLearnMoveStruct->scrollArrowTaskId1 = AddScrollIndicatorArrowPair(&gTempScrollArrowTemplate, &sLearnMoveStruct2.listOffset); - } -} - -static void RemoveScrollArrows(void) -{ - if (sLearnMoveStruct->scrollArrowTaskId2 != 0xFF) - { - RemoveScrollIndicatorArrowPair(sLearnMoveStruct->scrollArrowTaskId2); - sLearnMoveStruct->scrollArrowTaskId2 = 0xFF; - } - - if (sLearnMoveStruct->scrollArrowTaskId1 != 0xFF) - { - RemoveScrollIndicatorArrowPair(sLearnMoveStruct->scrollArrowTaskId1); - sLearnMoveStruct->scrollArrowTaskId1 = 0xFF; - } -} - -static void CreateMenuItemsList(void) -{ - s32 i; - u8 nickname[POKEMON_NAME_LENGTH + 1]; - - sLearnMoveStruct->numMenuChoices = GetMoveRelearnerMoves(&gPlayerParty[sLearnMoveStruct->partyMon], sLearnMoveStruct->movesToLearn); - - for (i = 0; i < sLearnMoveStruct->numMenuChoices; i++) - { - sLearnMoveStruct->menuItems[i].name = gMoveNames[sLearnMoveStruct->movesToLearn[i]]; - sLearnMoveStruct->menuItems[i].id = sLearnMoveStruct->movesToLearn[i]; - } - - GetMonData(&gPlayerParty[sLearnMoveStruct->partyMon], MON_DATA_NICKNAME, nickname); - StringCopy10(gStringVar1, nickname); - sLearnMoveStruct->menuItems[sLearnMoveStruct->numMenuChoices].name = gText_Cancel; - sLearnMoveStruct->menuItems[sLearnMoveStruct->numMenuChoices].id = LIST_B_PRESSED; - sLearnMoveStruct->numMenuChoices++; - sLearnMoveStruct->numToShowAtOnce = sub_81D28C8(sLearnMoveStruct->menuItems, sLearnMoveStruct->numMenuChoices); -} - -void ShowHideHearts(s32 item) -{ - u16 numHearts; - u16 i; - - if (!sLearnMoveStruct2.showContestInfo || item == LIST_B_PRESSED) - { - for (i = 0; i < 16; i++) - { - gSprites[sLearnMoveStruct->spriteIds[i]].invisible = TRUE; - } - } - else - { - numHearts = (u8)(gContestEffects[gContestMoves[item].effect].appeal / 10); - - if (numHearts == 0xFF) - { - numHearts = 0; - } - - for (i = 0; i < 8; i++) - { - if (i < numHearts) - { - StartSpriteAnim(&gSprites[sLearnMoveStruct->spriteIds[i]], 1); - } - else - { - StartSpriteAnim(&gSprites[sLearnMoveStruct->spriteIds[i]], 0); - } - gSprites[sLearnMoveStruct->spriteIds[i]].invisible = FALSE; - } - - numHearts = (u8)(gContestEffects[gContestMoves[item].effect].jam / 10); - - if (numHearts == 0xFF) - { - numHearts = 0; - } - - for (i = 0; i < 8; i++) - { - if (i < numHearts) - { - StartSpriteAnim(&gSprites[sLearnMoveStruct->spriteIds[i + 8]], 3); - } - else - { - StartSpriteAnim(&gSprites[sLearnMoveStruct->spriteIds[i + 8]], 2); - } - gSprites[sLearnMoveStruct->spriteIds[i + 8]].invisible = FALSE; - } - } -} diff --git a/src/list_menu.c b/src/list_menu.c index a5786754c..57bcc5c4f 100644 --- a/src/list_menu.c +++ b/src/list_menu.c @@ -341,7 +341,7 @@ s32 DoMysteryGiftListMenu(struct WindowTemplate *windowTemplate, struct ListMenu } if (gMain.newKeys & B_BUTTON) { - sMysteryGiftLinkMenu.currItemId = LIST_B_PRESSED; + sMysteryGiftLinkMenu.currItemId = LIST_CANCEL; sMysteryGiftLinkMenu.state = 2; } if (sMysteryGiftLinkMenu.state == 2) @@ -416,7 +416,7 @@ s32 ListMenu_ProcessInput(u8 listTaskId) } else if (gMain.newKeys & B_BUTTON) { - return LIST_B_PRESSED; + return LIST_CANCEL; } else if (gMain.newAndRepeatedKeys & DPAD_UP) { diff --git a/src/menu_specialized.c b/src/menu_specialized.c new file mode 100644 index 000000000..8371c7a70 --- /dev/null +++ b/src/menu_specialized.c @@ -0,0 +1,2094 @@ +#include "global.h" +#include "alloc.h" +#include "battle_main.h" +#include "contest_effect.h" +#include "gpu_regs.h" +#include "menu.h" +#include "international_string_util.h" +#include "menu.h" +#include "menu_specialized.h" +#include "move_relearner.h" +#include "palette.h" +#include "player_pc.h" +#include "pokemon_summary_screen.h" +#include "scanline_effect.h" +#include "sound.h" +#include "strings.h" +#include "string_util.h" +#include "text_window.h" +#include "trig.h" +#include "window.h" +#include "constants/songs.h" +#include "gba/io_reg.h" + +EWRAM_DATA static u8 sUnknown_0203CF48[3] = {0}; +EWRAM_DATA static struct ListMenuItem *sUnknown_0203CF4C = NULL; + +static void sub_81D1E7C(s32 itemIndex, bool8 onInit, struct ListMenu *list); +static void sub_81D24A4(struct UnknownStruct_81D1ED4 *a0); +static void sub_81D2634(struct UnknownStruct_81D1ED4 *a0); +static void MoveRelearnerCursorCallback(s32 itemIndex, bool8 onInit, struct ListMenu *list); +static void nullsub_79(void); + +static const struct WindowTemplate sUnknown_086253E8[] = +{ + { + .bg = 0, + .tilemapLeft = 1, + .tilemapTop = 1, + .width = 8, + .height = 2, + .paletteNum = 0xF, + .baseBlock = 0x8 + }, + { + .bg = 0, + .tilemapLeft = 21, + .tilemapTop = 1, + .width = 8, + .height = 18, + .paletteNum = 0xF, + .baseBlock = 0x18 + }, + { + .bg = 0, + .tilemapLeft = 1, + .tilemapTop = 1, + .width = 11, + .height = 8, + .paletteNum = 0xF, + .baseBlock = 0x18 + } +}; + +static const u8 sUnknown_08625400[] = +{ + 1, 2, 3 +}; + +static const u8 sEmptyItemName[] = _(""); + +static const struct ScanlineEffectParams sUnknown_08625404 = +{ + .dmaDest = (void*)REG_ADDR_WIN0H, + .dmaControl = SCANLINE_EFFECT_DMACNT_32BIT, + .initState = 1, + .unused9 = 0 +}; + + +static const u8 sUnknown_08625410[] = +{ + 4, + 5, + 6, + 7, + 8, + 9, 9, + 10, 10, + 0xB, 0xB, + 0xC, 0xC, + 0xD, 0xD, + 0xD, 0xD, + 0xE, 0xE, 0xE, 0xE, + 0xF, 0xF, 0xF, 0xF, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, + 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, + 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, + 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, 0x1A, + 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, + 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, + 0x1D, 0x1D, 0x1D, 0x1D, 0x1D, 0x1D, 0x1D, 0x1D, 0x1D, 0x1D, 0x1D, 0x1D, 0x1D, 0x1D, 0x1D, 0x1D, + 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, + 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x23 +}; + + +static const struct WindowTemplate sMoveRelearnerWindowTemplates[] = +{ + { + .bg = 1, + .tilemapLeft = 1, + .tilemapTop = 1, + .width = 16, + .height = 12, + .paletteNum = 0xF, + .baseBlock = 0xA + }, + { + .bg = 1, + .tilemapLeft = 1, + .tilemapTop = 1, + .width = 16, + .height = 12, + .paletteNum = 0xF, + .baseBlock = 0xCA + }, + { + .bg = 1, + .tilemapLeft = 19, + .tilemapTop = 1, + .width = 10, + .height = 12, + .paletteNum = 0xF, + .baseBlock = 0x18A + }, + { + .bg = 1, + .tilemapLeft = 4, + .tilemapTop = 15, + .width = 22, + .height = 4, + .paletteNum = 0xF, + .baseBlock = 0x202 + }, + { + .bg = 0, + .tilemapLeft = 22, + .tilemapTop = 8, + .width = 5, + .height = 4, + .paletteNum = 0xF, + .baseBlock = 0x25A + }, + DUMMY_WIN_TEMPLATE +}; + +static const struct WindowTemplate sMoveRelearnerYesNoMenuTemplate = +{ + .bg = 0, + .tilemapLeft = 22, + .tilemapTop = 8, + .width = 5, + .height = 4, + .paletteNum = 0xF, + .baseBlock = 0x25A +}; + + +static const struct ListMenuTemplate sMoveRelearnerMovesListTemplate = +{ + .items = NULL, + .moveCursorFunc = MoveRelearnerCursorCallback, + .itemPrintFunc = NULL, + .totalItems = 0, + .maxShowed = 0, + .windowId = 2, + .header_X = 0, + .item_X = 8, + .cursor_X = 0, + .upText_Y = 1, + .cursorPal = 2, + .fillValue = 1, + .cursorShadowPal = 3, + .lettersSpacing = 0, + .itemVerticalPadding = 0, + .scrollMultiple = LIST_NO_MULTIPLE_SCROLL, + .fontId = 1, + .cursorKind = 0 +}; + +bool8 sub_81D1C44(u8 count) +{ + u32 i; + struct ListMenuItem **v1; + v1 = &sUnknown_0203CF4C; + *v1 = Alloc(count * sizeof(struct ListMenuItem) + sizeof(struct ListMenuItem)); + + if (sUnknown_0203CF4C == NULL) + return FALSE; + + for (i = 0; i < ARRAY_COUNT(sUnknown_0203CF48); i = (u8)(i + 1)) + { + sUnknown_0203CF48[i] |= 0xFF; + } + + return TRUE; +} + +u8 sub_81D1C84(u8 a0) +{ + struct WindowTemplate template; + + u8 windowId = sUnknown_0203CF48[a0]; + if (windowId == 0xFF) + { + if (a0 == 2) + { + u32 v1; + u32 v2; + s32 v3; + + template = sUnknown_086253E8[2]; + v3 = GetMaxWidthInMenuTable(&gMailboxMailOptions[0], 4); + template.width = v3; + sUnknown_0203CF48[2] = AddWindow(&template); + } + else + { + sUnknown_0203CF48[a0] = AddWindow(&sUnknown_086253E8[a0]); + } + SetStandardWindowBorderStyle(sUnknown_0203CF48[a0], 0); + } + return sUnknown_0203CF48[a0]; +} + +void sub_81D1D04(u8 a0) +{ + ClearStdWindowAndFrameToTransparent(sUnknown_0203CF48[a0], 0); + ClearWindowTilemap(sUnknown_0203CF48[a0]); + RemoveWindow(sUnknown_0203CF48[a0]); + sUnknown_0203CF48[a0] = 0xFF; +} + +static u8 sub_81D1D34(u8 a0) +{ + return sUnknown_0203CF48[a0]; +} + +static void sub_81D1D44(u8 windowId, s32 itemId, u8 y) +{ + u8 buffer[30]; + u16 length; + + if (itemId == LIST_CANCEL) + return; + + StringCopy(buffer, gSaveBlock1Ptr->mail[6 + itemId].playerName); + sub_81DB52C(buffer); + length = StringLength(buffer); + if (length <= 5) + ConvertInternationalString(buffer, LANGUAGE_JAPANESE); + AddTextPrinterParameterized4(windowId, 1, 8, y, 0, 0, sUnknown_08625400, -1, buffer); +} + +u8 sub_81D1DC0(struct PlayerPCItemPageStruct *page) +{ + u16 i; + for (i = 0; i < page->count; i++) + { + sUnknown_0203CF4C[i].name = sEmptyItemName; + sUnknown_0203CF4C[i].id = i; + } + + sUnknown_0203CF4C[i].name = gText_Cancel2; + sUnknown_0203CF4C[i].id = LIST_CANCEL; + + gMultiuseListMenuTemplate.items = sUnknown_0203CF4C; + gMultiuseListMenuTemplate.totalItems = page->count + 1; + gMultiuseListMenuTemplate.windowId = sUnknown_0203CF48[1]; + gMultiuseListMenuTemplate.header_X = 0; + gMultiuseListMenuTemplate.item_X = 8; + gMultiuseListMenuTemplate.cursor_X = 0; + gMultiuseListMenuTemplate.maxShowed = 8; + gMultiuseListMenuTemplate.upText_Y = 9; + gMultiuseListMenuTemplate.cursorPal = 2; + gMultiuseListMenuTemplate.fillValue = 1; + gMultiuseListMenuTemplate.cursorShadowPal = 3; + gMultiuseListMenuTemplate.moveCursorFunc = sub_81D1E7C; + gMultiuseListMenuTemplate.itemPrintFunc = sub_81D1D44; + gMultiuseListMenuTemplate.fontId = 1; + gMultiuseListMenuTemplate.cursorKind = 0; + gMultiuseListMenuTemplate.lettersSpacing = 0; + gMultiuseListMenuTemplate.itemVerticalPadding = 0; + gMultiuseListMenuTemplate.scrollMultiple = LIST_NO_MULTIPLE_SCROLL; + return ListMenuInit(&gMultiuseListMenuTemplate, page->itemsAbove, page->cursorPos); +} + +static void sub_81D1E7C(s32 itemIndex, bool8 onInit, struct ListMenu *list) +{ + if (onInit != TRUE) + PlaySE(SE_SELECT); +} + +void sub_81D1E90(struct PlayerPCItemPageStruct *page) +{ + page->scrollIndicatorId = AddScrollIndicatorArrowPairParameterized(2, 0xC8, 12, 0x94, page->count - page->pageItems + 1, 0x6E, 0x6E, &page->itemsAbove); +} + +void sub_81D1EC0(void) +{ + Free(sUnknown_0203CF4C); +} + +void sub_81D1ED4(struct UnknownStruct_81D1ED4 *a0) +{ + u8 j; + u8 i; + for (j = 0; j < 5; j++) + { + for (i = 0; i < 10; i++) + { + a0->unk64[i][j].unk0 = 0; + a0->unk64[i][j].unk2 = 0; + } + for (i = 0; i < 4; i++) + { + a0->unk0[i][j] = 0; + a0->unk14[i][j].unk0 = 0x9B; + a0->unk14[i][j].unk2 = 0x5B; + } + + a0->unk12C[j].unk0 = 0; + a0->unk12C[j].unk2 = 0; + } + + a0->unk354 = 0; + a0->unk352 = 0; +} + +NAKED +void sub_81D1F84(struct UnknownStruct_81D1ED4 *arg0, struct UnknownSubStruct_81D1ED4 arg1[4][5], struct UnknownSubStruct_81D1ED4 arg2[4][5]) +{ + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + mov r7, r10\n\ + mov r6, r9\n\ + mov r5, r8\n\ + push {r5-r7}\n\ + sub sp, 0x8\n\ + mov r8, r0\n\ + str r1, [sp]\n\ + mov r9, r2\n\ + movs r7, 0\n\ +_081D1F98:\n\ + lsls r4, r7, 2\n\ + ldr r1, [sp]\n\ + adds r0, r4, r1\n\ + ldrh r1, [r0]\n\ + lsls r5, r1, 8\n\ + mov r2, r9\n\ + adds r0, r4, r2\n\ + ldrh r0, [r0]\n\ + subs r0, r1\n\ + lsls r0, 8\n\ + movs r1, 0xA\n\ + bl __divsi3\n\ + adds r6, r0, 0\n\ + movs r3, 0\n\ + adds r7, 0x1\n\ + mov r10, r7\n\ + mov r12, r4\n\ +_081D1FBC:\n\ + lsls r0, r3, 2\n\ + adds r0, r3\n\ + lsls r0, 2\n\ + add r0, r12\n\ + add r0, r8\n\ + asrs r2, r5, 8\n\ + asrs r1, r5, 7\n\ + movs r7, 0x1\n\ + ands r1, r7\n\ + adds r2, r1\n\ + adds r0, 0x64\n\ + strh r2, [r0]\n\ + adds r5, r6\n\ + adds r0, r3, 0x1\n\ + lsls r0, 16\n\ + lsrs r3, r0, 16\n\ + cmp r3, 0x8\n\ + bls _081D1FBC\n\ + lsls r0, r3, 2\n\ + adds r0, r3\n\ + lsls r0, 2\n\ + adds r0, r4, r0\n\ + add r0, r8\n\ + mov r1, r9\n\ + adds r2, r4, r1\n\ + ldrh r1, [r2]\n\ + adds r0, 0x64\n\ + strh r1, [r0]\n\ + ldr r7, [sp]\n\ + adds r0, r4, r7\n\ + ldrh r1, [r0, 0x2]\n\ + lsls r5, r1, 8\n\ + ldrh r0, [r2, 0x2]\n\ + subs r0, r1\n\ + lsls r0, 8\n\ + movs r1, 0xA\n\ + bl __divsi3\n\ + adds r6, r0, 0\n\ + movs r3, 0\n\ + str r4, [sp, 0x4]\n\ + movs r0, 0x1\n\ + mov r12, r0\n\ +_081D2012:\n\ + lsls r0, r3, 2\n\ + adds r0, r3\n\ + lsls r0, 2\n\ + ldr r1, [sp, 0x4]\n\ + adds r0, r1, r0\n\ + add r0, r8\n\ + asrs r2, r5, 8\n\ + asrs r1, r5, 7\n\ + mov r7, r12\n\ + ands r1, r7\n\ + adds r2, r1\n\ + adds r0, 0x66\n\ + strh r2, [r0]\n\ + adds r5, r6\n\ + adds r0, r3, 0x1\n\ + lsls r0, 16\n\ + lsrs r3, r0, 16\n\ + cmp r3, 0x8\n\ + bls _081D2012\n\ + lsls r0, r3, 2\n\ + adds r0, r3\n\ + lsls r0, 2\n\ + adds r0, r4, r0\n\ + add r0, r8\n\ + mov r2, r9\n\ + adds r1, r4, r2\n\ + ldrh r1, [r1, 0x2]\n\ + adds r0, 0x66\n\ + strh r1, [r0]\n\ + mov r7, r10\n\ + lsls r0, r7, 16\n\ + lsrs r7, r0, 16\n\ + cmp r7, 0x4\n\ + bls _081D1F98\n\ + ldr r1, =0x00000352\n\ + add r1, r8\n\ + movs r0, 0\n\ + strh r0, [r1]\n\ + add sp, 0x8\n\ + pop {r3-r5}\n\ + mov r8, r3\n\ + mov r9, r4\n\ + mov r10, r5\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .pool\n\ + .syntax divided"); +} + +bool32 sub_81D2074(struct UnknownStruct_81D1ED4 *a0) +{ + if (a0->unk352 < 10) + { + sub_81D2230(a0); + return ++a0->unk352 != 10; + } + else + { + return FALSE; + } + +} + +void sub_81D20AC(struct UnknownStruct_81D1ED4 *a0) +{ + a0->unk355 = 0; +} + +bool8 sub_81D20BC(struct UnknownStruct_81D1ED4 *arg0) +{ + struct ScanlineEffectParams params; + switch (arg0->unk355) + { + case 0: + ScanlineEffect_Clear(); + arg0->unk355++; + return TRUE; + case 1: + params = sUnknown_08625404; + ScanlineEffect_SetParams(params); + arg0->unk355++; + return FALSE; + default: + return FALSE; + } +} + +NAKED +void sub_81D2108(struct UnknownStruct_81D1ED4 *arg0) +{ + // Three of the additions are in the wrong order. +#ifdef NONMATCHING + u16 i; + u32 v3; + u32 v4; + u16 *scanBuffer1; + u16 *scanBuffer2; + u32 scanBufferWidth; + u32 mask; + u16 *unkBuff1; + u16 *unkBuff2; + u16 *unkBuff3; + u16 *unkBuff4; + + if (arg0->unk354 == 0) + return; + + sub_81D24A4(arg0); + sub_81D2634(arg0); + + i = 0; + scanBuffer1 = gScanlineEffectRegBuffers[0]; + scanBufferWidth = ARRAY_COUNT(gScanlineEffectRegBuffers[0]); + scanBuffer2 = scanBuffer1 + scanBufferWidth; + + // This function accesses the arrays "manually", where every other entry + // is just handled differently, rather than a pairwise struct. + unkBuff1 = (u16*)&arg0->unk13C[0].unk0; + mask = 0xFFFF; + unkBuff2 = (u16*)&arg0->unk13C[0].unk2; + unkBuff3 = (u16*)&arg0->unk248[0].unk0; + unkBuff4 = (u16*)&arg0->unk248[0].unk2; + + for (; i < 0x42; i++) + { + u32 offset1; + register u32 offset2 asm("r2"); + u32 offset3; + + offset1 = (i + 0x37) * 2; + offset2 = i + 0x37; + scanBuffer2[offset1] = (scanBuffer1[offset1] = (unkBuff1[i * 2] << 8) | unkBuff2[i * 2]) & mask; + + offset3 = offset2 * 2 + 1; + scanBuffer2[offset3] = (scanBuffer1[offset3] = (unkBuff3[i * 2] << 8) | unkBuff4[i * 2]) & mask; + } + + arg0->unk354 = 0; +#else + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + mov r7, r10\n\ + mov r6, r9\n\ + mov r5, r8\n\ + push {r5-r7}\n\ + sub sp, 0x10\n\ + adds r6, r0, 0\n\ + movs r1, 0xD5\n\ + lsls r1, 2\n\ + adds r0, r6, r1\n\ + ldrb r0, [r0]\n\ + cmp r0, 0\n\ + beq _081D21BE\n\ + adds r0, r6, 0\n\ + bl sub_81D24A4\n\ + adds r0, r6, 0\n\ + bl sub_81D2634\n\ + movs r7, 0\n\ + ldr r5, =gScanlineEffectRegBuffers\n\ + mov r12, r5\n\ + movs r0, 0xF0\n\ + lsls r0, 3\n\ + add r0, r12\n\ + mov r9, r0\n\ + movs r1, 0xA0\n\ + lsls r1, 1\n\ + adds r1, r6, r1\n\ + str r1, [sp]\n\ + ldr r5, =0x0000ffff\n\ + mov r8, r5\n\ + movs r0, 0xA1\n\ + lsls r0, 1\n\ + adds r0, r6, r0\n\ + str r0, [sp, 0x4]\n\ + movs r1, 0x92\n\ + lsls r1, 2\n\ + adds r1, r6, r1\n\ + str r1, [sp, 0x8]\n\ + ldr r5, =0x0000024a\n\ + adds r5, r6\n\ + mov r10, r5\n\ +_081D215E:\n\ + adds r2, r7, 0\n\ + adds r2, 0x37\n\ + lsls r3, r2, 2\n\ + mov r0, r9\n\ + adds r0, r3, r0\n\ + str r0, [sp, 0xC]\n\ + add r3, r12\n\ + lsls r4, r7, 2\n\ + ldr r1, [sp]\n\ + adds r0, r1, r4\n\ + ldrh r0, [r0]\n\ + lsls r0, 8\n\ + ldr r5, [sp, 0x4]\n\ + adds r1, r5, r4\n\ + ldrh r1, [r1]\n\ + orrs r0, r1\n\ + strh r0, [r3]\n\ + mov r1, r8\n\ + ands r0, r1\n\ + ldr r5, [sp, 0xC]\n\ + strh r0, [r5]\n\ + lsls r2, 1\n\ + adds r2, 0x1\n\ + lsls r2, 1\n\ + mov r0, r9\n\ + adds r3, r2, r0\n\ + add r2, r12\n\ + ldr r1, [sp, 0x8]\n\ + adds r0, r1, r4\n\ + ldrh r0, [r0]\n\ + lsls r0, 8\n\ + add r4, r10\n\ + ldrh r1, [r4]\n\ + orrs r0, r1\n\ + strh r0, [r2]\n\ + mov r5, r8\n\ + ands r0, r5\n\ + strh r0, [r3]\n\ + adds r0, r7, 0x1\n\ + lsls r0, 16\n\ + lsrs r7, r0, 16\n\ + cmp r7, 0x41\n\ + bls _081D215E\n\ + movs r0, 0xD5\n\ + lsls r0, 2\n\ + adds r1, r6, r0\n\ + movs r0, 0\n\ + strb r0, [r1]\n\ +_081D21BE:\n\ + add sp, 0x10\n\ + pop {r3-r5}\n\ + mov r8, r3\n\ + mov r9, r4\n\ + mov r10, r5\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .pool\n\ + .syntax divided"); +#endif +} + +void sub_81D21DC(u8 bg) +{ + u8 flags; + + if (bg > 3) + bg = 0; + + // Unset the WINOUT flag for the bg. + flags = (WINOUT_WIN01_BG_ALL | WINOUT_WIN01_OBJ) & ~(1 << bg); + + SetGpuReg(REG_OFFSET_WIN0H, WIN_RANGE(0, 0xF0)); + SetGpuReg(REG_OFFSET_WIN1H, WIN_RANGE(0, 0x9B)); + SetGpuReg(REG_OFFSET_WIN0V, WIN_RANGE(0x38, 0x79)); + SetGpuReg(REG_OFFSET_WIN1V, WIN_RANGE(0x38, 0x79)); + SetGpuReg(REG_OFFSET_WININ, WININ_WIN0_BG_ALL | WININ_WIN0_OBJ | WININ_WIN0_CLR | WININ_WIN1_BG_ALL | WININ_WIN1_OBJ | WININ_WIN1_CLR); + SetGpuReg(REG_OFFSET_WINOUT, flags); +} + +void sub_81D2230(struct UnknownStruct_81D1ED4 *arg0) +{ + u16 i; + for (i = 0; i < 5; i++) + { + arg0->unk12C[i] = arg0->unk64[arg0->unk352][i]; + } + arg0->unk354 = 1; +} + +NAKED +static void sub_81D2278(void *a0, void *a1, u16 *a2, u16 *a3, u8 a38, u32 a3C) +{ +#ifdef NONMATCHING + // a0 => sp0 + // a1 => r6 + // a2 => r5 + // a3 => sp4 + // a38 => r9 + // a3C => r7 + u32 v1; // r10 + u32 v2; // sp8 + u32 v3; // spC + u32 v4; + u32 v5; + u16 v6; // r8 + u32 v7; + u32 v8; // sp10 + + v3 = 0; + + // v4 => r4 + // v5 => r0 + // v7 => r1 + if (a2[1] < a3[1]) + { + v1 = a2[1]; + v5 = a3[1]; + v7 = a2[0]; + v4 = v7 << 10; + v2 = a3[0]; + } + else + { + v5 = a2[1]; + v1 = a3[1]; + v7 = a3[0]; + v4 = v7 << 10; + v2 = a2[0]; + } + + v6 = v5 - v1; + if (v6 != 0) + { + v3 = (v2 - v7) / v6; + } + v6++; + + if (a3C == 0) + { + v8 = + } +#else + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + mov r7, r10\n\ + mov r6, r9\n\ + mov r5, r8\n\ + push {r5-r7}\n\ + sub sp, 0x18\n\ + str r0, [sp]\n\ + adds r6, r1, 0\n\ + adds r5, r2, 0\n\ + str r3, [sp, 0x4]\n\ + ldr r0, [sp, 0x38]\n\ + ldr r7, [sp, 0x3C]\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + mov r9, r0\n\ + movs r0, 0\n\ + str r0, [sp, 0xC]\n\ + ldrh r0, [r5, 0x2]\n\ + ldrh r1, [r3, 0x2]\n\ + cmp r0, r1\n\ + bcs _081D22B2\n\ + adds r2, r0, 0\n\ + mov r10, r2\n\ + ldrh r0, [r3, 0x2]\n\ + ldrh r1, [r5]\n\ + lsls r4, r1, 10\n\ + ldrh r3, [r3]\n\ + str r3, [sp, 0x8]\n\ + b _081D22C6\n\ +_081D22B2:\n\ + ldrh r0, [r5, 0x2]\n\ + ldr r1, [sp, 0x4]\n\ + ldrh r1, [r1, 0x2]\n\ + mov r10, r1\n\ + ldr r2, [sp, 0x4]\n\ + ldrh r1, [r2]\n\ + lsls r4, r1, 10\n\ + ldrh r3, [r5]\n\ + str r3, [sp, 0x8]\n\ + mov r2, r10\n\ +_081D22C6:\n\ + subs r0, r2\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + mov r8, r0\n\ + cmp r0, 0\n\ + beq _081D22DE\n\ + subs r0, r3, r1\n\ + lsls r0, 10\n\ + mov r1, r8\n\ + bl __divsi3\n\ + str r0, [sp, 0xC]\n\ +_081D22DE:\n\ + mov r0, r8\n\ + adds r0, 0x1\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + mov r8, r0\n\ + cmp r7, 0\n\ + bne _081D2328\n\ + mov r0, r10\n\ + subs r0, 0x38\n\ + lsls r0, 2\n\ + adds r6, r0\n\ + movs r5, 0\n\ + mov r3, r9\n\ + lsls r3, 1\n\ + mov r12, r3\n\ + ldr r0, [sp, 0x8]\n\ + add r0, r9\n\ + str r0, [sp, 0x10]\n\ + cmp r7, r8\n\ + bcs _081D23B6\n\ + movs r7, 0x1\n\ +_081D2308:\n\ + adds r2, r3, r6\n\ + asrs r1, r4, 10\n\ + asrs r0, r4, 9\n\ + ands r0, r7\n\ + adds r1, r0\n\ + add r1, r9\n\ + strh r1, [r2]\n\ + ldr r1, [sp, 0xC]\n\ + adds r4, r1\n\ + adds r6, 0x4\n\ + adds r0, r5, 0x1\n\ + lsls r0, 16\n\ + lsrs r5, r0, 16\n\ + cmp r5, r8\n\ + bcc _081D2308\n\ + b _081D23B6\n\ +_081D2328:\n\ + ldr r2, [sp, 0xC]\n\ + cmp r2, 0\n\ + ble _081D23C0\n\ + mov r0, r10\n\ + subs r0, 0x38\n\ + lsls r0, 2\n\ + adds r7, r0\n\ + movs r5, 0\n\ + mov r3, r9\n\ + lsls r3, 1\n\ + mov r12, r3\n\ + ldr r0, [sp, 0x8]\n\ + add r0, r9\n\ + str r0, [sp, 0x10]\n\ + cmp r5, r8\n\ + bcs _081D237A\n\ + ldr r0, =0x00026bff\n\ + cmp r4, r0\n\ + bgt _081D237A\n\ + mov r1, r12\n\ + str r1, [sp, 0x14]\n\ +_081D2352:\n\ + ldr r3, [sp, 0x14]\n\ + adds r2, r3, r7\n\ + asrs r1, r4, 10\n\ + asrs r0, r4, 9\n\ + movs r3, 0x1\n\ + ands r0, r3\n\ + adds r1, r0\n\ + add r1, r9\n\ + strh r1, [r2]\n\ + ldr r0, [sp, 0xC]\n\ + adds r4, r0\n\ + adds r7, 0x4\n\ + adds r0, r5, 0x1\n\ + lsls r0, 16\n\ + lsrs r5, r0, 16\n\ + cmp r5, r8\n\ + bcs _081D237A\n\ + ldr r1, =0x00026bff\n\ + cmp r4, r1\n\ + ble _081D2352\n\ +_081D237A:\n\ + mov r2, r10\n\ + adds r1, r2, r5\n\ + ldr r3, [sp]\n\ + movs r2, 0xD4\n\ + lsls r2, 2\n\ + adds r0, r3, r2\n\ + strh r1, [r0]\n\ + ldrh r0, [r0]\n\ + subs r0, 0x38\n\ + lsls r0, 2\n\ + adds r6, r0\n\ + cmp r5, r8\n\ + bcs _081D23B6\n\ + mov r3, r12\n\ + movs r7, 0x1\n\ +_081D2398:\n\ + adds r2, r3, r6\n\ + asrs r1, r4, 10\n\ + asrs r0, r4, 9\n\ + ands r0, r7\n\ + adds r1, r0\n\ + add r1, r9\n\ + strh r1, [r2]\n\ + ldr r0, [sp, 0xC]\n\ + adds r4, r0\n\ + adds r6, 0x4\n\ + adds r0, r5, 0x1\n\ + lsls r0, 16\n\ + lsrs r5, r0, 16\n\ + cmp r5, r8\n\ + bcc _081D2398\n\ +_081D23B6:\n\ + subs r0, r6, 0x4\n\ + b _081D248C\n\ + .pool\n\ +_081D23C0:\n\ + ldr r1, [sp, 0xC]\n\ + cmp r1, 0\n\ + bge _081D2464\n\ + mov r0, r10\n\ + subs r0, 0x38\n\ + lsls r0, 2\n\ + adds r6, r0\n\ + movs r5, 0\n\ + mov r2, r9\n\ + lsls r2, 1\n\ + mov r12, r2\n\ + ldr r3, [sp, 0x8]\n\ + add r3, r9\n\ + str r3, [sp, 0x10]\n\ + cmp r5, r8\n\ + bcs _081D241E\n\ + adds r3, r2, r6\n\ + asrs r1, r4, 10\n\ + asrs r0, r4, 9\n\ + movs r2, 0x1\n\ + ands r0, r2\n\ + adds r1, r0\n\ + add r1, r9\n\ + strh r1, [r3]\n\ + b _081D2414\n\ +_081D23F2:\n\ + ldr r0, [sp, 0xC]\n\ + adds r4, r0\n\ + adds r6, 0x4\n\ + adds r0, r5, 0x1\n\ + lsls r0, 16\n\ + lsrs r5, r0, 16\n\ + cmp r5, r8\n\ + bcs _081D241E\n\ + mov r1, r12\n\ + adds r3, r1, r6\n\ + asrs r2, r4, 10\n\ + asrs r0, r4, 9\n\ + movs r1, 0x1\n\ + ands r0, r1\n\ + adds r2, r0\n\ + add r2, r9\n\ + strh r2, [r3]\n\ +_081D2414:\n\ + ldr r0, =0x00026bff\n\ + cmp r4, r0\n\ + bgt _081D23F2\n\ + movs r0, 0x9B\n\ + strh r0, [r3]\n\ +_081D241E:\n\ + mov r2, r10\n\ + adds r1, r2, r5\n\ + ldr r3, [sp]\n\ + movs r2, 0xD4\n\ + lsls r2, 2\n\ + adds r0, r3, r2\n\ + strh r1, [r0]\n\ + ldrh r0, [r0]\n\ + subs r0, 0x38\n\ + lsls r0, 2\n\ + adds r7, r0\n\ + cmp r5, r8\n\ + bcs _081D245A\n\ + mov r3, r12\n\ + movs r6, 0x1\n\ +_081D243C:\n\ + adds r2, r3, r7\n\ + asrs r1, r4, 10\n\ + asrs r0, r4, 9\n\ + ands r0, r6\n\ + adds r1, r0\n\ + add r1, r9\n\ + strh r1, [r2]\n\ + ldr r0, [sp, 0xC]\n\ + adds r4, r0\n\ + adds r7, 0x4\n\ + adds r0, r5, 0x1\n\ + lsls r0, 16\n\ + lsrs r5, r0, 16\n\ + cmp r5, r8\n\ + bcc _081D243C\n\ +_081D245A:\n\ + subs r0, r7, 0x4\n\ + b _081D248C\n\ + .pool\n\ +_081D2464:\n\ + ldr r1, [sp]\n\ + movs r2, 0xD4\n\ + lsls r2, 2\n\ + adds r0, r1, r2\n\ + mov r3, r10\n\ + strh r3, [r0]\n\ + mov r0, r10\n\ + subs r0, 0x38\n\ + lsls r0, 2\n\ + adds r6, r0\n\ + adds r7, r0\n\ + ldrh r0, [r5]\n\ + adds r0, 0x1\n\ + strh r0, [r6, 0x2]\n\ + ldr r1, [sp, 0x4]\n\ + ldrh r0, [r1]\n\ + strh r0, [r7]\n\ + movs r0, 0x9B\n\ + strh r0, [r7, 0x2]\n\ + b _081D2494\n\ +_081D248C:\n\ + add r0, r12\n\ + mov r2, sp\n\ + ldrh r2, [r2, 0x10]\n\ + strh r2, [r0]\n\ +_081D2494:\n\ + add sp, 0x18\n\ + pop {r3-r5}\n\ + mov r8, r3\n\ + mov r9, r4\n\ + mov r10, r5\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .syntax divided"); +#endif +} + +NAKED +static void sub_81D24A4(struct UnknownStruct_81D1ED4 *a0) +{ + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + sub sp, 0x8\n\ + adds r4, r0, 0\n\ + movs r0, 0x97\n\ + lsls r0, 1\n\ + adds r2, r4, r0\n\ + movs r3, 0x99\n\ + lsls r3, 1\n\ + adds r1, r4, r3\n\ + ldrh r0, [r2]\n\ + ldrh r3, [r1]\n\ + cmp r0, r3\n\ + bcs _081D24E0\n\ + adds r7, r0, 0\n\ + movs r0, 0xA0\n\ + lsls r0, 1\n\ + adds r1, r4, r0\n\ + movs r3, 0x96\n\ + lsls r3, 1\n\ + adds r2, r4, r3\n\ + subs r0, 0x10\n\ + adds r3, r4, r0\n\ + movs r0, 0x1\n\ + str r0, [sp]\n\ + movs r0, 0\n\ + str r0, [sp, 0x4]\n\ + adds r0, r4, 0\n\ + bl sub_81D2278\n\ + b _081D2500\n\ +_081D24E0:\n\ + ldrh r7, [r1]\n\ + movs r2, 0xA0\n\ + lsls r2, 1\n\ + adds r1, r4, r2\n\ + movs r3, 0x98\n\ + lsls r3, 1\n\ + adds r2, r4, r3\n\ + movs r0, 0x96\n\ + lsls r0, 1\n\ + adds r3, r4, r0\n\ + movs r0, 0\n\ + str r0, [sp]\n\ + str r0, [sp, 0x4]\n\ + adds r0, r4, 0\n\ + bl sub_81D2278\n\ +_081D2500:\n\ + movs r1, 0xA0\n\ + lsls r1, 1\n\ + adds r5, r4, r1\n\ + movs r3, 0x98\n\ + lsls r3, 1\n\ + adds r2, r4, r3\n\ + movs r0, 0x9A\n\ + lsls r0, 1\n\ + adds r6, r4, r0\n\ + movs r0, 0x1\n\ + str r0, [sp]\n\ + movs r0, 0\n\ + str r0, [sp, 0x4]\n\ + adds r0, r4, 0\n\ + adds r1, r5, 0\n\ + adds r3, r6, 0\n\ + bl sub_81D2278\n\ + movs r2, 0\n\ + movs r1, 0x9B\n\ + lsls r1, 1\n\ + adds r0, r4, r1\n\ + movs r3, 0x9D\n\ + lsls r3, 1\n\ + adds r1, r4, r3\n\ + ldrh r0, [r0]\n\ + ldrh r1, [r1]\n\ + cmp r0, r1\n\ + bhi _081D253C\n\ + movs r2, 0x1\n\ +_081D253C:\n\ + movs r0, 0x9C\n\ + lsls r0, 1\n\ + adds r3, r4, r0\n\ + str r2, [sp]\n\ + movs r1, 0x92\n\ + lsls r1, 2\n\ + adds r0, r4, r1\n\ + str r0, [sp, 0x4]\n\ + adds r0, r4, 0\n\ + adds r1, r5, 0\n\ + adds r2, r6, 0\n\ + bl sub_81D2278\n\ + movs r2, 0x38\n\ + cmp r2, r7\n\ + bcs _081D257E\n\ + adds r6, r5, 0\n\ + movs r3, 0\n\ + movs r0, 0xA1\n\ + lsls r0, 1\n\ + adds r5, r4, r0\n\ +_081D2566:\n\ + adds r0, r2, 0\n\ + subs r0, 0x38\n\ + lsls r0, 2\n\ + adds r1, r6, r0\n\ + strh r3, [r1]\n\ + adds r0, r5, r0\n\ + strh r3, [r0]\n\ + adds r0, r2, 0x1\n\ + lsls r0, 16\n\ + lsrs r2, r0, 16\n\ + cmp r2, r7\n\ + bcc _081D2566\n\ +_081D257E:\n\ + movs r1, 0x97\n\ + lsls r1, 1\n\ + adds r0, r4, r1\n\ + ldrh r2, [r0]\n\ + movs r3, 0xD4\n\ + lsls r3, 2\n\ + adds r0, r4, r3\n\ + ldrh r1, [r0]\n\ + cmp r2, r1\n\ + bhi _081D25B2\n\ + movs r1, 0xA0\n\ + lsls r1, 1\n\ + adds r3, r4, r1\n\ + movs r5, 0x9B\n\ + adds r1, r0, 0\n\ +_081D259C:\n\ + adds r0, r2, 0\n\ + subs r0, 0x38\n\ + lsls r0, 2\n\ + adds r0, r3, r0\n\ + strh r5, [r0]\n\ + adds r0, r2, 0x1\n\ + lsls r0, 16\n\ + lsrs r2, r0, 16\n\ + ldrh r0, [r1]\n\ + cmp r2, r0\n\ + bls _081D259C\n\ +_081D25B2:\n\ + movs r2, 0x9B\n\ + lsls r2, 1\n\ + adds r1, r4, r2\n\ + movs r3, 0xD4\n\ + lsls r3, 2\n\ + adds r0, r4, r3\n\ + ldrh r0, [r0]\n\ + ldrh r1, [r1]\n\ + cmp r0, r1\n\ + bcs _081D25C8\n\ + adds r0, r1, 0\n\ +_081D25C8:\n\ + adds r0, 0x1\n\ + lsls r0, 16\n\ + lsrs r2, r0, 16\n\ + cmp r2, 0x79\n\ + bhi _081D25F8\n\ + movs r0, 0xA0\n\ + lsls r0, 1\n\ + adds r6, r4, r0\n\ + movs r3, 0\n\ + movs r1, 0xA1\n\ + lsls r1, 1\n\ + adds r5, r4, r1\n\ +_081D25E0:\n\ + adds r0, r2, 0\n\ + subs r0, 0x38\n\ + lsls r0, 2\n\ + adds r1, r6, r0\n\ + strh r3, [r1]\n\ + adds r0, r5, r0\n\ + strh r3, [r0]\n\ + adds r0, r2, 0x1\n\ + lsls r0, 16\n\ + lsrs r2, r0, 16\n\ + cmp r2, 0x79\n\ + bls _081D25E0\n\ +_081D25F8:\n\ + movs r2, 0x38\n\ + movs r3, 0xA0\n\ + lsls r3, 1\n\ + adds r5, r4, r3\n\ + movs r0, 0xA1\n\ + lsls r0, 1\n\ + adds r4, r0\n\ + movs r6, 0x9B\n\ +_081D2608:\n\ + adds r0, r2, 0\n\ + subs r0, 0x38\n\ + lsls r1, r0, 2\n\ + adds r3, r5, r1\n\ + ldrh r0, [r3]\n\ + cmp r0, 0\n\ + bne _081D2620\n\ + adds r0, r4, r1\n\ + ldrh r0, [r0]\n\ + cmp r0, 0\n\ + beq _081D2620\n\ + strh r6, [r3]\n\ +_081D2620:\n\ + adds r0, r2, 0x1\n\ + lsls r0, 16\n\ + lsrs r2, r0, 16\n\ + cmp r2, 0x79\n\ + bls _081D2608\n\ + add sp, 0x8\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .syntax divided"); +} + +NAKED +static void sub_81D2634(struct UnknownStruct_81D1ED4 *a0) +{ + asm(".syntax unified\n\ + push {r4-r6,lr}\n\ + sub sp, 0x8\n\ + adds r4, r0, 0\n\ + movs r0, 0x97\n\ + lsls r0, 1\n\ + adds r2, r4, r0\n\ + movs r3, 0x9F\n\ + lsls r3, 1\n\ + adds r1, r4, r3\n\ + ldrh r0, [r2]\n\ + ldrh r5, [r1]\n\ + cmp r0, r5\n\ + bcs _081D266E\n\ + adds r6, r0, 0\n\ + movs r0, 0x92\n\ + lsls r0, 2\n\ + adds r1, r4, r0\n\ + subs r3, 0x12\n\ + adds r2, r4, r3\n\ + movs r5, 0x9E\n\ + lsls r5, 1\n\ + adds r3, r4, r5\n\ + movs r0, 0\n\ + str r0, [sp]\n\ + str r0, [sp, 0x4]\n\ + adds r0, r4, 0\n\ + bl sub_81D2278\n\ + b _081D2690\n\ +_081D266E:\n\ + ldrh r6, [r1]\n\ + movs r0, 0x92\n\ + lsls r0, 2\n\ + adds r1, r4, r0\n\ + movs r3, 0x9E\n\ + lsls r3, 1\n\ + adds r2, r4, r3\n\ + movs r5, 0x96\n\ + lsls r5, 1\n\ + adds r3, r4, r5\n\ + movs r0, 0x1\n\ + str r0, [sp]\n\ + movs r0, 0\n\ + str r0, [sp, 0x4]\n\ + adds r0, r4, 0\n\ + bl sub_81D2278\n\ +_081D2690:\n\ + movs r0, 0x92\n\ + lsls r0, 2\n\ + adds r5, r4, r0\n\ + movs r1, 0x9E\n\ + lsls r1, 1\n\ + adds r2, r4, r1\n\ + movs r0, 0x9C\n\ + lsls r0, 1\n\ + adds r3, r4, r0\n\ + movs r0, 0\n\ + str r0, [sp]\n\ + str r0, [sp, 0x4]\n\ + adds r0, r4, 0\n\ + adds r1, r5, 0\n\ + bl sub_81D2278\n\ + cmp r6, 0x38\n\ + ble _081D26C8\n\ + movs r0, 0\n\ + adds r1, r5, 0\n\ + adds r2, r6, 0\n\ + subs r2, 0x38\n\ +_081D26BC:\n\ + strh r0, [r1]\n\ + strh r0, [r1, 0x2]\n\ + adds r1, 0x4\n\ + subs r2, 0x1\n\ + cmp r2, 0\n\ + bne _081D26BC\n\ +_081D26C8:\n\ + movs r1, 0x97\n\ + lsls r1, 1\n\ + adds r0, r4, r1\n\ + ldrh r2, [r0]\n\ + movs r3, 0xD4\n\ + lsls r3, 2\n\ + adds r0, r4, r3\n\ + ldrh r5, [r0]\n\ + cmp r2, r5\n\ + bgt _081D26F6\n\ + movs r3, 0x9B\n\ + adds r1, r0, 0\n\ + lsls r0, r2, 2\n\ + movs r5, 0xB5\n\ + lsls r5, 1\n\ + adds r0, r5\n\ + adds r0, r4\n\ +_081D26EA:\n\ + strh r3, [r0]\n\ + adds r0, 0x4\n\ + adds r2, 0x1\n\ + ldrh r5, [r1]\n\ + cmp r2, r5\n\ + ble _081D26EA\n\ +_081D26F6:\n\ + movs r1, 0x9D\n\ + lsls r1, 1\n\ + adds r0, r4, r1\n\ + ldrh r0, [r0]\n\ + adds r1, r0, 0x1\n\ + movs r2, 0xD4\n\ + lsls r2, 2\n\ + adds r0, r4, r2\n\ + ldrh r0, [r0]\n\ + cmp r0, r1\n\ + bge _081D270E\n\ + adds r0, r1, 0\n\ +_081D270E:\n\ + adds r2, r0, 0\n\ + cmp r2, 0x79\n\ + bgt _081D272C\n\ + movs r1, 0\n\ + lsls r0, r2, 2\n\ + movs r3, 0xB4\n\ + lsls r3, 1\n\ + adds r0, r3\n\ + adds r0, r4\n\ +_081D2720:\n\ + strh r1, [r0]\n\ + strh r1, [r0, 0x2]\n\ + adds r0, 0x4\n\ + adds r2, 0x1\n\ + cmp r2, 0x79\n\ + ble _081D2720\n\ +_081D272C:\n\ + movs r3, 0\n\ + movs r5, 0x92\n\ + lsls r5, 2\n\ + adds r1, r4, r5\n\ + movs r2, 0x41\n\ +_081D2736:\n\ + ldrh r0, [r1]\n\ + ldrh r4, [r1, 0x2]\n\ + cmp r0, r4\n\ + bcc _081D2742\n\ + strh r3, [r1, 0x2]\n\ + strh r3, [r1]\n\ +_081D2742:\n\ + adds r1, 0x4\n\ + subs r2, 0x1\n\ + cmp r2, 0\n\ + bge _081D2736\n\ + add sp, 0x8\n\ + pop {r4-r6}\n\ + pop {r0}\n\ + bx r0\n\ + .syntax divided"); +} + +NAKED +void sub_81D2754(struct UnknownStruct_81D1ED4 *arg0, struct UnknownSubStruct_81D1ED4 *arg1) +{ + // There are some register-renaming issues here. The cause of the problem seems to be that + // GCC tries to save sUnknown_08625410 in a register, instead of loading the constant repeatedly. + // But this is one too many things to keep track of, so GCC is forced to use the stack. +#ifdef NONMATCHING + u8* v1; + u8 v2; + u8 v3; + s8 v4; + u16 v5; + + v1 = arg0->unk0[0]; + v2 = sUnknown_08625410[*v1]; + v1++; + arg1[0].unk0 = 0x9B; + arg1[0].unk2 = 0x5B - v2; + for (v3 = 0x40, v4 = 0, v5 = 1; v5 < 5; v5++) + { + v3 += 0x33; + v4--; + if (v4 < 0) + { + v4 = 4; + } + if (v4 == 2) + { + v3++; + } + + v2 = sUnknown_08625410[*v1]; + v1++; + arg1[v4].unk0 = ((gSineTable[v3 + 0x40] * v2) >> 8) + 0x9B; + arg1[v4].unk2 = ((gSineTable[v3] * v2) >> 8) - 0x5B; + if (v4 <= 2 && (v2 != 0x20 || v4 != 2)) + { + arg1[v4].unk0 = arg1[v4].unk0 + 1; + } + } +#else + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + mov r7, r10\n\ + mov r6, r9\n\ + mov r5, r8\n\ + push {r5-r7}\n\ + adds r6, r0, 0\n\ + mov r8, r1\n\ + ldr r1, =sUnknown_08625410\n\ + ldrb r0, [r6]\n\ + adds r0, r1\n\ + ldrb r2, [r0]\n\ + adds r6, 0x1\n\ + movs r0, 0x9B\n\ + mov r3, r8\n\ + strh r0, [r3]\n\ + movs r0, 0x5B\n\ + subs r0, r2\n\ + strh r0, [r3, 0x2]\n\ + movs r7, 0x40\n\ + movs r0, 0\n\ + mov r12, r0\n\ + movs r2, 0x1\n\ + mov r9, r2\n\ + ldr r3, =gSineTable\n\ + mov r10, r3\n\ +_081D2786:\n\ + adds r0, r7, 0\n\ + adds r0, 0x33\n\ + lsls r0, 24\n\ + lsrs r7, r0, 24\n\ + mov r1, r12\n\ + lsls r0, r1, 24\n\ + movs r2, 0xFF\n\ + lsls r2, 24\n\ + adds r0, r2\n\ + lsrs r3, r0, 24\n\ + mov r12, r3\n\ + cmp r0, 0\n\ + bge _081D27A4\n\ + movs r0, 0x4\n\ + mov r12, r0\n\ +_081D27A4:\n\ + mov r1, r12\n\ + lsls r0, r1, 24\n\ + asrs r4, r0, 24\n\ + cmp r4, 0x2\n\ + bne _081D27B4\n\ + adds r0, r7, 0x1\n\ + lsls r0, 24\n\ + lsrs r7, r0, 24\n\ +_081D27B4:\n\ + ldrb r0, [r6]\n\ + ldr r2, =sUnknown_08625410\n\ + adds r0, r2\n\ + ldrb r2, [r0]\n\ + adds r6, 0x1\n\ + lsls r0, r4, 2\n\ + mov r1, r8\n\ + adds r3, r0, r1\n\ + adds r0, r7, 0\n\ + adds r0, 0x40\n\ + lsls r0, 1\n\ + add r0, r10\n\ + movs r1, 0\n\ + ldrsh r0, [r0, r1]\n\ + muls r0, r2\n\ + asrs r5, r0, 8\n\ + adds r0, r5, 0\n\ + adds r0, 0x9B\n\ + strh r0, [r3]\n\ + lsls r0, r7, 1\n\ + add r0, r10\n\ + movs r1, 0\n\ + ldrsh r0, [r0, r1]\n\ + adds r1, r2, 0\n\ + muls r1, r0\n\ + asrs r1, 8\n\ + movs r0, 0x5B\n\ + subs r0, r1\n\ + strh r0, [r3, 0x2]\n\ + cmp r4, 0x2\n\ + bgt _081D2800\n\ + cmp r2, 0x20\n\ + bne _081D27FA\n\ + cmp r4, 0x2\n\ + beq _081D2800\n\ +_081D27FA:\n\ + adds r0, r5, 0\n\ + adds r0, 0x9C\n\ + strh r0, [r3]\n\ +_081D2800:\n\ + mov r0, r9\n\ + adds r0, 0x1\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + mov r9, r0\n\ + cmp r0, 0x4\n\ + bls _081D2786\n\ + pop {r3-r5}\n\ + mov r8, r3\n\ + mov r9, r4\n\ + mov r10, r5\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .pool\n\ + .syntax divided"); +#endif +} + +void InitMoveRelearnerWindows(bool8 useContextWindow) +{ + u8 i; + + InitWindows(sMoveRelearnerWindowTemplates); + DeactivateAllTextPrinters(); + LoadUserWindowBorderGfx(0, 1, 0xE0); + LoadPalette(gUnknown_0860F074, 0xF0, 0x20); + + for (i = 0; i < 5; i++) + { + FillWindowPixelBuffer(i, PIXEL_FILL(1)); + } + + if (!useContextWindow) + { + PutWindowTilemap(0); + DrawStdFrameWithCustomTileAndPalette(0, 0, 0x1, 0xE); + } + else + { + PutWindowTilemap(1); + DrawStdFrameWithCustomTileAndPalette(1, 0, 1, 0xE); + } + PutWindowTilemap(2); + PutWindowTilemap(3); + DrawStdFrameWithCustomTileAndPalette(2, 0, 1, 0xE); + DrawStdFrameWithCustomTileAndPalette(3, 0, 1, 0xE); + nullsub_79(); + schedule_bg_copy_tilemap_to_vram(1); +} + +static void nullsub_79(void) +{ + +} + +u8 LoadMoveRelearnerMovesList(const struct ListMenuItem *items, u16 numChoices) +{ + gMultiuseListMenuTemplate = sMoveRelearnerMovesListTemplate; + gMultiuseListMenuTemplate.totalItems = numChoices; + gMultiuseListMenuTemplate.items = items; + + if (numChoices < 6) + { + gMultiuseListMenuTemplate.maxShowed = numChoices; + } + else + { + gMultiuseListMenuTemplate.maxShowed = 6; + } + return gMultiuseListMenuTemplate.maxShowed; +} + +NAKED +static void MoveRelearnerLoadBattleMoveDescription(u32 chosenMove) +{ + // Two small issues, and a few renamed registers. +#ifdef NONMATCHING + u8 offset; + s32 width; + const struct BattleMove *move; + u8 buffer[0x20]; + const u8 *labelStr; + + FillWindowPixelBuffer(0, PIXEL_FILL(1)); + labelStr = gText_MoveRelearnerBattleMoves; + offset = GetStringCenterAlignXOffset(1, labelStr, 0x80); + AddTextPrinterParameterized(0, 1, labelStr, offset, 1, TEXT_SPEED_FF, NULL); + + labelStr = gText_MoveRelearnerPP; + AddTextPrinterParameterized(0, 1, labelStr, 4, 0x29, TEXT_SPEED_FF, NULL); + + labelStr = gText_MoveRelearnerPower; + offset = GetStringRightAlignXOffset(1, labelStr, 0x6A); + AddTextPrinterParameterized(0, 1, labelStr, offset, 0x19, TEXT_SPEED_FF, NULL); + + labelStr = gText_MoveRelearnerAccuracy; + offset = GetStringRightAlignXOffset(1, labelStr, 0x6A); + AddTextPrinterParameterized(0, 1, labelStr, offset, 0x29, TEXT_SPEED_FF, NULL); + if (chosenMove == LIST_CANCEL) + { + CopyWindowToVram(0, 2); + return; + } + move = &gBattleMoves[chosenMove]; + labelStr = gTypeNames[move->type]; + // GCC tries to be smart, and preserves the same 0x19 from above for this. + // The original asm just loads the constant 0x19 twice. + AddTextPrinterParameterized(0, 1, labelStr, 4, 0x19, TEXT_SPEED_FF, NULL); + + // GCC tries to generate this as: + // add r4, r0, 0 + // add r4, r4, 4 + // But the original asm is: + // add r4, r0, 4 + width = 4 + GetStringWidth(1, gText_MoveRelearnerPP, 0); + + ConvertIntToDecimalStringN(buffer, move->pp, 0, 2); + AddTextPrinterParameterized(0, 1, buffer, width, 0x29, TEXT_SPEED_FF, NULL); + + + if (move->power < 2) + { + labelStr = gText_ThreeDashes; + } + else + { + ConvertIntToDecimalStringN(buffer, move->power, 0, 3); + labelStr = buffer; + } + AddTextPrinterParameterized(0, 1, labelStr, 0x6A, 0x19, TEXT_SPEED_FF, NULL); + + if (move->accuracy == 0) + { + labelStr = gText_ThreeDashes; + } + else + { + ConvertIntToDecimalStringN(buffer, move->accuracy, 0, 3); + labelStr = buffer; + } + AddTextPrinterParameterized(0, 1, labelStr, 0x6A, 0x29, TEXT_SPEED_FF, NULL); + labelStr = gMoveDescriptionPointers[chosenMove - 1]; + AddTextPrinterParameterized(0, 7, labelStr, 0, 0x41, 0, NULL); +#else + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + mov r7, r10\n\ + mov r6, r9\n\ + mov r5, r8\n\ + push {r5-r7}\n\ + sub sp, 0x2C\n\ + mov r9, r0\n\ + movs r0, 0\n\ + movs r1, 0x11\n\ + bl FillWindowPixelBuffer\n\ + ldr r5, =gText_MoveRelearnerBattleMoves\n\ + movs r0, 0x1\n\ + adds r1, r5, 0\n\ + movs r2, 0x80\n\ + bl GetStringCenterAlignXOffset\n\ + adds r4, r0, 0\n\ + lsls r3, r4, 24\n\ + lsrs r3, 24\n\ + movs r0, 0x1\n\ + str r0, [sp]\n\ + movs r0, 0xFF\n\ + mov r8, r0\n\ + str r0, [sp, 0x4]\n\ + movs r7, 0\n\ + str r7, [sp, 0x8]\n\ + movs r0, 0\n\ + movs r1, 0x1\n\ + adds r2, r5, 0\n\ + bl AddTextPrinterParameterized\n\ + ldr r5, =gText_MoveRelearnerPP\n\ + movs r1, 0x29\n\ + mov r10, r1\n\ + str r1, [sp]\n\ + mov r0, r8\n\ + str r0, [sp, 0x4]\n\ + str r7, [sp, 0x8]\n\ + movs r0, 0\n\ + movs r1, 0x1\n\ + adds r2, r5, 0\n\ + movs r3, 0x4\n\ + bl AddTextPrinterParameterized\n\ + ldr r5, =gText_MoveRelearnerPower\n\ + movs r0, 0x1\n\ + adds r1, r5, 0\n\ + movs r2, 0x6A\n\ + bl GetStringRightAlignXOffset\n\ + adds r4, r0, 0\n\ + lsls r3, r4, 24\n\ + lsrs r3, 24\n\ + movs r1, 0x19\n\ + str r1, [sp]\n\ + mov r0, r8\n\ + str r0, [sp, 0x4]\n\ + str r7, [sp, 0x8]\n\ + movs r0, 0\n\ + movs r1, 0x1\n\ + adds r2, r5, 0\n\ + bl AddTextPrinterParameterized\n\ + ldr r5, =gText_MoveRelearnerAccuracy\n\ + movs r0, 0x1\n\ + adds r1, r5, 0\n\ + movs r2, 0x6A\n\ + bl GetStringRightAlignXOffset\n\ + adds r4, r0, 0\n\ + lsls r3, r4, 24\n\ + lsrs r3, 24\n\ + mov r1, r10\n\ + str r1, [sp]\n\ + mov r0, r8\n\ + str r0, [sp, 0x4]\n\ + str r7, [sp, 0x8]\n\ + movs r0, 0\n\ + movs r1, 0x1\n\ + adds r2, r5, 0\n\ + bl AddTextPrinterParameterized\n\ + movs r0, 0x2\n\ + negs r0, r0\n\ + cmp r9, r0\n\ + bne _081D29C4\n\ + movs r0, 0\n\ + movs r1, 0x2\n\ + bl CopyWindowToVram\n\ + b _081D2AB6\n\ + .pool\n\ +_081D29C4:\n\ + mov r1, r9\n\ + lsls r0, r1, 1\n\ + add r0, r9\n\ + lsls r0, 2\n\ + ldr r1, =gBattleMoves\n\ + adds r6, r0, r1\n\ + ldrb r1, [r6, 0x2]\n\ + lsls r0, r1, 3\n\ + subs r0, r1\n\ + ldr r1, =gTypeNames\n\ + adds r5, r0, r1\n\ + movs r0, 0x19\n\ + str r0, [sp]\n\ + mov r1, r8\n\ + str r1, [sp, 0x4]\n\ + str r7, [sp, 0x8]\n\ + movs r0, 0\n\ + movs r1, 0x1\n\ + adds r2, r5, 0\n\ + movs r3, 0x4\n\ + bl AddTextPrinterParameterized\n\ + ldr r1, =gText_MoveRelearnerPP\n\ + movs r0, 0x1\n\ + movs r2, 0\n\ + bl GetStringWidth\n\ + adds r4, r0, 0x4\n\ + ldrb r1, [r6, 0x4]\n\ + add r0, sp, 0xC\n\ + movs r2, 0\n\ + movs r3, 0x2\n\ + bl ConvertIntToDecimalStringN\n\ + lsls r3, r4, 24\n\ + lsrs r3, 24\n\ + mov r0, r10\n\ + str r0, [sp]\n\ + mov r1, r8\n\ + str r1, [sp, 0x4]\n\ + str r7, [sp, 0x8]\n\ + movs r0, 0\n\ + movs r1, 0x1\n\ + add r2, sp, 0xC\n\ + bl AddTextPrinterParameterized\n\ + ldrb r0, [r6, 0x1]\n\ + cmp r0, 0x1\n\ + bhi _081D2A3C\n\ + ldr r5, =gText_ThreeDashes\n\ + b _081D2A4A\n\ + .pool\n\ +_081D2A3C:\n\ + ldrb r1, [r6, 0x1]\n\ + add r0, sp, 0xC\n\ + movs r2, 0\n\ + movs r3, 0x3\n\ + bl ConvertIntToDecimalStringN\n\ + add r5, sp, 0xC\n\ +_081D2A4A:\n\ + movs r0, 0x19\n\ + str r0, [sp]\n\ + movs r0, 0xFF\n\ + str r0, [sp, 0x4]\n\ + movs r0, 0\n\ + str r0, [sp, 0x8]\n\ + movs r1, 0x1\n\ + adds r2, r5, 0\n\ + movs r3, 0x6A\n\ + bl AddTextPrinterParameterized\n\ + ldrb r0, [r6, 0x3]\n\ + cmp r0, 0\n\ + bne _081D2A70\n\ + ldr r5, =gText_ThreeDashes\n\ + b _081D2A7E\n\ + .pool\n\ +_081D2A70:\n\ + ldrb r1, [r6, 0x3]\n\ + add r0, sp, 0xC\n\ + movs r2, 0\n\ + movs r3, 0x3\n\ + bl ConvertIntToDecimalStringN\n\ + add r5, sp, 0xC\n\ +_081D2A7E:\n\ + movs r0, 0x29\n\ + str r0, [sp]\n\ + movs r0, 0xFF\n\ + str r0, [sp, 0x4]\n\ + movs r4, 0\n\ + str r4, [sp, 0x8]\n\ + movs r0, 0\n\ + movs r1, 0x1\n\ + adds r2, r5, 0\n\ + movs r3, 0x6A\n\ + bl AddTextPrinterParameterized\n\ + ldr r1, =gMoveDescriptionPointers\n\ + mov r0, r9\n\ + subs r0, 0x1\n\ + lsls r0, 2\n\ + adds r0, r1\n\ + ldr r5, [r0]\n\ + movs r0, 0x41\n\ + str r0, [sp]\n\ + str r4, [sp, 0x4]\n\ + str r4, [sp, 0x8]\n\ + movs r0, 0\n\ + movs r1, 0x7\n\ + adds r2, r5, 0\n\ + movs r3, 0\n\ + bl AddTextPrinterParameterized\n\ +_081D2AB6:\n\ + add sp, 0x2C\n\ + pop {r3-r5}\n\ + mov r8, r3\n\ + mov r9, r4\n\ + mov r10, r5\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .pool\n\ + .syntax divided"); +#endif +} + +NAKED +static void MoveRelearnerMenuLoadContestMoveDescription(u32 chosenMove) +{ +#ifdef NONMATCHING + //u8 offset; + const u8 *labelStr; + const struct ContestMove *move; + u8 category; + const u8 **temp; + + MoveRelearnerShowHideHearts(chosenMove); + FillWindowPixelBuffer(1, PIXEL_FILL(1)); + labelStr = gText_MoveRelearnerContestMovesTitle; + // GCC compiles these as: + // add r3, r0, 0 + // lsls r3, r3, 24 + // lsrs r3, r3, 24 + // But in the original asm: + // lsls r3, r0, 24 + // lsrs r3, r3, 24 + //offset = GetStringCenterAlignXOffset(1, labelStr, 0x80); + AddTextPrinterParameterized(1, 1, labelStr, GetStringCenterAlignXOffset(1, labelStr, 0x80), 1, TEXT_SPEED_FF, NULL); + + labelStr = gText_MoveRelearnerAppeal; + //offset = GetStringRightAlignXOffset(1, labelStr, 0x5C); + AddTextPrinterParameterized(1, 1, labelStr, GetStringCenterAlignXOffset(1, labelStr, 0x5C), 0x19, TEXT_SPEED_FF, NULL); + + labelStr = gText_MoveRelearnerJam; + //offset = GetStringRightAlignXOffset(1, labelStr, 0x5C); + AddTextPrinterParameterized(1, 1, labelStr, GetStringCenterAlignXOffset(1, labelStr, 0x5C), 0x29, TEXT_SPEED_FF, NULL); + + if (chosenMove == MENU_NOTHING_CHOSEN) + { + CopyWindowToVram(1, 2); + return; + } + + move = &gContestMoves[chosenMove]; + temp = (const u8**)gContestMoveTypeTextPointers; + category = move->contestCategory; + labelStr = temp[category]; + AddTextPrinterParameterized(1, 1, labelStr, 4, 0x19, TEXT_SPEED_FF, NULL); + + labelStr = gContestEffectDescriptionPointers[move->effect]; + AddTextPrinterParameterized(1, 1, labelStr, 0, 0x41, TEXT_SPEED_FF, NULL); + + CopyWindowToVram(1, 2); +#else + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + mov r7, r8\n\ + push {r7}\n\ + sub sp, 0xC\n\ + adds r4, r0, 0\n\ + bl MoveRelearnerShowHideHearts\n\ + movs r0, 0x1\n\ + movs r1, 0x11\n\ + bl FillWindowPixelBuffer\n\ + ldr r5, =gText_MoveRelearnerContestMovesTitle\n\ + movs r0, 0x1\n\ + adds r1, r5, 0\n\ + movs r2, 0x80\n\ + bl GetStringCenterAlignXOffset\n\ + lsls r3, r0, 24\n\ + lsrs r3, 24\n\ + movs r0, 0x1\n\ + str r0, [sp]\n\ + movs r7, 0xFF\n\ + str r7, [sp, 0x4]\n\ + movs r6, 0\n\ + str r6, [sp, 0x8]\n\ + movs r1, 0x1\n\ + adds r2, r5, 0\n\ + bl AddTextPrinterParameterized\n\ + ldr r5, =gText_MoveRelearnerAppeal\n\ + movs r0, 0x1\n\ + adds r1, r5, 0\n\ + movs r2, 0x5C\n\ + bl GetStringRightAlignXOffset\n\ + lsls r3, r0, 24\n\ + lsrs r3, 24\n\ + movs r0, 0x19\n\ + mov r8, r0\n\ + str r0, [sp]\n\ + str r7, [sp, 0x4]\n\ + str r6, [sp, 0x8]\n\ + movs r0, 0x1\n\ + movs r1, 0x1\n\ + adds r2, r5, 0\n\ + bl AddTextPrinterParameterized\n\ + ldr r5, =gText_MoveRelearnerJam\n\ + movs r0, 0x1\n\ + adds r1, r5, 0\n\ + movs r2, 0x5C\n\ + bl GetStringRightAlignXOffset\n\ + lsls r3, r0, 24\n\ + lsrs r3, 24\n\ + movs r0, 0x29\n\ + str r0, [sp]\n\ + str r7, [sp, 0x4]\n\ + str r6, [sp, 0x8]\n\ + movs r0, 0x1\n\ + movs r1, 0x1\n\ + adds r2, r5, 0\n\ + bl AddTextPrinterParameterized\n\ + movs r0, 0x2\n\ + negs r0, r0\n\ + cmp r4, r0\n\ + bne _081D2B6C\n\ + movs r0, 0x1\n\ + movs r1, 0x2\n\ + bl CopyWindowToVram\n\ + b _081D2BB8\n\ + .pool\n\ +_081D2B6C:\n\ + lsls r4, 3\n\ + ldr r0, =gContestMoves\n\ + adds r4, r0\n\ + ldr r1, =gContestMoveTypeTextPointers\n\ + ldrb r0, [r4, 0x1]\n\ + lsls r0, 29\n\ + lsrs r0, 27\n\ + adds r0, r1\n\ + ldr r5, [r0]\n\ + mov r0, r8\n\ + str r0, [sp]\n\ + str r7, [sp, 0x4]\n\ + str r6, [sp, 0x8]\n\ + movs r0, 0x1\n\ + movs r1, 0x1\n\ + adds r2, r5, 0\n\ + movs r3, 0x4\n\ + bl AddTextPrinterParameterized\n\ + ldr r1, =gContestEffectDescriptionPointers\n\ + ldrb r0, [r4]\n\ + lsls r0, 2\n\ + adds r0, r1\n\ + ldr r5, [r0]\n\ + movs r0, 0x41\n\ + str r0, [sp]\n\ + str r7, [sp, 0x4]\n\ + str r6, [sp, 0x8]\n\ + movs r0, 0x1\n\ + movs r1, 0x7\n\ + adds r2, r5, 0\n\ + movs r3, 0\n\ + bl AddTextPrinterParameterized\n\ + movs r0, 0x1\n\ + movs r1, 0x2\n\ + bl CopyWindowToVram\n\ +_081D2BB8:\n\ + add sp, 0xC\n\ + pop {r3}\n\ + mov r8, r3\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .pool\n\ + .syntax divided"); +#endif +} + +static void MoveRelearnerCursorCallback(s32 itemIndex, bool8 onInit, struct ListMenu *list) +{ + if (onInit != TRUE) + PlaySE(SE_SELECT); + MoveRelearnerLoadBattleMoveDescription(itemIndex); + MoveRelearnerMenuLoadContestMoveDescription(itemIndex); +} + +void MoveRelearnerPrintText(u8 *str) +{ + u8 speed; + + FillWindowPixelBuffer(3, PIXEL_FILL(1)); + gTextFlags.canABSpeedUpPrint = TRUE; + speed = GetPlayerTextSpeedDelay(); + AddTextPrinterParameterized2(3, 1, str, speed, NULL, TEXT_COLOR_DARK_GREY, TEXT_COLOR_WHITE, 3); +} + +bool16 MoveRelearnerRunTextPrinters(void) +{ + RunTextPrinters(); + return IsTextPrinterActive(3); +} + +void MoveRelearnerCreateYesNoMenu(void) +{ + CreateYesNoMenu(&sMoveRelearnerYesNoMenuTemplate, 1, 0xE, 0); +}
\ No newline at end of file diff --git a/src/move_relearner.c b/src/move_relearner.c new file mode 100644 index 000000000..e148b9ace --- /dev/null +++ b/src/move_relearner.c @@ -0,0 +1,976 @@ +#include "global.h" +#include "main.h" +#include "battle.h" +#include "bg.h" +#include "contest_effect.h" +#include "data2.h" +#include "event_data.h" +#include "field_screen_effect.h" +#include "gpu_regs.h" +#include "move_relearner.h" +#include "list_menu.h" +#include "alloc.h" +#include "menu.h" +#include "menu_helpers.h" +#include "menu_specialized.h" +#include "overworld.h" +#include "palette.h" +#include "pokemon_summary_screen.h" +#include "script.h" +#include "sound.h" +#include "sprite.h" +#include "string_util.h" +#include "strings.h" +#include "task.h" +#include "constants/rgb.h" +#include "constants/songs.h" + +/* + * Move relearner state machine + * ------------------------ + * + * Entry point: TeachMoveRelearnerMove + * + * TeachMoveRelearnerMove + * Task_WaitForFadeOut + * CB2_InitLearnMove + * - Creates moveDisplayArrowTask to listen to right/left buttons. + * - Creates moveListScrollArrowTask to listen to up/down buttons. + * - Whenever the selected move changes (and once on init), the MoveRelearnerCursorCallback + * is called (see sMoveRelearnerMovesListTemplate). That callback will reload the contest + * display and battle display windows for the new move. Both are always loaded in + * memory, but only the currently active one is copied to VRAM. The exception to this + * is the appeal and jam hearts, which are sprites. MoveRelearnerShowHideHearts is called + * while reloading the contest display to control them. + * DoMoveRelearnerMain: MENU_STATE_FADE_TO_BLACK + * DoMoveRelearnerMain: MENU_STATE_WAIT_FOR_FADE + * - Go to MENU_STATE_IDLE_BATTLE_MODE + * + * DoMoveRelearnerMain: MENU_STATE_SETUP_BATTLE_MODE + * DoMoveRelearnerMain: MENU_STATE_IDLE_BATTLE_MODE + * - If the player selected a move (pressed A), go to MENU_STATE_PRINT_TEACH_MOVE_PROMPT. + * - If the player cancelled (pressed B), go to MENU_STATE_PRINT_GIVE_UP_PROMPT. + * - If the player pressed left or right, swap the move display window to contest mode, + * and go to MENU_STATE_SETUP_CONTEST_MODE. + * + * DoMoveRelearnerMain: MENU_STATE_SETUP_CONTEST_MODE + * DoMoveRelearnerMain: MENU_STATE_IDLE_CONTEST_MODE + * - If the player selected a move, go to MENU_STATE_PRINT_TEACH_MOVE_PROMPT. + * - If the player cancelled, go to MENU_STATE_PRINT_GIVE_UP_PROMPT + * - If the player pressed left or right, swap the move display window to battle mode, + * and go to MENU_STATE_SETUP_BATTLE_MODE. + * + * DoMoveRelearnerMain: MENU_STATE_PRINT_TEACH_MOVE_PROMPT + * DoMoveRelearnerMain: MENU_STATE_TEACH_MOVE_CONFIRM + * - Wait for the player to confirm. + * - If cancelled, go to either MENU_STATE_SETUP_BATTLE_MODE or MENU_STATE_SETUP_CONTEST_MODE. + * - If confirmed and the pokemon had an empty move slot, set VAR_0x8004 to TRUE and go to + * MENU_STATE_PRINT_TEXT_THEN_FANFARE. + * - If confirmed and the pokemon doesn't have an empty move slot, go to + * MENU_STATE_PRINT_TRYING_TO_LEARN_PROMPT. + * + * DoMoveRelearnerMain: MENU_STATE_PRINT_TRYING_TO_LEARN_PROMPT + * DoMoveRelearnerMain: MENU_STATE_WAIT_FOR_TRYING_TO_LEARN + * DoMoveRelearnerMain: MENU_STATE_CONFIRM_DELETE_OLD_MOVE + * - If the player confirms, go to MENU_STATE_PRINT_WHICH_MOVE_PROMPT. + * - If the player cancels, go to MENU_STATE_PRINT_STOP_TEACHING + * + * DoMoveRelearnerMain: MENU_STATE_PRINT_STOP_TEACHING + * DoMoveRelearnerMain: MENU_STATE_WAIT_FOR_STOP_TEACHING + * DoMoveRelearnerMain: MENU_STATE_CONFIRM_STOP_TEACHING + * - If the player confirms, go to MENU_STATE_CHOOSE_SETUP_STATE. + * - If the player cancels, go back to MENU_STATE_PRINT_TRYING_TO_LEARN_PROMPT. + * + * DoMoveRelearnerMain: MENU_STATE_PRINT_WHICH_MOVE_PROMPT + * DoMoveRelearnerMain: MENU_STATE_SHOW_MOVE_SUMMARY_SCREEN + * - Go to ShowSelectMovePokemonSummaryScreen. When done, control returns to + * CB2_InitLearnMoveReturnFromSelectMove. + * + * DoMoveRelearnerMain: MENU_STATE_DOUBLE_FANFARE_FORGOT_MOVE + * DoMoveRelearnerMain: MENU_STATE_PRINT_TEXT_THEN_FANFARE + * DoMoveRelearnerMain: MENU_STATE_WAIT_FOR_FANFARE + * DoMoveRelearnerMain: MENU_STATE_WAIT_FOR_A_BUTTON + * DoMoveRelearnerMain: MENU_STATE_FADE_AND_RETURN + * DoMoveRelearnerMain: MENU_STATE_RETURN_TO_FIELD + * - Clean up and go to CB2_ReturnToField. + * + * DoMoveRelearnerMain: MENU_STATE_PRINT_GIVE_UP_PROMPT + * DoMoveRelearnerMain: MENU_STATE_GIVE_UP_CONFIRM + * - If the player confirms, go to MENU_STATE_FADE_AND_RETURN, and set VAR_0x8004 to FALSE. + * - If the player cancels, go to either MENU_STATE_SETUP_BATTLE_MODE or + * MENU_STATE_SETUP_CONTEST_MODE. + * + * CB2_InitLearnMoveReturnFromSelectMove: + * - Do most of the same stuff as CB2_InitLearnMove. + * DoMoveRelearnerMain: MENU_STATE_FADE_FROM_SUMMARY_SCREEN + * DoMoveRelearnerMain: MENU_STATE_TRY_OVERWRITE_MOVE + * - If any of the pokemon's existing moves were chosen, overwrite the move and + * go to MENU_STATE_DOUBLE_FANFARE_FORGOT_MOVE and set VAR_0x8004 to TRUE. + * - If the chosen move is the one the player selected before the summary screen, + * go to MENU_STATE_PRINT_STOP_TEACHING. + * + */ + +#define MENU_STATE_FADE_TO_BLACK 0 +#define MENU_STATE_WAIT_FOR_FADE 1 +#define MENU_STATE_UNREACHABLE 2 +#define MENU_STATE_SETUP_BATTLE_MODE 3 +#define MENU_STATE_IDLE_BATTLE_MODE 4 +#define MENU_STATE_SETUP_CONTEST_MODE 5 +#define MENU_STATE_IDLE_CONTEST_MODE 6 +// State 7 is skipped. +#define MENU_STATE_PRINT_TEACH_MOVE_PROMPT 8 +#define MENU_STATE_TEACH_MOVE_CONFIRM 9 +// States 10 and 11 are skipped. +#define MENU_STATE_PRINT_GIVE_UP_PROMPT 12 +#define MENU_STATE_GIVE_UP_CONFIRM 13 +#define MENU_STATE_FADE_AND_RETURN 14 +#define MENU_STATE_RETURN_TO_FIELD 15 +#define MENU_STATE_PRINT_TRYING_TO_LEARN_PROMPT 16 +#define MENU_STATE_WAIT_FOR_TRYING_TO_LEARN 17 +#define MENU_STATE_CONFIRM_DELETE_OLD_MOVE 18 +#define MENU_STATE_PRINT_WHICH_MOVE_PROMPT 19 +#define MENU_STATE_SHOW_MOVE_SUMMARY_SCREEN 20 +// States 21, 22, and 23 are skipped. +#define MENU_STATE_PRINT_STOP_TEACHING 24 +#define MENU_STATE_WAIT_FOR_STOP_TEACHING 25 +#define MENU_STATE_CONFIRM_STOP_TEACHING 26 +#define MENU_STATE_CHOOSE_SETUP_STATE 27 +#define MENU_STATE_FADE_FROM_SUMMARY_SCREEN 28 +#define MENU_STATE_TRY_OVERWRITE_MOVE 29 +#define MENU_STATE_DOUBLE_FANFARE_FORGOT_MOVE 30 +#define MENU_STATE_PRINT_TEXT_THEN_FANFARE 31 +#define MENU_STATE_WAIT_FOR_FANFARE 32 +#define MENU_STATE_WAIT_FOR_A_BUTTON 33 + +// The different versions of hearts are selected using animation +// commands. +#define APPEAL_HEART_EMPTY 0 +#define APPEAL_HEART_FULL 1 +#define JAM_HEART_EMPTY 2 +#define JAM_HEART_FULL 3 + +static EWRAM_DATA struct +{ + u8 state; + u8 heartSpriteIds[16]; /*0x001*/ + u16 movesToLearn[4]; /*0x012*/ + u8 filler1A[0x44 - 0x1A]; /*0x01A*/ + u8 partyMon; /*0x044*/ + u8 moveSlot; /*0x045*/ + struct ListMenuItem menuItems[20]; /*0x048*/ + u8 fillerE8[0x110 - 0xE8]; /*0x0E8*/ + u8 numMenuChoices; /*0x110*/ + u8 numToShowAtOnce; /*0x111*/ + u8 moveListMenuTask; /*0x112*/ + u8 moveListScrollArrowTask; /*0x113*/ + u8 moveDisplayArrowTask; /*0x114*/ + u16 scrollOffset; /*0x116*/ +} *sMoveRelearnerStruct = {0}; + +static EWRAM_DATA struct { + u16 listOffset; + u16 listRow; + bool8 showContestInfo; +} sMoveRelearnerMenuSate = {0}; + +static const u16 sMoveRelearnerPaletteData[] = INCBIN_U16("graphics/interface/ui_learn_move.gbapal"); + +// The arrow sprites in this spritesheet aren't used. The scroll-arrow system provides its own +// arrow sprites. +static const u8 sMoveRelearnerSpriteSheetData[] = INCBIN_U8("graphics/interface/ui_learn_move.4bpp"); + +static const struct OamData sHeartSpriteOamData = +{ + .y = 0, + .affineMode = 0, + .objMode = ST_OAM_OBJ_NORMAL, + .mosaic = 0, + .bpp = ST_OAM_4BPP, + .shape = ST_OAM_SQUARE, + .x = 0, + .matrixNum = 0, + .size = 0, + .tileNum = 0, + .priority = 0, + .paletteNum = 0, + .affineParam = 0, +}; + +static const struct OamData sUnusedOam1 = +{ + .y = 0, + .affineMode = 0, + .objMode = ST_OAM_OBJ_NORMAL, + .mosaic = 0, + .bpp = ST_OAM_4BPP, + .shape = ST_OAM_V_RECTANGLE, + .x = 0, + .matrixNum = 0, + .size = 0, + .tileNum = 0, + .priority = 0, + .paletteNum = 0, + .affineParam = 0, +}; + +static const struct OamData sUnusedOam2 = +{ + .y = 0, + .affineMode = 0, + .objMode = ST_OAM_OBJ_NORMAL, + .mosaic = 0, + .bpp = ST_OAM_4BPP, + .shape = ST_OAM_H_RECTANGLE, + .x = 0, + .matrixNum = 0, + .size = 0, + .tileNum = 0, + .priority = 0, + .paletteNum = 0, + .affineParam = 0, +}; + +static const struct SpriteSheet sMoveRelearnerSpriteSheet = +{ + .data = sMoveRelearnerSpriteSheetData, + .size = 0x180, + .tag = 5525 +}; + +static const struct SpritePalette sMoveRelearnerPalette = +{ + .data = sMoveRelearnerPaletteData, + .tag = 5526 +}; + +static const struct ScrollArrowsTemplate sDisplayModeArrowsTemplate = +{ + .firstArrowType = SCROLL_ARROW_LEFT, + .firstX = 27, + .firstY = 16, + .secondArrowType = SCROLL_ARROW_RIGHT, + .secondX = 117, + .secondY = 16, + .fullyUpThreshold = -1, + .fullyDownThreshold = -1, + .tileTag = 5325, + .palTag = 5325, + .palNum = 0, +}; + +static const struct ScrollArrowsTemplate sMoveListScrollArrowsTemplate = +{ + .firstArrowType = SCROLL_ARROW_UP, + .firstX = 192, + .firstY = 8, + .secondArrowType = SCROLL_ARROW_DOWN, + .secondX = 192, + .secondY = 104, + .fullyUpThreshold = 0, + .fullyDownThreshold = 0, + .tileTag = 5425, + .palTag = 5425, + .palNum = 0, +}; + +static const union AnimCmd sHeartSprite_AppealEmptyFrame[] = +{ + ANIMCMD_FRAME(8, 5, FALSE, FALSE), + ANIMCMD_END +}; + +static const union AnimCmd sHeartSprite_AppealFullFrame[] = +{ + ANIMCMD_FRAME(9, 5, FALSE, FALSE), + ANIMCMD_END +}; + +static const union AnimCmd sHeartSprite_JamEmptyFrame[] = +{ + ANIMCMD_FRAME(10, 5, FALSE, FALSE), + ANIMCMD_END +}; + +static const union AnimCmd sHeartSprite_JamFullFrame[] = +{ + ANIMCMD_FRAME(11, 5, FALSE, FALSE), + ANIMCMD_END +}; + +static const union AnimCmd *const sHeartSpriteAnimationCommands[] = +{ + [APPEAL_HEART_EMPTY] = sHeartSprite_AppealEmptyFrame, + [APPEAL_HEART_FULL] = sHeartSprite_AppealFullFrame, + [JAM_HEART_EMPTY] = sHeartSprite_JamEmptyFrame, + [JAM_HEART_FULL] = sHeartSprite_JamFullFrame, +}; + +static const struct SpriteTemplate sConstestMoveHeartSprite = +{ + .tileTag = 5525, + .paletteTag = 5526, + .oam = &sHeartSpriteOamData, + .anims = sHeartSpriteAnimationCommands, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCallbackDummy +}; + +static const struct BgTemplate sMoveRelearnerMenuBackgroundTemplates[] = +{ + { + .bg = 0, + .charBaseIndex = 0, + .mapBaseIndex = 31, + .screenSize = 0, + .paletteMode = 0, + .priority = 0, + .baseTile = 0, + }, + { + .bg = 1, + .charBaseIndex = 0, + .mapBaseIndex = 30, + .screenSize = 0, + .paletteMode = 0, + .priority = 1, + .baseTile = 0, + }, +}; + +static void DoMoveRelearnerMain(void); +static void CreateLearnableMovesList(void); +static void CreateUISprites(void); +static void CB2_MoveRelearnerMain(void); +static void Task_WaitForFadeOut(u8 taskId); +static void CB2_InitLearnMove(void); +static void CB2_InitLearnMoveReturnFromSelectMove(void); +static void InitMoveRelearnerBackgroundLayers(void); +static void AddScrollArrows(void); +static void HandleInput(u8); +static void ShowTeachMoveText(u8); +static s32 GetCurrentSelectedMove(void); +static void FreeMoveRelearnerResources(void); +static void RemoveScrollArrows(void); +static void HideHeartSpritesAndShowTeachMoveText(bool8); + +static void VBlankCB_MoveRelearner(void) +{ + LoadOam(); + ProcessSpriteCopyRequests(); + TransferPlttBuffer(); +} + +// Script arguments: The pokemon to teach is in VAR_0x8004 +void TeachMoveRelearnerMove(void) +{ + ScriptContext2_Enable(); + CreateTask(Task_WaitForFadeOut, 10); + // Fade to black + BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 0x10, RGB_BLACK); +} + +static void Task_WaitForFadeOut(u8 taskId) +{ + if (!gPaletteFade.active) + { + SetMainCallback2(CB2_InitLearnMove); + gFieldCallback = FieldCallback_ReturnToEventScript2; + DestroyTask(taskId); + } +} + +static void CB2_InitLearnMove(void) +{ + ResetSpriteData(); + FreeAllSpritePalettes(); + ResetTasks(); + clear_scheduled_bg_copies_to_vram(); + sMoveRelearnerStruct = AllocZeroed(sizeof(*sMoveRelearnerStruct)); + sMoveRelearnerStruct->partyMon = gSpecialVar_0x8004; + SetVBlankCallback(VBlankCB_MoveRelearner); + + InitMoveRelearnerBackgroundLayers(); + InitMoveRelearnerWindows(FALSE); + + sMoveRelearnerMenuSate.listOffset = 0; + sMoveRelearnerMenuSate.listRow = 0; + sMoveRelearnerMenuSate.showContestInfo = FALSE; + + CreateLearnableMovesList(); + + LoadSpriteSheet(&sMoveRelearnerSpriteSheet); + LoadSpritePalette(&sMoveRelearnerPalette); + CreateUISprites(); + + sMoveRelearnerStruct->moveListMenuTask = ListMenuInit(&gMultiuseListMenuTemplate, sMoveRelearnerMenuSate.listOffset, sMoveRelearnerMenuSate.listRow); + FillPalette(RGB_BLACK, 0, 2); + SetMainCallback2(CB2_MoveRelearnerMain); +} + +static void CB2_InitLearnMoveReturnFromSelectMove(void) +{ + ResetSpriteData(); + FreeAllSpritePalettes(); + ResetTasks(); + clear_scheduled_bg_copies_to_vram(); + sMoveRelearnerStruct = AllocZeroed(sizeof(*sMoveRelearnerStruct)); + sMoveRelearnerStruct->state = MENU_STATE_FADE_FROM_SUMMARY_SCREEN; + sMoveRelearnerStruct->partyMon = gSpecialVar_0x8004; + sMoveRelearnerStruct->moveSlot = gSpecialVar_0x8005; + SetVBlankCallback(VBlankCB_MoveRelearner); + + InitMoveRelearnerBackgroundLayers(); + InitMoveRelearnerWindows(sMoveRelearnerMenuSate.showContestInfo); + CreateLearnableMovesList(); + + LoadSpriteSheet(&sMoveRelearnerSpriteSheet); + LoadSpritePalette(&sMoveRelearnerPalette); + CreateUISprites(); + + sMoveRelearnerStruct->moveListMenuTask = ListMenuInit(&gMultiuseListMenuTemplate, sMoveRelearnerMenuSate.listOffset, sMoveRelearnerMenuSate.listRow); + FillPalette(RGB_BLACK, 0, 2); + SetMainCallback2(CB2_MoveRelearnerMain); +} + +static void InitMoveRelearnerBackgroundLayers(void) +{ + ResetVramOamAndBgCntRegs(); + ResetBgsAndClearDma3BusyFlags(0); + InitBgsFromTemplates(0, sMoveRelearnerMenuBackgroundTemplates, ARRAY_COUNT(sMoveRelearnerMenuBackgroundTemplates)); + ResetAllBgsCoordinates(); + SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_MODE_0 | + DISPCNT_OBJ_1D_MAP | + DISPCNT_OBJ_ON); + ShowBg(0); + ShowBg(1); + SetGpuReg(REG_OFFSET_BLDCNT, 0); +} + +static void CB2_MoveRelearnerMain(void) +{ + DoMoveRelearnerMain(); + RunTasks(); + AnimateSprites(); + BuildOamBuffer(); + do_scheduled_bg_tilemap_copies_to_vram(); + UpdatePaletteFade(); +} + +static void FormatAndPrintText(const u8 *src) +{ + StringExpandPlaceholders(gStringVar4, src); + MoveRelearnerPrintText(gStringVar4); +} + +// See the state machine doc at the top of the file. +static void DoMoveRelearnerMain(void) +{ + switch (sMoveRelearnerStruct->state) + { + case MENU_STATE_FADE_TO_BLACK: + sMoveRelearnerStruct->state++; + HideHeartSpritesAndShowTeachMoveText(FALSE); + BeginNormalPaletteFade(0xFFFFFFFF, 0, 16, 0, RGB_BLACK); + break; + case MENU_STATE_WAIT_FOR_FADE: + if (!gPaletteFade.active) + { + sMoveRelearnerStruct->state = MENU_STATE_IDLE_BATTLE_MODE; + } + break; + case MENU_STATE_UNREACHABLE: + sMoveRelearnerStruct->state++; + break; + case MENU_STATE_SETUP_BATTLE_MODE: + + HideHeartSpritesAndShowTeachMoveText(FALSE); + sMoveRelearnerStruct->state++; + AddScrollArrows(); + break; + case MENU_STATE_IDLE_BATTLE_MODE: + HandleInput(FALSE); + break; + case MENU_STATE_SETUP_CONTEST_MODE: + ShowTeachMoveText(FALSE); + sMoveRelearnerStruct->state++; + AddScrollArrows(); + break; + case MENU_STATE_IDLE_CONTEST_MODE: + HandleInput(TRUE); + break; + case MENU_STATE_PRINT_TEACH_MOVE_PROMPT: + if (!MoveRelearnerRunTextPrinters()) + { + MoveRelearnerCreateYesNoMenu(); + sMoveRelearnerStruct->state++; + } + break; + case MENU_STATE_TEACH_MOVE_CONFIRM: + { + s8 selection = Menu_ProcessInputNoWrapClearOnChoose(); + + if (selection == 0) + { + if (GiveMoveToMon(&gPlayerParty[sMoveRelearnerStruct->partyMon], GetCurrentSelectedMove()) != 0xFFFF) + { + FormatAndPrintText(gText_MoveRelearnerPkmnLearnedMove); + gSpecialVar_0x8004 = TRUE; + sMoveRelearnerStruct->state = MENU_STATE_PRINT_TEXT_THEN_FANFARE; + } + else + { + sMoveRelearnerStruct->state = MENU_STATE_PRINT_TRYING_TO_LEARN_PROMPT; + } + } + else if (selection == MENU_B_PRESSED || selection == 1) + { + if (sMoveRelearnerMenuSate.showContestInfo == FALSE) + { + sMoveRelearnerStruct->state = MENU_STATE_SETUP_BATTLE_MODE; + } + else if (sMoveRelearnerMenuSate.showContestInfo == TRUE) + { + sMoveRelearnerStruct->state = MENU_STATE_SETUP_CONTEST_MODE; + } + } + } + break; + case MENU_STATE_PRINT_GIVE_UP_PROMPT: + if (!MoveRelearnerRunTextPrinters()) + { + MoveRelearnerCreateYesNoMenu(); + sMoveRelearnerStruct->state++; + } + break; + case MENU_STATE_GIVE_UP_CONFIRM: + { + s8 selection = Menu_ProcessInputNoWrapClearOnChoose(); + + if (selection == 0) + { + gSpecialVar_0x8004 = FALSE; + sMoveRelearnerStruct->state = MENU_STATE_FADE_AND_RETURN; + } + else if (selection == -1 || selection == 1) + { + if (sMoveRelearnerMenuSate.showContestInfo == FALSE) + { + sMoveRelearnerStruct->state = MENU_STATE_SETUP_BATTLE_MODE; + } + else if (sMoveRelearnerMenuSate.showContestInfo == TRUE) + { + sMoveRelearnerStruct->state = MENU_STATE_SETUP_CONTEST_MODE; + } + } + } + break; + case MENU_STATE_PRINT_TRYING_TO_LEARN_PROMPT: + FormatAndPrintText(gText_MoveRelearnerPkmnTryingToLearnMove); + sMoveRelearnerStruct->state++; + break; + case MENU_STATE_WAIT_FOR_TRYING_TO_LEARN: + if (!MoveRelearnerRunTextPrinters()) + { + MoveRelearnerCreateYesNoMenu(); + sMoveRelearnerStruct->state = MENU_STATE_CONFIRM_DELETE_OLD_MOVE; + } + break; + case MENU_STATE_CONFIRM_DELETE_OLD_MOVE: + { + s8 var = Menu_ProcessInputNoWrapClearOnChoose(); + + if (var == 0) + { + FormatAndPrintText(gText_MoveRelearnerWhichMoveToForget); + sMoveRelearnerStruct->state = MENU_STATE_PRINT_WHICH_MOVE_PROMPT; + } + else if (var == -1 || var == 1) + { + sMoveRelearnerStruct->state = MENU_STATE_PRINT_STOP_TEACHING; + } + } + break; + case MENU_STATE_PRINT_STOP_TEACHING: + StringCopy(gStringVar2, gMoveNames[GetCurrentSelectedMove()]); + FormatAndPrintText(gText_MoveRelearnerStopTryingToTeachMove); + sMoveRelearnerStruct->state++; + break; + case MENU_STATE_WAIT_FOR_STOP_TEACHING: + if (!MoveRelearnerRunTextPrinters()) + { + MoveRelearnerCreateYesNoMenu(); + sMoveRelearnerStruct->state++; + } + break; + case MENU_STATE_CONFIRM_STOP_TEACHING: + { + s8 var = Menu_ProcessInputNoWrapClearOnChoose(); + + if (var == 0) + { + sMoveRelearnerStruct->state = MENU_STATE_CHOOSE_SETUP_STATE; + } + else if (var == MENU_B_PRESSED || var == 1) + { + // What's the point? It gets set to MENU_STATE_PRINT_TRYING_TO_LEARN_PROMPT, anyway. + if (sMoveRelearnerMenuSate.showContestInfo == FALSE) + { + sMoveRelearnerStruct->state = MENU_STATE_SETUP_BATTLE_MODE; + } + else if (sMoveRelearnerMenuSate.showContestInfo == TRUE) + { + sMoveRelearnerStruct->state = MENU_STATE_SETUP_CONTEST_MODE; + } + sMoveRelearnerStruct->state = MENU_STATE_PRINT_TRYING_TO_LEARN_PROMPT; + } + } + break; + case MENU_STATE_CHOOSE_SETUP_STATE: + if (!MoveRelearnerRunTextPrinters()) + { + FillWindowPixelBuffer(3, 0x11); + if (sMoveRelearnerMenuSate.showContestInfo == FALSE) + { + sMoveRelearnerStruct->state = MENU_STATE_SETUP_BATTLE_MODE; + } + else if (sMoveRelearnerMenuSate.showContestInfo == TRUE) + { + sMoveRelearnerStruct->state = MENU_STATE_SETUP_CONTEST_MODE; + } + } + break; + case MENU_STATE_PRINT_WHICH_MOVE_PROMPT: + if (!MoveRelearnerRunTextPrinters()) + { + sMoveRelearnerStruct->state = MENU_STATE_SHOW_MOVE_SUMMARY_SCREEN; + BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, RGB_BLACK); + } + break; + case MENU_STATE_SHOW_MOVE_SUMMARY_SCREEN: + if (!gPaletteFade.active) + { + ShowSelectMovePokemonSummaryScreen(gPlayerParty, sMoveRelearnerStruct->partyMon, gPlayerPartyCount - 1, CB2_InitLearnMoveReturnFromSelectMove, GetCurrentSelectedMove()); + FreeMoveRelearnerResources(); + } + break; + case 21: + if (!MoveRelearnerRunTextPrinters()) + { + sMoveRelearnerStruct->state = MENU_STATE_FADE_AND_RETURN; + } + break; + case 22: + BeginNormalPaletteFade(0xFFFFFFFF, 0, 16, 0, RGB_BLACK); + break; + case MENU_STATE_FADE_AND_RETURN: + BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, RGB_BLACK); + sMoveRelearnerStruct->state++; + break; + case MENU_STATE_RETURN_TO_FIELD: + if (!gPaletteFade.active) + { + FreeMoveRelearnerResources(); + SetMainCallback2(CB2_ReturnToField); + } + break; + case MENU_STATE_FADE_FROM_SUMMARY_SCREEN: + BeginNormalPaletteFade(0xFFFFFFFF, 0, 16, 0, RGB_BLACK); + sMoveRelearnerStruct->state++; + if (sMoveRelearnerMenuSate.showContestInfo == FALSE) + { + HideHeartSpritesAndShowTeachMoveText(TRUE); + } + else if (sMoveRelearnerMenuSate.showContestInfo == TRUE) + { + ShowTeachMoveText(TRUE); + } + RemoveScrollArrows(); + CopyWindowToVram(3, 2); + break; + case MENU_STATE_TRY_OVERWRITE_MOVE: + if (!gPaletteFade.active) + { + if (sMoveRelearnerStruct->moveSlot == MAX_MON_MOVES) + { + sMoveRelearnerStruct->state = MENU_STATE_PRINT_STOP_TEACHING; + } + else + { + u16 moveId = GetMonData(&gPlayerParty[sMoveRelearnerStruct->partyMon], MON_DATA_MOVE1 + sMoveRelearnerStruct->moveSlot); + + StringCopy(gStringVar3, gMoveNames[moveId]); + RemoveMonPPBonus(&gPlayerParty[sMoveRelearnerStruct->partyMon], sMoveRelearnerStruct->moveSlot); + SetMonMoveSlot(&gPlayerParty[sMoveRelearnerStruct->partyMon], GetCurrentSelectedMove(), sMoveRelearnerStruct->moveSlot); + StringCopy(gStringVar2, gMoveNames[GetCurrentSelectedMove()]); + FormatAndPrintText(gText_MoveRelearnerAndPoof); + sMoveRelearnerStruct->state = MENU_STATE_DOUBLE_FANFARE_FORGOT_MOVE; + gSpecialVar_0x8004 = TRUE; + } + } + break; + case MENU_STATE_DOUBLE_FANFARE_FORGOT_MOVE: + if (!MoveRelearnerRunTextPrinters()) + { + FormatAndPrintText(gText_MoveRelearnerPkmnForgotMoveAndLearnedNew); + sMoveRelearnerStruct->state = MENU_STATE_PRINT_TEXT_THEN_FANFARE; + PlayFanfare(MUS_FANFA1); + } + break; + case MENU_STATE_PRINT_TEXT_THEN_FANFARE: + if (!MoveRelearnerRunTextPrinters()) + { + PlayFanfare(MUS_FANFA1); + sMoveRelearnerStruct->state = MENU_STATE_WAIT_FOR_FANFARE; + } + break; + case MENU_STATE_WAIT_FOR_FANFARE: + if (IsFanfareTaskInactive()) + { + sMoveRelearnerStruct->state = MENU_STATE_WAIT_FOR_A_BUTTON; + } + break; + case MENU_STATE_WAIT_FOR_A_BUTTON: + if (gMain.newKeys & A_BUTTON) + { + PlaySE(SE_SELECT); + sMoveRelearnerStruct->state = MENU_STATE_FADE_AND_RETURN; + } + break; + } +} + +static void FreeMoveRelearnerResources(void) +{ + RemoveScrollArrows(); + DestroyListMenuTask(sMoveRelearnerStruct->moveListMenuTask, &sMoveRelearnerMenuSate.listOffset, &sMoveRelearnerMenuSate.listRow); + FreeAllWindowBuffers(); + FREE_AND_SET_NULL(sMoveRelearnerStruct); + ResetSpriteData(); + FreeAllSpritePalettes(); +} + +// Note: The hearts are already made invisible by MoveRelearnerShowHideHearts, +// which is called whenever the cursor in either list changes. +static void HideHeartSpritesAndShowTeachMoveText(bool8 onlyHideSprites) +{ + s32 i; + + for (i = 0; i < 16; i++) + { + gSprites[sMoveRelearnerStruct->heartSpriteIds[i]].invisible = TRUE; + } + + if (!onlyHideSprites) + { + StringExpandPlaceholders(gStringVar4, gText_TeachWhichMoveToPkmn); + FillWindowPixelBuffer(3, 0x11); + AddTextPrinterParameterized(3, 1, gStringVar4, 0, 1, 0, NULL); + } +} + +static void HandleInput(bool8 showContest) +{ + s32 itemId = ListMenu_ProcessInput(sMoveRelearnerStruct->moveListMenuTask); + ListMenuGetScrollAndRow(sMoveRelearnerStruct->moveListMenuTask, &sMoveRelearnerMenuSate.listOffset, &sMoveRelearnerMenuSate.listRow); + + switch (itemId) + { + case LIST_NOTHING_CHOSEN: + if (!(gMain.newKeys & (DPAD_LEFT | DPAD_RIGHT)) && !GetLRKeysState()) + { + break; + } + + PlaySE(SE_SELECT); + + if (showContest == FALSE) + { + PutWindowTilemap(1); + sMoveRelearnerStruct->state = MENU_STATE_SETUP_CONTEST_MODE; + sMoveRelearnerMenuSate.showContestInfo = TRUE; + } + else + { + PutWindowTilemap(0); + sMoveRelearnerStruct->state = MENU_STATE_SETUP_BATTLE_MODE; + sMoveRelearnerMenuSate.showContestInfo = FALSE; + } + + schedule_bg_copy_tilemap_to_vram(1); + MoveRelearnerShowHideHearts(GetCurrentSelectedMove()); + break; + case LIST_CANCEL: + PlaySE(SE_SELECT); + RemoveScrollArrows(); + sMoveRelearnerStruct->state = MENU_STATE_PRINT_GIVE_UP_PROMPT; + StringExpandPlaceholders(gStringVar4, gText_MoveRelearnerGiveUp); + MoveRelearnerPrintText(gStringVar4); + break; + default: + PlaySE(SE_SELECT); + RemoveScrollArrows(); + sMoveRelearnerStruct->state = MENU_STATE_PRINT_TEACH_MOVE_PROMPT; + StringCopy(gStringVar2, gMoveNames[itemId]); + StringExpandPlaceholders(gStringVar4, gText_MoveRelearnerTeachMoveConfirm); + MoveRelearnerPrintText(gStringVar4); + break; + } +} + +static s32 GetCurrentSelectedMove(void) +{ + return sMoveRelearnerStruct->menuItems[sMoveRelearnerMenuSate.listRow + sMoveRelearnerMenuSate.listOffset].id; +} + +// Theory: This used to make the heart sprites visible again (i.e. +// this was the inverse of HideHeartsAndShowTeachMoveText), but the +// code was commented out. The bool argument would have been named +// "justShowHearts." The code for showing/hiding the heards was moved +// to MoveRelearnerShowHideHearts, which is called whenever a new move is +// selected and whenever the display mode changes. +static void ShowTeachMoveText(bool8 shouldDoNothingInstead) +{ + if (shouldDoNothingInstead == FALSE) + { + StringExpandPlaceholders(gStringVar4, gText_TeachWhichMoveToPkmn); + FillWindowPixelBuffer(3, 0x11); + AddTextPrinterParameterized(3, 1, gStringVar4, 0, 1, 0, NULL); + } +} + +static void CreateUISprites(void) +{ + int i; + + sMoveRelearnerStruct->moveDisplayArrowTask = 0xFF; + sMoveRelearnerStruct->moveListScrollArrowTask = 0xFF; + AddScrollArrows(); + + // These are the appeal hearts. + for (i = 0; i < 8; i++) + { + sMoveRelearnerStruct->heartSpriteIds[i] = CreateSprite(&sConstestMoveHeartSprite, (i - (i / 4) * 4) * 8 + 104, (i / 4) * 8 + 36, 0); + } + + // These are the jam harts. + // The animation is used to toggle between full/empty heart sprites. + for (i = 0; i < 8; i++) + { + sMoveRelearnerStruct->heartSpriteIds[i + 8] = CreateSprite(&sConstestMoveHeartSprite, (i - (i / 4) * 4) * 8 + 104, (i / 4) * 8 + 52, 0); + StartSpriteAnim(&gSprites[sMoveRelearnerStruct->heartSpriteIds[i + 8]], 2); + } + + for (i = 0; i < 16; i++) + { + gSprites[sMoveRelearnerStruct->heartSpriteIds[i]].invisible = TRUE; + } +} + +static void AddScrollArrows(void) +{ + if (sMoveRelearnerStruct->moveDisplayArrowTask == 0xFF) + { + sMoveRelearnerStruct->moveDisplayArrowTask = AddScrollIndicatorArrowPair(&sDisplayModeArrowsTemplate, &sMoveRelearnerStruct->scrollOffset); + } + + if (sMoveRelearnerStruct->moveListScrollArrowTask == 0xFF) + { + gTempScrollArrowTemplate = sMoveListScrollArrowsTemplate; + gTempScrollArrowTemplate.fullyDownThreshold = sMoveRelearnerStruct->numMenuChoices - sMoveRelearnerStruct->numToShowAtOnce; + sMoveRelearnerStruct->moveListScrollArrowTask = AddScrollIndicatorArrowPair(&gTempScrollArrowTemplate, &sMoveRelearnerMenuSate.listOffset); + } +} + +static void RemoveScrollArrows(void) +{ + if (sMoveRelearnerStruct->moveDisplayArrowTask != 0xFF) + { + RemoveScrollIndicatorArrowPair(sMoveRelearnerStruct->moveDisplayArrowTask); + sMoveRelearnerStruct->moveDisplayArrowTask = 0xFF; + } + + if (sMoveRelearnerStruct->moveListScrollArrowTask != 0xFF) + { + RemoveScrollIndicatorArrowPair(sMoveRelearnerStruct->moveListScrollArrowTask); + sMoveRelearnerStruct->moveListScrollArrowTask = 0xFF; + } +} + +static void CreateLearnableMovesList(void) +{ + s32 i; + u8 nickname[POKEMON_NAME_LENGTH + 1]; + + sMoveRelearnerStruct->numMenuChoices = GetMoveRelearnerMoves(&gPlayerParty[sMoveRelearnerStruct->partyMon], sMoveRelearnerStruct->movesToLearn); + + for (i = 0; i < sMoveRelearnerStruct->numMenuChoices; i++) + { + sMoveRelearnerStruct->menuItems[i].name = gMoveNames[sMoveRelearnerStruct->movesToLearn[i]]; + sMoveRelearnerStruct->menuItems[i].id = sMoveRelearnerStruct->movesToLearn[i]; + } + + GetMonData(&gPlayerParty[sMoveRelearnerStruct->partyMon], MON_DATA_NICKNAME, nickname); + StringCopy10(gStringVar1, nickname); + sMoveRelearnerStruct->menuItems[sMoveRelearnerStruct->numMenuChoices].name = gText_Cancel; + sMoveRelearnerStruct->menuItems[sMoveRelearnerStruct->numMenuChoices].id = LIST_CANCEL; + sMoveRelearnerStruct->numMenuChoices++; + sMoveRelearnerStruct->numToShowAtOnce = LoadMoveRelearnerMovesList(sMoveRelearnerStruct->menuItems, sMoveRelearnerStruct->numMenuChoices); +} + +void MoveRelearnerShowHideHearts(s32 moveId) +{ + u16 numHearts; + u16 i; + + if (!sMoveRelearnerMenuSate.showContestInfo || moveId == LIST_CANCEL) + { + for (i = 0; i < 16; i++) + { + gSprites[sMoveRelearnerStruct->heartSpriteIds[i]].invisible = TRUE; + } + } + else + { + numHearts = (u8)(gContestEffects[gContestMoves[moveId].effect].appeal / 10); + + if (numHearts == 0xFF) + { + numHearts = 0; + } + + for (i = 0; i < 8; i++) + { + if (i < numHearts) + { + StartSpriteAnim(&gSprites[sMoveRelearnerStruct->heartSpriteIds[i]], 1); + } + else + { + StartSpriteAnim(&gSprites[sMoveRelearnerStruct->heartSpriteIds[i]], 0); + } + gSprites[sMoveRelearnerStruct->heartSpriteIds[i]].invisible = FALSE; + } + + numHearts = (u8)(gContestEffects[gContestMoves[moveId].effect].jam / 10); + + if (numHearts == 0xFF) + { + numHearts = 0; + } + + for (i = 0; i < 8; i++) + { + if (i < numHearts) + { + StartSpriteAnim(&gSprites[sMoveRelearnerStruct->heartSpriteIds[i + 8]], 3); + } + else + { + StartSpriteAnim(&gSprites[sMoveRelearnerStruct->heartSpriteIds[i + 8]], 2); + } + gSprites[sMoveRelearnerStruct->heartSpriteIds[i + 8]].invisible = FALSE; + } + } +} diff --git a/src/overworld.c b/src/overworld.c index 0ff8d5b7f..ce1e21ab1 100644 --- a/src/overworld.c +++ b/src/overworld.c @@ -1688,7 +1688,7 @@ void CB2_ReturnToFieldContinueScript(void) void CB2_ReturnToFieldContinueScriptPlayMapMusic(void) { FieldClearVBlankHBlankCallbacks(); - gFieldCallback = sub_80AF168; + gFieldCallback = FieldCallback_ReturnToEventScript2; CB2_ReturnToField(); } diff --git a/src/party_menu.c b/src/party_menu.c index bedd0ce57..7db24b6ca 100755 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -37,15 +37,16 @@ #include "main.h" #include "menu.h" #include "menu_helpers.h" +#include "menu_specialized.h" #include "metatile_behavior.h" #include "overworld.h" #include "palette.h" #include "party_menu.h" +#include "player_pc.h" #include "pokemon.h" #include "pokemon_icon.h" #include "pokemon_storage_system.h" #include "pokemon_summary_screen.h" -#include "pokenav.h" #include "region_map.h" #include "reshow_battle_screen.h" #include "rom_8011DC0.h" @@ -6006,7 +6007,7 @@ static void sub_81B767C(u8 taskId) s16 *arrayPtr = gUnknown_0203CEC4->data; arrayPtr[12] = sub_81B3364(); - sub_81D3640(arrayPtr[12], arrayPtr, &arrayPtr[6], 1, 2, 3); + DrawLevelUpWindowPg1(arrayPtr[12], arrayPtr, &arrayPtr[6], 1, 2, 3); CopyWindowToVram(arrayPtr[12], 2); schedule_bg_copy_tilemap_to_vram(2); } @@ -6015,7 +6016,7 @@ static void sub_81B76C8(u8 taskId) { s16 *arrayPtr = gUnknown_0203CEC4->data; - sub_81D3784(arrayPtr[12], &arrayPtr[6], 1, 2, 3); + DrawLevelUpWindowPg2(arrayPtr[12], &arrayPtr[6], 1, 2, 3); CopyWindowToVram(arrayPtr[12], 2); schedule_bg_copy_tilemap_to_vram(2); } @@ -7288,7 +7289,7 @@ static void sub_81B9640(u8 taskId) void sub_81B968C(void) { ShowPokemonSummaryScreen(PSS_MODE_SELECT_MOVE, gPlayerParty, gSpecialVar_0x8004, gPlayerPartyCount - 1, CB2_ReturnToField); - gFieldCallback = sub_80AF168; + gFieldCallback = FieldCallback_ReturnToEventScript2; } void sub_81B96D0(void) diff --git a/src/player_pc.c b/src/player_pc.c index 6e78533e7..49b9cc5f5 100644 --- a/src/player_pc.c +++ b/src/player_pc.c @@ -20,7 +20,6 @@ #include "overworld.h" #include "palette.h" #include "party_menu.h" -#include "pokenav.h" #include "player_pc.h" #include "script.h" #include "sound.h" @@ -29,6 +28,7 @@ #include "strings.h" #include "task.h" #include "window.h" +#include "menu_specialized.h" // structures struct Struct203BCC4 @@ -645,7 +645,7 @@ static void Mailbox_ProcessInput(u8 taskId) { case LIST_NOTHING_CHOSEN: break; - case LIST_B_PRESSED: + case LIST_CANCEL: PlaySE(SE_SELECT); RemoveScrollIndicatorArrowPair(playerPCItemPageInfo.scrollIndicatorId); Mailbox_ReturnToPlayerPC(taskId); @@ -1151,7 +1151,7 @@ static void ItemStorage_ProcessInput(u8 taskId) { case LIST_NOTHING_CHOSEN: break; - case LIST_B_PRESSED: + case LIST_CANCEL: PlaySE(SE_SELECT); ItemStorage_GoBackToPlayerPCMenu(taskId); break; @@ -1226,7 +1226,7 @@ static void sub_816C4FC(u8 taskId) { case LIST_NOTHING_CHOSEN: break; - case LIST_B_PRESSED: + case LIST_CANCEL: if (gMain.newKeys & A_BUTTON) { ItemStorage_DoItemSwap(taskId, FALSE); diff --git a/src/pokeblock.c b/src/pokeblock.c index ee18d0251..325c2d5d0 100644 --- a/src/pokeblock.c +++ b/src/pokeblock.c @@ -709,7 +709,7 @@ static void HandlePokeblockListMenuItems(void) StringCopy(sPokeblockMenu->menuItemsStrings[i], gText_StowCase); sPokeblockMenu->items[i].name = sPokeblockMenu->menuItemsStrings[i]; - sPokeblockMenu->items[i].id = LIST_B_PRESSED; + sPokeblockMenu->items[i].id = LIST_CANCEL; gMultiuseListMenuTemplate = sPokeblockListMenuTemplate; gMultiuseListMenuTemplate.fontId = 7; @@ -751,7 +751,7 @@ static void sub_8135FCC(s32 pkblId) FillWindowPixelBuffer(7, PIXEL_FILL(0)); - if (pkblId != LIST_B_PRESSED) + if (pkblId != LIST_CANCEL) { pokeblock = &gSaveBlock1Ptr->pokeblocks[pkblId]; rectTilemapSrc[0] = 0x17; @@ -959,7 +959,7 @@ static void Task_FreeDataAndExitPokeblockCase(u8 taskId) if (!gPaletteFade.active) { if (sPokeblockMenu->caseId == PBLOCK_CASE_FEEDER || sPokeblockMenu->caseId == PBLOCK_CASE_GIVE) - gFieldCallback = sub_80AF168; + gFieldCallback = FieldCallback_ReturnToEventScript2; DestroyListMenuTask(data[0], &sSavedPokeblockData.lastItemPage, &sSavedPokeblockData.lastItemPos); sub_8136418(); @@ -1011,7 +1011,7 @@ static void Task_HandlePokeblockMenuInput(u8 taskId) { case LIST_NOTHING_CHOSEN: break; - case LIST_B_PRESSED: + case LIST_CANCEL: PlaySE(SE_SELECT); gSpecialVar_Result = 0xFFFF; gSpecialVar_ItemId = 0; @@ -1066,7 +1066,7 @@ static void Task_HandlePokeblocksSwapInput(u8 taskId) { case LIST_NOTHING_CHOSEN: break; - case LIST_B_PRESSED: // same id as STOW CASE field + case LIST_CANCEL: // same id as STOW CASE field PlaySE(SE_SELECT); if (gMain.newKeys & A_BUTTON) HandlePokeblocksSwap(taskId, FALSE); diff --git a/src/roulette.c b/src/roulette.c index 5c08c99a0..39db5630b 100644 --- a/src/roulette.c +++ b/src/roulette.c @@ -1984,7 +1984,7 @@ static void sub_8141E7C(u8 taskId) // end roulette ? ResetPaletteFade(); ResetSpriteData(); sub_8140418(); - gFieldCallback = sub_80AF168; + gFieldCallback = FieldCallback_ReturnToEventScript2; SetMainCallback2(CB2_ReturnToField); DestroyTask(taskId); } diff --git a/src/secret_base.c b/src/secret_base.c index 4b270e424..e19aecba3 100644 --- a/src/secret_base.c +++ b/src/secret_base.c @@ -389,7 +389,7 @@ void sub_80E8FD0(u8 taskId) } sub_80E8F9C(); WarpIntoMap(); - gFieldCallback = sub_80AF168; + gFieldCallback = FieldCallback_ReturnToEventScript2; SetMainCallback2(CB2_LoadMap); DestroyTask(taskId); break; @@ -957,7 +957,7 @@ void sub_80E9E90(u8 taskId) { case LIST_NOTHING_CHOSEN: break; - case LIST_B_PRESSED: + case LIST_CANCEL: PlaySE(SE_SELECT); DestroyListMenuTask(data[5], NULL, NULL); RemoveScrollIndicatorArrowPair(data[8]); diff --git a/src/shop.c b/src/shop.c index e03e2ab0c..32caafb64 100755 --- a/src/shop.c +++ b/src/shop.c @@ -918,7 +918,7 @@ static void Task_BuyMenu(u8 taskId) { case LIST_NOTHING_CHOSEN: break; - case LIST_B_PRESSED: + case LIST_CANCEL: PlaySE(SE_SELECT); ExitBuyMenu(taskId); break; diff --git a/src/strings.c b/src/strings.c index f81a19083..577d26f5c 100644 --- a/src/strings.c +++ b/src/strings.c @@ -1742,23 +1742,23 @@ const u8 gText_TrainerHill2F[] = _("2F"); const u8 gText_TrainerHill3F[] = _("3F"); const u8 gText_TrainerHill4F[] = _("4F"); const u8 gText_TeachWhichMoveToPkmn[] = _("Teach which move to {STR_VAR_1}?"); -const u8 gText_TeachX[] = _("Teach {STR_VAR_2}?"); -const u8 gText_PkmnLearnedMove4[] = _("{STR_VAR_1} learned\n{STR_VAR_2}!"); -const u8 gText_PkmnTryingToLearnMove[] = _("{STR_VAR_1} is trying to learn\n{STR_VAR_2}.\pBut {STR_VAR_1} can't learn more\nthan four moves.\pDelete an older move to make\nroom for {STR_VAR_2}?"); -const u8 gText_StopTryingToTeachMove[] = _("Stop trying to teach\n{STR_VAR_2}?"); -const u8 gText_12AndPoof[] = _("{PAUSE 32}1, {PAUSE 15}2, and {PAUSE 15}… {PAUSE 15}… {PAUSE 15}… {PAUSE 15}{PLAY_SE 0x0038}Poof!\p"); -const u8 gText_PkmnForgotMoveAndLearnedNew[] = _("{STR_VAR_1} forgot {STR_VAR_3}.\pAnd…\p{STR_VAR_1} learned {STR_VAR_2}."); +const u8 gText_MoveRelearnerTeachMoveConfirm[] = _("Teach {STR_VAR_2}?"); +const u8 gText_MoveRelearnerPkmnLearnedMove[] = _("{STR_VAR_1} learned\n{STR_VAR_2}!"); +const u8 gText_MoveRelearnerPkmnTryingToLearnMove[] = _("{STR_VAR_1} is trying to learn\n{STR_VAR_2}.\pBut {STR_VAR_1} can't learn more\nthan four moves.\pDelete an older move to make\nroom for {STR_VAR_2}?"); +const u8 gText_MoveRelearnerStopTryingToTeachMove[] = _("Stop trying to teach\n{STR_VAR_2}?"); +const u8 gText_MoveRelearnerAndPoof[] = _("{PAUSE 32}1, {PAUSE 15}2, and {PAUSE 15}… {PAUSE 15}… {PAUSE 15}… {PAUSE 15}{PLAY_SE 0x0038}Poof!\p"); +const u8 gText_MoveRelearnerPkmnForgotMoveAndLearnedNew[] = _("{STR_VAR_1} forgot {STR_VAR_3}.\pAnd…\p{STR_VAR_1} learned {STR_VAR_2}."); const u8 gUnknown_085EF9C8[] = _("{STR_VAR_1} did not learn the\nmove {STR_VAR_2}."); -const u8 gText_GiveUpTeachingNewMove[] = _("Give up trying to teach a new\nmove to {STR_VAR_1}?"); -const u8 gText_WhichMoveToForget2[] = _("Which move should be\nforgotten?\p"); -const u8 gText_BattleMoves2[] = _("BATTLE MOVES"); -const u8 gText_ContestMoves2[] = _("CONTEST MOVES"); +const u8 gText_MoveRelearnerGiveUp[] = _("Give up trying to teach a new\nmove to {STR_VAR_1}?"); +const u8 gText_MoveRelearnerWhichMoveToForget[] = _("Which move should be\nforgotten?\p"); +const u8 gText_MoveRelearnerBattleMoves[] = _("BATTLE MOVES"); +const u8 gText_MoveRelearnerContestMovesTitle[] = _("CONTEST MOVES"); const u8 gUnknown_085EFA4C[] = _("TYPE/"); -const u8 gText_PPSlash[] = _("PP/"); -const u8 gText_PowerSlash[] = _("POWER/"); -const u8 gText_AccuracySlash[] = _("ACCURACY/"); -const u8 gText_Appeal2[] = _("APPEAL"); -const u8 gText_Jam2[] = _("JAM"); +const u8 gText_MoveRelearnerPP[] = _("PP/"); +const u8 gText_MoveRelearnerPower[] = _("POWER/"); +const u8 gText_MoveRelearnerAccuracy[] = _("ACCURACY/"); +const u8 gText_MoveRelearnerAppeal[] = _("APPEAL"); +const u8 gText_MoveRelearnerJam[] = _("JAM"); const u8 gText_Kira[] = _("KIRA"); const u8 gText_Amy[] = _("AMY"); const u8 gText_John[] = _("JOHN"); diff --git a/src/trade.c b/src/trade.c index be6768fe3..df8f493f1 100644 --- a/src/trade.c +++ b/src/trade.c @@ -6141,7 +6141,7 @@ static void sub_807F110(u8 taskId) if (!gPaletteFade.active) { SetMainCallback2(sub_807B270); - gFieldCallback = sub_80AF168; + gFieldCallback = FieldCallback_ReturnToEventScript2; DestroyTask(taskId); } } diff --git a/src/use_pokeblock.c b/src/use_pokeblock.c index 762019ecd..b06d0cba9 100644 --- a/src/use_pokeblock.c +++ b/src/use_pokeblock.c @@ -4,6 +4,7 @@ #include "alloc.h" #include "palette.h" #include "pokenav.h" +#include "menu_specialized.h" #include "scanline_effect.h" #include "text.h" #include "bg.h" @@ -33,7 +34,7 @@ struct UsePokeblockSubStruct struct UsePokeblockStruct { u8 field_0[0x7C58]; - u8 field_7C58[0x378]; + struct UnknownStruct_81D1ED4 field_7C58; struct UsePokeblockSubStruct info; }; @@ -130,7 +131,7 @@ void sub_8166340(void) LoadOam(); ProcessSpriteCopyRequests(); TransferPlttBuffer(); - sub_81D2108(gUnknown_0203BCAC->field_7C58); + sub_81D2108(&gUnknown_0203BCAC->field_7C58); ScanlineEffect_InitHBlankDmaTransfer(); } @@ -146,7 +147,7 @@ void sub_8166380(void) { case 0: gUnknown_0203BCAC->field_0[0x7B10] = 0xFF; - sub_81D1ED4(gUnknown_0203BCAC->field_7C58); + sub_81D1ED4(&gUnknown_0203BCAC->field_7C58); gUnknown_0203BC90->field_50++; break; case 1: @@ -202,19 +203,19 @@ void sub_8166380(void) gUnknown_0203BC90->field_50++; break; case 11: - sub_81D2754(gUnknown_0203BCAC->field_7C58, &gUnknown_0203BCAC->field_0[0x7C6C]); - sub_81D20AC(gUnknown_0203BCAC->field_7C58); + sub_81D2754(&gUnknown_0203BCAC->field_7C58, gUnknown_0203BCAC->field_7C58.unk14[0]); + sub_81D20AC(&gUnknown_0203BCAC->field_7C58); gUnknown_0203BC90->field_50++; break; case 12: - if (!sub_81D20BC(gUnknown_0203BCAC->field_7C58)) + if (!sub_81D20BC(&gUnknown_0203BCAC->field_7C58)) { - sub_81D1F84(gUnknown_0203BCAC->field_7C58, &gUnknown_0203BCAC->field_7C58[0x14], &gUnknown_0203BCAC->field_7C58[0x14]); + sub_81D1F84(&gUnknown_0203BCAC->field_7C58, gUnknown_0203BCAC->field_7C58.unk14, gUnknown_0203BCAC->field_7C58.unk14); gUnknown_0203BC90->field_50++; } break; case 13: - sub_81D2230(gUnknown_0203BCAC->field_7C58); + sub_81D2230(&gUnknown_0203BCAC->field_7C58); gUnknown_0203BC90->field_50++; break; case 14: diff --git a/src/walda_phrase.c b/src/walda_phrase.c index 83004777f..e8c1e4aed 100644 --- a/src/walda_phrase.c +++ b/src/walda_phrase.c @@ -70,7 +70,7 @@ static void CB2_HandleGivenWaldaPhrase(void) } StringCopy(gStringVar1, GetWaldaPhrasePtr()); - gFieldCallback = sub_80AF168; + gFieldCallback = FieldCallback_ReturnToEventScript2; SetMainCallback2(CB2_ReturnToField); } |