#include "global.h" #include "battle_pike.h" #include "battle_pyramid.h" #include "battle_pyramid_bag.h" #include "bg.h" #include "event_data.h" #include "event_object_movement.h" #include "event_object_lock.h" #include "event_scripts.h" #include "fieldmap.h" #include "field_effect.h" #include "field_player_avatar.h" #include "field_specials.h" #include "field_weather.h" #include "field_screen_effect.h" #include "frontier_pass.h" #include "frontier_util.h" #include "gpu_regs.h" #include "international_string_util.h" #include "item_menu.h" #include "link.h" #include "load_save.h" #include "main.h" #include "menu.h" #include "new_game.h" #include "option_menu.h" #include "overworld.h" #include "palette.h" #include "party_menu.h" #include "pokedex.h" #include "pokenav.h" #include "safari_zone.h" #include "save.h" #include "scanline_effect.h" #include "script.h" #include "sound.h" #include "start_menu.h" #include "strings.h" #include "string_util.h" #include "task.h" #include "text.h" #include "text_window.h" #include "trainer_card.h" #include "window.h" #include "constants/songs.h" #include "union_room.h" #include "constants/rgb.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 sInitStartMenuData[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; // 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 Task_SaveAfterLinkBattle(u8 taskId); static void Task_WaitForBattleTowerLinkSave(u8 taskId); static bool8 FieldCB_ReturnToFieldStartMenu(void); static const struct WindowTemplate sSafariBallsWindowTemplate = {0, 1, 1, 9, 4, 0xF, 8}; static const u8* const sPyramidFloorNames[] = { 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 sBgTemplates_LinkBattleSave[] = { { .bg = 0, .charBaseIndex = 2, .mapBaseIndex = 31, .screenSize = 0, .paletteMode = 0, .priority = 0, .baseTile = 0 } }; static const struct WindowTemplate sWindowTemplates_LinkBattleSave[] = { { .bg = 0, .tilemapLeft = 2, .tilemapTop = 15, .width = 26, .height = 4, .paletteNum = 15, .baseBlock = 0x194 }, DUMMY_WIN_TEMPLATE }; static const struct WindowTemplate sSaveInfoWindowTemplate = { .bg = 0, .tilemapLeft = 1, .tilemapTop = 1, .width = 14, .height = 10, .paletteNum = 15, .baseBlock = 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 BuildMultiPartnerRoomStartMenu(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 HideSaveMessageWindow(void); static void HideSaveInfoWindow(void); static void SaveStartTimer(void); static bool8 SaveSuccesTimer(void); static bool8 SaveErrorTimer(void); static void InitBattlePyramidRetire(void); static void VBlankCB_LinkBattleSave(void); static bool32 InitSaveWindowAfterLinkBattle(u8 *par1); static void CB2_SaveAfterLinkBattle(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 (IsOverworldLinkActive() == TRUE) { BuildLinkModeStartMenu(); } else if (InUnionRoom() == TRUE) { BuildUnionRoomStartMenu(); } else if (GetSafariZoneFlag() == TRUE) { BuildSafariZoneStartMenu(); } else if (InBattlePike()) { BuildBattlePikeStartMenu(); } else if (InBattlePyramid()) { BuildBattlePyramidStartMenu(); } else if (InMultiPartnerRoom()) { BuildMultiPartnerRoomStartMenu(); } 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 BuildMultiPartnerRoomStartMenu(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, FONT_NORMAL, gStringVar4, 0, 1, TEXT_SKIP_DRAW, NULL); CopyWindowToVram(sSafariBallsWindowId, COPYWIN_GFX); } 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, sPyramidFloorNames[gSaveBlock2Ptr->frontier.curChallengeBattleNum]); StringExpandPlaceholders(gStringVar4, gText_BattlePyramidFloor); AddTextPrinterParameterized(sBattlePyramidFloorWindowId, FONT_NORMAL, gStringVar4, 0, 1, TEXT_SKIP_DRAW, NULL); CopyWindowToVram(sBattlePyramidFloorWindowId, COPYWIN_GFX); } static void RemoveExtraStartMenuWindows(void) { if (GetSafariZoneFlag()) { ClearStdWindowAndFrameToTransparent(sSafariBallsWindowId, FALSE); CopyWindowToVram(sSafariBallsWindowId, COPYWIN_GFX); 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(), FONT_NORMAL, gStringVar4, 8, (index << 4) + 9, TEXT_SKIP_DRAW, NULL); } index++; if (index >= sNumStartMenuActions) { *pIndex = index; return TRUE; } count--; } while (count != 0); *pIndex = index; return FALSE; } static bool32 InitStartMenuStep(void) { s8 state = sInitStartMenuData[0]; switch (state) { case 0: sInitStartMenuData[0]++; break; case 1: BuildStartMenuActions(); sInitStartMenuData[0]++; break; case 2: LoadMessageBoxAndBorderGfx(); DrawStdWindowFrame(AddStartMenuWindow(sNumStartMenuActions), FALSE); sInitStartMenuData[1] = 0; sInitStartMenuData[0]++; break; case 3: if (GetSafariZoneFlag()) ShowSafariBallsWindow(); if (InBattlePyramid()) ShowPyramidFloorWindow(); sInitStartMenuData[0]++; break; case 4: if (PrintStartMenuActions(&sInitStartMenuData[1], 2)) sInitStartMenuData[0]++; break; case 5: sStartMenuCursorPos = InitMenuNormal(GetStartMenuWindowId(), FONT_NORMAL, 0, 9, 16, sNumStartMenuActions, sStartMenuCursorPos); CopyWindowToVram(GetStartMenuWindowId(), COPYWIN_MAP); return TRUE; } return FALSE; } static void InitStartMenu(void) { sInitStartMenuData[0] = 0; sInitStartMenuData[1] = 0; while (!InitStartMenuStep()) ; } static void StartMenuTask(u8 taskId) { if (InitStartMenuStep() == TRUE) SwitchTaskToFollowupFunc(taskId); } static void CreateStartMenuTask(TaskFunc followupFunc) { u8 taskId; sInitStartMenuData[0] = 0; sInitStartMenuData[1] = 0; taskId = CreateTask(StartMenuTask, 0x50); SetTaskFuncWithFollowupFunc(taskId, StartMenuTask, followupFunc); } static bool8 FieldCB_ReturnToFieldStartMenu(void) { if (InitStartMenuStep() == FALSE) { return FALSE; } ReturnToFieldOpenStartMenu(); return TRUE; } void ShowReturnToFieldStartMenu(void) { sInitStartMenuData[0] = 0; sInitStartMenuData[1] = 0; gFieldCallback2 = FieldCB_ReturnToFieldStartMenu; } void Task_ShowStartMenu(u8 taskId) { struct Task* task = &gTasks[taskId]; switch(task->data[0]) { case 0: if (InUnionRoom() == TRUE) SetUsingUnionRoomStartMenu(); gMenuCallback = HandleStartMenuInput; task->data[0]++; break; case 1: if (gMenuCallback() == TRUE) DestroyTask(taskId); break; } } void ShowStartMenu(void) { if (!IsOverworldLinkActive()) { FreezeObjectEvents(); PlayerFreeze(); StopPlayerAvatar(); } CreateStartMenuTask(Task_ShowStartMenu); ScriptContext2_Enable(); } static bool8 HandleStartMenuInput(void) { if (JOY_NEW(DPAD_UP)) { PlaySE(SE_SELECT); sStartMenuCursorPos = Menu_MoveCursor(-1); } if (JOY_NEW(DPAD_DOWN)) { PlaySE(SE_SELECT); sStartMenuCursorPos = Menu_MoveCursor(1); } if (JOY_NEW(A_BUTTON)) { PlaySE(SE_SELECT); if (sStartMenuItems[sCurrentStartMenuActions[sStartMenuCursorPos]].func.u8_void == StartMenuPokedexCallback) { if (GetNationalPokedexCount(FLAG_GET_SEEN) == 0) return FALSE; } gMenuCallback = sStartMenuItems[sCurrentStartMenuActions[sStartMenuCursorPos]].func.u8_void; if (gMenuCallback != StartMenuSaveCallback && gMenuCallback != StartMenuExitCallback && gMenuCallback != StartMenuSafariZoneRetireCallback && gMenuCallback != StartMenuBattlePyramidRetireCallback) { FadeScreen(FADE_TO_BLACK, 0); } return FALSE; } if (JOY_NEW(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_OpenPokedex); 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_InitPokeNav); // Display PokeNav return TRUE; } return FALSE; } static bool8 StartMenuPlayerNameCallback(void) { if (!gPaletteFade.active) { PlayRainStoppingSoundEffect(); RemoveExtraStartMenuWindows(); CleanupOverworldWindowsAndTilemaps(); if (IsOverworldLinkActive() || 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(gLocalLinkPlayerId, CB2_ReturnToFieldWithOpenMenu); return TRUE; } return FALSE; } static bool8 StartMenuBattlePyramidRetireCallback(void) { gMenuCallback = BattlePyramidRetireStartCallback; // Confirm retire return FALSE; } // Functionally unused void ShowBattlePyramidStartMenu(void) { ClearDialogWindowAndFrameToTransparent(0, FALSE); ScriptUnfreezeObjectEvents(); CreateStartMenuTask(Task_ShowStartMenu); 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); ScriptUnfreezeObjectEvents(); 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); ScriptUnfreezeObjectEvents(); ScriptContext2_Disable(); ScriptContext1_SetupScript(BattlePyramid_Retire); return TRUE; } return FALSE; } static void InitSave(void) { SaveMapView(); 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) { InitSave(); CreateTask(SaveGameTask, 0x50); } static void ShowSaveMessage(const u8 *message, u8 (*saveCallback)(void)) { StringExpandPlaceholders(gStringVar4, message); LoadMessageBoxAndFrameGfx(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 HideSaveMessageWindow(void) { ClearDialogWindowAndFrame(0, TRUE); } static void HideSaveInfoWindow(void) { RemoveSaveInfoWindow(); } static void SaveStartTimer(void) { sSaveDialogTimer = 60; } static bool8 SaveSuccesTimer(void) { sSaveDialogTimer--; if (JOY_HELD(A_BUTTON)) { PlaySE(SE_SELECT); return TRUE; } if (sSaveDialogTimer == 0) { return TRUE; } return FALSE; } static bool8 SaveErrorTimer(void) { if (sSaveDialogTimer != 0) { sSaveDialogTimer--; } else if (JOY_HELD(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 SAVE_STATUS_EMPTY: case SAVE_STATUS_CORRUPT: 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(); HideSaveMessageWindow(); return SAVE_CANCELED; } return SAVE_IN_PROGRESS; } // A different save file exists static u8 SaveFileExistsCallback(void) { if (gDifferentSaveFile == TRUE) { ShowSaveMessage(gText_DifferentSaveFile, SaveConfirmOverwriteDefaultNoCallback); } else { sSaveDialogCallback = SaveSavingMessageCallback; } 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(); HideSaveMessageWindow(); 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); PausePyramidChallenge(); if (gDifferentSaveFile == TRUE) { saveStatus = TrySavingData(SAVE_OVERWRITE_DIFFERENT_FILE); gDifferentSaveFile = FALSE; } else { saveStatus = TrySavingData(SAVE_NORMAL); } if (saveStatus == SAVE_STATUS_OK) ShowSaveMessage(gText_PlayerSavedGame, SaveSuccessCallback); else 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 HideSaveMessageWindow(); return SAVE_SUCCESS; } return SAVE_IN_PROGRESS; } static void VBlankCB_LinkBattleSave(void) { TransferPlttBuffer(); } static bool32 InitSaveWindowAfterLinkBattle(u8 *state) { switch (*state) { case 0: SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_MODE_0); SetVBlankCallback(NULL); ScanlineEffect_Stop(); DmaClear16(3, PLTT, PLTT_SIZE); DmaFillLarge16(3, 0, (void *)VRAM, VRAM_SIZE, 0x1000); break; case 1: ResetSpriteData(); ResetTasks(); ResetPaletteFade(); ScanlineEffect_Clear(); break; case 2: ResetBgsAndClearDma3BusyFlags(0); InitBgsFromTemplates(0, sBgTemplates_LinkBattleSave, ARRAY_COUNT(sBgTemplates_LinkBattleSave)); InitWindows(sWindowTemplates_LinkBattleSave); LoadUserWindowBorderGfx_(0, 8, 224); Menu_LoadStdPalAt(240); break; case 3: ShowBg(0); BlendPalettes(PALETTES_ALL, 16, RGB_BLACK); SetVBlankCallback(VBlankCB_LinkBattleSave); EnableInterrupts(1); break; case 4: return TRUE; } (*state)++; return FALSE; } void CB2_SetUpSaveAfterLinkBattle(void) { if (InitSaveWindowAfterLinkBattle(&gMain.state)) { CreateTask(Task_SaveAfterLinkBattle, 0x50); SetMainCallback2(CB2_SaveAfterLinkBattle); } } static void CB2_SaveAfterLinkBattle(void) { RunTasks(); UpdatePaletteFade(); } static void Task_SaveAfterLinkBattle(u8 taskId) { s16 *state = gTasks[taskId].data; if (!gPaletteFade.active) { switch (*state) { case 0: FillWindowPixelBuffer(0, PIXEL_FILL(1)); AddTextPrinterParameterized2(0, FONT_NORMAL, gText_SavingDontTurnOffPower, TEXT_SKIP_DRAW, NULL, TEXT_COLOR_DARK_GRAY, TEXT_COLOR_WHITE, TEXT_COLOR_LIGHT_GRAY); DrawTextBorderOuter(0, 8, 14); PutWindowTilemap(0); CopyWindowToVram(0, COPYWIN_FULL); BeginNormalPaletteFade(PALETTES_ALL, 0, 16, 0, RGB_BLACK); if (gWirelessCommType != 0 && InUnionRoom()) { if (Link_AnyPartnersPlayingFRLG_JP()) { *state = 1; } else { *state = 5; } } else { gSoftResetDisabled = 1; *state = 1; } break; case 1: SetContinueGameWarpStatusToDynamicWarp(); WriteSaveBlock2(); *state = 2; break; case 2: if (WriteSaveBlock1Sector()) { ClearContinueGameWarpStatus2(); *state = 3; gSoftResetDisabled = 0; } break; case 3: BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 16, RGB_BLACK); *state = 4; break; case 4: FreeAllWindowBuffers(); SetMainCallback2(gMain.savedCallback); DestroyTask(taskId); break; case 5: CreateTask(Task_LinkFullSave, 5); *state = 6; break; case 6: if (!FuncIsActiveTask(Task_LinkFullSave)) { *state = 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; BufferSaveMenuText(SAVE_MENU_LOCATION, gStringVar4, TEXT_COLOR_GREEN); AddTextPrinterParameterized(sSaveInfoWindowId, FONT_NORMAL, gStringVar4, 0, yOffset, TEXT_SKIP_DRAW, NULL); // Print player name yOffset += 16; AddTextPrinterParameterized(sSaveInfoWindowId, FONT_NORMAL, gText_SavingPlayer, 0, yOffset, TEXT_SKIP_DRAW, NULL); BufferSaveMenuText(SAVE_MENU_NAME, gStringVar4, color); xOffset = GetStringRightAlignXOffset(FONT_NORMAL, gStringVar4, 0x70); PrintPlayerNameOnWindow(sSaveInfoWindowId, gStringVar4, xOffset, yOffset); // Print badge count yOffset += 16; AddTextPrinterParameterized(sSaveInfoWindowId, FONT_NORMAL, gText_SavingBadges, 0, yOffset, TEXT_SKIP_DRAW, NULL); BufferSaveMenuText(SAVE_MENU_BADGES, gStringVar4, color); xOffset = GetStringRightAlignXOffset(FONT_NORMAL, gStringVar4, 0x70); AddTextPrinterParameterized(sSaveInfoWindowId, FONT_NORMAL, gStringVar4, xOffset, yOffset, TEXT_SKIP_DRAW, NULL); if (FlagGet(FLAG_SYS_POKEDEX_GET) == TRUE) { // Print pokedex count yOffset += 16; AddTextPrinterParameterized(sSaveInfoWindowId, FONT_NORMAL, gText_SavingPokedex, 0, yOffset, TEXT_SKIP_DRAW, NULL); BufferSaveMenuText(SAVE_MENU_CAUGHT, gStringVar4, color); xOffset = GetStringRightAlignXOffset(FONT_NORMAL, gStringVar4, 0x70); AddTextPrinterParameterized(sSaveInfoWindowId, FONT_NORMAL, gStringVar4, xOffset, yOffset, TEXT_SKIP_DRAW, NULL); } // Print play time yOffset += 16; AddTextPrinterParameterized(sSaveInfoWindowId, FONT_NORMAL, gText_SavingTime, 0, yOffset, TEXT_SKIP_DRAW, NULL); BufferSaveMenuText(SAVE_MENU_PLAY_TIME, gStringVar4, color); xOffset = GetStringRightAlignXOffset(FONT_NORMAL, gStringVar4, 0x70); AddTextPrinterParameterized(sSaveInfoWindowId, FONT_NORMAL, gStringVar4, xOffset, yOffset, TEXT_SKIP_DRAW, NULL); CopyWindowToVram(sSaveInfoWindowId, COPYWIN_GFX); } static void RemoveSaveInfoWindow(void) { ClearStdWindowAndFrame(sSaveInfoWindowId, FALSE); RemoveWindow(sSaveInfoWindowId); } static void Task_WaitForBattleTowerLinkSave(u8 taskId) { if (!FuncIsActiveTask(Task_LinkFullSave)) { DestroyTask(taskId); EnableBothScriptContexts(); } } #define tInBattleTower data[2] void SaveForBattleTowerLink(void) { u8 taskId = CreateTask(Task_LinkFullSave, 5); gTasks[taskId].tInBattleTower = TRUE; gTasks[CreateTask(Task_WaitForBattleTowerLinkSave, 6)].data[1] = taskId; } #undef tInBattleTower static void HideStartMenuWindow(void) { ClearStdWindowAndFrame(GetStartMenuWindowId(), TRUE); RemoveStartMenuWindow(); ScriptUnfreezeObjectEvents(); ScriptContext2_Disable(); } void HideStartMenu(void) { PlaySE(SE_SELECT); HideStartMenuWindow(); } void AppendToList(u8 *list, u8 *pos, u8 newEntry) { list[*pos] = newEntry; (*pos)++; }