Document main_menu state machine, name window constants

The new names for the constants (and newly named functions) give a much
better understanding of what the window system is trying to do.
This commit is contained in:
Phlosioneer
2019-02-11 00:05:20 -05:00
parent 6f1d2b870c
commit d979ac3bf3
69 changed files with 480 additions and 334 deletions

View File

@@ -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);
@@ -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);
ClearWindowAndBorder(0, TRUE);
ClearWindowAndBorder(1, TRUE);
ClearWindowAndBorder(2, TRUE);
ClearWindowAndBorder(3, TRUE);
ClearWindowAndBorder(4, TRUE);
ClearWindowAndBorder(5, TRUE);
ClearWindowAndBorder(6, TRUE);
ClearWindowAndBorder(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_BUFFER_WHITE);
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_BUFFER_WHITE);
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_BUFFER_WHITE);
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_BUFFER_WHITE);
PutWindowTilemap(windowId);
if (copyToVram == TRUE)
CopyWindowToVram(windowId, 3);