summaryrefslogtreecommitdiff
path: root/src/main_menu.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/main_menu.c')
-rw-r--r--src/main_menu.c221
1 files changed, 176 insertions, 45 deletions
diff --git a/src/main_menu.c b/src/main_menu.c
index 4cd5c8e14..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();
@@ -1147,7 +1278,7 @@ static void Task_NewGameBirchSpeech_Init(u8 taskId)
SetGpuReg(REG_OFFSET_BLDY, 0);
LZ77UnCompVram(sBirchSpeechShadowGfx, (void*)VRAM);
- LZ77UnCompVram(sBirchSpeechBgMap, (void*)(VRAM + 0x3800));
+ LZ77UnCompVram(sBirchSpeechBgMap, (void*)(BG_SCREEN_ADDR(7)));
LoadPalette(sBirchSpeechBgPals, 0, 64);
LoadPalette(sBirchSpeechPlatformBlackPal, 1, 16);
ScanlineEffect_Stop();
@@ -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;
@@ -1687,7 +1818,7 @@ static void CB2_NewGameBirchSpeech_ReturnFromNamingScreen(void)
DmaFill16(3, 0, PLTT, PLTT_SIZE);
ResetPaletteFade();
LZ77UnCompVram(sBirchSpeechShadowGfx, (u8*)VRAM);
- LZ77UnCompVram(sBirchSpeechBgMap, (u8*)(VRAM + 0x3800));
+ LZ77UnCompVram(sBirchSpeechBgMap, (u8*)(BG_SCREEN_ADDR(7)));
LoadPalette(sBirchSpeechBgPals, 0, 64);
LoadPalette(&sBirchSpeechBgGradientPal[1], 1, 16);
ResetTasks();
@@ -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);