diff options
Diffstat (limited to 'src/main_menu.c')
-rw-r--r-- | src/main_menu.c | 217 |
1 files changed, 174 insertions, 43 deletions
diff --git a/src/main_menu.c b/src/main_menu.c index 82a30aa59..e6e29d942 100644 --- a/src/main_menu.c +++ b/src/main_menu.c @@ -39,6 +39,135 @@ #include "title_screen.h" #include "window.h" +/* + * Main menu state machine + * ----------------------- + * + * Entry point: CB2_InitMainMenu + * + * Note: States advance sequentially unless otherwise stated. + * + * CB2_InitMainMenu / CB2_ReinitMainMenu + * - Both of these states call InitMainMenu, which does all the work. + * - In the Reinit case, the init code will check if the user came from + * the options screen. If they did, then the options menu item is + * pre-selected. + * + * Task_MainMenuCheckSaveFile + * - Determines how many menu options to show based on whether + * the save file is Ok, empty, corrupted, etc. + * - If there was an error loading the save file, advance to + * Task_WaitForSaveFileErrorWindow. + * - If there were no errors, advance to Task_MainMenuCheckBattery. + * - Note that the check to enable Mystery Events would normally happen + * here, but this version of Emerald has them disabled. + * + * Task_WaitForSaveFileErrorWindow + * - Wait for the text to finish printing and then for the A button + * to be pressed. + * + * Task_MainMenuCheckBattery + * - If the battery is OK, advance to Task_DisplayMainMenu. + * - If the battery is dry, advance to Task_WaitForBatteryDryErrorWindow. + * + * Task_WaitForBatteryDryErrorWindow + * - Wait for the text to finish printing and then for the A button + * to be pressed. + * + * Task_DisplayMainWindow + * - Display the buttons to the user. If the menu is in HAS_MYSTERY_EVENTS + * mode, there are too many buttons for one screen and a scrollbar is added, + * and the scrollbar task is spawned (Task_ScrollIndicatorArrowPairOnMainMenu). + * + * Task_HighlightSelectedMainMenuItem + * - Update the UI to match the currently selected item. + * + * Task_HandleMainMenuInput + * - If A is pressed, advance to Task_HandleMainMenuAPressed. + * - If B is pressed, return to the title screen via CB2_InitTitleScreen. + * - If Up or Down is pressed, handle scrolling if there is a scroll bar, change + * the selection, then go back to Task_HighlightSelectedMainMenuItem. + * + * Task_HandleMainMenuAPressed + * - If the user selected New Game, advance to Task_NewGameBirchSpeech_Init. + * - If the user selected Continue, advance to CB2_ContinueSavedGame. + * - If the user selected the Options menu, advance to CB2_InitOptionMenu. + * - If the user selected Mystery Gift, advance to CB2_MysteryGift. However, + * if the wireless adapter was removed, instead advance to + * Task_DisplayMainMenuInvalidActionError. + * - Code to start a Mystery Event is present here, but is unreachable in this + * version. + * + * Task_HandleMainMenuBPressed + * - Clean up the main menu and go back to CB2_InitTitleScreen. + * + * Task_DisplayMainMenuInvalidActionError + * - Print one of three different error messages, wait for the text to stop + * printing, and then wait for A or B to be pressed. + * - Then advance to Task_HandleMainMenuBPressed. + * + * Task_NewGameBirchSpeechInit + * - Load the sprites for the intro speech, start playing music + * Task_NewGameBirchSpeech_WaitToShowBirch + * - Spawn Task_NewGameBirchSpeech_FadeInTarget1OutTarget2 + * - Spawn Task_NewGameBirchSpeech_FadePlatformOut + * - Both of these tasks destroy themselves when done. + * Task_NewGameBirchSpeech_WaitForSpriteFadeInWelcome + * Task_NewGameBirchSpeech_ThisIsAPokemon + * - When the text is done printing, spawns Task_NewGameBirchSpeechSub_InitPokeball + * Task_NewGameBirchSpeech_MainSpeech + * Task_NewGameBirchSpeech_AndYouAre + * Task_NewGameBirchSpeech_StartBirchLotadPlatformFade + * Task_NewGameBirchSpeech_StartBirchLotadPlatformFade + * Task_NewGameBirchSpeech_SlidePlatformAway + * Task_NewGameBirchSpeech_StartPlayerFadeIn + * Task_NewGameBirchSpeech_WaitForPlayerFadeIn + * Task_NewGameBirchSpeech_BoyOrGirl + * Task_NewGameBirchSpeech_WaitToShowGenderMenu + * Task_NewGameBirchSpeech_ChooseGender + * - Animates by advancing to Task_NewGameBirchSpeech_SlideOutOldGenderSprite + * whenever the player's selection changes. + * - Advances to Task_NewGameBirchSpeech_WhatsYourName when done. + * + * Task_NewGameBirchSpeech_SlideOutOldGenderSprite + * Task_NewGameBirchSpeech_SlideInNewGenderSprite + * - Returns back to Task_NewGameBirchSpeech_ChooseGender. + * + * Task_NewGameBirchSpeech_WhatsYourName + * Task_NewGameBirchSpeech_WaitForWhatsYourNameToPrint + * Task_NewGameBirchSpeech_WaitPressBeforeNameChoice + * Task_NewGameBirchSpeech_StartNamingScreen + * C2_NamingScreen + * - Returns to CB2_NewGameBirchSpeech_ReturnFromNamingScreen when done + * CB2_NewGameBirchSpeech_ReturnFromNamingScreen + * Task_NewGameBirchSpeech_ReturnFromNamingScreenShowTextbox + * Task_NewGameBirchSpeech_SoItsPlayerName + * Task_NewGameBirchSpeech_CreateNameYesNo + * Task_NewGameBirchSpeech_ProcessNameYesNoMenu + * - If confirmed, advance to Task_NewGameBirchSpeech_SlidePlatformAway2. + * - Otherwise, return to Task_NewGameBirchSpeech_BoyOrGirl. + * + * Task_NewGameBirchSpeech_SlidePlatformAway2 + * Task_NewGameBirchSpeech_ReshowBirchLotad + * Task_NewGameBirchSpeech_WaitForSpriteFadeInAndTextPrinter + * Task_NewGameBirchSpeech_AreYouReady + * Task_NewGameBirchSpeech_ShrinkPlayer + * Task_NewGameBirchSpeech_WaitForPlayerShrink + * Task_NewGameBirchSpeech_FadePlayerToWhite + * Task_NewGameBirchSpeech_Cleanup + * - Advances to CB2_NewGame. + * + * Task_NewGameBirchSpeechSub_InitPokeball + * - Advances to Task_NewGameBirchSpeechSub_WaitForLotad + * Task_NewGameBirchSpeechSub_WaitForLotad + * - Destroys itself when done. + */ + +// These two defines are used with the sCurrItemAndOptionsMenuCheck, +// to distinguish between its two parts. +#define OPTION_MENU_FLAG 0x8000 +#define CURRENT_ITEM_MASK 0x7FFF + // Static type declarations // Static RAM declarations @@ -112,7 +241,7 @@ static void SpriteCB_MovePlayerDownWhileShrinking(struct Sprite*); static void Task_NewGameBirchSpeech_WaitForPlayerShrink(u8); static void Task_NewGameBirchSpeech_FadePlayerToWhite(u8); static void Task_NewGameBirchSpeech_Cleanup(u8); -static void nullsub_11(); +static void SpriteCB_Null(); static void Task_NewGameBirchSpeech_ReturnFromNamingScreenShowTextbox(u8); static void MainMenu_FormatSavegamePlayer(void); static void MainMenu_FormatSavegamePokedex(void); @@ -247,7 +376,7 @@ static const struct WindowTemplate sWindowTemplates_MainMenu[] = DUMMY_WIN_TEMPLATE }; -static const struct WindowTemplate gUnknown_082FF080[] = +static const struct WindowTemplate gNewGameBirchSpeechTextWindows[] = { { .bg = 0, @@ -542,7 +671,7 @@ static void Task_MainMenuCheckSaveFile(u8 taskId) gTasks[taskId].func = Task_WaitForSaveFileErrorWindow; break; } - if (sCurrItemAndOptionMenuCheck & 0x8000) // are we returning from the options menu? + if (sCurrItemAndOptionMenuCheck & OPTION_MENU_FLAG) // are we returning from the options menu? { switch (tMenuType) // if so, highlight the OPTIONS item { @@ -558,7 +687,7 @@ static void Task_MainMenuCheckSaveFile(u8 taskId) break; } } - sCurrItemAndOptionMenuCheck &= 0x7FFF; // turn off the "returning from options menu" flag + sCurrItemAndOptionMenuCheck &= CURRENT_ITEM_MASK; // turn off the "returning from options menu" flag tCurrItem = sCurrItemAndOptionMenuCheck; tItemCount = tMenuType + 2; } @@ -637,6 +766,8 @@ static void Task_DisplayMainMenu(u8 taskId) palette = RGB(26, 26, 25); LoadPalette(&palette, 252, 2); + // Note: If there is no save file, the save block is zeroed out, + // so the default gender is MALE. if (gSaveBlock2Ptr->playerGender == MALE) { palette = RGB(4, 16, 31); @@ -652,8 +783,8 @@ static void Task_DisplayMainMenu(u8 taskId) { case HAS_NO_SAVED_GAME: default: - FillWindowPixelBuffer(0, 0xAA); - FillWindowPixelBuffer(1, 0xAA); + FillWindowPixelBuffer(0, PIXEL_FILL(0xA)); + FillWindowPixelBuffer(1, PIXEL_FILL(0xA)); AddTextPrinterParameterized3(0, 1, 0, 1, sTextColor_Headers, -1, gText_MainMenuNewGame); AddTextPrinterParameterized3(1, 1, 0, 1, sTextColor_Headers, -1, gText_MainMenuOption); PutWindowTilemap(0); @@ -664,9 +795,9 @@ static void Task_DisplayMainMenu(u8 taskId) DrawMainMenuWindowBorder(&sWindowTemplates_MainMenu[1], MAIN_MENU_BORDER_TILE); break; case HAS_SAVED_GAME: - FillWindowPixelBuffer(2, 0xAA); - FillWindowPixelBuffer(3, 0xAA); - FillWindowPixelBuffer(4, 0xAA); + FillWindowPixelBuffer(2, PIXEL_FILL(0xA)); + FillWindowPixelBuffer(3, PIXEL_FILL(0xA)); + FillWindowPixelBuffer(4, PIXEL_FILL(0xA)); AddTextPrinterParameterized3(2, 1, 0, 1, sTextColor_Headers, -1, gText_MainMenuContinue); AddTextPrinterParameterized3(3, 1, 0, 1, sTextColor_Headers, -1, gText_MainMenuNewGame); AddTextPrinterParameterized3(4, 1, 0, 1, sTextColor_Headers, -1, gText_MainMenuOption); @@ -682,10 +813,10 @@ static void Task_DisplayMainMenu(u8 taskId) DrawMainMenuWindowBorder(&sWindowTemplates_MainMenu[4], MAIN_MENU_BORDER_TILE); break; case HAS_MYSTERY_GIFT: - FillWindowPixelBuffer(2, 0xAA); - FillWindowPixelBuffer(3, 0xAA); - FillWindowPixelBuffer(4, 0xAA); - FillWindowPixelBuffer(5, 0xAA); + FillWindowPixelBuffer(2, PIXEL_FILL(0xA)); + FillWindowPixelBuffer(3, PIXEL_FILL(0xA)); + FillWindowPixelBuffer(4, PIXEL_FILL(0xA)); + FillWindowPixelBuffer(5, PIXEL_FILL(0xA)); AddTextPrinterParameterized3(2, 1, 0, 1, sTextColor_Headers, -1, gText_MainMenuContinue); AddTextPrinterParameterized3(3, 1, 0, 1, sTextColor_Headers, -1, gText_MainMenuNewGame); AddTextPrinterParameterized3(4, 1, 0, 1, sTextColor_Headers, -1, gText_MainMenuMysteryGift); @@ -705,11 +836,11 @@ static void Task_DisplayMainMenu(u8 taskId) DrawMainMenuWindowBorder(&sWindowTemplates_MainMenu[5], MAIN_MENU_BORDER_TILE); break; case HAS_MYSTERY_EVENTS: - FillWindowPixelBuffer(2, 0xAA); - FillWindowPixelBuffer(3, 0xAA); - FillWindowPixelBuffer(4, 0xAA); - FillWindowPixelBuffer(5, 0xAA); - FillWindowPixelBuffer(6, 0xAA); + FillWindowPixelBuffer(2, PIXEL_FILL(0xA)); + FillWindowPixelBuffer(3, PIXEL_FILL(0xA)); + FillWindowPixelBuffer(4, PIXEL_FILL(0xA)); + FillWindowPixelBuffer(5, PIXEL_FILL(0xA)); + FillWindowPixelBuffer(6, PIXEL_FILL(0xA)); AddTextPrinterParameterized3(2, 1, 0, 1, sTextColor_Headers, -1, gText_MainMenuContinue); AddTextPrinterParameterized3(3, 1, 0, 1, sTextColor_Headers, -1, gText_MainMenuNewGame); AddTextPrinterParameterized3(4, 1, 0, 1, sTextColor_Headers, -1, gText_MainMenuMysteryGift2); @@ -813,14 +944,14 @@ static void Task_HandleMainMenuAPressed(u8 taskId) { if (gTasks[taskId].tMenuType == HAS_MYSTERY_EVENTS) RemoveScrollIndicatorArrowPair(gTasks[taskId].tScrollArrowTaskId); - sub_819746C(0, 1); - sub_819746C(1, 1); - sub_819746C(2, 1); - sub_819746C(3, 1); - sub_819746C(4, 1); - sub_819746C(5, 1); - sub_819746C(6, 1); - sub_819746C(7, 1); + ClearStdWindowAndFrame(0, TRUE); + ClearStdWindowAndFrame(1, TRUE); + ClearStdWindowAndFrame(2, TRUE); + ClearStdWindowAndFrame(3, TRUE); + ClearStdWindowAndFrame(4, TRUE); + ClearStdWindowAndFrame(5, TRUE); + ClearStdWindowAndFrame(6, TRUE); + ClearStdWindowAndFrame(7, TRUE); wirelessAdapterConnected = IsWirelessAdapterConnected(); switch (gTasks[taskId].tMenuType) { @@ -973,7 +1104,7 @@ static void Task_HandleMainMenuAPressed(u8 taskId) if (action != ACTION_OPTION) sCurrItemAndOptionMenuCheck = 0; else - sCurrItemAndOptionMenuCheck |= 0x8000; // entering the options menu + sCurrItemAndOptionMenuCheck |= OPTION_MENU_FLAG; // entering the options menu } } @@ -981,7 +1112,7 @@ static void Task_HandleMainMenuBPressed(u8 taskId) { if (!gPaletteFade.active) { - if (gTasks[taskId].tMenuType == 3) + if (gTasks[taskId].tMenuType == HAS_MYSTERY_EVENTS) RemoveScrollIndicatorArrowPair(gTasks[taskId].tScrollArrowTaskId); sCurrItemAndOptionMenuCheck = 0; FreeAllWindowBuffers(); @@ -1199,7 +1330,7 @@ static void Task_NewGameBirchSpeech_WaitForSpriteFadeInWelcome(u8 taskId) } else { - InitWindows(gUnknown_082FF080); + InitWindows(gNewGameBirchSpeechTextWindows); LoadMainMenuWindowFrameTiles(0, 0xF3); LoadMessageBoxGfx(0, 0xFC, 0xF0); NewGameBirchSpeech_ShowDialogueWindow(0, 1); @@ -1642,7 +1773,7 @@ static void Task_NewGameBirchSpeech_FadePlayerToWhite(u8 taskId) if (!gPaletteFade.active) { spriteId = gTasks[taskId].tPlayerSpriteId; - gSprites[spriteId].callback = nullsub_11; + gSprites[spriteId].callback = SpriteCB_Null; SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_ON | DISPCNT_OBJ_1D_MAP); BeginNormalPaletteFade(0xFFFF0000, 0, 0, 16, RGB_WHITEALPHA); gTasks[taskId].func = Task_NewGameBirchSpeech_Cleanup; @@ -1730,14 +1861,14 @@ static void CB2_NewGameBirchSpeech_ReturnFromNamingScreen(void) REG_IME = savedIme; SetVBlankCallback(VBlankCB_MainMenu); SetMainCallback2(CB2_MainMenu); - InitWindows(gUnknown_082FF080); + InitWindows(gNewGameBirchSpeechTextWindows); LoadMainMenuWindowFrameTiles(0, 0xF3); LoadMessageBoxGfx(0, 0xFC, 0xF0); PutWindowTilemap(0); CopyWindowToVram(0, 3); } -static void nullsub_11(struct Sprite *sprite) +static void SpriteCB_Null(struct Sprite *sprite) { } @@ -1763,22 +1894,22 @@ static void AddBirchSpeechObjects(u8 taskId) u8 maySpriteId; birchSpriteId = AddNewGameBirchObject(0x88, 0x3C, 1); - gSprites[birchSpriteId].callback = nullsub_11; + gSprites[birchSpriteId].callback = SpriteCB_Null; gSprites[birchSpriteId].oam.priority = 0; gSprites[birchSpriteId].invisible = TRUE; gTasks[taskId].tBirchSpriteId = birchSpriteId; lotadSpriteId = NewGameBirchSpeech_CreateLotadSprite(100, 0x4B); - gSprites[lotadSpriteId].callback = nullsub_11; + gSprites[lotadSpriteId].callback = SpriteCB_Null; gSprites[lotadSpriteId].oam.priority = 0; gSprites[lotadSpriteId].invisible = TRUE; gTasks[taskId].tLotadSpriteId = lotadSpriteId; brendanSpriteId = CreateTrainerSprite(FacilityClassToPicIndex(FACILITY_CLASS_BRENDAN), 120, 60, 0, &gDecompressionBuffer[0]); - gSprites[brendanSpriteId].callback = nullsub_11; + gSprites[brendanSpriteId].callback = SpriteCB_Null; gSprites[brendanSpriteId].invisible = TRUE; gSprites[brendanSpriteId].oam.priority = 0; gTasks[taskId].tBrendanSpriteId = brendanSpriteId; maySpriteId = CreateTrainerSprite(FacilityClassToPicIndex(FACILITY_CLASS_MAY), 120, 60, 0, &gDecompressionBuffer[0x800]); - gSprites[maySpriteId].callback = nullsub_11; + gSprites[maySpriteId].callback = SpriteCB_Null; gSprites[maySpriteId].invisible = TRUE; gSprites[maySpriteId].oam.priority = 0; gTasks[taskId].tMaySpriteId = maySpriteId; @@ -1966,8 +2097,8 @@ static void NewGameBirchSpeech_StartFadePlatformOut(u8 taskId, u8 delay) static void NewGameBirchSpeech_ShowGenderMenu(void) { - DrawMainMenuWindowBorder(&gUnknown_082FF080[1], 0xF3); - FillWindowPixelBuffer(1, 17); + DrawMainMenuWindowBorder(&gNewGameBirchSpeechTextWindows[1], 0xF3); + FillWindowPixelBuffer(1, PIXEL_FILL(1)); PrintMenuTable(1, 2, sMenuActions_Gender); InitMenuInUpperLeftCornerPlaySoundWhenAPressed(1, 2, 0); PutWindowTilemap(1); @@ -1995,7 +2126,7 @@ static void NewGameBirchSpeech_SetDefaultPlayerName(u8 nameId) static void CreateMainMenuErrorWindow(const u8* str) { - FillWindowPixelBuffer(7, 17); + FillWindowPixelBuffer(7, PIXEL_FILL(1)); AddTextPrinterParameterized(7, 1, str, 0, 1, 2, 0); PutWindowTilemap(7); CopyWindowToVram(7, 2); @@ -2105,12 +2236,12 @@ static void NewGameBirchSpeech_ClearGenderWindowTilemap(u8 a, u8 b, u8 c, u8 d, FillBgTilemapBufferRect(a, 0, b + 0xFF, c + 0xFF, d + 2, e + 2, 2); } -static void NewGameBirchSpeech_ClearGenderWindow(u8 windowId, u8 a) +static void NewGameBirchSpeech_ClearGenderWindow(u8 windowId, bool8 copyToVram) { CallWindowFunction(windowId, NewGameBirchSpeech_ClearGenderWindowTilemap); - FillWindowPixelBuffer(windowId, 0x11); + FillWindowPixelBuffer(windowId, PIXEL_FILL(1)); ClearWindowTilemap(windowId); - if (a == 1) + if (copyToVram == TRUE) CopyWindowToVram(windowId, 3); } @@ -2146,7 +2277,7 @@ void CreateYesNoMenuParameterized(u8 a, u8 b, u16 c, u16 d, u8 e, u8 f) static void NewGameBirchSpeech_ShowDialogueWindow(u8 windowId, u8 copyToVram) { CallWindowFunction(windowId, NewGameBirchSpeech_CreateDialogueWindowBorder); - FillWindowPixelBuffer(windowId, 17); + FillWindowPixelBuffer(windowId, PIXEL_FILL(1)); PutWindowTilemap(windowId); if (copyToVram == TRUE) CopyWindowToVram(windowId, 3); |