#include #include "sm64.h" #include "audio/external.h" #include "game/game_init.h" #include "game/ingame_menu.h" #include "game/object_helpers.h" #include "game/area.h" #include "game/save_file.h" #include "game/spawn_object.h" #include "game/object_list_processor.h" #include "game/segment2.h" #include "game/segment7.h" #include "game/print.h" #include "engine/behavior_script.h" #include "engine/graph_node.h" #include "engine/math_util.h" #include "behavior_data.h" #include "text_strings.h" #include "file_select.h" #include "dialog_ids.h" #include "eu_translation.h" #ifdef VERSION_EU #undef LANGUAGE_FUNCTION #define LANGUAGE_FUNCTION sLanguageMode #endif /** * @file file_select.c * This file implements how the file select and it's menus render and function. * That includes button IDs rendered as object models, strings, hand cursor, * special menu messages and phases, button states and button clicked checks. */ #ifdef VERSION_US // The current sound mode is automatically centered on US due to // the large length difference between options. // sSoundTextY unused (EU supports its existence). static s16 sSoundTextX; static s16 sSoundTextY; #endif //! @Bug (UB Array Access) For PAL, more buttons were added than the array was extended. //! This causes no currently known issues on console (as the other variables are not changed //! while this is used) but can cause issues with other compilers. #ifdef VERSION_EU #ifdef AVOID_UB #define NUM_BUTTONS 36 #else #define NUM_BUTTONS 34 #endif #else #define NUM_BUTTONS 32 #endif // Amount of main menu buttons defined in the code called by spawn_object_rel_with_rot. // See file_select.h for the names in MenuButtonTypes. static struct Object *sMainMenuButtons[NUM_BUTTONS]; #ifdef VERSION_EU // The current sound mode is automatically centered on US due to // the large length difference between options. // sSoundTextY is unused static s16 sSoundTextX; static s16 sSoundTextY; #endif // Used to defined yes/no fade colors after a file is selected in the erase menu. // sYesNoColor[0]: YES | sYesNoColor[1]: NO static u8 sYesNoColor[2]; // Unused variable that is written to define centered X value for some strings. #ifdef VERSION_EU static s16 sCenteredX; #endif // The button that is selected when it is clicked. static s8 sSelectedButtonID = MENU_BUTTON_NONE; // Whether we are on the main menu or one of the submenus. static s8 sCurrentMenuLevel = MENU_LAYER_MAIN; // Used for text opacifying. If it is below 250, it is constantly incremented. static u8 sTextBaseAlpha = 0; // 2D position of the cursor on the screen. // sCursorPos[0]: X | sCursorPos[1]: Y static f32 sCursorPos[] = {0, 0}; // Determines which graphic to use for the cursor. static s16 sCursorClickingTimer = 0; // Equal to sCursorPos if the cursor gets clicked, {-10000, -10000} otherwise. static s16 sClickPos[] = {-10000, -10000}; // Used for determining which file has been selected during copying and erasing. static s8 sSelectedFileIndex = -1; // Whether to fade out text or not. static s8 sFadeOutText = FALSE; // The message currently being displayed at the top of a menu. static s8 sStatusMessageID = 0; // Used for text fading. The alpha value of text is calculated as // sTextBaseAlpha - sTextFadeAlpha. static u8 sTextFadeAlpha = 0; // File select timer that keeps counting until it reaches 1000. // Used to prevent buttons from being clickable as soon as a menu loads. // Gets reset when you click an empty save, existing saves in copy and erase menus // and when you click yes/no in the erase confirmation prompt. static s16 sMainMenuTimer = 0; // Sound mode menu buttonID, has different values compared to gSoundMode in audio. // 0: gSoundMode = 0 (Stereo) | 1: gSoundMode = 3 (Mono) | 2: gSoundMode = 1 (Headset) static s8 sSoundMode = 0; // Active language for PAL arrays, values defined similar to sSoundMode // 0: English | 1: French | 2: German #ifdef VERSION_EU static s8 sLanguageMode = LANGUAGE_ENGLISH; #endif // Tracks which button will be pressed in the erase confirmation prompt (yes/no). static s8 sEraseYesNoHoverState = MENU_ERASE_HOVER_NONE; // Used for the copy menu, defines if the game as all 4 save slots with data. // if TRUE, it doesn't allow copying more files. static s8 sAllFilesExist = FALSE; // Defines the value of the save slot selected in the menu. // Mario A: 1 | Mario B: 2 | Mario C: 3 | Mario D: 4 static s8 sSelectedFileNum = 0; // Which coin score mode to use when scoring files. 0 for local // coin high score, 1 for high score across all files. static s8 sScoreFileCoinScoreMode = 0; // In PAL, if no save file exists, open the language menu so the user can find it. #ifdef VERSION_EU static s8 sOpenLangSettings = FALSE; #endif #ifndef VERSION_EU static unsigned char textReturn[] = { TEXT_RETURN }; #else static unsigned char textReturn[][8] = {{ TEXT_RETURN }, { TEXT_RETURN_FR }, { TEXT_RETURN_DE }}; #endif #ifndef VERSION_EU static unsigned char textViewScore[] = { TEXT_CHECK_SCORE }; #else static unsigned char textViewScore[][12] = {{ TEXT_CHECK_SCORE }, {TEXT_CHECK_SCORE_FR}, {TEXT_CHECK_SCORE_DE}}; #endif #ifndef VERSION_EU static unsigned char textCopyFileButton[] = { TEXT_COPY_FILE_BUTTON }; #else static unsigned char textCopyFileButton[][15] = {{ TEXT_COPY_FILE }, { TEXT_COPY_FILE_FR }, { TEXT_COPY_FILE_DE }}; #endif #ifndef VERSION_EU static unsigned char textEraseFileButton[] = { TEXT_ERASE_FILE_BUTTON }; #else static unsigned char textEraseFileButton[][16] = { {TEXT_ERASE_FILE}, {TEXT_ERASE_FILE_FR}, {TEXT_ERASE_FILE_DE} }; #endif #ifndef VERSION_EU static unsigned char textSoundModes[][8] = { { TEXT_STEREO }, { TEXT_MONO }, { TEXT_HEADSET } }; #endif static unsigned char textMarioA[] = { TEXT_FILE_MARIO_A }; static unsigned char textMarioB[] = { TEXT_FILE_MARIO_B }; static unsigned char textMarioC[] = { TEXT_FILE_MARIO_C }; static unsigned char textMarioD[] = { TEXT_FILE_MARIO_D }; #ifndef VERSION_EU static unsigned char textNew[] = { TEXT_NEW }; static unsigned char starIcon[] = { GLYPH_STAR, GLYPH_SPACE }; static unsigned char xIcon[] = { GLYPH_MULTIPLY, GLYPH_SPACE }; #endif #ifndef VERSION_EU static unsigned char textSelectFile[] = { TEXT_SELECT_FILE }; #else static unsigned char textSelectFile[][17] = {{ TEXT_SELECT_FILE }, { TEXT_SELECT_FILE_FR }, { TEXT_SELECT_FILE_DE }}; #endif #ifndef VERSION_EU static unsigned char textScore[] = { TEXT_SCORE }; #else static unsigned char textScore[][9] = {{ TEXT_SCORE }, { TEXT_SCORE_FR }, { TEXT_SCORE_DE }}; #endif #ifndef VERSION_EU static unsigned char textCopy[] = { TEXT_COPY }; #else static unsigned char textCopy[][9] = {{ TEXT_COPY }, { TEXT_COPY_FR }, { TEXT_COPY_DE }}; #endif #ifndef VERSION_EU static unsigned char textErase[] = { TEXT_ERASE }; #else static unsigned char textErase[][8] = {{ TEXT_ERASE }, { TEXT_ERASE_FR }, { TEXT_ERASE_DE }}; #endif #ifdef VERSION_EU static unsigned char textOption[][9] = {{ TEXT_OPTION }, { TEXT_OPTION_FR }, { TEXT_OPTION_DE } }; #endif #ifndef VERSION_EU static unsigned char textCheckFile[] = { TEXT_CHECK_FILE }; #else static unsigned char textCheckFile[][18] = {{ TEXT_CHECK_FILE }, { TEXT_CHECK_FILE_FR }, { TEXT_CHECK_FILE_DE }}; #endif #ifndef VERSION_EU static unsigned char textNoSavedDataExists[] = { TEXT_NO_SAVED_DATA_EXISTS }; #else static unsigned char textNoSavedDataExists[][30] = {{ TEXT_NO_SAVED_DATA_EXISTS }, { TEXT_NO_SAVED_DATA_EXISTS_FR }, { TEXT_NO_SAVED_DATA_EXISTS_DE }}; #endif #ifndef VERSION_EU static unsigned char textCopyFile[] = { TEXT_COPY_FILE }; #else static unsigned char textCopyFile[][16] = {{ TEXT_COPY_FILE_BUTTON }, { TEXT_COPY_FILE_BUTTON_FR }, { TEXT_COPY_FILE_BUTTON_DE }}; #endif #ifndef VERSION_EU static unsigned char textCopyItToWhere[] = { TEXT_COPY_IT_TO_WHERE }; #else static unsigned char textCopyItToWhere[][18] = {{ TEXT_COPY_IT_TO_WHERE }, { TEXT_COPY_IT_TO_WHERE_FR }, { TEXT_COPY_IT_TO_WHERE_DE }}; #endif #ifndef VERSION_EU static unsigned char textNoSavedDataExistsCopy[] = { TEXT_NO_SAVED_DATA_EXISTS }; #endif #ifndef VERSION_EU static unsigned char textCopyCompleted[] = { TEXT_COPYING_COMPLETED }; #else static unsigned char textCopyCompleted[][18] = {{ TEXT_COPYING_COMPLETED }, { TEXT_COPYING_COMPLETED_FR }, { TEXT_COPYING_COMPLETED_DE }}; #endif #ifndef VERSION_EU static unsigned char textSavedDataExists[] = { TEXT_SAVED_DATA_EXISTS }; #else static unsigned char textSavedDataExists[][20] = {{ TEXT_SAVED_DATA_EXISTS }, { TEXT_SAVED_DATA_EXISTS_FR }, { TEXT_SAVED_DATA_EXISTS_DE }}; #endif #ifndef VERSION_EU static unsigned char textNoFileToCopyFrom[] = { TEXT_NO_FILE_TO_COPY_FROM }; #else static unsigned char textNoFileToCopyFrom[][21] = {{ TEXT_NO_FILE_TO_COPY_FROM }, { TEXT_NO_FILE_TO_COPY_FROM_FR }, { TEXT_NO_FILE_TO_COPY_FROM_DE }}; #endif #ifndef VERSION_EU static unsigned char textYes[] = { TEXT_YES }; #else static unsigned char textYes[][4] = {{ TEXT_YES }, { TEXT_YES_FR }, { TEXT_YES_DE }}; #endif #ifndef VERSION_EU static unsigned char textNo[] = { TEXT_NO }; #else static unsigned char textNo[][5] = {{ TEXT_NO }, { TEXT_NO_FR }, { TEXT_NO_DE }}; #endif #ifdef VERSION_EU // In EU, Erase File and Sound Select strings are outside it's print string function static unsigned char textEraseFile[][17] = { { TEXT_ERASE_FILE_BUTTON }, { TEXT_ERASE_FILE_BUTTON_FR }, { TEXT_ERASE_FILE_BUTTON_DE } }; static unsigned char textSure[][8] = {{ TEXT_SURE }, { TEXT_SURE_FR }, { TEXT_SURE_DE }}; static unsigned char textMarioAJustErased[][20] = { { TEXT_FILE_MARIO_A_JUST_ERASED }, { TEXT_FILE_MARIO_A_JUST_ERASED_FR }, { TEXT_FILE_MARIO_A_JUST_ERASED_DE } }; static unsigned char textSoundSelect[][13] = { { TEXT_SOUND_SELECT }, { TEXT_SOUND_SELECT_FR }, { TEXT_SOUND_SELECT_DE } }; static unsigned char textLanguageSelect[][17] = { { TEXT_LANGUAGE_SELECT }, { TEXT_LANGUAGE_SELECT_FR }, { TEXT_LANGUAGE_SELECT_DE } }; static unsigned char textSoundModes[][10] = { { TEXT_STEREO }, { TEXT_MONO }, { TEXT_HEADSET }, { TEXT_STEREO_FR }, { TEXT_MONO_FR }, { TEXT_HEADSET_FR }, { TEXT_STEREO_DE }, { TEXT_MONO_DE }, { TEXT_HEADSET_DE } }; static unsigned char textLanguage[][9] = {{ TEXT_ENGLISH }, { TEXT_FRENCH }, { TEXT_GERMAN }}; static unsigned char textMario[] = { TEXT_MARIO }; static unsigned char textHiScore[][15] = {{ TEXT_HI_SCORE }, { TEXT_HI_SCORE_FR }, { TEXT_HI_SCORE_DE }}; static unsigned char textMyScore[][10] = {{ TEXT_MY_SCORE }, { TEXT_MY_SCORE_FR }, { TEXT_MY_SCORE_DE }}; static unsigned char textNew[][5] = {{ TEXT_NEW }, { TEXT_NEW_FR }, { TEXT_NEW_DE }}; static unsigned char starIcon[] = { GLYPH_STAR, GLYPH_SPACE }; static unsigned char xIcon[] = { GLYPH_MULTIPLY, GLYPH_SPACE }; #endif /** * Yellow Background Menu Initial Action * Rotates the background at 180 grades and it's scale. * Although the scale is properly applied in the loop function. */ void beh_yellow_background_menu_init(void) { gCurrentObject->oFaceAngleYaw = 0x8000; gCurrentObject->oMenuButtonScale = 9.0f; } /** * Yellow Background Menu Loop Action * Properly scales the background in the main menu. */ void beh_yellow_background_menu_loop(void) { cur_obj_scale(9.0f); } /** * Check if a button was clicked. * depth = 200.0 for main menu, 22.0 for submenus. */ s32 check_clicked_button(s16 x, s16 y, f32 depth) { f32 a = 52.4213; f32 newX = ((f32) x * 160.0) / (a * depth); f32 newY = ((f32) y * 120.0) / (a * 3 / 4 * depth); s16 maxX = newX + 25.0f; s16 minX = newX - 25.0f; s16 maxY = newY + 21.0f; s16 minY = newY - 21.0f; if (sClickPos[0] < maxX && minX < sClickPos[0] && sClickPos[1] < maxY && minY < sClickPos[1]) { return TRUE; } return FALSE; } /** * Grow from main menu, used by selecting files and menus. */ static void bhv_menu_button_growing_from_main_menu(struct Object *button) { if (button->oMenuButtonTimer < 16) { button->oFaceAngleYaw += 0x800; } if (button->oMenuButtonTimer < 8) { button->oFaceAnglePitch += 0x800; } if (button->oMenuButtonTimer >= 8 && button->oMenuButtonTimer < 16) { button->oFaceAnglePitch -= 0x800; } button->oParentRelativePosX -= button->oMenuButtonOrigPosX / 16.0; button->oParentRelativePosY -= button->oMenuButtonOrigPosY / 16.0; if (button->oPosZ < button->oMenuButtonOrigPosZ + 17800.0) { button->oParentRelativePosZ += 1112.5; } button->oMenuButtonTimer++; if (button->oMenuButtonTimer == 16) { button->oParentRelativePosX = 0.0f; button->oParentRelativePosY = 0.0f; button->oMenuButtonState = MENU_BUTTON_STATE_FULLSCREEN; button->oMenuButtonTimer = 0; } } /** * Shrink back to main menu, used to return back while inside menus. */ static void bhv_menu_button_shrinking_to_main_menu(struct Object *button) { if (button->oMenuButtonTimer < 16) { button->oFaceAngleYaw -= 0x800; } if (button->oMenuButtonTimer < 8) { button->oFaceAnglePitch -= 0x800; } if (button->oMenuButtonTimer >= 8 && button->oMenuButtonTimer < 16) { button->oFaceAnglePitch += 0x800; } button->oParentRelativePosX += button->oMenuButtonOrigPosX / 16.0; button->oParentRelativePosY += button->oMenuButtonOrigPosY / 16.0; if (button->oPosZ > button->oMenuButtonOrigPosZ) { button->oParentRelativePosZ -= 1112.5; } button->oMenuButtonTimer++; if (button->oMenuButtonTimer == 16) { button->oParentRelativePosX = button->oMenuButtonOrigPosX; button->oParentRelativePosY = button->oMenuButtonOrigPosY; button->oMenuButtonState = MENU_BUTTON_STATE_DEFAULT; button->oMenuButtonTimer = 0; } } /** * Grow from submenu, used by selecting a file in the score menu. */ static void bhv_menu_button_growing_from_submenu(struct Object *button) { if (button->oMenuButtonTimer < 16) { button->oFaceAngleYaw += 0x800; } if (button->oMenuButtonTimer < 8) { button->oFaceAnglePitch += 0x800; } if (button->oMenuButtonTimer >= 8 && button->oMenuButtonTimer < 16) { button->oFaceAnglePitch -= 0x800; } button->oParentRelativePosX -= button->oMenuButtonOrigPosX / 16.0; button->oParentRelativePosY -= button->oMenuButtonOrigPosY / 16.0; button->oParentRelativePosZ -= 116.25; button->oMenuButtonTimer++; if (button->oMenuButtonTimer == 16) { button->oParentRelativePosX = 0.0f; button->oParentRelativePosY = 0.0f; button->oMenuButtonState = MENU_BUTTON_STATE_FULLSCREEN; button->oMenuButtonTimer = 0; } } /** * Shrink back to submenu, used to return back while inside a score save menu. */ static void bhv_menu_button_shrinking_to_submenu(struct Object *button) { if (button->oMenuButtonTimer < 16) { button->oFaceAngleYaw -= 0x800; } if (button->oMenuButtonTimer < 8) { button->oFaceAnglePitch -= 0x800; } if (button->oMenuButtonTimer >= 8 && button->oMenuButtonTimer < 16) { button->oFaceAnglePitch += 0x800; } button->oParentRelativePosX += button->oMenuButtonOrigPosX / 16.0; button->oParentRelativePosY += button->oMenuButtonOrigPosY / 16.0; if (button->oPosZ > button->oMenuButtonOrigPosZ) { button->oParentRelativePosZ += 116.25; } button->oMenuButtonTimer++; if (button->oMenuButtonTimer == 16) { button->oParentRelativePosX = button->oMenuButtonOrigPosX; button->oParentRelativePosY = button->oMenuButtonOrigPosY; button->oMenuButtonState = MENU_BUTTON_STATE_DEFAULT; button->oMenuButtonTimer = 0; } } /** * A small increase and decrease in size. * Used by failed copy/erase/score operations and sound mode select. */ static void bhv_menu_button_zoom_in_out(struct Object *button) { if (sCurrentMenuLevel == MENU_LAYER_MAIN) { if (button->oMenuButtonTimer < 4) { button->oParentRelativePosZ -= 20.0f; } if (button->oMenuButtonTimer >= 4) { button->oParentRelativePosZ += 20.0f; } } else { if (button->oMenuButtonTimer < 4) { button->oParentRelativePosZ += 20.0f; } if (button->oMenuButtonTimer >= 4) { button->oParentRelativePosZ -= 20.0f; } } button->oMenuButtonTimer++; if (button->oMenuButtonTimer == 8) { button->oMenuButtonState = MENU_BUTTON_STATE_DEFAULT; button->oMenuButtonTimer = 0; } } /** * A small temporary increase in size. * Used while selecting a target copy/erase file or yes/no erase confirmation prompt. */ static void bhv_menu_button_zoom_in(struct Object *button) { button->oMenuButtonScale += 0.0022; button->oMenuButtonTimer++; if (button->oMenuButtonTimer == 10) { button->oMenuButtonState = MENU_BUTTON_STATE_DEFAULT; button->oMenuButtonTimer = 0; } } /** * A small temporary decrease in size. * Used after selecting a target copy/erase file or * yes/no erase confirmation prompt to undo the zoom in. */ static void bhv_menu_button_zoom_out(struct Object *button) { button->oMenuButtonScale -= 0.0022; button->oMenuButtonTimer++; if (button->oMenuButtonTimer == 10) { button->oMenuButtonState = MENU_BUTTON_STATE_DEFAULT; button->oMenuButtonTimer = 0; } } /** * Menu Buttons Menu Initial Action * Aligns menu buttons so they can stay in their original * positions when you choose a button. */ void bhv_menu_button_init(void) { gCurrentObject->oMenuButtonOrigPosX = gCurrentObject->oParentRelativePosX; gCurrentObject->oMenuButtonOrigPosY = gCurrentObject->oParentRelativePosY; } /** * Menu Buttons Menu Loop Action * Handles the functions of the button states and * object scale for each button. */ void bhv_menu_button_loop(void) { switch (gCurrentObject->oMenuButtonState) { case MENU_BUTTON_STATE_DEFAULT: // Button state gCurrentObject->oMenuButtonOrigPosZ = gCurrentObject->oPosZ; break; case MENU_BUTTON_STATE_GROWING: // Switching from button to menu state if (sCurrentMenuLevel == MENU_LAYER_MAIN) { bhv_menu_button_growing_from_main_menu(gCurrentObject); } if (sCurrentMenuLevel == MENU_LAYER_SUBMENU) { bhv_menu_button_growing_from_submenu(gCurrentObject); // Only used for score files } sTextBaseAlpha = 0; sCursorClickingTimer = 4; break; case MENU_BUTTON_STATE_FULLSCREEN: // Menu state break; case MENU_BUTTON_STATE_SHRINKING: // Switching from menu to button state if (sCurrentMenuLevel == MENU_LAYER_MAIN) { bhv_menu_button_shrinking_to_main_menu(gCurrentObject); } if (sCurrentMenuLevel == MENU_LAYER_SUBMENU) { bhv_menu_button_shrinking_to_submenu(gCurrentObject); // Only used for score files } sTextBaseAlpha = 0; sCursorClickingTimer = 4; break; case MENU_BUTTON_STATE_ZOOM_IN_OUT: bhv_menu_button_zoom_in_out(gCurrentObject); sCursorClickingTimer = 4; break; case MENU_BUTTON_STATE_ZOOM_IN: bhv_menu_button_zoom_in(gCurrentObject); sCursorClickingTimer = 4; break; case MENU_BUTTON_STATE_ZOOM_OUT: bhv_menu_button_zoom_out(gCurrentObject); sCursorClickingTimer = 4; break; } cur_obj_scale(gCurrentObject->oMenuButtonScale); } /** * Handles how to exit the score file menu using button states. */ void exit_score_file_to_score_menu(struct Object *scoreFileButton, s8 scoreButtonID) { // Begin exit if (scoreFileButton->oMenuButtonState == MENU_BUTTON_STATE_FULLSCREEN && sCursorClickingTimer == 2) { play_sound(SOUND_MENU_CAMERA_ZOOM_OUT, gDefaultSoundArgs); scoreFileButton->oMenuButtonState = MENU_BUTTON_STATE_SHRINKING; } // End exit if (scoreFileButton->oMenuButtonState == MENU_BUTTON_STATE_DEFAULT) { sSelectedButtonID = scoreButtonID; if (sCurrentMenuLevel == MENU_LAYER_SUBMENU) { sCurrentMenuLevel = MENU_LAYER_MAIN; } } } /** * Render buttons for the score menu. * Also check if the save file exists to render a different Mario button. */ void render_score_menu_buttons(struct Object *scoreButton) { // File A if (save_file_exists(SAVE_FILE_A) == TRUE) { sMainMenuButtons[MENU_BUTTON_SCORE_FILE_A] = spawn_object_rel_with_rot(scoreButton, MODEL_MAIN_MENU_MARIO_SAVE_BUTTON, bhvMenuButton, 711, 311, -100, 0, -0x8000, 0); } else { sMainMenuButtons[MENU_BUTTON_SCORE_FILE_A] = spawn_object_rel_with_rot(scoreButton, MODEL_MAIN_MENU_MARIO_NEW_BUTTON, bhvMenuButton, 711, 311, -100, 0, -0x8000, 0); } sMainMenuButtons[MENU_BUTTON_SCORE_FILE_A]->oMenuButtonScale = 0.11111111f; // File B if (save_file_exists(SAVE_FILE_B) == TRUE) { sMainMenuButtons[MENU_BUTTON_SCORE_FILE_B] = spawn_object_rel_with_rot(scoreButton, MODEL_MAIN_MENU_MARIO_SAVE_BUTTON, bhvMenuButton, -166, 311, -100, 0, -0x8000, 0); } else { sMainMenuButtons[MENU_BUTTON_SCORE_FILE_B] = spawn_object_rel_with_rot(scoreButton, MODEL_MAIN_MENU_MARIO_NEW_BUTTON, bhvMenuButton, -166, 311, -100, 0, -0x8000, 0); } sMainMenuButtons[MENU_BUTTON_SCORE_FILE_B]->oMenuButtonScale = 0.11111111f; // File C if (save_file_exists(SAVE_FILE_C) == TRUE) { sMainMenuButtons[MENU_BUTTON_SCORE_FILE_C] = spawn_object_rel_with_rot( scoreButton, MODEL_MAIN_MENU_MARIO_SAVE_BUTTON, bhvMenuButton, 711, 0, -100, 0, -0x8000, 0); } else { sMainMenuButtons[MENU_BUTTON_SCORE_FILE_C] = spawn_object_rel_with_rot( scoreButton, MODEL_MAIN_MENU_MARIO_NEW_BUTTON, bhvMenuButton, 711, 0, -100, 0, -0x8000, 0); } sMainMenuButtons[MENU_BUTTON_SCORE_FILE_C]->oMenuButtonScale = 0.11111111f; // File D if (save_file_exists(SAVE_FILE_D) == TRUE) { sMainMenuButtons[MENU_BUTTON_SCORE_FILE_D] = spawn_object_rel_with_rot(scoreButton, MODEL_MAIN_MENU_MARIO_SAVE_BUTTON, bhvMenuButton, -166, 0, -100, 0, -0x8000, 0); } else { sMainMenuButtons[MENU_BUTTON_SCORE_FILE_D] = spawn_object_rel_with_rot( scoreButton, MODEL_MAIN_MENU_MARIO_NEW_BUTTON, bhvMenuButton, -166, 0, -100, 0, -0x8000, 0); } sMainMenuButtons[MENU_BUTTON_SCORE_FILE_D]->oMenuButtonScale = 0.11111111f; // Return to main menu button sMainMenuButtons[MENU_BUTTON_SCORE_RETURN] = spawn_object_rel_with_rot( scoreButton, MODEL_MAIN_MENU_YELLOW_FILE_BUTTON, bhvMenuButton, 711, -388, -100, 0, -0x8000, 0); sMainMenuButtons[MENU_BUTTON_SCORE_RETURN]->oMenuButtonScale = 0.11111111f; // Switch to copy menu button sMainMenuButtons[MENU_BUTTON_SCORE_COPY_FILE] = spawn_object_rel_with_rot( scoreButton, MODEL_MAIN_MENU_BLUE_COPY_BUTTON, bhvMenuButton, 0, -388, -100, 0, -0x8000, 0); sMainMenuButtons[MENU_BUTTON_SCORE_COPY_FILE]->oMenuButtonScale = 0.11111111f; // Switch to erase menu button sMainMenuButtons[MENU_BUTTON_SCORE_ERASE_FILE] = spawn_object_rel_with_rot( scoreButton, MODEL_MAIN_MENU_RED_ERASE_BUTTON, bhvMenuButton, -711, -388, -100, 0, -0x8000, 0); sMainMenuButtons[MENU_BUTTON_SCORE_ERASE_FILE]->oMenuButtonScale = 0.11111111f; } #ifdef VERSION_EU #define SCORE_TIMER 46 #else #define SCORE_TIMER 31 #endif /** * In the score menu, checks if a button was clicked to play a sound, button state and other functions. */ void check_score_menu_clicked_buttons(struct Object *scoreButton) { if (scoreButton->oMenuButtonState == MENU_BUTTON_STATE_FULLSCREEN) { s32 buttonID; // Configure score menu button group for (buttonID = MENU_BUTTON_SCORE_MIN; buttonID < MENU_BUTTON_SCORE_MAX; buttonID++) { s16 buttonX = sMainMenuButtons[buttonID]->oPosX; s16 buttonY = sMainMenuButtons[buttonID]->oPosY; if (check_clicked_button(buttonX, buttonY, 22.0f) == TRUE && sMainMenuTimer >= SCORE_TIMER) { // If menu button clicked, select it if (buttonID == MENU_BUTTON_SCORE_RETURN || buttonID == MENU_BUTTON_SCORE_COPY_FILE || buttonID == MENU_BUTTON_SCORE_ERASE_FILE) { play_sound(SOUND_MENU_CLICK_FILE_SELECT, gDefaultSoundArgs); sMainMenuButtons[buttonID]->oMenuButtonState = MENU_BUTTON_STATE_ZOOM_IN_OUT; sSelectedButtonID = buttonID; } else { // Check if a save file is clicked if (sMainMenuTimer >= SCORE_TIMER) { // If clicked in a existing save file, select it too see it's score if (save_file_exists(buttonID - MENU_BUTTON_SCORE_MIN) == TRUE) { play_sound(SOUND_MENU_CAMERA_ZOOM_IN, gDefaultSoundArgs); sMainMenuButtons[buttonID]->oMenuButtonState = MENU_BUTTON_STATE_GROWING; sSelectedButtonID = buttonID; } else { // If clicked in a non-existing save file, play buzz sound play_sound(SOUND_MENU_CAMERA_BUZZ, gDefaultSoundArgs); sMainMenuButtons[buttonID]->oMenuButtonState = MENU_BUTTON_STATE_ZOOM_IN_OUT; if (sMainMenuTimer >= SCORE_TIMER) { sFadeOutText = TRUE; sMainMenuTimer = 0; } } } } sCurrentMenuLevel = MENU_LAYER_SUBMENU; break; } } } } #undef SCORE_TIMER /** * Render buttons for the copy menu. * Also check if the save file exists to render a different Mario button. */ void render_copy_menu_buttons(struct Object *copyButton) { // File A if (save_file_exists(SAVE_FILE_A) == TRUE) { sMainMenuButtons[MENU_BUTTON_COPY_FILE_A] = spawn_object_rel_with_rot(copyButton, MODEL_MAIN_MENU_MARIO_SAVE_BUTTON, bhvMenuButton, 711, 311, -100, 0, -0x8000, 0); } else { sMainMenuButtons[MENU_BUTTON_COPY_FILE_A] = spawn_object_rel_with_rot( copyButton, MODEL_MAIN_MENU_MARIO_NEW_BUTTON, bhvMenuButton, 711, 311, -100, 0, -0x8000, 0); } sMainMenuButtons[MENU_BUTTON_COPY_FILE_A]->oMenuButtonScale = 0.11111111f; // File B if (save_file_exists(SAVE_FILE_B) == TRUE) { sMainMenuButtons[MENU_BUTTON_COPY_FILE_B] = spawn_object_rel_with_rot(copyButton, MODEL_MAIN_MENU_MARIO_SAVE_BUTTON, bhvMenuButton, -166, 311, -100, 0, -0x8000, 0); } else { sMainMenuButtons[MENU_BUTTON_COPY_FILE_B] = spawn_object_rel_with_rot(copyButton, MODEL_MAIN_MENU_MARIO_NEW_BUTTON, bhvMenuButton, -166, 311, -100, 0, -0x8000, 0); } sMainMenuButtons[MENU_BUTTON_COPY_FILE_B]->oMenuButtonScale = 0.11111111f; // File C if (save_file_exists(SAVE_FILE_C) == TRUE) { sMainMenuButtons[MENU_BUTTON_COPY_FILE_C] = spawn_object_rel_with_rot( copyButton, MODEL_MAIN_MENU_MARIO_SAVE_BUTTON, bhvMenuButton, 711, 0, -100, 0, -0x8000, 0); } else { sMainMenuButtons[MENU_BUTTON_COPY_FILE_C] = spawn_object_rel_with_rot( copyButton, MODEL_MAIN_MENU_MARIO_NEW_BUTTON, bhvMenuButton, 711, 0, -100, 0, -0x8000, 0); } sMainMenuButtons[MENU_BUTTON_COPY_FILE_C]->oMenuButtonScale = 0.11111111f; // File D if (save_file_exists(SAVE_FILE_D) == TRUE) { sMainMenuButtons[MENU_BUTTON_COPY_FILE_D] = spawn_object_rel_with_rot( copyButton, MODEL_MAIN_MENU_MARIO_SAVE_BUTTON, bhvMenuButton, -166, 0, -100, 0, -0x8000, 0); } else { sMainMenuButtons[MENU_BUTTON_COPY_FILE_D] = spawn_object_rel_with_rot( copyButton, MODEL_MAIN_MENU_MARIO_NEW_BUTTON, bhvMenuButton, -166, 0, -100, 0, -0x8000, 0); } sMainMenuButtons[MENU_BUTTON_COPY_FILE_D]->oMenuButtonScale = 0.11111111f; // Return to main menu button sMainMenuButtons[MENU_BUTTON_COPY_RETURN] = spawn_object_rel_with_rot( copyButton, MODEL_MAIN_MENU_YELLOW_FILE_BUTTON, bhvMenuButton, 711, -388, -100, 0, -0x8000, 0); sMainMenuButtons[MENU_BUTTON_COPY_RETURN]->oMenuButtonScale = 0.11111111f; // Switch to scire menu button sMainMenuButtons[MENU_BUTTON_COPY_CHECK_SCORE] = spawn_object_rel_with_rot( copyButton, MODEL_MAIN_MENU_GREEN_SCORE_BUTTON, bhvMenuButton, 0, -388, -100, 0, -0x8000, 0); sMainMenuButtons[MENU_BUTTON_COPY_CHECK_SCORE]->oMenuButtonScale = 0.11111111f; // Switch to erase menu button sMainMenuButtons[MENU_BUTTON_COPY_ERASE_FILE] = spawn_object_rel_with_rot( copyButton, MODEL_MAIN_MENU_RED_ERASE_BUTTON, bhvMenuButton, -711, -388, -100, 0, -0x8000, 0); sMainMenuButtons[MENU_BUTTON_COPY_ERASE_FILE]->oMenuButtonScale = 0.11111111f; } #ifdef VERSION_EU #define BUZZ_TIMER 36 #else #define BUZZ_TIMER 21 #endif /** * Copy Menu phase actions that handles what to do when a file button is clicked. */ void copy_action_file_button(struct Object *copyButton, s32 copyFileButtonID) { switch (copyButton->oMenuButtonActionPhase) { case COPY_PHASE_MAIN: // Copy Menu Main Phase if (sAllFilesExist == TRUE) { // Don't enable copy if all save files exists return; } if (save_file_exists(copyFileButtonID - MENU_BUTTON_COPY_MIN) == TRUE) { // If clicked in a existing save file, ask where it wants to copy play_sound(SOUND_MENU_CLICK_FILE_SELECT, gDefaultSoundArgs); sMainMenuButtons[copyFileButtonID]->oMenuButtonState = MENU_BUTTON_STATE_ZOOM_IN; sSelectedFileIndex = copyFileButtonID - MENU_BUTTON_COPY_MIN; copyButton->oMenuButtonActionPhase = COPY_PHASE_COPY_WHERE; sFadeOutText = TRUE; sMainMenuTimer = 0; } else { // If clicked in a non-existing save file, play buzz sound play_sound(SOUND_MENU_CAMERA_BUZZ, gDefaultSoundArgs); sMainMenuButtons[copyFileButtonID]->oMenuButtonState = MENU_BUTTON_STATE_ZOOM_IN_OUT; if (sMainMenuTimer >= BUZZ_TIMER) { sFadeOutText = TRUE; sMainMenuTimer = 0; } } break; case COPY_PHASE_COPY_WHERE: // Copy Menu "COPY IT TO WHERE?" Phase (after a file is selected) sMainMenuButtons[copyFileButtonID]->oMenuButtonState = MENU_BUTTON_STATE_ZOOM_IN_OUT; if (save_file_exists(copyFileButtonID - MENU_BUTTON_COPY_MIN) == FALSE) { // If clicked in a non-existing save file, copy the file play_sound(SOUND_MENU_STAR_SOUND, gDefaultSoundArgs); copyButton->oMenuButtonActionPhase = COPY_PHASE_COPY_COMPLETE; sFadeOutText = TRUE; sMainMenuTimer = 0; save_file_copy(sSelectedFileIndex, copyFileButtonID - MENU_BUTTON_COPY_MIN); sMainMenuButtons[copyFileButtonID]->header.gfx.sharedChild = gLoadedGraphNodes[MODEL_MAIN_MENU_MARIO_SAVE_BUTTON_FADE]; sMainMenuButtons[copyFileButtonID - MENU_BUTTON_COPY_MIN]->header.gfx.sharedChild = gLoadedGraphNodes[MODEL_MAIN_MENU_MARIO_SAVE_BUTTON_FADE]; } else { // If clicked in a existing save file, play buzz sound if (MENU_BUTTON_COPY_FILE_A + sSelectedFileIndex == copyFileButtonID) { play_sound(SOUND_MENU_CAMERA_BUZZ, gDefaultSoundArgs); sMainMenuButtons[MENU_BUTTON_COPY_FILE_A + sSelectedFileIndex]->oMenuButtonState = MENU_BUTTON_STATE_ZOOM_OUT; copyButton->oMenuButtonActionPhase = COPY_PHASE_MAIN; sFadeOutText = TRUE; return; } if (sMainMenuTimer >= BUZZ_TIMER) { sFadeOutText = TRUE; sMainMenuTimer = 0; } } break; } } #ifdef VERSION_EU #define ACTION_TIMER 41 #define MAIN_RETURN_TIMER 36 #else #define ACTION_TIMER 31 #define MAIN_RETURN_TIMER 31 #endif /** * In the copy menu, checks if a button was clicked to play a sound, button state and other functions. */ void check_copy_menu_clicked_buttons(struct Object *copyButton) { if (copyButton->oMenuButtonState == MENU_BUTTON_STATE_FULLSCREEN) { s32 buttonID; // Configure copy menu button group for (buttonID = MENU_BUTTON_COPY_MIN; buttonID < MENU_BUTTON_COPY_MAX; buttonID++) { s16 buttonX = sMainMenuButtons[buttonID]->oPosX; s16 buttonY = sMainMenuButtons[buttonID]->oPosY; if (check_clicked_button(buttonX, buttonY, 22.0f) == TRUE) { // If menu button clicked, select it if (buttonID == MENU_BUTTON_COPY_RETURN || buttonID == MENU_BUTTON_COPY_CHECK_SCORE || buttonID == MENU_BUTTON_COPY_ERASE_FILE) { if (copyButton->oMenuButtonActionPhase == COPY_PHASE_MAIN) { play_sound(SOUND_MENU_CLICK_FILE_SELECT, gDefaultSoundArgs); sMainMenuButtons[buttonID]->oMenuButtonState = MENU_BUTTON_STATE_ZOOM_IN_OUT; sSelectedButtonID = buttonID; } } else { // Check if a file button is clicked to play a copy action if (sMainMenuButtons[buttonID]->oMenuButtonState == MENU_BUTTON_STATE_DEFAULT && sMainMenuTimer >= ACTION_TIMER) { copy_action_file_button(copyButton, buttonID); } } sCurrentMenuLevel = MENU_LAYER_SUBMENU; break; } } // After copy is complete, return to main copy phase if (copyButton->oMenuButtonActionPhase == COPY_PHASE_COPY_COMPLETE && sMainMenuTimer >= MAIN_RETURN_TIMER) { copyButton->oMenuButtonActionPhase = COPY_PHASE_MAIN; sMainMenuButtons[MENU_BUTTON_COPY_MIN + sSelectedFileIndex]->oMenuButtonState = MENU_BUTTON_STATE_ZOOM_OUT; } } } /** * Render buttons for the erase menu. * Also check if the save file exists to render a different Mario button. */ void render_erase_menu_buttons(struct Object *eraseButton) { // File A if (save_file_exists(SAVE_FILE_A) == TRUE) { sMainMenuButtons[MENU_BUTTON_ERASE_FILE_A] = spawn_object_rel_with_rot(eraseButton, MODEL_MAIN_MENU_MARIO_SAVE_BUTTON, bhvMenuButton, 711, 311, -100, 0, -0x8000, 0); } else { sMainMenuButtons[MENU_BUTTON_ERASE_FILE_A] = spawn_object_rel_with_rot(eraseButton, MODEL_MAIN_MENU_MARIO_NEW_BUTTON, bhvMenuButton, 711, 311, -100, 0, -0x8000, 0); } sMainMenuButtons[MENU_BUTTON_ERASE_FILE_A]->oMenuButtonScale = 0.11111111f; // File B if (save_file_exists(SAVE_FILE_B) == TRUE) { sMainMenuButtons[MENU_BUTTON_ERASE_FILE_B] = spawn_object_rel_with_rot(eraseButton, MODEL_MAIN_MENU_MARIO_SAVE_BUTTON, bhvMenuButton, -166, 311, -100, 0, -0x8000, 0); } else { sMainMenuButtons[MENU_BUTTON_ERASE_FILE_B] = spawn_object_rel_with_rot(eraseButton, MODEL_MAIN_MENU_MARIO_NEW_BUTTON, bhvMenuButton, -166, 311, -100, 0, -0x8000, 0); } sMainMenuButtons[MENU_BUTTON_ERASE_FILE_B]->oMenuButtonScale = 0.11111111f; // File C if (save_file_exists(SAVE_FILE_C) == TRUE) { sMainMenuButtons[MENU_BUTTON_ERASE_FILE_C] = spawn_object_rel_with_rot( eraseButton, MODEL_MAIN_MENU_MARIO_SAVE_BUTTON, bhvMenuButton, 711, 0, -100, 0, -0x8000, 0); } else { sMainMenuButtons[MENU_BUTTON_ERASE_FILE_C] = spawn_object_rel_with_rot( eraseButton, MODEL_MAIN_MENU_MARIO_NEW_BUTTON, bhvMenuButton, 711, 0, -100, 0, -0x8000, 0); } sMainMenuButtons[MENU_BUTTON_ERASE_FILE_C]->oMenuButtonScale = 0.11111111f; // File D if (save_file_exists(SAVE_FILE_D) == TRUE) { sMainMenuButtons[MENU_BUTTON_ERASE_FILE_D] = spawn_object_rel_with_rot(eraseButton, MODEL_MAIN_MENU_MARIO_SAVE_BUTTON, bhvMenuButton, -166, 0, -100, 0, -0x8000, 0); } else { sMainMenuButtons[MENU_BUTTON_ERASE_FILE_D] = spawn_object_rel_with_rot( eraseButton, MODEL_MAIN_MENU_MARIO_NEW_BUTTON, bhvMenuButton, -166, 0, -100, 0, -0x8000, 0); } sMainMenuButtons[MENU_BUTTON_ERASE_FILE_D]->oMenuButtonScale = 0.11111111f; // Return to main menu button sMainMenuButtons[MENU_BUTTON_ERASE_RETURN] = spawn_object_rel_with_rot( eraseButton, MODEL_MAIN_MENU_YELLOW_FILE_BUTTON, bhvMenuButton, 711, -388, -100, 0, -0x8000, 0); sMainMenuButtons[MENU_BUTTON_ERASE_RETURN]->oMenuButtonScale = 0.11111111f; // Switch to score menu button sMainMenuButtons[MENU_BUTTON_ERASE_CHECK_SCORE] = spawn_object_rel_with_rot( eraseButton, MODEL_MAIN_MENU_GREEN_SCORE_BUTTON, bhvMenuButton, 0, -388, -100, 0, -0x8000, 0); sMainMenuButtons[MENU_BUTTON_ERASE_CHECK_SCORE]->oMenuButtonScale = 0.11111111f; // Switch to copy menu button sMainMenuButtons[MENU_BUTTON_ERASE_COPY_FILE] = spawn_object_rel_with_rot( eraseButton, MODEL_MAIN_MENU_BLUE_COPY_BUTTON, bhvMenuButton, -711, -388, -100, 0, -0x8000, 0); sMainMenuButtons[MENU_BUTTON_ERASE_COPY_FILE]->oMenuButtonScale = 0.11111111f; } /** * Erase Menu phase actions that handles what to do when a file button is clicked. */ void erase_action_file_button(struct Object *eraseButton, s32 eraseFileButtonID) { switch (eraseButton->oMenuButtonActionPhase) { case ERASE_PHASE_MAIN: // Erase Menu Main Phase if (save_file_exists(eraseFileButtonID - MENU_BUTTON_ERASE_MIN) == TRUE) { // If clicked in a existing save file, ask if it wants to delete it play_sound(SOUND_MENU_CLICK_FILE_SELECT, gDefaultSoundArgs); sMainMenuButtons[eraseFileButtonID]->oMenuButtonState = MENU_BUTTON_STATE_ZOOM_IN; sSelectedFileIndex = eraseFileButtonID - MENU_BUTTON_ERASE_MIN; eraseButton->oMenuButtonActionPhase = ERASE_PHASE_PROMPT; sFadeOutText = TRUE; sMainMenuTimer = 0; } else { // If clicked in a non-existing save file, play buzz sound play_sound(SOUND_MENU_CAMERA_BUZZ, gDefaultSoundArgs); sMainMenuButtons[eraseFileButtonID]->oMenuButtonState = MENU_BUTTON_STATE_ZOOM_IN_OUT; if (sMainMenuTimer >= BUZZ_TIMER) { sFadeOutText = TRUE; sMainMenuTimer = 0; } } break; case ERASE_PHASE_PROMPT: // Erase Menu "SURE? YES NO" Phase (after a file is selected) if (MENU_BUTTON_ERASE_MIN + sSelectedFileIndex == eraseFileButtonID) { // If clicked in a existing save file, play click sound and zoom out button // Note: The prompt functions are actually called when the ERASE_MSG_PROMPT // message is displayed with print_erase_menu_prompt play_sound(SOUND_MENU_CLICK_FILE_SELECT, gDefaultSoundArgs); sMainMenuButtons[MENU_BUTTON_ERASE_MIN + sSelectedFileIndex]->oMenuButtonState = MENU_BUTTON_STATE_ZOOM_OUT; eraseButton->oMenuButtonActionPhase = ERASE_PHASE_MAIN; sFadeOutText = TRUE; } break; } } #undef BUZZ_TIMER /** * In the erase menu, checks if a button was clicked to play a sound, button state and other functions. */ void check_erase_menu_clicked_buttons(struct Object *eraseButton) { if (eraseButton->oMenuButtonState == MENU_BUTTON_STATE_FULLSCREEN) { s32 buttonID; // Configure erase menu button group for (buttonID = MENU_BUTTON_ERASE_MIN; buttonID < MENU_BUTTON_ERASE_MAX; buttonID++) { s16 buttonX = sMainMenuButtons[buttonID]->oPosX; s16 buttonY = sMainMenuButtons[buttonID]->oPosY; if (check_clicked_button(buttonX, buttonY, 22.0f) == TRUE) { // If menu button clicked, select it if (buttonID == MENU_BUTTON_ERASE_RETURN || buttonID == MENU_BUTTON_ERASE_CHECK_SCORE || buttonID == MENU_BUTTON_ERASE_COPY_FILE) { if (eraseButton->oMenuButtonActionPhase == ERASE_PHASE_MAIN) { play_sound(SOUND_MENU_CLICK_FILE_SELECT, gDefaultSoundArgs); sMainMenuButtons[buttonID]->oMenuButtonState = MENU_BUTTON_STATE_ZOOM_IN_OUT; sSelectedButtonID = buttonID; } } else { // Check if a file button is clicked to play an erase action if (sMainMenuTimer >= ACTION_TIMER) { erase_action_file_button(eraseButton, buttonID); } } sCurrentMenuLevel = MENU_LAYER_SUBMENU; break; } } // After erase is complete, return to main erase phase if (eraseButton->oMenuButtonActionPhase == ERASE_PHASE_MARIO_ERASED && sMainMenuTimer >= MAIN_RETURN_TIMER) { eraseButton->oMenuButtonActionPhase = ERASE_PHASE_MAIN; sMainMenuButtons[MENU_BUTTON_ERASE_MIN + sSelectedFileIndex]->oMenuButtonState = MENU_BUTTON_STATE_ZOOM_OUT; } } } #undef ACTION_TIMER #undef MAIN_RETURN_TIMER #ifdef VERSION_EU #define SOUND_BUTTON_Y 388 #else #define SOUND_BUTTON_Y 0 #endif /** * Render buttons for the sound mode menu. */ void render_sound_mode_menu_buttons(struct Object *soundModeButton) { // Stereo option button sMainMenuButtons[MENU_BUTTON_STEREO] = spawn_object_rel_with_rot( soundModeButton, MODEL_MAIN_MENU_GENERIC_BUTTON, bhvMenuButton, 533, SOUND_BUTTON_Y, -100, 0, -0x8000, 0); sMainMenuButtons[MENU_BUTTON_STEREO]->oMenuButtonScale = 0.11111111f; // Mono option button sMainMenuButtons[MENU_BUTTON_MONO] = spawn_object_rel_with_rot( soundModeButton, MODEL_MAIN_MENU_GENERIC_BUTTON, bhvMenuButton, 0, SOUND_BUTTON_Y, -100, 0, -0x8000, 0); sMainMenuButtons[MENU_BUTTON_MONO]->oMenuButtonScale = 0.11111111f; // Headset option button sMainMenuButtons[MENU_BUTTON_HEADSET] = spawn_object_rel_with_rot( soundModeButton, MODEL_MAIN_MENU_GENERIC_BUTTON, bhvMenuButton, -533, SOUND_BUTTON_Y, -100, 0, -0x8000, 0); sMainMenuButtons[MENU_BUTTON_HEADSET]->oMenuButtonScale = 0.11111111f; #ifdef VERSION_EU // English option button sMainMenuButtons[MENU_BUTTON_LANGUAGE_ENGLISH] = spawn_object_rel_with_rot( soundModeButton, MODEL_MAIN_MENU_GENERIC_BUTTON, bhvMenuButton, 533, -111, -100, 0, -0x8000, 0); sMainMenuButtons[MENU_BUTTON_LANGUAGE_ENGLISH]->oMenuButtonScale = 0.11111111f; // French option button sMainMenuButtons[MENU_BUTTON_LANGUAGE_FRENCH] = spawn_object_rel_with_rot( soundModeButton, MODEL_MAIN_MENU_GENERIC_BUTTON, bhvMenuButton, 0, -111, -100, 0, -0x8000, 0); sMainMenuButtons[MENU_BUTTON_LANGUAGE_FRENCH]->oMenuButtonScale = 0.11111111f; // German option button sMainMenuButtons[MENU_BUTTON_LANGUAGE_GERMAN] = spawn_object_rel_with_rot( soundModeButton, MODEL_MAIN_MENU_GENERIC_BUTTON, bhvMenuButton, -533, -111, -100, 0, -0x8000, 0); sMainMenuButtons[MENU_BUTTON_LANGUAGE_GERMAN]->oMenuButtonScale = 0.11111111f; // Return button sMainMenuButtons[MENU_BUTTON_LANGUAGE_RETURN] = spawn_object_rel_with_rot( soundModeButton, MODEL_MAIN_MENU_YELLOW_FILE_BUTTON, bhvMenuButton, 0, -533, -100, 0, -0x8000, 0); sMainMenuButtons[MENU_BUTTON_LANGUAGE_RETURN]->oMenuButtonScale = 0.11111111f; #else // Zoom in current selection sMainMenuButtons[MENU_BUTTON_OPTION_MIN + sSoundMode]->oMenuButtonState = MENU_BUTTON_STATE_ZOOM_IN; #endif } #undef SOUND_BUTTON_Y /** * In the sound mode menu, checks if a button was clicked to change sound mode & button state. */ void check_sound_mode_menu_clicked_buttons(struct Object *soundModeButton) { if (soundModeButton->oMenuButtonState == MENU_BUTTON_STATE_FULLSCREEN) { s32 buttonID; // Configure sound mode menu button group for (buttonID = MENU_BUTTON_OPTION_MIN; buttonID < MENU_BUTTON_OPTION_MAX; buttonID++) { s16 buttonX = sMainMenuButtons[buttonID]->oPosX; s16 buttonY = sMainMenuButtons[buttonID]->oPosY; if (check_clicked_button(buttonX, buttonY, 22.0f) == TRUE) { // If sound mode button clicked, select it and define sound mode // The check will always be true because of the group configured above (In JP & US) if (buttonID == MENU_BUTTON_STEREO || buttonID == MENU_BUTTON_MONO || buttonID == MENU_BUTTON_HEADSET) { if (soundModeButton->oMenuButtonActionPhase == SOUND_MODE_PHASE_MAIN) { play_sound(SOUND_MENU_CLICK_FILE_SELECT, gDefaultSoundArgs); sMainMenuButtons[buttonID]->oMenuButtonState = MENU_BUTTON_STATE_ZOOM_IN_OUT; #ifndef VERSION_EU // Sound menu buttons don't return to Main Menu in EU // because they don't have a case in bhv_menu_button_manager_loop sSelectedButtonID = buttonID; #endif sSoundMode = buttonID - MENU_BUTTON_OPTION_MIN; save_file_set_sound_mode(sSoundMode); } } #ifdef VERSION_EU // If language mode button clicked, select it and change language if (buttonID == MENU_BUTTON_LANGUAGE_ENGLISH || buttonID == MENU_BUTTON_LANGUAGE_FRENCH || buttonID == MENU_BUTTON_LANGUAGE_GERMAN) { if (soundModeButton->oMenuButtonActionPhase == SOUND_MODE_PHASE_MAIN) { play_sound(SOUND_MENU_CLICK_FILE_SELECT, gDefaultSoundArgs); sMainMenuButtons[buttonID]->oMenuButtonState = MENU_BUTTON_STATE_ZOOM_IN_OUT; sLanguageMode = buttonID - MENU_BUTTON_LANGUAGE_MIN; eu_set_language(sLanguageMode); } } // If neither of the buttons above are pressed, return to main menu if (buttonID == MENU_BUTTON_LANGUAGE_RETURN) { play_sound(SOUND_MENU_CLICK_FILE_SELECT, gDefaultSoundArgs); sMainMenuButtons[buttonID]->oMenuButtonState = MENU_BUTTON_STATE_ZOOM_IN_OUT; sSelectedButtonID = buttonID; } #endif sCurrentMenuLevel = MENU_LAYER_SUBMENU; break; } } } } /** * Loads a save file selected after it goes into a full screen state * retuning sSelectedFileNum to a save value defined in fileNum. */ void load_main_menu_save_file(struct Object *fileButton, s32 fileNum) { if (fileButton->oMenuButtonState == MENU_BUTTON_STATE_FULLSCREEN) { sSelectedFileNum = fileNum; } } /** * Returns from the previous menu back to the main menu using * the return button (or sound mode) as source button. */ void return_to_main_menu(s16 prevMenuButtonID, struct Object *sourceButton) { s32 buttonID; // If the source button is in default state and the previous menu in full screen, // play zoom out sound and shrink previous menu if (sourceButton->oMenuButtonState == MENU_BUTTON_STATE_DEFAULT && sMainMenuButtons[prevMenuButtonID]->oMenuButtonState == MENU_BUTTON_STATE_FULLSCREEN) { play_sound(SOUND_MENU_CAMERA_ZOOM_OUT, gDefaultSoundArgs); sMainMenuButtons[prevMenuButtonID]->oMenuButtonState = MENU_BUTTON_STATE_SHRINKING; sCurrentMenuLevel = MENU_LAYER_MAIN; } // If the previous button is in default state, return back to the main menu if (sMainMenuButtons[prevMenuButtonID]->oMenuButtonState == MENU_BUTTON_STATE_DEFAULT) { sSelectedButtonID = MENU_BUTTON_NONE; // Hide buttons of corresponding button menu groups if (prevMenuButtonID == MENU_BUTTON_SCORE) { for (buttonID = MENU_BUTTON_SCORE_MIN; buttonID < MENU_BUTTON_SCORE_MAX; buttonID++) { mark_obj_for_deletion(sMainMenuButtons[buttonID]); } } if (prevMenuButtonID == MENU_BUTTON_COPY) { for (buttonID = MENU_BUTTON_COPY_MIN; buttonID < MENU_BUTTON_COPY_MAX; buttonID++) { mark_obj_for_deletion(sMainMenuButtons[buttonID]); } } if (prevMenuButtonID == MENU_BUTTON_ERASE) { for (buttonID = MENU_BUTTON_ERASE_MIN; buttonID < MENU_BUTTON_ERASE_MAX; buttonID++) { mark_obj_for_deletion(sMainMenuButtons[buttonID]); } } if (prevMenuButtonID == MENU_BUTTON_SOUND_MODE) { for (buttonID = MENU_BUTTON_OPTION_MIN; buttonID < MENU_BUTTON_OPTION_MAX; buttonID++) { mark_obj_for_deletion(sMainMenuButtons[buttonID]); } } } } /** * Loads score menu from the previous menu using "CHECK SCORE" as source button. */ void load_score_menu_from_submenu(s16 prevMenuButtonID, struct Object *sourceButton) { s32 buttonID; // If the source button is in default state and the previous menu in full screen, // play zoom out sound and shrink previous menu if (sourceButton->oMenuButtonState == MENU_BUTTON_STATE_DEFAULT && sMainMenuButtons[prevMenuButtonID]->oMenuButtonState == MENU_BUTTON_STATE_FULLSCREEN) { play_sound(SOUND_MENU_CAMERA_ZOOM_OUT, gDefaultSoundArgs); sMainMenuButtons[prevMenuButtonID]->oMenuButtonState = MENU_BUTTON_STATE_SHRINKING; sCurrentMenuLevel = MENU_LAYER_MAIN; } // If the previous button is in default state if (sMainMenuButtons[prevMenuButtonID]->oMenuButtonState == MENU_BUTTON_STATE_DEFAULT) { // Hide buttons of corresponding button menu groups if (prevMenuButtonID == MENU_BUTTON_SCORE) //! Not possible, this is checking if the score menu //! was opened from the score menu! { for (buttonID = MENU_BUTTON_SCORE_MIN; buttonID < MENU_BUTTON_SCORE_MAX; buttonID++) { mark_obj_for_deletion(sMainMenuButtons[buttonID]); } } if (prevMenuButtonID == MENU_BUTTON_COPY) { for (buttonID = MENU_BUTTON_COPY_MIN; buttonID < MENU_BUTTON_COPY_MAX; buttonID++) { mark_obj_for_deletion(sMainMenuButtons[buttonID]); } } if (prevMenuButtonID == MENU_BUTTON_ERASE) { for (buttonID = MENU_BUTTON_ERASE_MIN; buttonID < MENU_BUTTON_ERASE_MAX; buttonID++) { mark_obj_for_deletion(sMainMenuButtons[buttonID]); } } // Play zoom in sound, select score menu and render it's buttons sSelectedButtonID = MENU_BUTTON_SCORE; play_sound(SOUND_MENU_CAMERA_ZOOM_IN, gDefaultSoundArgs); sMainMenuButtons[MENU_BUTTON_SCORE]->oMenuButtonState = MENU_BUTTON_STATE_GROWING; render_score_menu_buttons(sMainMenuButtons[MENU_BUTTON_SCORE]); } } /** * Loads copy menu from the previous menu using "COPY FILE" as source button. */ void load_copy_menu_from_submenu(s16 prevMenuButtonID, struct Object *sourceButton) { s32 buttonID; // If the source button is in default state and the previous menu in full screen, // play zoom out sound and shrink previous menu if (sourceButton->oMenuButtonState == MENU_BUTTON_STATE_DEFAULT && sMainMenuButtons[prevMenuButtonID]->oMenuButtonState == MENU_BUTTON_STATE_FULLSCREEN) { play_sound(SOUND_MENU_CAMERA_ZOOM_OUT, gDefaultSoundArgs); sMainMenuButtons[prevMenuButtonID]->oMenuButtonState = MENU_BUTTON_STATE_SHRINKING; sCurrentMenuLevel = MENU_LAYER_MAIN; } // If the previous button is in default state if (sMainMenuButtons[prevMenuButtonID]->oMenuButtonState == MENU_BUTTON_STATE_DEFAULT) { // Hide buttons of corresponding button menu groups if (prevMenuButtonID == MENU_BUTTON_SCORE) { for (buttonID = MENU_BUTTON_SCORE_MIN; buttonID < MENU_BUTTON_SCORE_MAX; buttonID++) { mark_obj_for_deletion(sMainMenuButtons[buttonID]); } } if (prevMenuButtonID == MENU_BUTTON_COPY) //! Not possible, this is checking if the copy menu //! was opened from the copy menu! { for (buttonID = MENU_BUTTON_COPY_MIN; buttonID < MENU_BUTTON_COPY_MAX; buttonID++) { mark_obj_for_deletion(sMainMenuButtons[buttonID]); } } if (prevMenuButtonID == MENU_BUTTON_ERASE) { for (buttonID = MENU_BUTTON_ERASE_MIN; buttonID < MENU_BUTTON_ERASE_MAX; buttonID++) { mark_obj_for_deletion(sMainMenuButtons[buttonID]); } } // Play zoom in sound, select copy menu and render it's buttons sSelectedButtonID = MENU_BUTTON_COPY; play_sound(SOUND_MENU_CAMERA_ZOOM_IN, gDefaultSoundArgs); sMainMenuButtons[MENU_BUTTON_COPY]->oMenuButtonState = MENU_BUTTON_STATE_GROWING; render_copy_menu_buttons(sMainMenuButtons[MENU_BUTTON_COPY]); } } /** * Loads erase menu from the previous menu using "ERASE FILE" as source button. */ void load_erase_menu_from_submenu(s16 prevMenuButtonID, struct Object *sourceButton) { s32 buttonID; // If the source button is in default state and the previous menu in full screen, // play zoom out sound and shrink previous menu if (sourceButton->oMenuButtonState == MENU_BUTTON_STATE_DEFAULT && sMainMenuButtons[prevMenuButtonID]->oMenuButtonState == MENU_BUTTON_STATE_FULLSCREEN) { play_sound(SOUND_MENU_CAMERA_ZOOM_OUT, gDefaultSoundArgs); sMainMenuButtons[prevMenuButtonID]->oMenuButtonState = MENU_BUTTON_STATE_SHRINKING; sCurrentMenuLevel = MENU_LAYER_MAIN; } // If the previous button is in default state if (sMainMenuButtons[prevMenuButtonID]->oMenuButtonState == MENU_BUTTON_STATE_DEFAULT) { // Hide buttons of corresponding button menu groups if (prevMenuButtonID == MENU_BUTTON_SCORE) { for (buttonID = MENU_BUTTON_SCORE_MIN; buttonID < MENU_BUTTON_SCORE_MAX; buttonID++) { mark_obj_for_deletion(sMainMenuButtons[buttonID]); } } if (prevMenuButtonID == MENU_BUTTON_COPY) { for (buttonID = MENU_BUTTON_COPY_MIN; buttonID < MENU_BUTTON_COPY_MAX; buttonID++) { mark_obj_for_deletion(sMainMenuButtons[buttonID]); } } if (prevMenuButtonID == MENU_BUTTON_ERASE) //! Not possible, this is checking if the erase menu //! was opened from the erase menu! { for (buttonID = MENU_BUTTON_ERASE_MIN; buttonID < MENU_BUTTON_ERASE_MAX; buttonID++) { mark_obj_for_deletion(sMainMenuButtons[buttonID]); } } // Play zoom in sound, select erase menu and render it's buttons sSelectedButtonID = MENU_BUTTON_ERASE; play_sound(SOUND_MENU_CAMERA_ZOOM_IN, gDefaultSoundArgs); sMainMenuButtons[MENU_BUTTON_ERASE]->oMenuButtonState = MENU_BUTTON_STATE_GROWING; render_erase_menu_buttons(sMainMenuButtons[MENU_BUTTON_ERASE]); } } /** * Menu Buttons Menu Manager Initial Action * Creates models of the buttons in the menu. For the Mario buttons it * checks if a save file exists to render an specific button model for it. * Unlike buttons on submenus, these are never hidden or recreated. */ void bhv_menu_button_manager_init(void) { // File A if (save_file_exists(SAVE_FILE_A) == TRUE) { sMainMenuButtons[MENU_BUTTON_PLAY_FILE_A] = spawn_object_rel_with_rot(gCurrentObject, MODEL_MAIN_MENU_MARIO_SAVE_BUTTON_FADE, bhvMenuButton, -6400, 2800, 0, 0, 0, 0); } else { sMainMenuButtons[MENU_BUTTON_PLAY_FILE_A] = spawn_object_rel_with_rot(gCurrentObject, MODEL_MAIN_MENU_MARIO_NEW_BUTTON_FADE, bhvMenuButton, -6400, 2800, 0, 0, 0, 0); } sMainMenuButtons[MENU_BUTTON_PLAY_FILE_A]->oMenuButtonScale = 1.0f; // File B if (save_file_exists(SAVE_FILE_B) == TRUE) { sMainMenuButtons[MENU_BUTTON_PLAY_FILE_B] = spawn_object_rel_with_rot(gCurrentObject, MODEL_MAIN_MENU_MARIO_SAVE_BUTTON_FADE, bhvMenuButton, 1500, 2800, 0, 0, 0, 0); } else { sMainMenuButtons[MENU_BUTTON_PLAY_FILE_B] = spawn_object_rel_with_rot(gCurrentObject, MODEL_MAIN_MENU_MARIO_NEW_BUTTON_FADE, bhvMenuButton, 1500, 2800, 0, 0, 0, 0); } sMainMenuButtons[MENU_BUTTON_PLAY_FILE_B]->oMenuButtonScale = 1.0f; // File C if (save_file_exists(SAVE_FILE_C) == TRUE) { sMainMenuButtons[MENU_BUTTON_PLAY_FILE_C] = spawn_object_rel_with_rot(gCurrentObject, MODEL_MAIN_MENU_MARIO_SAVE_BUTTON_FADE, bhvMenuButton, -6400, 0, 0, 0, 0, 0); } else { sMainMenuButtons[MENU_BUTTON_PLAY_FILE_C] = spawn_object_rel_with_rot( gCurrentObject, MODEL_MAIN_MENU_MARIO_NEW_BUTTON_FADE, bhvMenuButton, -6400, 0, 0, 0, 0, 0); } sMainMenuButtons[MENU_BUTTON_PLAY_FILE_C]->oMenuButtonScale = 1.0f; // File D if (save_file_exists(SAVE_FILE_D) == TRUE) { sMainMenuButtons[MENU_BUTTON_PLAY_FILE_D] = spawn_object_rel_with_rot( gCurrentObject, MODEL_MAIN_MENU_MARIO_SAVE_BUTTON_FADE, bhvMenuButton, 1500, 0, 0, 0, 0, 0); } else { sMainMenuButtons[MENU_BUTTON_PLAY_FILE_D] = spawn_object_rel_with_rot( gCurrentObject, MODEL_MAIN_MENU_MARIO_NEW_BUTTON_FADE, bhvMenuButton, 1500, 0, 0, 0, 0, 0); } sMainMenuButtons[MENU_BUTTON_PLAY_FILE_D]->oMenuButtonScale = 1.0f; // Score menu button sMainMenuButtons[MENU_BUTTON_SCORE] = spawn_object_rel_with_rot( gCurrentObject, MODEL_MAIN_MENU_GREEN_SCORE_BUTTON, bhvMenuButton, -6400, -3500, 0, 0, 0, 0); sMainMenuButtons[MENU_BUTTON_SCORE]->oMenuButtonScale = 1.0f; // Copy menu button sMainMenuButtons[MENU_BUTTON_COPY] = spawn_object_rel_with_rot( gCurrentObject, MODEL_MAIN_MENU_BLUE_COPY_BUTTON, bhvMenuButton, -2134, -3500, 0, 0, 0, 0); sMainMenuButtons[MENU_BUTTON_COPY]->oMenuButtonScale = 1.0f; // Erase menu button sMainMenuButtons[MENU_BUTTON_ERASE] = spawn_object_rel_with_rot( gCurrentObject, MODEL_MAIN_MENU_RED_ERASE_BUTTON, bhvMenuButton, 2134, -3500, 0, 0, 0, 0); sMainMenuButtons[MENU_BUTTON_ERASE]->oMenuButtonScale = 1.0f; // Sound mode menu button (Option Mode in EU) sMainMenuButtons[MENU_BUTTON_SOUND_MODE] = spawn_object_rel_with_rot( gCurrentObject, MODEL_MAIN_MENU_PURPLE_SOUND_BUTTON, bhvMenuButton, 6400, -3500, 0, 0, 0, 0); sMainMenuButtons[MENU_BUTTON_SOUND_MODE]->oMenuButtonScale = 1.0f; sTextBaseAlpha = 0; } #if defined(VERSION_JP) || defined(VERSION_SH) #define SAVE_FILE_SOUND SOUND_MENU_STAR_SOUND #else #define SAVE_FILE_SOUND SOUND_MENU_STAR_SOUND_OKEY_DOKEY #endif /** * In the main menu, check if a button was clicked to play it's button growing state. * Also play a sound and/or render buttons depending of the button ID selected. */ void check_main_menu_clicked_buttons(void) { #ifdef VERSION_EU if (sMainMenuTimer >= 5) { #endif // Sound mode menu is handled separately because the button ID for it // is not grouped with the IDs of the other submenus. if (check_clicked_button(sMainMenuButtons[MENU_BUTTON_SOUND_MODE]->oPosX, sMainMenuButtons[MENU_BUTTON_SOUND_MODE]->oPosY, 200.0f) == TRUE) { sMainMenuButtons[MENU_BUTTON_SOUND_MODE]->oMenuButtonState = MENU_BUTTON_STATE_GROWING; sSelectedButtonID = MENU_BUTTON_SOUND_MODE; } else { // Main Menu buttons s8 buttonID; // Configure Main Menu button group for (buttonID = MENU_BUTTON_MAIN_MIN; buttonID < MENU_BUTTON_MAIN_MAX; buttonID++) { s16 buttonX = sMainMenuButtons[buttonID]->oPosX; s16 buttonY = sMainMenuButtons[buttonID]->oPosY; if (check_clicked_button(buttonX, buttonY, 200.0f) == TRUE) { // If menu button clicked, select it sMainMenuButtons[buttonID]->oMenuButtonState = MENU_BUTTON_STATE_GROWING; sSelectedButtonID = buttonID; break; } } } #ifdef VERSION_EU // Open Options Menu if sOpenLangSettings is TRUE (It's TRUE when there's no saves) if (sOpenLangSettings == TRUE) { sMainMenuButtons[MENU_BUTTON_SOUND_MODE]->oMenuButtonState = MENU_BUTTON_STATE_GROWING; sSelectedButtonID = MENU_BUTTON_SOUND_MODE; sOpenLangSettings = FALSE; } #endif // Play sound of the save file clicked switch (sSelectedButtonID) { case MENU_BUTTON_PLAY_FILE_A: play_sound(SAVE_FILE_SOUND, gDefaultSoundArgs); break; case MENU_BUTTON_PLAY_FILE_B: play_sound(SAVE_FILE_SOUND, gDefaultSoundArgs); break; case MENU_BUTTON_PLAY_FILE_C: play_sound(SAVE_FILE_SOUND, gDefaultSoundArgs); break; case MENU_BUTTON_PLAY_FILE_D: play_sound(SAVE_FILE_SOUND, gDefaultSoundArgs); break; // Play sound of the button clicked and render buttons of that menu. case MENU_BUTTON_SCORE: play_sound(SOUND_MENU_CAMERA_ZOOM_IN, gDefaultSoundArgs); render_score_menu_buttons(sMainMenuButtons[MENU_BUTTON_SCORE]); break; case MENU_BUTTON_COPY: play_sound(SOUND_MENU_CAMERA_ZOOM_IN, gDefaultSoundArgs); render_copy_menu_buttons(sMainMenuButtons[MENU_BUTTON_COPY]); break; case MENU_BUTTON_ERASE: play_sound(SOUND_MENU_CAMERA_ZOOM_IN, gDefaultSoundArgs); render_erase_menu_buttons(sMainMenuButtons[MENU_BUTTON_ERASE]); break; case MENU_BUTTON_SOUND_MODE: play_sound(SOUND_MENU_CAMERA_ZOOM_IN, gDefaultSoundArgs); render_sound_mode_menu_buttons(sMainMenuButtons[MENU_BUTTON_SOUND_MODE]); break; } #ifdef VERSION_EU } #endif } #undef SAVE_FILE_SOUND /** * Menu Buttons Menu Manager Loop Action * Calls a menu function depending of the button chosen. * sSelectedButtonID is MENU_BUTTON_NONE when the file select * is loaded, and that checks what buttonID is clicked in the main menu. */ void bhv_menu_button_manager_loop(void) { switch (sSelectedButtonID) { case MENU_BUTTON_NONE: check_main_menu_clicked_buttons(); break; case MENU_BUTTON_PLAY_FILE_A: load_main_menu_save_file(sMainMenuButtons[MENU_BUTTON_PLAY_FILE_A], 1); break; case MENU_BUTTON_PLAY_FILE_B: load_main_menu_save_file(sMainMenuButtons[MENU_BUTTON_PLAY_FILE_B], 2); break; case MENU_BUTTON_PLAY_FILE_C: load_main_menu_save_file(sMainMenuButtons[MENU_BUTTON_PLAY_FILE_C], 3); break; case MENU_BUTTON_PLAY_FILE_D: load_main_menu_save_file(sMainMenuButtons[MENU_BUTTON_PLAY_FILE_D], 4); break; case MENU_BUTTON_SCORE: check_score_menu_clicked_buttons(sMainMenuButtons[MENU_BUTTON_SCORE]); break; case MENU_BUTTON_COPY: check_copy_menu_clicked_buttons(sMainMenuButtons[MENU_BUTTON_COPY]); break; case MENU_BUTTON_ERASE: check_erase_menu_clicked_buttons(sMainMenuButtons[MENU_BUTTON_ERASE]); break; case MENU_BUTTON_SCORE_FILE_A: exit_score_file_to_score_menu(sMainMenuButtons[MENU_BUTTON_SCORE_FILE_A], MENU_BUTTON_SCORE); break; case MENU_BUTTON_SCORE_FILE_B: exit_score_file_to_score_menu(sMainMenuButtons[MENU_BUTTON_SCORE_FILE_B], MENU_BUTTON_SCORE); break; case MENU_BUTTON_SCORE_FILE_C: exit_score_file_to_score_menu(sMainMenuButtons[MENU_BUTTON_SCORE_FILE_C], MENU_BUTTON_SCORE); break; case MENU_BUTTON_SCORE_FILE_D: exit_score_file_to_score_menu(sMainMenuButtons[MENU_BUTTON_SCORE_FILE_D], MENU_BUTTON_SCORE); break; case MENU_BUTTON_SCORE_RETURN: return_to_main_menu(MENU_BUTTON_SCORE, sMainMenuButtons[MENU_BUTTON_SCORE_RETURN]); break; case MENU_BUTTON_SCORE_COPY_FILE: load_copy_menu_from_submenu(MENU_BUTTON_SCORE, sMainMenuButtons[MENU_BUTTON_SCORE_COPY_FILE]); break; case MENU_BUTTON_SCORE_ERASE_FILE: load_erase_menu_from_submenu(MENU_BUTTON_SCORE, sMainMenuButtons[MENU_BUTTON_SCORE_ERASE_FILE]); break; case MENU_BUTTON_COPY_FILE_A: break; case MENU_BUTTON_COPY_FILE_B: break; case MENU_BUTTON_COPY_FILE_C: break; case MENU_BUTTON_COPY_FILE_D: break; case MENU_BUTTON_COPY_RETURN: return_to_main_menu(MENU_BUTTON_COPY, sMainMenuButtons[MENU_BUTTON_COPY_RETURN]); break; case MENU_BUTTON_COPY_CHECK_SCORE: load_score_menu_from_submenu(MENU_BUTTON_COPY, sMainMenuButtons[MENU_BUTTON_COPY_CHECK_SCORE]); break; case MENU_BUTTON_COPY_ERASE_FILE: load_erase_menu_from_submenu(MENU_BUTTON_COPY, sMainMenuButtons[MENU_BUTTON_COPY_ERASE_FILE]); break; case MENU_BUTTON_ERASE_FILE_A: break; case MENU_BUTTON_ERASE_FILE_B: break; case MENU_BUTTON_ERASE_FILE_C: break; case MENU_BUTTON_ERASE_FILE_D: break; case MENU_BUTTON_ERASE_RETURN: return_to_main_menu(MENU_BUTTON_ERASE, sMainMenuButtons[MENU_BUTTON_ERASE_RETURN]); break; case MENU_BUTTON_ERASE_CHECK_SCORE: load_score_menu_from_submenu(MENU_BUTTON_ERASE, sMainMenuButtons[MENU_BUTTON_ERASE_CHECK_SCORE]); break; case MENU_BUTTON_ERASE_COPY_FILE: load_copy_menu_from_submenu(MENU_BUTTON_ERASE, sMainMenuButtons[MENU_BUTTON_ERASE_COPY_FILE]); break; case MENU_BUTTON_SOUND_MODE: check_sound_mode_menu_clicked_buttons(sMainMenuButtons[MENU_BUTTON_SOUND_MODE]); break; // STEREO, MONO and HEADSET buttons are undefined so they can be selected without // exiting the Options menu, as a result they added a return button #ifdef VERSION_EU case MENU_BUTTON_LANGUAGE_RETURN: return_to_main_menu(MENU_BUTTON_SOUND_MODE, sMainMenuButtons[MENU_BUTTON_LANGUAGE_RETURN]); break; #else case MENU_BUTTON_STEREO: return_to_main_menu(MENU_BUTTON_SOUND_MODE, sMainMenuButtons[MENU_BUTTON_STEREO]); break; case MENU_BUTTON_MONO: return_to_main_menu(MENU_BUTTON_SOUND_MODE, sMainMenuButtons[MENU_BUTTON_MONO]); break; case MENU_BUTTON_HEADSET: return_to_main_menu(MENU_BUTTON_SOUND_MODE, sMainMenuButtons[MENU_BUTTON_HEADSET]); break; #endif } sClickPos[0] = -10000; sClickPos[1] = -10000; } /** * Cursor function that handles button inputs. * If the cursor is clicked, sClickPos uses the same value as sCursorPos. */ void handle_cursor_button_input(void) { // If scoring a file, pressing A just changes the coin score mode. if (sSelectedButtonID == MENU_BUTTON_SCORE_FILE_A || sSelectedButtonID == MENU_BUTTON_SCORE_FILE_B || sSelectedButtonID == MENU_BUTTON_SCORE_FILE_C || sSelectedButtonID == MENU_BUTTON_SCORE_FILE_D) { if (gPlayer3Controller->buttonPressed #ifdef VERSION_EU & (B_BUTTON | START_BUTTON | Z_TRIG)) { #else & (B_BUTTON | START_BUTTON)) { #endif sClickPos[0] = sCursorPos[0]; sClickPos[1] = sCursorPos[1]; sCursorClickingTimer = 1; } else if (gPlayer3Controller->buttonPressed & A_BUTTON) { sScoreFileCoinScoreMode = 1 - sScoreFileCoinScoreMode; play_sound(SOUND_MENU_CLICK_FILE_SELECT, gDefaultSoundArgs); } } else { // If cursor is clicked if (gPlayer3Controller->buttonPressed #ifdef VERSION_EU & (A_BUTTON | B_BUTTON | START_BUTTON | Z_TRIG)) { #else & (A_BUTTON | B_BUTTON | START_BUTTON)) { #endif sClickPos[0] = sCursorPos[0]; sClickPos[1] = sCursorPos[1]; sCursorClickingTimer = 1; } } } /** * Cursor function that handles analog stick input and button presses with a function near the end. */ void handle_controller_cursor_input(void) { s16 rawStickX = gPlayer3Controller->rawStickX; s16 rawStickY = gPlayer3Controller->rawStickY; // Handle deadzone if (rawStickY > -2 && rawStickY < 2) { rawStickY = 0; } if (rawStickX > -2 && rawStickX < 2) { rawStickX = 0; } // Move cursor sCursorPos[0] += rawStickX / 8; sCursorPos[1] += rawStickY / 8; // Stop cursor from going offscreen if (sCursorPos[0] > 132.0f) { sCursorPos[0] = 132.0f; } if (sCursorPos[0] < -132.0f) { sCursorPos[0] = -132.0f; } if (sCursorPos[1] > 90.0f) { sCursorPos[1] = 90.0f; } if (sCursorPos[1] < -90.0f) { sCursorPos[1] = -90.0f; } if (sCursorClickingTimer == 0) { handle_cursor_button_input(); } } /** * Prints the cursor (Mario Hand, different to the one in the Mario screen) * and loads it's controller inputs in handle_controller_cursor_input * to be usable on the file select. */ void print_menu_cursor(void) { handle_controller_cursor_input(); create_dl_translation_matrix(MENU_MTX_PUSH, sCursorPos[0] + 160.0f - 5.0, sCursorPos[1] + 120.0f - 25.0, 0.0f); // Get the right graphic to use for the cursor. if (sCursorClickingTimer == 0) // Idle gSPDisplayList(gDisplayListHead++, dl_menu_idle_hand); if (sCursorClickingTimer != 0) // Grabbing gSPDisplayList(gDisplayListHead++, dl_menu_grabbing_hand); gSPPopMatrix(gDisplayListHead++, G_MTX_MODELVIEW); if (sCursorClickingTimer != 0) { sCursorClickingTimer++; // This is a very strange way to implement a timer? It counts up and // then resets to 0 instead of just counting down to 0. if (sCursorClickingTimer == 5) { sCursorClickingTimer = 0; } } } /** * Prints a hud string depending of the hud table list defined with text fade properties. */ void print_hud_lut_string_fade(s8 hudLUT, s16 x, s16 y, const unsigned char *text) { gSPDisplayList(gDisplayListHead++, dl_rgba16_text_begin); gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, sTextBaseAlpha - sTextFadeAlpha); print_hud_lut_string(hudLUT, x, y, text); gSPDisplayList(gDisplayListHead++, dl_rgba16_text_end); } /** * Prints a generic white string with text fade properties. */ void print_generic_string_fade(s16 x, s16 y, const unsigned char *text) { gSPDisplayList(gDisplayListHead++, dl_ia_text_begin); gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, sTextBaseAlpha - sTextFadeAlpha); print_generic_string(x, y, text); gSPDisplayList(gDisplayListHead++, dl_ia_text_end); } /** * Updates text fade at the top of a menu. */ s32 update_text_fade_out(void) { if (sFadeOutText == TRUE) { sTextFadeAlpha += 50; if (sTextFadeAlpha == 250) { sFadeOutText = FALSE; return TRUE; } } else { if (sTextFadeAlpha > 0) { sTextFadeAlpha -= 50; } } return FALSE; } /** * Prints the amount of stars of a save file. * If a save doesn't exist, print "NEW" instead. */ void print_save_file_star_count(s8 fileIndex, s16 x, s16 y) { u8 starCountText[4]; s8 offset = 0; s16 starCount; if (save_file_exists(fileIndex) == TRUE) { starCount = save_file_get_total_star_count(fileIndex, 0, 24); // Print star icon print_hud_lut_string(HUD_LUT_GLOBAL, x, y, starIcon); // If star count is less than 100, print x icon and move // the star count text one digit to the right. if (starCount < 100) { print_hud_lut_string(HUD_LUT_GLOBAL, x + 16, y, xIcon); offset = 16; } // Print star count int_to_str(starCount, starCountText); print_hud_lut_string(HUD_LUT_GLOBAL, x + offset + 16, y, starCountText); } else { // Print "new" text print_hud_lut_string(HUD_LUT_GLOBAL, x, y, LANGUAGE_ARRAY(textNew)); } } #if defined(VERSION_JP) || defined(VERSION_SH) #define SELECT_FILE_X 96 #define SCORE_X 50 #define COPY_X 115 #define ERASE_X 180 #define SOUNDMODE_X1 235 #define SAVEFILE_X1 92 #define SAVEFILE_X2 209 #define MARIOTEXT_X1 92 #define MARIOTEXT_X2 207 #elif VERSION_US #define SELECT_FILE_X 93 #define SCORE_X 52 #define COPY_X 117 #define ERASE_X 177 #define SOUNDMODE_X1 sSoundTextX #define SAVEFILE_X1 92 #define SAVEFILE_X2 209 #define MARIOTEXT_X1 92 #define MARIOTEXT_X2 207 #elif VERSION_EU #define SELECT_FILE_X 93 #define SCORE_X 52 #define COPY_X 117 #define ERASE_X 177 #define SOUNDMODE_X1 sSoundTextX #define SAVEFILE_X1 97 #define SAVEFILE_X2 204 #define MARIOTEXT_X1 97 #define MARIOTEXT_X2 204 #endif /** * Prints main menu strings that shows on the yellow background menu screen. * * In EU this function acts like "print_save_file_strings" because * print_main_lang_strings is first called to render the strings for the 4 buttons. * Same rule applies for score, copy and erase strings. */ void print_main_menu_strings(void) { // Print "SELECT FILE" text gSPDisplayList(gDisplayListHead++, dl_rgba16_text_begin); gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, sTextBaseAlpha); #ifndef VERSION_EU print_hud_lut_string(HUD_LUT_DIFF, SELECT_FILE_X, 35, textSelectFile); #endif // Print file star counts print_save_file_star_count(SAVE_FILE_A, SAVEFILE_X1, 78); print_save_file_star_count(SAVE_FILE_B, SAVEFILE_X2, 78); print_save_file_star_count(SAVE_FILE_C, SAVEFILE_X1, 118); print_save_file_star_count(SAVE_FILE_D, SAVEFILE_X2, 118); gSPDisplayList(gDisplayListHead++, dl_rgba16_text_end); #ifndef VERSION_EU // Print menu names gSPDisplayList(gDisplayListHead++, dl_ia_text_begin); gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, sTextBaseAlpha); print_generic_string(SCORE_X, 39, textScore); print_generic_string(COPY_X, 39, textCopy); print_generic_string(ERASE_X, 39, textErase); #if !defined(VERSION_JP) && !defined(VERSION_SH) sSoundTextX = get_str_x_pos_from_center(254, textSoundModes[sSoundMode], 10.0f); #endif print_generic_string(SOUNDMODE_X1, 39, textSoundModes[sSoundMode]); gSPDisplayList(gDisplayListHead++, dl_ia_text_end); #endif // Print file names gSPDisplayList(gDisplayListHead++, dl_menu_ia8_text_begin); gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, sTextBaseAlpha); print_menu_generic_string(MARIOTEXT_X1, 65, textMarioA); print_menu_generic_string(MARIOTEXT_X2, 65, textMarioB); print_menu_generic_string(MARIOTEXT_X1, 105, textMarioC); print_menu_generic_string(MARIOTEXT_X2, 105, textMarioD); gSPDisplayList(gDisplayListHead++, dl_menu_ia8_text_end); } #ifdef VERSION_EU /** * Prints the first part main menu strings that shows on the yellow background menu screen. * Has the strings for the 4 buttons below the save buttons that get changed depending of the language. * Calls print_main_menu_strings to print the remaining strings. */ void print_main_lang_strings(void) { s16 centeredX; gSPDisplayList(gDisplayListHead++, dl_rgba16_text_begin); gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, sTextBaseAlpha); centeredX = get_str_x_pos_from_center_scale(160, textSelectFile[sLanguageMode], 12.0f); sCenteredX = centeredX; print_hud_lut_string(HUD_LUT_GLOBAL, centeredX, 35, textSelectFile[sLanguageMode]); gSPDisplayList(gDisplayListHead++, dl_rgba16_text_end); gSPDisplayList(gDisplayListHead++, dl_ia_text_begin); gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, sTextBaseAlpha); centeredX = get_str_x_pos_from_center(76, textScore[sLanguageMode], 10.0f); sCenteredX = centeredX; print_generic_string(centeredX, 39, textScore[sLanguageMode]); centeredX = get_str_x_pos_from_center(131, textCopy[sLanguageMode], 10.0f); sCenteredX = centeredX; print_generic_string(centeredX, 39, textCopy[sLanguageMode]); centeredX = get_str_x_pos_from_center(189, textErase[sLanguageMode], 10.0f); sCenteredX = centeredX; print_generic_string(centeredX, 39, textErase[sLanguageMode]); centeredX = get_str_x_pos_from_center(245, textOption[sLanguageMode], 10.0f); sCenteredX = centeredX; print_generic_string(centeredX, 39, textOption[sLanguageMode]); gSPDisplayList(gDisplayListHead++, dl_ia_text_end); print_main_menu_strings(); } #endif #ifdef VERSION_EU #define CHECK_FILE_X checkFileX #define NOSAVE_DATA_X1 noSaveDataX #elif VERSION_JP #define CHECK_FILE_X 90 #define NOSAVE_DATA_X1 90 #else #define CHECK_FILE_X 95 #define NOSAVE_DATA_X1 99 #endif /** * Defines IDs for the top message of the score menu and displays it if the ID is called in messageID. */ void score_menu_display_message(s8 messageID) { #ifdef VERSION_EU s16 checkFileX, noSaveDataX; #endif switch (messageID) { case SCORE_MSG_CHECK_FILE: #ifdef VERSION_EU checkFileX = get_str_x_pos_from_center_scale(160, LANGUAGE_ARRAY(textCheckFile), 12.0f); #endif print_hud_lut_string_fade(HUD_LUT_DIFF, CHECK_FILE_X, 35, LANGUAGE_ARRAY(textCheckFile)); break; case SCORE_MSG_NOSAVE_DATA: #ifdef VERSION_EU noSaveDataX = get_str_x_pos_from_center(160, LANGUAGE_ARRAY(textNoSavedDataExists), 10.0f); #endif print_generic_string_fade(NOSAVE_DATA_X1, 190, LANGUAGE_ARRAY(textNoSavedDataExists)); break; } } #if defined(VERSION_JP) || defined(VERSION_SH) #define RETURN_X 45 #define COPYFILE_X1 128 #define ERASEFILE_X1 228 #elif VERSION_EU #define RETURN_X centeredX #define COPYFILE_X1 centeredX #define ERASEFILE_X1 centeredX #else #define RETURN_X 44 #define COPYFILE_X1 135 #define ERASEFILE_X1 231 #endif #ifdef VERSION_EU #define FADEOUT_TIMER 35 #else #define FADEOUT_TIMER 20 #endif /** * Prints score menu strings that shows on the green background menu screen. */ void print_score_menu_strings(void) { #ifdef VERSION_EU s16 centeredX; #endif // Update and print the message at the top of the menu. if (sMainMenuTimer == FADEOUT_TIMER) { sFadeOutText = TRUE; } if (update_text_fade_out() == TRUE) { if (sStatusMessageID == SCORE_MSG_CHECK_FILE) { sStatusMessageID = SCORE_MSG_NOSAVE_DATA; } else { sStatusMessageID = SCORE_MSG_CHECK_FILE; } } // Print messageID called above score_menu_display_message(sStatusMessageID); #ifndef VERSION_EU // Print file star counts gSPDisplayList(gDisplayListHead++, dl_rgba16_text_begin); gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, sTextBaseAlpha); print_save_file_star_count(SAVE_FILE_A, 90, 76); print_save_file_star_count(SAVE_FILE_B, 211, 76); print_save_file_star_count(SAVE_FILE_C, 90, 119); print_save_file_star_count(SAVE_FILE_D, 211, 119); gSPDisplayList(gDisplayListHead++, dl_rgba16_text_end); #endif // Print menu names gSPDisplayList(gDisplayListHead++, dl_ia_text_begin); gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, sTextBaseAlpha); #ifdef VERSION_EU centeredX = get_str_x_pos_from_center(69, textReturn[sLanguageMode], 10.0f); #endif print_generic_string(RETURN_X, 35, LANGUAGE_ARRAY(textReturn)); #ifdef VERSION_EU centeredX = get_str_x_pos_from_center(159, textCopyFileButton[sLanguageMode], 10.0f); #endif print_generic_string(COPYFILE_X1, 35, LANGUAGE_ARRAY(textCopyFileButton)); #ifdef VERSION_EU centeredX = get_str_x_pos_from_center(249, textEraseFileButton[sLanguageMode], 10.0f); #endif print_generic_string(ERASEFILE_X1, 35, LANGUAGE_ARRAY(textEraseFileButton)); gSPDisplayList(gDisplayListHead++, dl_ia_text_end); #ifdef VERSION_EU print_main_menu_strings(); #else // Print file names gSPDisplayList(gDisplayListHead++, dl_menu_ia8_text_begin); gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, sTextBaseAlpha); print_menu_generic_string(89, 62, textMarioA); print_menu_generic_string(211, 62, textMarioB); print_menu_generic_string(89, 105, textMarioC); print_menu_generic_string(211, 105, textMarioD); gSPDisplayList(gDisplayListHead++, dl_menu_ia8_text_end); #endif } #if defined(VERSION_JP) || defined(VERSION_SH) #define NOFILE_COPY_X 90 #define COPY_FILE_X 90 #define COPYIT_WHERE_X 90 #define NOSAVE_DATA_X2 90 #define COPYCOMPLETE_X 90 #define SAVE_EXISTS_X1 90 #elif VERSION_EU #define NOFILE_COPY_X centeredX #define COPY_FILE_X centeredX #define COPYIT_WHERE_X centeredX #define NOSAVE_DATA_X2 centeredX #define COPYCOMPLETE_X centeredX #define SAVE_EXISTS_X1 centeredX #else #define NOFILE_COPY_X 119 #define COPY_FILE_X 104 #define COPYIT_WHERE_X 109 #define NOSAVE_DATA_X2 101 #define COPYCOMPLETE_X 110 #define SAVE_EXISTS_X1 110 #endif /** * Defines IDs for the top message of the copy menu and displays it if the ID is called in messageID. */ void copy_menu_display_message(s8 messageID) { #ifdef VERSION_EU s16 centeredX; #endif switch (messageID) { case COPY_MSG_MAIN_TEXT: if (sAllFilesExist == TRUE) { #ifdef VERSION_EU centeredX = get_str_x_pos_from_center(160, textNoFileToCopyFrom[sLanguageMode], 10.0f); #endif print_generic_string_fade(NOFILE_COPY_X, 190, LANGUAGE_ARRAY(textNoFileToCopyFrom)); } else { #ifdef VERSION_EU centeredX = get_str_x_pos_from_center_scale(160, textCopyFile[sLanguageMode], 12.0f); #endif print_hud_lut_string_fade(HUD_LUT_DIFF, COPY_FILE_X, 35, LANGUAGE_ARRAY(textCopyFile)); } break; case COPY_MSG_COPY_WHERE: #ifdef VERSION_EU centeredX = get_str_x_pos_from_center(160, textCopyItToWhere[sLanguageMode], 10.0f); #endif print_generic_string_fade(COPYIT_WHERE_X, 190, LANGUAGE_ARRAY(textCopyItToWhere)); break; case COPY_MSG_NOSAVE_EXISTS: #ifdef VERSION_EU centeredX = get_str_x_pos_from_center(160, textNoSavedDataExists[sLanguageMode], 10.0f); print_generic_string_fade(NOSAVE_DATA_X2, 190, textNoSavedDataExists[sLanguageMode]); #else print_generic_string_fade(NOSAVE_DATA_X2, 190, textNoSavedDataExistsCopy); #endif break; case COPY_MSG_COPY_COMPLETE: #ifdef VERSION_EU centeredX = get_str_x_pos_from_center(160, textCopyCompleted[sLanguageMode], 10.0f); #endif print_generic_string_fade(COPYCOMPLETE_X, 190, LANGUAGE_ARRAY(textCopyCompleted)); break; case COPY_MSG_SAVE_EXISTS: #ifdef VERSION_EU centeredX = get_str_x_pos_from_center(160, textSavedDataExists[sLanguageMode], 10.0f); #endif print_generic_string_fade(SAVE_EXISTS_X1, 190, LANGUAGE_ARRAY(textSavedDataExists)); break; } } /** * Updates messageIDs of the copy menu depending of the copy phase value defined. */ void copy_menu_update_message(void) { switch (sMainMenuButtons[MENU_BUTTON_COPY]->oMenuButtonActionPhase) { case COPY_PHASE_MAIN: if (sMainMenuTimer == FADEOUT_TIMER) { sFadeOutText = TRUE; } if (update_text_fade_out() == TRUE) { if (sStatusMessageID == COPY_MSG_MAIN_TEXT) { sStatusMessageID = COPY_MSG_NOSAVE_EXISTS; } else { sStatusMessageID = COPY_MSG_MAIN_TEXT; } } break; case COPY_PHASE_COPY_WHERE: if (sMainMenuTimer == FADEOUT_TIMER && sStatusMessageID == COPY_MSG_SAVE_EXISTS) { sFadeOutText = TRUE; } if (update_text_fade_out() == TRUE) { if (sStatusMessageID != COPY_MSG_COPY_WHERE) { sStatusMessageID = COPY_MSG_COPY_WHERE; } else { sStatusMessageID = COPY_MSG_SAVE_EXISTS; } } break; case COPY_PHASE_COPY_COMPLETE: if (sMainMenuTimer == FADEOUT_TIMER) { sFadeOutText = TRUE; } if (update_text_fade_out() == TRUE) { if (sStatusMessageID != COPY_MSG_COPY_COMPLETE) { sStatusMessageID = COPY_MSG_COPY_COMPLETE; } else { sStatusMessageID = COPY_MSG_MAIN_TEXT; } } break; } } #if defined(VERSION_JP) || defined(VERSION_SH) #define VIEWSCORE_X1 133 #define ERASEFILE_X2 220 #elif VERSION_EU #define VIEWSCORE_X1 centeredX #define ERASEFILE_X2 centeredX #else #define VIEWSCORE_X1 128 #define ERASEFILE_X2 230 #endif /** * Prints copy menu strings that shows on the blue background menu screen. */ void print_copy_menu_strings(void) { #ifdef VERSION_EU s16 centeredX; #endif // Update and print the message at the top of the menu. copy_menu_update_message(); // Print messageID called inside a copy_menu_update_message case copy_menu_display_message(sStatusMessageID); #ifndef VERSION_EU // Print file star counts gSPDisplayList(gDisplayListHead++, dl_rgba16_text_begin); gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, sTextBaseAlpha); print_save_file_star_count(SAVE_FILE_A, 90, 76); print_save_file_star_count(SAVE_FILE_B, 211, 76); print_save_file_star_count(SAVE_FILE_C, 90, 119); print_save_file_star_count(SAVE_FILE_D, 211, 119); gSPDisplayList(gDisplayListHead++, dl_rgba16_text_end); #endif // Print menu names gSPDisplayList(gDisplayListHead++, dl_ia_text_begin); gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, sTextBaseAlpha); #ifdef VERSION_EU centeredX = get_str_x_pos_from_center(69, textReturn[sLanguageMode], 10.0f); #endif print_generic_string(RETURN_X, 35, LANGUAGE_ARRAY(textReturn)); #ifdef VERSION_EU centeredX = get_str_x_pos_from_center(159, textViewScore[sLanguageMode], 10.0f); #endif print_generic_string(VIEWSCORE_X1, 35, LANGUAGE_ARRAY(textViewScore)); #ifdef VERSION_EU centeredX = get_str_x_pos_from_center(249, textEraseFileButton[sLanguageMode], 10.0f); #endif print_generic_string(ERASEFILE_X2, 35, LANGUAGE_ARRAY(textEraseFileButton)); gSPDisplayList(gDisplayListHead++, dl_ia_text_end); #ifdef VERSION_EU print_main_menu_strings(); #else // Print file names gSPDisplayList(gDisplayListHead++, dl_menu_ia8_text_begin); gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, sTextBaseAlpha); print_menu_generic_string(89, 62, textMarioA); print_menu_generic_string(211, 62, textMarioB); print_menu_generic_string(89, 105, textMarioC); print_menu_generic_string(211, 105, textMarioD); gSPDisplayList(gDisplayListHead++, dl_menu_ia8_text_end); #endif } #if defined(VERSION_JP) || defined(VERSION_SH) #define CURSOR_X 160.0f #define MENU_ERASE_YES_MIN_X 0x91 #define MENU_ERASE_YES_MAX_X 0xA4 #else #define CURSOR_X (x + 0x46) #define MENU_ERASE_YES_MIN_X 0x8C #define MENU_ERASE_YES_MAX_X 0xA9 #endif #define MENU_ERASE_YES_NO_MIN_Y 0xBF #define MENU_ERASE_YES_NO_MAX_Y 0xD2 #define MENU_ERASE_NO_MIN_X 0xBD #define MENU_ERASE_NO_MAX_X 0xDA /** * Prints the "YES NO" prompt and checks if one of the prompts are hovered to do it's functions. */ void print_erase_menu_prompt(s16 x, s16 y) { s16 colorFade = gGlobalTimer << 12; s16 cursorX = sCursorPos[0] + CURSOR_X; s16 cursorY = sCursorPos[1] + 120.0f; if (cursorX < MENU_ERASE_YES_MAX_X && cursorX >= MENU_ERASE_YES_MIN_X && cursorY < MENU_ERASE_YES_NO_MAX_Y && cursorY >= MENU_ERASE_YES_NO_MIN_Y) { // Fade "YES" string color but keep "NO" gray sYesNoColor[0] = sins(colorFade) * 50.0f + 205.0f; sYesNoColor[1] = 150; sEraseYesNoHoverState = MENU_ERASE_HOVER_YES; } else if (cursorX < MENU_ERASE_NO_MAX_X && cursorX >= MENU_ERASE_NO_MIN_X && cursorY < MENU_ERASE_YES_NO_MAX_Y && cursorY >= MENU_ERASE_YES_NO_MIN_Y) { // Fade "NO" string color but keep "YES" gray sYesNoColor[0] = 150; sYesNoColor[1] = sins(colorFade) * 50.0f + 205.0f; sEraseYesNoHoverState = MENU_ERASE_HOVER_NO; } else { // Don't fade both strings and keep them gray sYesNoColor[0] = 150; sYesNoColor[1] = 150; sEraseYesNoHoverState = MENU_ERASE_HOVER_NONE; } // If the cursor is clicked... if (sCursorClickingTimer == 2) { // ..and is hovering "YES", delete file if (sEraseYesNoHoverState == MENU_ERASE_HOVER_YES) { play_sound(SOUND_MARIO_WAAAOOOW, gDefaultSoundArgs); sMainMenuButtons[MENU_BUTTON_ERASE]->oMenuButtonActionPhase = ERASE_PHASE_MARIO_ERASED; sFadeOutText = TRUE; sMainMenuTimer = 0; save_file_erase(sSelectedFileIndex); sMainMenuButtons[MENU_BUTTON_ERASE_MIN + sSelectedFileIndex]->header.gfx.sharedChild = gLoadedGraphNodes[MODEL_MAIN_MENU_MARIO_NEW_BUTTON_FADE]; sMainMenuButtons[sSelectedFileIndex]->header.gfx.sharedChild = gLoadedGraphNodes[MODEL_MAIN_MENU_MARIO_NEW_BUTTON_FADE]; sEraseYesNoHoverState = MENU_ERASE_HOVER_NONE; // ..and is hovering "NO", return back to main phase } else if (sEraseYesNoHoverState == MENU_ERASE_HOVER_NO) { play_sound(SOUND_MENU_CLICK_FILE_SELECT, gDefaultSoundArgs); sMainMenuButtons[MENU_BUTTON_ERASE_MIN + sSelectedFileIndex]->oMenuButtonState = MENU_BUTTON_STATE_ZOOM_OUT; sMainMenuButtons[MENU_BUTTON_ERASE]->oMenuButtonActionPhase = ERASE_PHASE_MAIN; sFadeOutText = TRUE; sMainMenuTimer = 0; sEraseYesNoHoverState = MENU_ERASE_HOVER_NONE; } } // Print "YES NO" strings gSPDisplayList(gDisplayListHead++, dl_ia_text_begin); gDPSetEnvColor(gDisplayListHead++, sYesNoColor[0], sYesNoColor[0], sYesNoColor[0], sTextBaseAlpha); print_generic_string(x + 56, y, LANGUAGE_ARRAY(textYes)); gDPSetEnvColor(gDisplayListHead++, sYesNoColor[1], sYesNoColor[1], sYesNoColor[1], sTextBaseAlpha); print_generic_string(x + 98, y, LANGUAGE_ARRAY(textNo)); gSPDisplayList(gDisplayListHead++, dl_ia_text_end); } // MARIO_ERASED_VAR is the value there the letter "A" is, it works like this: // US and EU --- JP // M a r i o A --- マ リ オ A // 0 1 2 3 4 5 6 --- 0 1 2 3 #if defined(VERSION_JP) || defined(VERSION_SH) #define ERASE_FILE_X 96 #define NOSAVE_DATA_X3 90 #define MARIO_ERASED_VAR 3 #define MARIO_ERASED_X 90 #define SAVE_EXISTS_X2 90 #elif VERSION_EU #define ERASE_FILE_X centeredX #define NOSAVE_DATA_X3 centeredX #define MARIO_ERASED_VAR 6 #define MARIO_ERASED_X centeredX #define SAVE_EXISTS_X2 centeredX #else #define ERASE_FILE_X 98 #define NOSAVE_DATA_X3 100 #define MARIO_ERASED_VAR 6 #define MARIO_ERASED_X 100 #define SAVE_EXISTS_X2 100 #endif /** * Defines IDs for the top message of the erase menu and displays it if the ID is called in messageID. */ void erase_menu_display_message(s8 messageID) { #ifdef VERSION_EU s16 centeredX; #endif #ifndef VERSION_EU unsigned char textEraseFile[] = { TEXT_ERASE_FILE }; unsigned char textSure[] = { TEXT_SURE }; unsigned char textNoSavedDataExists[] = { TEXT_NO_SAVED_DATA_EXISTS }; unsigned char textMarioAJustErased[] = { TEXT_FILE_MARIO_A_JUST_ERASED }; unsigned char textSavedDataExists[] = { TEXT_SAVED_DATA_EXISTS }; #endif switch (messageID) { case ERASE_MSG_MAIN_TEXT: #ifdef VERSION_EU centeredX = get_str_x_pos_from_center_scale(160, textEraseFile[sLanguageMode], 12.0f); #endif print_hud_lut_string_fade(HUD_LUT_DIFF, ERASE_FILE_X, 35, LANGUAGE_ARRAY(textEraseFile)); break; case ERASE_MSG_PROMPT: print_generic_string_fade(90, 190, LANGUAGE_ARRAY(textSure)); print_erase_menu_prompt(90, 190); // YES NO, has functions for it too break; case ERASE_MSG_NOSAVE_EXISTS: #ifdef VERSION_EU centeredX = get_str_x_pos_from_center(160, textNoSavedDataExists[sLanguageMode], 10.0f); #endif print_generic_string_fade(NOSAVE_DATA_X3, 190, LANGUAGE_ARRAY(textNoSavedDataExists)); break; case ERASE_MSG_MARIO_ERASED: LANGUAGE_ARRAY(textMarioAJustErased)[MARIO_ERASED_VAR] = sSelectedFileIndex + 10; #ifdef VERSION_EU centeredX = get_str_x_pos_from_center(160, textMarioAJustErased[sLanguageMode], 10.0f); #endif print_generic_string_fade(MARIO_ERASED_X, 190, LANGUAGE_ARRAY(textMarioAJustErased)); break; case ERASE_MSG_SAVE_EXISTS: // unused #ifdef VERSION_EU centeredX = get_str_x_pos_from_center(160, textSavedDataExists[sLanguageMode], 10.0f); #endif print_generic_string_fade(SAVE_EXISTS_X2, 190, LANGUAGE_ARRAY(textSavedDataExists)); break; } } /** * Updates messageIDs of the erase menu depending of the erase phase value defined. */ void erase_menu_update_message(void) { switch (sMainMenuButtons[MENU_BUTTON_ERASE]->oMenuButtonActionPhase) { case ERASE_PHASE_MAIN: if (sMainMenuTimer == FADEOUT_TIMER && sStatusMessageID == ERASE_MSG_NOSAVE_EXISTS) { sFadeOutText = TRUE; } if (update_text_fade_out() == TRUE) { if (sStatusMessageID == ERASE_MSG_MAIN_TEXT) { sStatusMessageID = ERASE_MSG_NOSAVE_EXISTS; } else { sStatusMessageID = ERASE_MSG_MAIN_TEXT; } } break; case ERASE_PHASE_PROMPT: if (update_text_fade_out() == TRUE) { if (sStatusMessageID != ERASE_MSG_PROMPT) { sStatusMessageID = ERASE_MSG_PROMPT; } sCursorPos[0] = 43.0f; sCursorPos[1] = 80.0f; } break; case ERASE_PHASE_MARIO_ERASED: if (sMainMenuTimer == FADEOUT_TIMER) { sFadeOutText = TRUE; } if (update_text_fade_out() == TRUE) { if (sStatusMessageID != ERASE_MSG_MARIO_ERASED) { sStatusMessageID = ERASE_MSG_MARIO_ERASED; } else { sStatusMessageID = ERASE_MSG_MAIN_TEXT; } } break; } } #if defined(VERSION_JP) || defined(VERSION_SH) #define VIEWSCORE_X2 133 #define COPYFILE_X2 223 #else #define VIEWSCORE_X2 127 #define COPYFILE_X2 233 #endif /** * Prints erase menu strings that shows on the red background menu screen. */ void print_erase_menu_strings(void) { #ifdef VERSION_EU s16 centeredX; #endif // Update and print the message at the top of the menu. erase_menu_update_message(); // Print messageID called inside a erase_menu_update_message case erase_menu_display_message(sStatusMessageID); #ifndef VERSION_EU // Print file star counts gSPDisplayList(gDisplayListHead++, dl_rgba16_text_begin); gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, sTextBaseAlpha); print_save_file_star_count(SAVE_FILE_A, 90, 76); print_save_file_star_count(SAVE_FILE_B, 211, 76); print_save_file_star_count(SAVE_FILE_C, 90, 119); print_save_file_star_count(SAVE_FILE_D, 211, 119); gSPDisplayList(gDisplayListHead++, dl_rgba16_text_end); #endif // Print menu names gSPDisplayList(gDisplayListHead++, dl_ia_text_begin); gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, sTextBaseAlpha); #ifdef VERSION_EU centeredX = get_str_x_pos_from_center(69, textReturn[sLanguageMode], 10.0f); print_generic_string(centeredX, 35, textReturn[sLanguageMode]); centeredX = get_str_x_pos_from_center(159, textViewScore[sLanguageMode], 10.0f); print_generic_string(centeredX, 35, textViewScore[sLanguageMode]); centeredX = get_str_x_pos_from_center(249, textCopyFileButton[sLanguageMode], 10.0f); print_generic_string(centeredX, 35, textCopyFileButton[sLanguageMode]); #else print_generic_string(RETURN_X, 35, textReturn); print_generic_string(VIEWSCORE_X2, 35, textViewScore); print_generic_string(COPYFILE_X2, 35, textCopyFileButton); #endif gSPDisplayList(gDisplayListHead++, dl_ia_text_end); #ifdef VERSION_EU print_main_menu_strings(); #else // Print file names gSPDisplayList(gDisplayListHead++, dl_menu_ia8_text_begin); gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, sTextBaseAlpha); print_menu_generic_string(89, 62, textMarioA); print_menu_generic_string(211, 62, textMarioB); print_menu_generic_string(89, 105, textMarioC); print_menu_generic_string(211, 105, textMarioD); gSPDisplayList(gDisplayListHead++, dl_menu_ia8_text_end); #endif } #if defined(VERSION_JP) || defined(VERSION_SH) #define SOUND_HUD_X 96 #elif VERSION_US #define SOUND_HUD_X 88 #endif /** * Prints sound mode menu strings that shows on the purple background menu screen. * * In EU, this function acts like "print_option_mode_menu_strings" because of languages. */ void print_sound_mode_menu_strings(void) { s32 mode; #ifdef VERSION_US s16 textX; #elif VERSION_EU s32 textX; #endif #ifndef VERSION_EU unsigned char textSoundSelect[] = { TEXT_SOUND_SELECT }; #endif // Print "SOUND SELECT" text gSPDisplayList(gDisplayListHead++, dl_rgba16_text_begin); gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, sTextBaseAlpha); #ifdef VERSION_EU print_hud_lut_string(HUD_LUT_DIFF, 47, 32, textSoundSelect[sLanguageMode]); print_hud_lut_string(HUD_LUT_DIFF, 47, 101, textLanguageSelect[sLanguageMode]); #else print_hud_lut_string(HUD_LUT_DIFF, SOUND_HUD_X, 35, textSoundSelect); #endif gSPDisplayList(gDisplayListHead++, dl_rgba16_text_end); gSPDisplayList(gDisplayListHead++, dl_ia_text_begin); #ifdef VERSION_EU // In EU their X position get increased each string // Print sound mode names for (mode = 0, textX = 90; mode < 3; textX += 70, mode++) { if (mode == sSoundMode) { gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, sTextBaseAlpha); } else { gDPSetEnvColor(gDisplayListHead++, 0, 0, 0, sTextBaseAlpha); } print_generic_string( get_str_x_pos_from_center(textX, textSoundModes[sLanguageMode * 3 + mode], 10.0f), 141, textSoundModes[sLanguageMode * 3 + mode]); } // In EU, print language mode names for (mode = 0, textX = 90; mode < 3; textX += 70, mode++) { if (mode == sLanguageMode) { gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, sTextBaseAlpha); } else { gDPSetEnvColor(gDisplayListHead++, 0, 0, 0, sTextBaseAlpha); } print_generic_string( get_str_x_pos_from_center(textX, textLanguage[mode], 10.0f), 72, textLanguage[mode]); } #else // Print sound mode names for (mode = 0; mode < 3; mode++) { if (mode == sSoundMode) { gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, sTextBaseAlpha); } else { gDPSetEnvColor(gDisplayListHead++, 0, 0, 0, sTextBaseAlpha); } #ifdef VERSION_US // Mode names are centered correctly on US textX = get_str_x_pos_from_center(mode * 74 + 87, textSoundModes[mode], 10.0f); print_generic_string(textX, 87, textSoundModes[mode]); #elif VERSION_JP print_generic_string(mode * 74 + 67, 87, textSoundModes[mode]); #endif } #endif #ifdef VERSION_EU gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, sTextBaseAlpha); print_generic_string(182, 29, textReturn[sLanguageMode]); #endif gSPDisplayList(gDisplayListHead++, dl_ia_text_end); } unsigned char textStarX[] = { TEXT_STAR_X }; /** * Prints castle secret stars collected in a score menu save file. */ void print_score_file_castle_secret_stars(s8 fileIndex, s16 x, s16 y) { unsigned char secretStarsText[20]; // Print "[star] x" print_menu_generic_string(x, y, textStarX); // Print number of castle secret stars int_to_str(save_file_get_total_star_count(fileIndex, 15, 24), secretStarsText); #ifdef VERSION_EU print_menu_generic_string(x + 20, y, secretStarsText); #else print_menu_generic_string(x + 16, y, secretStarsText); #endif } #if defined(VERSION_JP) || defined(VERSION_SH) #define HISCORE_COIN_ICON_X 0 #define HISCORE_COIN_TEXT_X 16 #define HISCORE_COIN_NAMES_X 45 #else #define HISCORE_COIN_ICON_X 18 #define HISCORE_COIN_TEXT_X 34 #define HISCORE_COIN_NAMES_X 60 #endif /** * Prints course coins collected in a score menu save file. */ void print_score_file_course_coin_score(s8 fileIndex, s16 courseIndex, s16 x, s16 y) { unsigned char coinScoreText[20]; u8 stars = save_file_get_star_flags(fileIndex, courseIndex); unsigned char textCoinX[] = { TEXT_COIN_X }; unsigned char textStar[] = { TEXT_STAR }; #if defined(VERSION_JP) || defined(VERSION_SH) #define LENGTH 5 #else #define LENGTH 8 #endif unsigned char fileNames[][LENGTH] = { { TEXT_4DASHES }, // huh? { TEXT_SCORE_MARIO_A }, { TEXT_SCORE_MARIO_B }, { TEXT_SCORE_MARIO_C }, { TEXT_SCORE_MARIO_D }, }; #undef LENGTH // MYSCORE if (sScoreFileCoinScoreMode == 0) { // Print "[coin] x" print_menu_generic_string(x + 25, y, textCoinX); // Print coin score int_to_str(save_file_get_course_coin_score(fileIndex, courseIndex), coinScoreText); print_menu_generic_string(x + 41, y, coinScoreText); // If collected, print 100 coin star if (stars & (1 << 6)) { print_menu_generic_string(x + 70, y, textStar); } } // HISCORE else { // Print "[coin] x" print_menu_generic_string(x + HISCORE_COIN_ICON_X, y, textCoinX); // Print coin highscore int_to_str((u16) save_file_get_max_coin_score(courseIndex) & 0xFFFF, coinScoreText); print_menu_generic_string(x + HISCORE_COIN_TEXT_X, y, coinScoreText); // Print coin highscore file print_menu_generic_string(x + HISCORE_COIN_NAMES_X, y, fileNames[(save_file_get_max_coin_score(courseIndex) >> 16) & 0xFFFF]); } } /** * Prints stars collected in a score menu save file. */ void print_score_file_star_score(s8 fileIndex, s16 courseIndex, s16 x, s16 y) { s16 i = 0; unsigned char starScoreText[19]; u8 stars = save_file_get_star_flags(fileIndex, courseIndex); s8 starCount = save_file_get_course_star_count(fileIndex, courseIndex); // Don't count 100 coin star if (stars & (1 << 6)) { starCount--; } // Add 1 star character for every star collected for (i = 0; i < starCount; i++) { starScoreText[i] = DIALOG_CHAR_STAR_FILLED; } // Terminating byte starScoreText[i] = DIALOG_CHAR_TERMINATOR; print_menu_generic_string(x, y, starScoreText); } #if defined(VERSION_JP) || defined(VERSION_SH) #define MARIO_X 28 #define FILE_LETTER_X 86 #define LEVEL_NAME_X 23 #define SECRET_STARS_X 152 #define MYSCORE_X 237 #define HISCORE_X 237 #else #define MARIO_X 25 #define FILE_LETTER_X 95 #define LEVEL_NAME_X 29 #define SECRET_STARS_X 171 #define MYSCORE_X 238 #define HISCORE_X 231 #endif #ifdef VERSION_EU #include "game/segment7.h" #endif /** * Prints save file score strings that shows when a save file is chosen inside the score menu. */ void print_save_file_scores(s8 fileIndex) { #ifndef VERSION_EU unsigned char textMario[] = { TEXT_MARIO }; #endif #ifndef VERSION_US unsigned char textFileLetter[] = { TEXT_ZERO }; #endif #if defined(VERSION_JP) || defined(VERSION_SH) void **levelNameTable = segmented_to_virtual(seg2_course_name_table); #endif #ifndef VERSION_EU unsigned char textHiScore[] = { TEXT_HI_SCORE }; unsigned char textMyScore[] = { TEXT_MY_SCORE }; #ifdef VERSION_US unsigned char textFileLetter[] = { TEXT_ZERO }; void **levelNameTable = segmented_to_virtual(seg2_course_name_table); #endif #else void **levelNameTable; switch (sLanguageMode) { case LANGUAGE_ENGLISH: levelNameTable = segmented_to_virtual(eu_course_strings_en_table); break; case LANGUAGE_FRENCH: levelNameTable = segmented_to_virtual(eu_course_strings_fr_table); break; case LANGUAGE_GERMAN: levelNameTable = segmented_to_virtual(eu_course_strings_de_table); break; } #endif textFileLetter[0] = fileIndex + ASCII_TO_DIALOG('A'); // get letter of file selected // Print file name at top gSPDisplayList(gDisplayListHead++, dl_rgba16_text_begin); gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, sTextBaseAlpha); print_hud_lut_string(HUD_LUT_DIFF, MARIO_X, 15, textMario); print_hud_lut_string(HUD_LUT_GLOBAL, FILE_LETTER_X, 15, textFileLetter); // Print save file star count at top print_save_file_star_count(fileIndex, 124, 15); gSPDisplayList(gDisplayListHead++, dl_rgba16_text_end); // Print course scores gSPDisplayList(gDisplayListHead++, dl_menu_ia8_text_begin); gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, sTextBaseAlpha); //! Huge print list, for loops exist for a reason! // PADCHAR is used to difference an x position value between // JP and US when the course number is only one digit. #if defined(VERSION_JP) || defined(VERSION_SH) #define PADCHAR 0 #define PRINT_COURSE_SCORES(courseIndex, pad) \ print_menu_generic_string(23 + (pad * 3), 23 + 12 * courseIndex, segmented_to_virtual(levelNameTable[courseIndex - 1])); \ print_score_file_star_score(fileIndex, courseIndex - 1, 152, 23 + 12 * courseIndex); \ print_score_file_course_coin_score(fileIndex, courseIndex - 1, 213, 23 + 12 * courseIndex); #else #define PADCHAR 1 #define PRINT_COURSE_SCORES(courseIndex, pad) \ print_menu_generic_string(23 + (pad * 3), 23 + 12 * courseIndex, segmented_to_virtual(levelNameTable[courseIndex - 1])); \ print_score_file_star_score(fileIndex, courseIndex - 1, 171, 23 + 12 * courseIndex); \ print_score_file_course_coin_score(fileIndex, courseIndex - 1, 213, 23 + 12 * courseIndex); #endif // Course values are indexed, from Bob-omb Battlefield to Rainbow Ride PRINT_COURSE_SCORES(COURSE_BOB, PADCHAR) // BOB PRINT_COURSE_SCORES(COURSE_WF, PADCHAR) // WF PRINT_COURSE_SCORES(COURSE_JRB, PADCHAR) // JRB PRINT_COURSE_SCORES(COURSE_CCM, PADCHAR) // CCM PRINT_COURSE_SCORES(COURSE_BBH, PADCHAR) // BBH PRINT_COURSE_SCORES(COURSE_HMC, PADCHAR) // HMC PRINT_COURSE_SCORES(COURSE_LLL, PADCHAR) // LLL PRINT_COURSE_SCORES(COURSE_SSL, PADCHAR) // SSL PRINT_COURSE_SCORES(COURSE_DDD, PADCHAR) // DDD PRINT_COURSE_SCORES(COURSE_SL, 0) // SL PRINT_COURSE_SCORES(COURSE_WDW, 0) // WDW PRINT_COURSE_SCORES(COURSE_TTM, 0) // TTM PRINT_COURSE_SCORES(COURSE_THI, 0) // THI PRINT_COURSE_SCORES(COURSE_TTC, 0) // TTC PRINT_COURSE_SCORES(COURSE_RR, 0) // RR #undef PRINT_COURSE_SCORES #undef PADCHAR // Print level name print_menu_generic_string(LEVEL_NAME_X, 215, segmented_to_virtual(levelNameTable[25])); // Print castle secret stars print_score_file_castle_secret_stars(fileIndex, SECRET_STARS_X, 215); // Print current coin score mode if (sScoreFileCoinScoreMode == 0) { #ifdef VERSION_EU print_menu_generic_string(get_str_x_pos_from_center(257, textMyScore[sLanguageMode], 10.0f), 24, textMyScore[sLanguageMode]); #else print_menu_generic_string(MYSCORE_X, 24, textMyScore); #endif } else { #ifdef VERSION_EU print_menu_generic_string(get_str_x_pos_from_center(257, textHiScore[sLanguageMode], 10.0f), 24,textHiScore[sLanguageMode]); #else print_menu_generic_string(HISCORE_X, 24, textHiScore); #endif } gSPDisplayList(gDisplayListHead++, dl_menu_ia8_text_end); } /** * Prints file select strings depending on the menu selected. * Also checks if all saves exists and defines text and main menu timers. */ static void print_file_select_strings(void) { UNUSED s32 unused1; UNUSED s32 unused2; create_dl_ortho_matrix(); switch (sSelectedButtonID) { case MENU_BUTTON_NONE: #ifdef VERSION_EU // Ultimately calls print_main_menu_strings, but prints main language strings first. print_main_lang_strings(); #else print_main_menu_strings(); #endif break; case MENU_BUTTON_SCORE: print_score_menu_strings(); sScoreFileCoinScoreMode = 0; break; case MENU_BUTTON_COPY: print_copy_menu_strings(); break; case MENU_BUTTON_ERASE: print_erase_menu_strings(); break; case MENU_BUTTON_SCORE_FILE_A: print_save_file_scores(SAVE_FILE_A); break; case MENU_BUTTON_SCORE_FILE_B: print_save_file_scores(SAVE_FILE_B); break; case MENU_BUTTON_SCORE_FILE_C: print_save_file_scores(SAVE_FILE_C); break; case MENU_BUTTON_SCORE_FILE_D: print_save_file_scores(SAVE_FILE_D); break; case MENU_BUTTON_SOUND_MODE: print_sound_mode_menu_strings(); break; } // If all 4 save file exists, define true to sAllFilesExist to prevent more copies in copy menu if (save_file_exists(SAVE_FILE_A) == TRUE && save_file_exists(SAVE_FILE_B) == TRUE && save_file_exists(SAVE_FILE_C) == TRUE && save_file_exists(SAVE_FILE_D) == TRUE) { sAllFilesExist = TRUE; } else { sAllFilesExist = FALSE; } // Timers for menu alpha text and the main menu itself if (sTextBaseAlpha < 250) { sTextBaseAlpha += 10; } if (sMainMenuTimer < 1000) { sMainMenuTimer += 1; } } /** * Geo function that prints file select strings and the cursor. */ Gfx *geo_file_select_strings_and_menu_cursor(s32 callContext, UNUSED struct GraphNode *node, UNUSED f32 mtx[4][4]) { if (callContext == GEO_CONTEXT_RENDER) { print_file_select_strings(); print_menu_cursor(); } return NULL; } /** * Initiates file select values after Mario Screen. * Relocates cursor position of the last save if the game goes back to the Mario Screen * either completing a course choosing "SAVE & QUIT" or having a game over. */ s32 lvl_init_menu_values_and_cursor_pos(UNUSED s32 arg, UNUSED s32 unused) { #ifdef VERSION_EU s8 fileNum; #endif sSelectedButtonID = MENU_BUTTON_NONE; sCurrentMenuLevel = MENU_LAYER_MAIN; sTextBaseAlpha = 0; // Place the cursor over the save file that was being played. // gCurrSaveFileNum is 1 by default when the game boots, as such // the cursor will point on Mario A save file. switch (gCurrSaveFileNum) { case 1: // File A sCursorPos[0] = -94.0f; sCursorPos[1] = 46.0f; break; case 2: // File B sCursorPos[0] = 24.0f; sCursorPos[1] = 46.0f; break; case 3: // File C sCursorPos[0] = -94.0f; sCursorPos[1] = 5.0f; break; case 4: // File D sCursorPos[0] = 24.0f; sCursorPos[1] = 5.0f; break; } sClickPos[0] = -10000; sClickPos[1] = -10000; sCursorClickingTimer = 0; sSelectedFileNum = 0; sSelectedFileIndex = MENU_BUTTON_NONE; sFadeOutText = FALSE; sStatusMessageID = 0; sTextFadeAlpha = 0; sMainMenuTimer = 0; sEraseYesNoHoverState = MENU_ERASE_HOVER_NONE; sSoundMode = save_file_get_sound_mode(); #ifdef VERSION_EU sLanguageMode = eu_get_language(); for (fileNum = 0; fileNum < 4; fileNum++) { if (save_file_exists(fileNum) == TRUE) { sOpenLangSettings = FALSE; break; } else { sOpenLangSettings = TRUE; } } #endif //! no return value #ifdef AVOID_UB return 0; #endif } /** * Updates file select menu button objects so they can be interacted. * When a save file is selected, it returns fileNum value * defined in load_main_menu_save_file. */ s32 lvl_update_obj_and_load_file_selected(UNUSED s32 arg, UNUSED s32 unused) { area_update_objects(); return sSelectedFileNum; }