#include "global.h" #include "start_menu.h" #include "menu.h" #include "safari_zone.h" #include "event_data.h" #include "window.h" #include "string_util.h" #include "text.h" #include "strings.h" #include "bg.h" #include "field_effect.h" #include "party_menu.h" #include "frontier_pass.h" #include "task.h" #include "overworld.h" #include "link.h" #include "frontier_util.h" #include "field_specials.h" #include "event_object_movement.h" #include "script.h" #include "main.h" #include "sound.h" #include "pokedex.h" #include "field_weather.h" #include "palette.h" #include "item_menu.h" #include "option_menu.h" #include "event_scripts.h" #include "save.h" #include "gpu_regs.h" #include "scanline_effect.h" #include "text_window.h" #include "load_save.h" #include "trainer_card.h" #include "international_string_util.h" #include "constants/songs.h" #include "field_player_avatar.h" #include "battle_pyramid.h" #include "battle_pyramid_bag.h" #include "battle_pike.h" #include "new_game.h" // Menu actions enum { MENU_ACTION_POKEDEX, MENU_ACTION_POKEMON, MENU_ACTION_BAG, MENU_ACTION_POKENAV, MENU_ACTION_PLAYER, MENU_ACTION_SAVE, MENU_ACTION_OPTION, MENU_ACTION_EXIT, MENU_ACTION_RETIRE_SAFARI, MENU_ACTION_PLAYER_LINK, MENU_ACTION_REST_FRONTIER, MENU_ACTION_RETIRE_FRONTIER, MENU_ACTION_PYRAMID_BAG }; // Save status enum { SAVE_IN_PROGRESS, SAVE_SUCCESS, SAVE_CANCELED, SAVE_ERROR }; // IWRAM common bool8 (*gMenuCallback)(void); // EWRAM EWRAM_DATA static u8 sSafariBallsWindowId = 0; EWRAM_DATA static u8 sBattlePyramidFloorWindowId = 0; EWRAM_DATA static u8 sStartMenuCursorPos = 0; EWRAM_DATA static u8 sNumStartMenuActions = 0; EWRAM_DATA static u8 sCurrentStartMenuActions[9] = {0}; EWRAM_DATA static u8 sUnknown_02037619[2] = {0}; EWRAM_DATA static u8 (*sSaveDialogCallback)(void) = NULL; EWRAM_DATA static u8 sSaveDialogTimer = 0; EWRAM_DATA static bool8 sSavingComplete = FALSE; EWRAM_DATA static u8 sSaveInfoWindowId = 0; // Extern variables. extern u8 gUnknown_03005DB4; // Extern functions in not decompiled files. extern void sub_80AF688(void); extern void var_800D_set_xB(void); extern void sub_808B864(void); extern void CB2_Pokedex(void); extern void PlayRainStoppingSoundEffect(void); extern void CB2_PokeNav(void); extern void ScriptUnfreezeEventObjects(void); extern void save_serialize_map(void); // Menu action callbacks static bool8 StartMenuPokedexCallback(void); static bool8 StartMenuPokemonCallback(void); static bool8 StartMenuBagCallback(void); static bool8 StartMenuPokeNavCallback(void); static bool8 StartMenuPlayerNameCallback(void); static bool8 StartMenuSaveCallback(void); static bool8 StartMenuOptionCallback(void); static bool8 StartMenuExitCallback(void); static bool8 StartMenuSafariZoneRetireCallback(void); static bool8 StartMenuLinkModePlayerNameCallback(void); static bool8 StartMenuBattlePyramidRetireCallback(void); static bool8 StartMenuBattlePyramidBagCallback(void); // Menu callbacks static bool8 SaveStartCallback(void); static bool8 SaveCallback(void); static bool8 BattlePyramidRetireStartCallback(void); static bool8 BattlePyramidRetireReturnCallback(void); static bool8 BattlePyramidRetireCallback(void); static bool8 HandleStartMenuInput(void); // Save dialog callbacks static u8 SaveConfirmSaveCallback(void); static u8 SaveYesNoCallback(void); static u8 SaveConfirmInputCallback(void); static u8 SaveFileExistsCallback(void); static u8 SaveConfirmOverwriteDefaultNoCallback(void); static u8 SaveConfirmOverwriteCallback(void); static u8 SaveOverwriteInputCallback(void); static u8 SaveSavingMessageCallback(void); static u8 SaveDoSaveCallback(void); static u8 SaveSuccessCallback(void); static u8 SaveReturnSuccessCallback(void); static u8 SaveErrorCallback(void); static u8 SaveReturnErrorCallback(void); static u8 BattlePyramidConfirmRetireCallback(void); static u8 BattlePyramidRetireYesNoCallback(void); static u8 BattlePyramidRetireInputCallback(void); // Task callbacks static void StartMenuTask(u8 taskId); static void SaveGameTask(u8 taskId); static void sub_80A0550(u8 taskId); static void sub_80A08A4(u8 taskId); // Some other callback static bool8 sub_809FA00(void); static const struct WindowTemplate sSafariBallsWindowTemplate = {0, 1, 1, 9, 4, 0xF, 8}; static const u8* const sPyramindFloorNames[] = { gText_Floor1, gText_Floor2, gText_Floor3, gText_Floor4, gText_Floor5, gText_Floor6, gText_Floor7, gText_Peak }; static const struct WindowTemplate sPyramidFloorWindowTemplate_2 = {0, 1, 1, 0xA, 4, 0xF, 8}; static const struct WindowTemplate sPyramidFloorWindowTemplate_1 = {0, 1, 1, 0xC, 4, 0xF, 8}; static const struct MenuAction sStartMenuItems[] = { {gText_MenuPokedex, {.u8_void = StartMenuPokedexCallback}}, {gText_MenuPokemon, {.u8_void = StartMenuPokemonCallback}}, {gText_MenuBag, {.u8_void = StartMenuBagCallback}}, {gText_MenuPokenav, {.u8_void = StartMenuPokeNavCallback}}, {gText_MenuPlayer, {.u8_void = StartMenuPlayerNameCallback}}, {gText_MenuSave, {.u8_void = StartMenuSaveCallback}}, {gText_MenuOption, {.u8_void = StartMenuOptionCallback}}, {gText_MenuExit, {.u8_void = StartMenuExitCallback}}, {gText_MenuRetire, {.u8_void = StartMenuSafariZoneRetireCallback}}, {gText_MenuPlayer, {.u8_void = StartMenuLinkModePlayerNameCallback}}, {gText_MenuRest, {.u8_void = StartMenuSaveCallback}}, {gText_MenuRetire, {.u8_void = StartMenuBattlePyramidRetireCallback}}, {gText_MenuBag, {.u8_void = StartMenuBattlePyramidBagCallback}} }; static const struct BgTemplate sUnknown_085105A8[] = { { .bg = 0, .charBaseIndex = 2, .mapBaseIndex = 31, .screenSize = 0, .paletteMode = 0, .priority = 0, .baseTile = 0 } }; static const struct WindowTemplate sUnknown_085105AC[] = { {0, 2, 0xF, 0x1A, 4, 0xF, 0x194}, DUMMY_WIN_TEMPLATE }; static const struct WindowTemplate sSaveInfoWindowTemplate = {0, 1, 1, 0xE, 0xA, 0xF, 8}; // Local functions static void BuildStartMenuActions(void); static void AddStartMenuAction(u8 action); static void BuildNormalStartMenu(void); static void BuildSafariZoneStartMenu(void); static void BuildLinkModeStartMenu(void); static void BuildUnionRoomStartMenu(void); static void BuildBattlePikeStartMenu(void); static void BuildBattlePyramidStartMenu(void); static void BuildMultiBattleRoomStartMenu(void); static void ShowSafariBallsWindow(void); static void ShowPyramidFloorWindow(void); static void RemoveExtraStartMenuWindows(void); static bool32 PrintStartMenuActions(s8 *pIndex, u32 count); static bool32 InitStartMenuStep(void); static void InitStartMenu(void); static void CreateStartMenuTask(TaskFunc followupFunc); static void InitSave(void); static u8 RunSaveCallback(void); static void ShowSaveMessage(const u8 *message, u8 (*saveCallback)(void)); static void sub_80A0014(void); static void HideSaveInfoWindow(void); static void SaveStartTimer(void); static bool8 SaveSuccesTimer(void); static bool8 SaveErrorTimer(void); static void InitBattlePyramidRetire(void); static void sub_80A03D8(void); static bool32 sub_80A03E4(u8 *par1); static void sub_80A0540(void); static void ShowSaveInfoWindow(void); static void RemoveSaveInfoWindow(void); static void HideStartMenuWindow(void); void SetDexPokemonPokenavFlags(void) // unused { FlagSet(FLAG_SYS_POKEDEX_GET); FlagSet(FLAG_SYS_POKEMON_GET); FlagSet(FLAG_SYS_POKENAV_GET); } static void BuildStartMenuActions(void) { sNumStartMenuActions = 0; if (is_c1_link_related_active() == TRUE) { BuildLinkModeStartMenu(); } else if (InUnionRoom() == TRUE) { BuildUnionRoomStartMenu(); } else if (GetSafariZoneFlag() == TRUE) { BuildSafariZoneStartMenu(); } else if (InBattlePike()) { BuildBattlePikeStartMenu(); } else if (InBattlePyramid()) { BuildBattlePyramidStartMenu(); } else if (InMultiBattleRoom()) { BuildMultiBattleRoomStartMenu(); } else { BuildNormalStartMenu(); } } static void AddStartMenuAction(u8 action) { AppendToList(sCurrentStartMenuActions, &sNumStartMenuActions, action); } static void BuildNormalStartMenu(void) { if (FlagGet(FLAG_SYS_POKEDEX_GET) == TRUE) { AddStartMenuAction(MENU_ACTION_POKEDEX); } if (FlagGet(FLAG_SYS_POKEMON_GET) == TRUE) { AddStartMenuAction(MENU_ACTION_POKEMON); } AddStartMenuAction(MENU_ACTION_BAG); if (FlagGet(FLAG_SYS_POKENAV_GET) == TRUE) { AddStartMenuAction(MENU_ACTION_POKENAV); } AddStartMenuAction(MENU_ACTION_PLAYER); AddStartMenuAction(MENU_ACTION_SAVE); AddStartMenuAction(MENU_ACTION_OPTION); AddStartMenuAction(MENU_ACTION_EXIT); } static void BuildSafariZoneStartMenu(void) { AddStartMenuAction(MENU_ACTION_RETIRE_SAFARI); AddStartMenuAction(MENU_ACTION_POKEDEX); AddStartMenuAction(MENU_ACTION_POKEMON); AddStartMenuAction(MENU_ACTION_BAG); AddStartMenuAction(MENU_ACTION_PLAYER); AddStartMenuAction(MENU_ACTION_OPTION); AddStartMenuAction(MENU_ACTION_EXIT); } static void BuildLinkModeStartMenu(void) { AddStartMenuAction(MENU_ACTION_POKEMON); AddStartMenuAction(MENU_ACTION_BAG); if (FlagGet(FLAG_SYS_POKENAV_GET) == TRUE) { AddStartMenuAction(MENU_ACTION_POKENAV); } AddStartMenuAction(MENU_ACTION_PLAYER_LINK); AddStartMenuAction(MENU_ACTION_OPTION); AddStartMenuAction(MENU_ACTION_EXIT); } static void BuildUnionRoomStartMenu(void) { AddStartMenuAction(MENU_ACTION_POKEMON); AddStartMenuAction(MENU_ACTION_BAG); if (FlagGet(FLAG_SYS_POKENAV_GET) == TRUE) { AddStartMenuAction(MENU_ACTION_POKENAV); } AddStartMenuAction(MENU_ACTION_PLAYER); AddStartMenuAction(MENU_ACTION_OPTION); AddStartMenuAction(MENU_ACTION_EXIT); } static void BuildBattlePikeStartMenu(void) { AddStartMenuAction(MENU_ACTION_POKEDEX); AddStartMenuAction(MENU_ACTION_POKEMON); AddStartMenuAction(MENU_ACTION_PLAYER); AddStartMenuAction(MENU_ACTION_OPTION); AddStartMenuAction(MENU_ACTION_EXIT); } static void BuildBattlePyramidStartMenu(void) { AddStartMenuAction(MENU_ACTION_POKEMON); AddStartMenuAction(MENU_ACTION_PYRAMID_BAG); AddStartMenuAction(MENU_ACTION_PLAYER); AddStartMenuAction(MENU_ACTION_REST_FRONTIER); AddStartMenuAction(MENU_ACTION_RETIRE_FRONTIER); AddStartMenuAction(MENU_ACTION_OPTION); AddStartMenuAction(MENU_ACTION_EXIT); } static void BuildMultiBattleRoomStartMenu(void) { AddStartMenuAction(MENU_ACTION_POKEMON); AddStartMenuAction(MENU_ACTION_PLAYER); AddStartMenuAction(MENU_ACTION_OPTION); AddStartMenuAction(MENU_ACTION_EXIT); } static void ShowSafariBallsWindow(void) { sSafariBallsWindowId = AddWindow(&sSafariBallsWindowTemplate); PutWindowTilemap(sSafariBallsWindowId); DrawStdWindowFrame(sSafariBallsWindowId, FALSE); ConvertIntToDecimalStringN(gStringVar1, gNumSafariBalls, STR_CONV_MODE_RIGHT_ALIGN, 2); StringExpandPlaceholders(gStringVar4, gText_SafariBallStock); AddTextPrinterParameterized(sSafariBallsWindowId, 1, gStringVar4, 0, 1, 0xFF, NULL); CopyWindowToVram(sSafariBallsWindowId, 2); } static void ShowPyramidFloorWindow(void) { if (gSaveBlock2Ptr->frontier.curChallengeBattleNum == 7) sBattlePyramidFloorWindowId = AddWindow(&sPyramidFloorWindowTemplate_1); else sBattlePyramidFloorWindowId = AddWindow(&sPyramidFloorWindowTemplate_2); PutWindowTilemap(sBattlePyramidFloorWindowId); DrawStdWindowFrame(sBattlePyramidFloorWindowId, FALSE); StringCopy(gStringVar1, sPyramindFloorNames[gSaveBlock2Ptr->frontier.curChallengeBattleNum]); StringExpandPlaceholders(gStringVar4, gText_BattlePyramidFloor); AddTextPrinterParameterized(sBattlePyramidFloorWindowId, 1, gStringVar4, 0, 1, 0xFF, NULL); CopyWindowToVram(sBattlePyramidFloorWindowId, 2); } static void RemoveExtraStartMenuWindows(void) { if (GetSafariZoneFlag()) { ClearStdWindowAndFrameToTransparent(sSafariBallsWindowId, FALSE); CopyWindowToVram(sSafariBallsWindowId, 2); RemoveWindow(sSafariBallsWindowId); } if (InBattlePyramid()) { ClearStdWindowAndFrameToTransparent(sBattlePyramidFloorWindowId, FALSE); RemoveWindow(sBattlePyramidFloorWindowId); } } static bool32 PrintStartMenuActions(s8 *pIndex, u32 count) { s8 index = *pIndex; do { if (sStartMenuItems[sCurrentStartMenuActions[index]].func.u8_void == StartMenuPlayerNameCallback) { PrintPlayerNameOnWindow(GetStartMenuWindowId(), sStartMenuItems[sCurrentStartMenuActions[index]].text, 8, (index << 4) + 9); } else { StringExpandPlaceholders(gStringVar4, sStartMenuItems[sCurrentStartMenuActions[index]].text); AddTextPrinterParameterized(GetStartMenuWindowId(), 1, gStringVar4, 8, (index << 4) + 9, 0xFF, NULL); } index++; if (index >= sNumStartMenuActions) { *pIndex = index; return TRUE; } count--; } while (count != 0); *pIndex = index; return FALSE; } static bool32 InitStartMenuStep(void) { s8 value = sUnknown_02037619[0]; switch (value) { case 0: sUnknown_02037619[0]++; break; case 1: BuildStartMenuActions(); sUnknown_02037619[0]++; break; case 2: sub_81973A4(); DrawStdWindowFrame(sub_81979C4(sNumStartMenuActions), FALSE); sUnknown_02037619[1] = 0; sUnknown_02037619[0]++; break; case 3: if (GetSafariZoneFlag()) ShowSafariBallsWindow(); if (InBattlePyramid()) ShowPyramidFloorWindow(); sUnknown_02037619[0]++; break; case 4: if (PrintStartMenuActions(&sUnknown_02037619[1], 2)) sUnknown_02037619[0]++; break; case 5: sStartMenuCursorPos = sub_81983AC(GetStartMenuWindowId(), 1, 0, 9, 16, sNumStartMenuActions, sStartMenuCursorPos); CopyWindowToVram(GetStartMenuWindowId(), TRUE); return TRUE; } return FALSE; } static void InitStartMenu(void) { sUnknown_02037619[0] = 0; sUnknown_02037619[1] = 0; while (!InitStartMenuStep()) ; } static void StartMenuTask(u8 taskId) { if (InitStartMenuStep() == TRUE) SwitchTaskToFollowupFunc(taskId); } static void CreateStartMenuTask(TaskFunc followupFunc) { u8 taskId; sUnknown_02037619[0] = 0; sUnknown_02037619[1] = 0; taskId = CreateTask(StartMenuTask, 0x50); SetTaskFuncWithFollowupFunc(taskId, StartMenuTask, followupFunc); } static bool8 sub_809FA00(void) { if (InitStartMenuStep() == FALSE) { return FALSE; } sub_80AF688(); return TRUE; } void sub_809FA18(void) // Called from field_screen.s { sUnknown_02037619[0] = 0; sUnknown_02037619[1] = 0; gFieldCallback2 = sub_809FA00; } void sub_809FA34(u8 taskId) // Referenced in field_screen.s and rom_8011DC0.s { struct Task* task = &gTasks[taskId]; switch(task->data[0]) { case 0: if (InUnionRoom() == TRUE) var_800D_set_xB(); gMenuCallback = HandleStartMenuInput; task->data[0]++; break; case 1: if (gMenuCallback() == TRUE) DestroyTask(taskId); break; } } void ShowStartMenu(void) // Called from overworld.c and field_control_avatar.s { if (!is_c1_link_related_active()) { FreezeEventObjects(); sub_808B864(); sub_808BCF4(); } CreateStartMenuTask(sub_809FA34); ScriptContext2_Enable(); } static bool8 HandleStartMenuInput(void) { if (gMain.newKeys & DPAD_UP) { PlaySE(SE_SELECT); sStartMenuCursorPos = Menu_MoveCursor(-1); } if (gMain.newKeys & DPAD_DOWN) { PlaySE(SE_SELECT); sStartMenuCursorPos = Menu_MoveCursor(1); } if (gMain.newKeys & A_BUTTON) { PlaySE(SE_SELECT); if (sStartMenuItems[sCurrentStartMenuActions[sStartMenuCursorPos]].func.u8_void == StartMenuPokedexCallback) { if (GetNationalPokedexCount(0) == 0) return FALSE; } gMenuCallback = sStartMenuItems[sCurrentStartMenuActions[sStartMenuCursorPos]].func.u8_void; if (gMenuCallback != StartMenuSaveCallback && gMenuCallback != StartMenuExitCallback && gMenuCallback != StartMenuSafariZoneRetireCallback && gMenuCallback != StartMenuBattlePyramidRetireCallback) { FadeScreen(1, 0); } return FALSE; } if (gMain.newKeys & (START_BUTTON | B_BUTTON)) { RemoveExtraStartMenuWindows(); HideStartMenu(); return TRUE; } return FALSE; } static bool8 StartMenuPokedexCallback(void) { if (!gPaletteFade.active) { IncrementGameStat(GAME_STAT_CHECKED_POKEDEX); PlayRainStoppingSoundEffect(); RemoveExtraStartMenuWindows(); CleanupOverworldWindowsAndTilemaps(); SetMainCallback2(CB2_Pokedex); return TRUE; } return FALSE; } static bool8 StartMenuPokemonCallback(void) { if (!gPaletteFade.active) { PlayRainStoppingSoundEffect(); RemoveExtraStartMenuWindows(); CleanupOverworldWindowsAndTilemaps(); SetMainCallback2(CB2_PartyMenuFromStartMenu); // Display party menu return TRUE; } return FALSE; } static bool8 StartMenuBagCallback(void) { if (!gPaletteFade.active) { PlayRainStoppingSoundEffect(); RemoveExtraStartMenuWindows(); CleanupOverworldWindowsAndTilemaps(); SetMainCallback2(CB2_BagMenuFromStartMenu); // Display bag menu return TRUE; } return FALSE; } static bool8 StartMenuPokeNavCallback(void) { if (!gPaletteFade.active) { PlayRainStoppingSoundEffect(); RemoveExtraStartMenuWindows(); CleanupOverworldWindowsAndTilemaps(); SetMainCallback2(CB2_PokeNav); // Display PokeNav return TRUE; } return FALSE; } static bool8 StartMenuPlayerNameCallback(void) { if (!gPaletteFade.active) { PlayRainStoppingSoundEffect(); RemoveExtraStartMenuWindows(); CleanupOverworldWindowsAndTilemaps(); if (is_c1_link_related_active() || InUnionRoom()) ShowPlayerTrainerCard(CB2_ReturnToFieldWithOpenMenu); // Display trainer card else if (FlagGet(FLAG_SYS_FRONTIER_PASS)) ShowFrontierPass(CB2_ReturnToFieldWithOpenMenu); // Display frontier pass else ShowPlayerTrainerCard(CB2_ReturnToFieldWithOpenMenu); // Display trainer card return TRUE; } return FALSE; } static bool8 StartMenuSaveCallback(void) { if (InBattlePyramid()) RemoveExtraStartMenuWindows(); gMenuCallback = SaveStartCallback; // Display save menu return FALSE; } static bool8 StartMenuOptionCallback(void) { if (!gPaletteFade.active) { PlayRainStoppingSoundEffect(); RemoveExtraStartMenuWindows(); CleanupOverworldWindowsAndTilemaps(); SetMainCallback2(CB2_InitOptionMenu); // Display option menu gMain.savedCallback = CB2_ReturnToFieldWithOpenMenu; return TRUE; } return FALSE; } static bool8 StartMenuExitCallback(void) { RemoveExtraStartMenuWindows(); HideStartMenu(); // Hide start menu return TRUE; } static bool8 StartMenuSafariZoneRetireCallback(void) { RemoveExtraStartMenuWindows(); HideStartMenu(); SafariZoneRetirePrompt(); return TRUE; } static bool8 StartMenuLinkModePlayerNameCallback(void) { if (!gPaletteFade.active) { PlayRainStoppingSoundEffect(); CleanupOverworldWindowsAndTilemaps(); ShowTrainerCardInLink(gUnknown_03005DB4, CB2_ReturnToFieldWithOpenMenu); return TRUE; } return FALSE; } static bool8 StartMenuBattlePyramidRetireCallback(void) { gMenuCallback = BattlePyramidRetireStartCallback; // Confirm retire return FALSE; } void sub_809FDD4(void) { ClearDialogWindowAndFrameToTransparent(0, FALSE); ScriptUnfreezeEventObjects(); CreateStartMenuTask(sub_809FA34); ScriptContext2_Enable(); } static bool8 StartMenuBattlePyramidBagCallback(void) { if (!gPaletteFade.active) { PlayRainStoppingSoundEffect(); RemoveExtraStartMenuWindows(); CleanupOverworldWindowsAndTilemaps(); SetMainCallback2(CB2_PyramidBagMenuFromStartMenu); return TRUE; } return FALSE; } static bool8 SaveStartCallback(void) { InitSave(); gMenuCallback = SaveCallback; return FALSE; } static bool8 SaveCallback(void) { switch (RunSaveCallback()) { case SAVE_IN_PROGRESS: return FALSE; case SAVE_CANCELED: // Back to start menu ClearDialogWindowAndFrameToTransparent(0, FALSE); InitStartMenu(); gMenuCallback = HandleStartMenuInput; return FALSE; case SAVE_SUCCESS: case SAVE_ERROR: // Close start menu ClearDialogWindowAndFrameToTransparent(0, TRUE); ScriptUnfreezeEventObjects(); ScriptContext2_Disable(); SoftResetInBattlePyramid(); return TRUE; } return FALSE; } static bool8 BattlePyramidRetireStartCallback(void) { InitBattlePyramidRetire(); gMenuCallback = BattlePyramidRetireCallback; return FALSE; } static bool8 BattlePyramidRetireReturnCallback(void) { InitStartMenu(); gMenuCallback = HandleStartMenuInput; return FALSE; } static bool8 BattlePyramidRetireCallback(void) { switch (RunSaveCallback()) { case SAVE_SUCCESS: // No (Stay in battle pyramid) RemoveExtraStartMenuWindows(); gMenuCallback = BattlePyramidRetireReturnCallback; return FALSE; case SAVE_IN_PROGRESS: return FALSE; case SAVE_CANCELED: // Yes (Retire from battle pyramid) ClearDialogWindowAndFrameToTransparent(0, TRUE); ScriptUnfreezeEventObjects(); ScriptContext2_Disable(); ScriptContext1_SetupScript(BattleFrontier_BattlePyramidEmptySquare_EventScript_252C88); return TRUE; } return FALSE; } static void InitSave(void) { save_serialize_map(); sSaveDialogCallback = SaveConfirmSaveCallback; sSavingComplete = FALSE; } static u8 RunSaveCallback(void) { // True if text is still printing if (RunTextPrintersAndIsPrinter0Active() == TRUE) { return SAVE_IN_PROGRESS; } sSavingComplete = FALSE; return sSaveDialogCallback(); } void SaveGame(void) // Called from cable_club.s { InitSave(); CreateTask(SaveGameTask, 0x50); } static void ShowSaveMessage(const u8 *message, u8 (*saveCallback)(void)) { StringExpandPlaceholders(gStringVar4, message); sub_819786C(0, TRUE); AddTextPrinterForMessage_2(TRUE); sSavingComplete = TRUE; sSaveDialogCallback = saveCallback; } static void SaveGameTask(u8 taskId) { u8 status = RunSaveCallback(); switch (status) { case SAVE_CANCELED: case SAVE_ERROR: gSpecialVar_Result = 0; break; case SAVE_SUCCESS: gSpecialVar_Result = status; break; case SAVE_IN_PROGRESS: return; } DestroyTask(taskId); EnableBothScriptContexts(); } static void sub_80A0014(void) { ClearDialogWindowAndFrame(0, TRUE); } static void HideSaveInfoWindow(void) { RemoveSaveInfoWindow(); } static void SaveStartTimer(void) { sSaveDialogTimer = 60; } static bool8 SaveSuccesTimer(void) { sSaveDialogTimer--; if (gMain.heldKeys & A_BUTTON) { PlaySE(SE_SELECT); return TRUE; } else if (sSaveDialogTimer == 0) { return TRUE; } return FALSE; } static bool8 SaveErrorTimer(void) { if (sSaveDialogTimer != 0) { sSaveDialogTimer--; } else if (gMain.heldKeys & A_BUTTON) { return TRUE; } return FALSE; } static u8 SaveConfirmSaveCallback(void) { ClearStdWindowAndFrame(GetStartMenuWindowId(), FALSE); RemoveStartMenuWindow(); ShowSaveInfoWindow(); if (InBattlePyramid()) { ShowSaveMessage(gText_BattlePyramidConfirmRest, SaveYesNoCallback); } else { ShowSaveMessage(gText_ConfirmSave, SaveYesNoCallback); } return SAVE_IN_PROGRESS; } static u8 SaveYesNoCallback(void) { DisplayYesNoMenuDefaultYes(); // Show Yes/No menu sSaveDialogCallback = SaveConfirmInputCallback; return SAVE_IN_PROGRESS; } static u8 SaveConfirmInputCallback(void) { switch (Menu_ProcessInputNoWrapClearOnChoose()) { case 0: // Yes switch (gSaveFileStatus) { case 0: case 2: if (gDifferentSaveFile == FALSE) { sSaveDialogCallback = SaveFileExistsCallback; return SAVE_IN_PROGRESS; } sSaveDialogCallback = SaveSavingMessageCallback; return SAVE_IN_PROGRESS; default: sSaveDialogCallback = SaveFileExistsCallback; return SAVE_IN_PROGRESS; } case -1: // B Button case 1: // No HideSaveInfoWindow(); sub_80A0014(); return SAVE_CANCELED; } return SAVE_IN_PROGRESS; } // A different save file exists static u8 SaveFileExistsCallback(void) { if (gDifferentSaveFile == TRUE) { ShowSaveMessage(gText_DifferentSaveFile, SaveConfirmOverwriteDefaultNoCallback); } else { ShowSaveMessage(gText_AlreadySavedFile, SaveConfirmOverwriteCallback); } return SAVE_IN_PROGRESS; } static u8 SaveConfirmOverwriteDefaultNoCallback(void) { DisplayYesNoMenuWithDefault(1); // Show Yes/No menu (No selected as default) sSaveDialogCallback = SaveOverwriteInputCallback; return SAVE_IN_PROGRESS; } static u8 SaveConfirmOverwriteCallback(void) { DisplayYesNoMenuDefaultYes(); // Show Yes/No menu sSaveDialogCallback = SaveOverwriteInputCallback; return SAVE_IN_PROGRESS; } static u8 SaveOverwriteInputCallback(void) { switch (Menu_ProcessInputNoWrapClearOnChoose()) { case 0: // Yes sSaveDialogCallback = SaveSavingMessageCallback; return SAVE_IN_PROGRESS; case -1: // B Button case 1: // No HideSaveInfoWindow(); sub_80A0014(); return SAVE_CANCELED; } return SAVE_IN_PROGRESS; } static u8 SaveSavingMessageCallback(void) { ShowSaveMessage(gText_SavingDontTurnOff, SaveDoSaveCallback); return SAVE_IN_PROGRESS; } static u8 SaveDoSaveCallback(void) { u8 saveStatus; IncrementGameStat(GAME_STAT_SAVED_GAME); sub_81A9E90(); if (gDifferentSaveFile == TRUE) { saveStatus = TrySavingData(SAVE_OVERWRITE_DIFFERENT_FILE); gDifferentSaveFile = FALSE; } else { saveStatus = TrySavingData(SAVE_NORMAL); } if (saveStatus == 1) // Save succeded { ShowSaveMessage(gText_PlayerSavedGame, SaveSuccessCallback); } else // Save error { ShowSaveMessage(gText_SaveError, SaveErrorCallback); } SaveStartTimer(); return SAVE_IN_PROGRESS; } static u8 SaveSuccessCallback(void) { if (!IsTextPrinterActive(0)) { PlaySE(SE_SAVE); sSaveDialogCallback = SaveReturnSuccessCallback; } return SAVE_IN_PROGRESS; } static u8 SaveReturnSuccessCallback(void) { if (!IsSEPlaying() && SaveSuccesTimer()) { HideSaveInfoWindow(); return SAVE_SUCCESS; } else { return SAVE_IN_PROGRESS; } } static u8 SaveErrorCallback(void) { if (!IsTextPrinterActive(0)) { PlaySE(SE_BOO); sSaveDialogCallback = SaveReturnErrorCallback; } return SAVE_IN_PROGRESS; } static u8 SaveReturnErrorCallback(void) { if (!SaveErrorTimer()) { return SAVE_IN_PROGRESS; } else { HideSaveInfoWindow(); return SAVE_ERROR; } } static void InitBattlePyramidRetire(void) { sSaveDialogCallback = BattlePyramidConfirmRetireCallback; sSavingComplete = FALSE; } static u8 BattlePyramidConfirmRetireCallback(void) { ClearStdWindowAndFrame(GetStartMenuWindowId(), FALSE); RemoveStartMenuWindow(); ShowSaveMessage(gText_BattlePyramidConfirmRetire, BattlePyramidRetireYesNoCallback); return SAVE_IN_PROGRESS; } static u8 BattlePyramidRetireYesNoCallback(void) { DisplayYesNoMenuWithDefault(1); // Show Yes/No menu (No selected as default) sSaveDialogCallback = BattlePyramidRetireInputCallback; return SAVE_IN_PROGRESS; } static u8 BattlePyramidRetireInputCallback(void) { switch (Menu_ProcessInputNoWrapClearOnChoose()) { case 0: // Yes return SAVE_CANCELED; case -1: // B Button case 1: // No sub_80A0014(); return SAVE_SUCCESS; } return SAVE_IN_PROGRESS; } static void sub_80A03D8(void) { TransferPlttBuffer(); } static bool32 sub_80A03E4(u8 *par1) { switch (*par1) { case 0: SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_MODE_0); SetVBlankCallback(NULL); ScanlineEffect_Stop(); DmaClear16(3, PLTT, PLTT_SIZE); DmaFillLarge16(3, 0, (void *)(VRAM + 0x0), 0x18000, 0x1000); break; case 1: ResetSpriteData(); ResetTasks(); ResetPaletteFade(); ScanlineEffect_Clear(); break; case 2: ResetBgsAndClearDma3BusyFlags(0); InitBgsFromTemplates(0, sUnknown_085105A8, ARRAY_COUNT(sUnknown_085105A8)); InitWindows(sUnknown_085105AC); LoadUserWindowBorderGfx_(0, 8, 224); sub_81978B0(240); break; case 3: ShowBg(0); BlendPalettes(-1, 16, 0); SetVBlankCallback(sub_80A03D8); EnableInterrupts(1); break; case 4: return TRUE; } (*par1)++; return FALSE; } void sub_80A0514(void) // Called from cable_club.s { if (sub_80A03E4(&gMain.state)) { CreateTask(sub_80A0550, 0x50); SetMainCallback2(sub_80A0540); } } static void sub_80A0540(void) { RunTasks(); UpdatePaletteFade(); } static void sub_80A0550(u8 taskId) { s16 *step = gTasks[taskId].data; if (!gPaletteFade.active) { switch (*step) { case 0: FillWindowPixelBuffer(0, PALETTE_NUM_TO_FILL_VALUE(1)); AddTextPrinterParameterized2(0, 1, gText_SavingDontTurnOffPower, 255, NULL, 2, 1, 3); sub_8098858(0, 8, 14); PutWindowTilemap(0); CopyWindowToVram(0, 3); BeginNormalPaletteFade(0xFFFFFFFF, 0, 16, 0, 0); if (gWirelessCommType != 0 && InUnionRoom()) { if (sub_800A07C()) { *step = 1; } else { *step = 5; } } else { gSoftResetDisabled = 1; *step = 1; } break; case 1: SetContinueGameWarpStatusToDynamicWarp(); sub_8153430(); *step = 2; break; case 2: if (sub_8153474()) { ClearContinueGameWarpStatus2(); *step = 3; gSoftResetDisabled = 0; } break; case 3: BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, 0); *step = 4; break; case 4: FreeAllWindowBuffers(); SetMainCallback2(gMain.savedCallback); DestroyTask(taskId); break; case 5: CreateTask(sub_8153688, 0x5); *step = 6; break; case 6: if (!FuncIsActiveTask(sub_8153688)) { *step = 3; } break; } } } static void ShowSaveInfoWindow(void) { struct WindowTemplate saveInfoWindow = sSaveInfoWindowTemplate; u8 gender; u8 color; u32 xOffset; u32 yOffset; if (!FlagGet(FLAG_SYS_POKEDEX_GET)) { saveInfoWindow.height -= 2; } sSaveInfoWindowId = AddWindow(&saveInfoWindow); DrawStdWindowFrame(sSaveInfoWindowId, FALSE); gender = gSaveBlock2Ptr->playerGender; color = TEXT_COLOR_RED; // Red when female, blue when male. if (gender == MALE) { color = TEXT_COLOR_BLUE; } // Print region name yOffset = 1; sub_819A344(3, gStringVar4, TEXT_COLOR_GREEN); AddTextPrinterParameterized(sSaveInfoWindowId, 1, gStringVar4, 0, yOffset, 0xFF, NULL); // Print player name yOffset = 0x11; AddTextPrinterParameterized(sSaveInfoWindowId, 1, gText_SavingPlayer, 0, yOffset, 0xFF, NULL); sub_819A344(0, gStringVar4, color); xOffset = GetStringRightAlignXOffset(1, gStringVar4, 0x70); PrintPlayerNameOnWindow(sSaveInfoWindowId, gStringVar4, xOffset, yOffset); // Print badge count yOffset = 0x21; AddTextPrinterParameterized(sSaveInfoWindowId, 1, gText_SavingBadges, 0, yOffset, 0xFF, NULL); sub_819A344(4, gStringVar4, color); xOffset = GetStringRightAlignXOffset(1, gStringVar4, 0x70); AddTextPrinterParameterized(sSaveInfoWindowId, 1, gStringVar4, xOffset, yOffset, 0xFF, NULL); if (FlagGet(FLAG_SYS_POKEDEX_GET) == TRUE) { // Print pokedex count yOffset = 0x31; AddTextPrinterParameterized(sSaveInfoWindowId, 1, gText_SavingPokedex, 0, yOffset, 0xFF, NULL); sub_819A344(1, gStringVar4, color); xOffset = GetStringRightAlignXOffset(1, gStringVar4, 0x70); AddTextPrinterParameterized(sSaveInfoWindowId, 1, gStringVar4, xOffset, yOffset, 0xFF, NULL); } // Print play time yOffset += 0x10; AddTextPrinterParameterized(sSaveInfoWindowId, 1, gText_SavingTime, 0, yOffset, 0xFF, NULL); sub_819A344(2, gStringVar4, color); xOffset = GetStringRightAlignXOffset(1, gStringVar4, 0x70); AddTextPrinterParameterized(sSaveInfoWindowId, 1, gStringVar4, xOffset, yOffset, 0xFF, NULL); CopyWindowToVram(sSaveInfoWindowId, 2); } static void RemoveSaveInfoWindow(void) { ClearStdWindowAndFrame(sSaveInfoWindowId, FALSE); RemoveWindow(sSaveInfoWindowId); } static void sub_80A08A4(u8 taskId) { if (!FuncIsActiveTask(sub_8153688)) { DestroyTask(taskId); EnableBothScriptContexts(); } } void sub_80A08CC(void) // Referenced in data/specials.inc and data/scripts/maps/BattleFrontier_BattleTowerLobby.inc { u8 taskId = CreateTask(sub_8153688, 0x5); gTasks[taskId].data[2] = 1; gTasks[CreateTask(sub_80A08A4, 0x6)].data[1] = taskId; } static void HideStartMenuWindow(void) { ClearStdWindowAndFrame(GetStartMenuWindowId(), TRUE); RemoveStartMenuWindow(); ScriptUnfreezeEventObjects(); ScriptContext2_Disable(); } void HideStartMenu(void) // Called from map_name_popup.s { PlaySE(SE_SELECT); HideStartMenuWindow(); } void AppendToList(u8 *list, u8 *pos, u8 newEntry) { list[*pos] = newEntry; (*pos)++; }