diff --git a/include/common.hpp b/include/common.hpp new file mode 100644 index 0000000..b1956a0 --- /dev/null +++ b/include/common.hpp @@ -0,0 +1,9 @@ +#pragma once + +#include + +typedef void (*GZAction)(u32 params); +typedef bool (*GZCheckCallback)(int itemIndex); + +// from oot-gc +extern "C" char* strcat(char* dst, const char* src); diff --git a/include/gz.hpp b/include/gz.hpp index df1394d..91e6995 100644 --- a/include/gz.hpp +++ b/include/gz.hpp @@ -55,6 +55,8 @@ class GZ { bool IsOnLand() { return gOverlayManager.mLoadedOverlays[OverlaySlot_6] == OverlayIndex_Land; } + bool IsSceneInit() { return gOverlayManager.mLoadedOverlays[OverlaySlot_1] == OverlayIndex_SceneInit; } + // global init void Init(); diff --git a/include/gz_commands.hpp b/include/gz_commands.hpp index f85fbe2..d246ac3 100644 --- a/include/gz_commands.hpp +++ b/include/gz_commands.hpp @@ -1,25 +1,27 @@ #pragma once +#include "common.hpp" #include "gz_controls.hpp" #include "gz_menu.hpp" #include typedef void (*GZCmdInit)(void); -typedef void (*GZCmdAction)(void); struct GZCmdItem { ButtonCombo btnCombo; - GZCmdAction actionCallback; + GZAction actionCallback; }; class GZCommandManager { public: Input* mpButtons; GZCmdItem* mpCommands; + GZMenu mMenu; GZCommandManager(); + void InitMenu(); void Update(); void Draw(Vec2b* pPos); }; diff --git a/include/gz_menu.hpp b/include/gz_menu.hpp index 0baf1ae..8c68c03 100644 --- a/include/gz_menu.hpp +++ b/include/gz_menu.hpp @@ -1,5 +1,6 @@ #pragma once +#include "common.hpp" #include "gz_controls.hpp" #include @@ -8,10 +9,12 @@ #include #include -typedef void (*GZMenuAction)(u32 params); +#define DRAW_TO_TOP_SCREEN 1 + struct GZMenu; -typedef enum InventoryAmountType { +typedef u32 InventoryAmountType; +enum InventoryAmountType_ { InventoryAmountType_Bow, InventoryAmountType_Bombs, InventoryAmountType_QuiverCapacity, @@ -21,21 +24,36 @@ typedef enum InventoryAmountType { InventoryAmountType_SmallKeys, InventoryAmountType_LightTears, InventoryAmountType_Max -} InventoryAmountType; +}; + +typedef u32 GZMenuItemType; +enum GZMenuItemType_ { + GZMenuItemType_Default, + GZMenuItemType_Bool, + GZMenuItemType_Increment, +}; struct GZMenuItem { - const char* mName; // menu item name - GZMenuAction mActionCallback; // associated action - u32 params; // parameters for the action callback - GZMenu* mSubMenu; // tied submenu - bool needSaveFile; // does it require the save data - s32 value; // misc value for internal use + const char* name; + GZMenuItemType eType; + GZCheckCallback checkCallback; // must be set when using `GZMenuItemType_Bool` + GZAction action; + u32 params; + GZMenu* submenu; + + // internal + int value; }; struct GZMenu { - GZMenuItem* mpItems; + const char* title; + GZMenu* parent; + GZMenuItem* entries; s32 mCount; - GZMenu* mPrev; + bool needSaveFile; + + // internal + s16 itemIndex; }; struct GZMenuState { @@ -90,16 +108,20 @@ class GZMenuManager { this->mState.isOpened = false; } - GZMenuItem* GetActiveMenuItem() { return &this->mpActiveMenu->mpItems[this->mState.itemIndex]; } + GZMenuItem* GetActiveMenuItem() { + return this->mState.itemIndex == 0 ? NULL : &this->mpActiveMenu->entries[this->mState.itemIndex - 1]; + } + bool IsMainMenuActive(); bool IsInventoryMenuActive(); bool IsAmountsMenuActive(); bool IsCommandsMenuActive(); bool IsSettingsMenuActive(); bool IsAboutMenuActive(); - void SetAmountString(s16 index, Vec2b* pPos, bool selected); - void ValidateNewIncrement(); + GZMenu* GetMainMenu(); + void SetAmountString(InventoryAmountType eType, Vec2b* pPos, bool selected); + void ValidateAmountIncrement(); void AssignPrevMenu(); void Update(); // update routine void SetupScreen(); // creates the strings etc diff --git a/include/gz_settings.hpp b/include/gz_settings.hpp index 0d733cb..6ed7244 100644 --- a/include/gz_settings.hpp +++ b/include/gz_settings.hpp @@ -16,26 +16,27 @@ extern "C" void func_02030d58(u16 lockID); // CARD_UnlockBackup #define MAX_POS_SLOTS 8 #define MAX_SAVE_PROFILES 8 -//! TODO: make it one setting set per save file - extern "C" { +// IMPORTANT: do not reorder, retype or resize members!!! otherwise it will break older versions + typedef struct GZProfileHeader { u8 curProfileIndex; -} GZProfileHeader __attribute__((aligned(32))); +} GZProfileHeader; // the save file is large so we don't care about packing stuff to save space typedef struct GZProfile { - u8 profileIndex; bool mFasterTitleScreen; // goes into the "touch or start to exit" state immediately bool mSkipTitleScreen; // same as above except it jump straight into the file select without requiring any input - s8 mPositionIndex; + s16 mPositionIndex; Vec3p mLandPosSlots[MAX_POS_SLOTS]; Vec3p mTrainPosSlots[MAX_POS_SLOTS]; } GZProfile; -#define GZ_SAVE_OFFSET 0xF5000 -#define GZ_PROFILE_HEADER_OFFSET (GZ_SAVE_OFFSET) -#define GZ_PROFILES_OFFSET (GZ_SAVE_OFFSET + sizeof(GZProfileHeader)) +// profiles first because they might take a lot of space +#define GZ_PROFILES_OFFSET 0xF5000 + +// profile header at the end because the space it will take shouldn't be that large +#define GZ_PROFILE_HEADER_OFFSET 0xFFF00 } class GZSettings { diff --git a/resources/decomp b/resources/decomp index 269e5c5..c2b66a9 160000 --- a/resources/decomp +++ b/resources/decomp @@ -1 +1 @@ -Subproject commit 269e5c5c56bbbb6c70a03b08a57c091aae03c6b0 +Subproject commit c2b66a9996fa3e030fd17f14478326baca0eb311 diff --git a/src/common.cpp b/src/common.cpp new file mode 100644 index 0000000..737b289 --- /dev/null +++ b/src/common.cpp @@ -0,0 +1,22 @@ +#include "common.hpp" + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wparentheses" + +// from oot-gc +extern "C" char* strcat(char* dst, const char* src) { + const u8* p = (u8*)src - 1; + u8* q = (u8*)dst - 1; + + while (*++q) + ; + + q--; + + while (*++q = *++p) + ; + + return (dst); +} + +#pragma GCC diagnostic pop diff --git a/src/gz_commands.cpp b/src/gz_commands.cpp index 2187b85..ee65514 100644 --- a/src/gz_commands.cpp +++ b/src/gz_commands.cpp @@ -12,17 +12,17 @@ extern "C" void DisplayDebugText(int, void*, int, int, const char*); extern "C" void DisplayDebugTextF(int, void*, int, int, const char*, ...); -static void ExecuteLevitate(); -static void ExecutePause(); -static void ExecuteFrameAdvance(); -static void ExecutePrevPosition(); -static void ExecuteNextPosition(); -static void ExecuteSavePosition(); -static void ExecuteLoadPosition(); -static void ExecuteVoidOut(); -static void ExecuteTurbo(); - -// commands with default button combos +static void ExecuteLevitate(u32 params); +static void ExecutePause(u32 params); +static void ExecuteFrameAdvance(u32 params); +static void ExecutePrevPosition(u32 params); +static void ExecuteNextPosition(u32 params); +static void ExecuteSavePosition(u32 params); +static void ExecuteLoadPosition(u32 params); +static void ExecuteVoidOut(u32 params); +static void ExecuteTurbo(u32 params); + +// commands with default button combos, assigning the held btn to none means it's not required (and vice versa) static GZCmdItem sCommands[] = { {ButtonCombo("Levitate", BTN_X, BTN_NONE), ExecuteLevitate}, {ButtonCombo("Pause/Unpause", BTN_NONE, BTN_DDOWN), ExecutePause}, @@ -35,9 +35,9 @@ static GZCmdItem sCommands[] = { {ButtonCombo("Turbo", BTN_R, BTN_B), ExecuteTurbo}, }; -static void ExecuteLevitate() { data_027e0478.mPlayer.mVel.y = FLOAT_TO_Q20(0.334375f); } +static void ExecuteLevitate(u32 params) { data_027e0478.mPlayer.mVel.y = FLOAT_TO_Q20(0.334375f); } -static void ExecutePause() { +static void ExecutePause(u32 params) { if (!gGZ.mState.isPaused) { gGZ.mState.isPaused = true; } else { @@ -45,9 +45,9 @@ static void ExecutePause() { } } -static void ExecuteFrameAdvance() { gGZ.mState.requestedFrames++; } +static void ExecuteFrameAdvance(u32 params) { gGZ.mState.requestedFrames++; } -static void ExecutePrevPosition() { +static void ExecutePrevPosition(u32 params) { GZProfile* pProfile = gSettings.GetProfile(); pProfile->mPositionIndex--; @@ -57,7 +57,7 @@ static void ExecutePrevPosition() { } } -static void ExecuteNextPosition() { +static void ExecuteNextPosition(u32 params) { GZProfile* pProfile = gSettings.GetProfile(); pProfile->mPositionIndex++; @@ -67,31 +67,50 @@ static void ExecuteNextPosition() { } } -static void ExecuteSavePosition() { +static void ExecuteSavePosition(u32 params) { GZProfile* pProfile = gSettings.GetProfile(); Vec3p* pPosArray = gSettings.GetPosArray(); pPosArray[pProfile->mPositionIndex] = data_027e0478.mPlayer.mPos; } -static void ExecuteLoadPosition() { +static void ExecuteLoadPosition(u32 params) { GZProfile* pProfile = gSettings.GetProfile(); Vec3p* pPosArray = gSettings.GetPosArray(); data_027e0478.mPlayer.mPos = pPosArray[pProfile->mPositionIndex]; } -static void ExecuteVoidOut() { +static void ExecuteVoidOut(u32 params) { if (gGZ.IsOnLand()) { data_027e0478.mPlayer.mPos.y = FLOAT_TO_Q20(-4000.0f); } } -static void ExecuteTurbo() {} +static void ExecuteTurbo(u32 params) {} GZCommandManager gCommandManager; GZCommandManager::GZCommandManager() { this->mpButtons = &gGZ.mButtons; this->mpCommands = sCommands; + this->InitMenu(); +} + +void GZCommandManager::InitMenu() { + this->mMenu.title = "Commands"; + this->mMenu.parent = gMenuManager.GetMainMenu(); + this->mMenu.mCount = ARRAY_LEN(sCommands); + this->mMenu.entries = new GZMenuItem[this->mMenu.mCount]; + this->mMenu.needSaveFile = false; + this->mMenu.itemIndex = 0; + + for (int i = 0; i < this->mMenu.mCount; i++) { + this->mMenu.entries[i].name = sCommands[i].btnCombo.name; + this->mMenu.entries[i].eType = GZMenuItemType_Default; + this->mMenu.entries[i].action = sCommands[i].actionCallback; + this->mMenu.entries[i].params = 0; + this->mMenu.entries[i].submenu = NULL; + this->mMenu.entries[i].value = 0; + } } void GZCommandManager::Update() { @@ -104,7 +123,7 @@ void GZCommandManager::Update() { if (pCmd->btnCombo.Executed(this->mpButtons)) { if (pCmd->actionCallback != NULL) { - pCmd->actionCallback(); + pCmd->actionCallback(0); } } } @@ -118,7 +137,7 @@ void GZCommandManager::Draw(Vec2b* pPos) { bool selected = i + 1 == gMenuManager.mState.itemIndex; pCmd->btnCombo.SetComboString(); - DisplayDebugText(0, &elemPos, 0, selected, pCmd->btnCombo.fullName); + DisplayDebugText(DRAW_TO_TOP_SCREEN, &elemPos, 0, selected, pCmd->btnCombo.fullName); elemPos.y++; } } diff --git a/src/gz_controls.cpp b/src/gz_controls.cpp index 4d8df6a..27d48d4 100644 --- a/src/gz_controls.cpp +++ b/src/gz_controls.cpp @@ -1,24 +1,9 @@ #include "gz_controls.hpp" +#include "common.hpp" #include #include -// from oot-gc -char* strcat(char* dst, const char* src) { - const u8* p = (u8*)src - 1; - u8* q = (u8*)dst - 1; - - while (*++q) - ; - - q--; - - while (*++q = *++p) - ; - - return (dst); -} - ButtonCombo::ButtonCombo() { this->name = NULL; this->Assign(BTN_NONE, BTN_NONE); diff --git a/src/gz_game.cpp b/src/gz_game.cpp index 922ede7..a9472bb 100644 --- a/src/gz_game.cpp +++ b/src/gz_game.cpp @@ -62,14 +62,7 @@ void CustomGame::Run() { do { gGZ.Update(); - - { - gMenuManager.Update(); - - if (gMenuManager.IsActive()) { - gMenuManager.Draw(); - } - } + gMenuManager.Update(); // stgz: pause and frame advance block { diff --git a/src/gz_menu.cpp b/src/gz_menu.cpp index e0fa826..4d57472 100644 --- a/src/gz_menu.cpp +++ b/src/gz_menu.cpp @@ -4,7 +4,10 @@ #include "gz_commands.hpp" #include "gz_settings.hpp" +#include +#include #include +#include #include #include #include @@ -49,150 +52,161 @@ */ struct Screen { - u8 unk_00[0x0C]; - u8 data[0x600]; + /* 00 */ u16 width; + /* 02 */ u16 height; + /* 04 */ u16 mUnk_04; + /* 06 */ u16 mUnk_06; // thing passed to func_0200a4a8 + /* 08 */ u32 mUnk_08; + /* 0C */ u8 data[0x600]; }; extern Screen data_0204d9d0[2]; extern "C" void DisplayDebugText(int, void*, int, int, const char*); extern "C" void DisplayDebugTextF(int, void*, int, int, const char*, ...); -extern "C" void DC_FlushAll(); -extern "C" void func_020131ec(); -extern "C" void func_02023770(int); -extern "C" void GX_SetGraphicsMode(int, int, int); extern "C" void GXS_SetGraphicsMode(int); extern "C" void func_0201b180(bool, bool); -extern "C" unk32 func_020147a8(); -extern "C" void func_0201b278(bool, bool); -extern "C" void SetBrightColor(void*, int); - -static void Quit(u32 params); -static void Back(u32 params); -static void UpdateInventory(u32 params); -static void UpdateAmounts(u32 params); - -// settings menu -static void PrevProfile(u32 params); -static void NextProfile(u32 params); -static void LoadDefaultProfile(u32 params); -static void SaveSettings(u32 params); +extern "C" void func_02027654(void*, int); // DC_FlushRange +extern "C" void func_020252ec(void*, int, int); // GX0_LoadBG0Scr extern GZMenu sMainMenu; extern GZMenu sInventoryMenu; extern GZMenu sAmountsMenu; extern GZMenu sCollectionMenu; extern GZMenu sSettingsMenu; -extern GZMenu sCommandsMenu; +extern GZMenu sDebugMenu; +extern GZMenu sRegsMenu; extern GZMenu sAboutMenu; +// clang-format off + +// -- main menu items -- + +static GZMenuItem sMainMenuItems[] = { + {"Inventory", GZMenuItemType_Default, NULL, NULL, 0, &sInventoryMenu, 0}, + {"Collection", GZMenuItemType_Default, NULL, NULL, 0, &sCollectionMenu, 0}, + {"Commands", GZMenuItemType_Default, NULL, NULL, 0, &gCommandManager.mMenu, 0}, + {"Settings", GZMenuItemType_Default, NULL, NULL, 0, &sSettingsMenu, 0}, + {"Debug", GZMenuItemType_Default, NULL, NULL, 0, &sDebugMenu, 0}, + {"About", GZMenuItemType_Default, NULL, NULL, 0, &sAboutMenu, 0}, +}; + +// -- inventory menu items -- + +static void UpdateInventory(u32 params); +static bool HasObtainedItem(int itemIndex); + static GZMenuItem sInventoryMenuItems[] = { - {"Back", Back, 0, NULL, false, 0}, - {"Whirlwind", UpdateInventory, ItemFlag_Whirlwind, NULL, true, 0}, - {"Boomerang", UpdateInventory, ItemFlag_Boomerang, NULL, true, 0}, - {"Whip", UpdateInventory, ItemFlag_Whip, NULL, true, 0}, - {"Bow", UpdateInventory, ItemFlag_Bow, NULL, true, 0}, - {"Bombs", UpdateInventory, ItemFlag_Bombs, NULL, true, 0}, - {"SandRod", UpdateInventory, ItemFlag_SandRod, NULL, true, 0}, - {"Amounts", NULL, 0, &sAmountsMenu, true, 0}, + {"Amounts", GZMenuItemType_Default, NULL, NULL, 0, &sAmountsMenu, 0}, + {"Whirlwind", GZMenuItemType_Bool, HasObtainedItem, UpdateInventory, ItemFlag_Whirlwind, NULL, 0}, + {"Boomerang", GZMenuItemType_Bool, HasObtainedItem, UpdateInventory, ItemFlag_Boomerang, NULL, 0}, + {"Whip", GZMenuItemType_Bool, HasObtainedItem, UpdateInventory, ItemFlag_Whip, NULL, 0}, + {"Bow", GZMenuItemType_Bool, HasObtainedItem, UpdateInventory, ItemFlag_Bow, NULL, 0}, + {"Bombs", GZMenuItemType_Bool, HasObtainedItem, UpdateInventory, ItemFlag_Bombs, NULL, 0}, + {"SandRod", GZMenuItemType_Bool, HasObtainedItem, UpdateInventory, ItemFlag_SandRod, NULL, 0}, }; +static void UpdateAmounts(u32 params); + static GZMenuItem sAmountsMenuItems[] = { - {"Back", Back, 0, NULL, false, 0}, - {"Bow", UpdateAmounts, InventoryAmountType_Bow, NULL, true, 0}, - {"Bombs", UpdateAmounts, InventoryAmountType_Bombs, NULL, true, 0}, - {"Quiver Capacity", UpdateAmounts, InventoryAmountType_QuiverCapacity, NULL, true, 0}, - {"Bomb Bag Capacity", UpdateAmounts, InventoryAmountType_BombCapacity, NULL, true, 0}, - {"Potion 1", UpdateAmounts, InventoryAmountType_Potion1, NULL, true, 0}, - {"Potion 2", UpdateAmounts, InventoryAmountType_Potion2, NULL, true, 0}, - {"Small Keys", UpdateAmounts, InventoryAmountType_SmallKeys, NULL, true, 0}, - {"Light Tears", UpdateAmounts, InventoryAmountType_LightTears, NULL, true, 0}, + {"Bow", GZMenuItemType_Increment, NULL, UpdateAmounts, InventoryAmountType_Bow, NULL, 0}, + {"Bombs", GZMenuItemType_Increment, NULL, UpdateAmounts, InventoryAmountType_Bombs, NULL, 0}, + {"Quiver Capacity", GZMenuItemType_Increment, NULL, UpdateAmounts, InventoryAmountType_QuiverCapacity, NULL, 0}, + {"Bomb Bag Capacity", GZMenuItemType_Increment, NULL, UpdateAmounts, InventoryAmountType_BombCapacity, NULL, 0}, + {"Potion 1", GZMenuItemType_Increment, NULL, UpdateAmounts, InventoryAmountType_Potion1, NULL, 0}, + {"Potion 2", GZMenuItemType_Increment, NULL, UpdateAmounts, InventoryAmountType_Potion2, NULL, 0}, + {"Small Keys", GZMenuItemType_Increment, NULL, UpdateAmounts, InventoryAmountType_SmallKeys, NULL, 0}, + {"Light Tears", GZMenuItemType_Increment, NULL, UpdateAmounts, InventoryAmountType_LightTears, NULL, 0}, }; +// -- collection menu items -- + static GZMenuItem sCollectionMenuItems[] = { - {"Back", Back, 0, NULL, false, 0}, - {"Shield", UpdateInventory, ItemFlag_Shield, NULL, true, 0}, - {"Sword", UpdateInventory, ItemFlag_Sword, NULL, true, 0}, - {"LokomoSword", UpdateInventory, ItemFlag_LokomoSword, NULL, true, 0}, - {"RecruitUniform", UpdateInventory, ItemFlag_RecruitUniform, NULL, true, 0}, - {"ScrollBeam", UpdateInventory, ItemFlag_ScrollBeam, NULL, true, 0}, - {"ScrollSpinAttack", UpdateInventory, ItemFlag_ScrollSpinAttack, NULL, true, 0}, - {"AncientShield", UpdateInventory, ItemFlag_AncientShield, NULL, true, 0}, - {"PanFlute", UpdateInventory, ItemFlag_PanFlute, NULL, true, 0}, + {"Shield", GZMenuItemType_Bool, HasObtainedItem, UpdateInventory, ItemFlag_Shield, NULL, 0}, + {"Sword", GZMenuItemType_Bool, HasObtainedItem, UpdateInventory, ItemFlag_Sword, NULL, 0}, + {"Lokomo Sword", GZMenuItemType_Bool, HasObtainedItem, UpdateInventory, ItemFlag_LokomoSword, NULL, 0}, + {"Recruit Uniform", GZMenuItemType_Bool, HasObtainedItem, UpdateInventory, ItemFlag_RecruitUniform, NULL, 0}, + {"Scroll Beam", GZMenuItemType_Bool, HasObtainedItem, UpdateInventory, ItemFlag_ScrollBeam, NULL, 0}, + {"Scroll Spin Attack", GZMenuItemType_Bool, HasObtainedItem, UpdateInventory, ItemFlag_ScrollSpinAttack, NULL, 0}, + {"Ancient Shield", GZMenuItemType_Bool, HasObtainedItem, UpdateInventory, ItemFlag_AncientShield, NULL, 0}, + {"Pan Flute", GZMenuItemType_Bool, HasObtainedItem, UpdateInventory, ItemFlag_PanFlute, NULL, 0}, }; +// -- settings menu items -- + +static void PrevProfile(u32 params); +static void NextProfile(u32 params); +static void LoadDefaultProfile(u32 params); +static void SaveSettings(u32 params); + static GZMenuItem sSettingsMenuItems[] = { - {"Back", Back, 0, NULL, false, 0}, - {"Prev Profile", PrevProfile, 0, NULL, false, 0}, - {"Next Profile", NextProfile, 0, NULL, false, 0}, - {"Load Default Profile", LoadDefaultProfile, 0, NULL, false, 0}, - {"Save Settings", SaveSettings, 0, NULL, false, 0}, + {"Prev Profile", GZMenuItemType_Default, NULL, PrevProfile, 0, NULL, 0}, + {"Next Profile", GZMenuItemType_Default, NULL, NextProfile, 0, NULL, 0}, + {"Load Default Profile", GZMenuItemType_Default, NULL, LoadDefaultProfile, 0, NULL, 0}, + {"Save Settings", GZMenuItemType_Default, NULL, SaveSettings, 0, NULL, 0}, }; -static GZMenuItem sCommandsMenuItems[] = { - {"Back", Back, 0, NULL, false, 0}, -}; +// -- debug menu items -- -static GZMenuItem sAboutMenuItems[] = { - {"Back", Back, 0, NULL, false, 0}, +static GZMenuItem sDebugMenuItems[] = { + {"Regs", GZMenuItemType_Default, NULL, NULL, 0, &sRegsMenu, 0}, }; -static GZMenuItem sMainMenuItems[] = { - {"Quit", Quit, 0, NULL, false, 0}, - {"Inventory", NULL, 0, &sInventoryMenu, true, 0}, - {"Collection", NULL, 0, &sCollectionMenu, true, 0}, - {"Settings", NULL, 0, &sSettingsMenu, false, 0}, - {"Commands", NULL, 0, &sCommandsMenu, false, 0}, - {"About", NULL, 0, &sAboutMenu, false, 0}, +static void UpdateRegs(u32 params); +static bool IsLayerEnabled(int itemIndex); + +static GZMenuItem sRegsMenuItems[] = { + {"Init. State", GZMenuItemType_Default, NULL, UpdateRegs, 0xFF, NULL, 0}, + {"Toggle BG1", GZMenuItemType_Bool, IsLayerEnabled, UpdateRegs, 9, NULL, 0}, + {"Toggle BG2", GZMenuItemType_Bool, IsLayerEnabled, UpdateRegs, 10, NULL, 0}, + {"Toggle BG3", GZMenuItemType_Bool, IsLayerEnabled, UpdateRegs, 11, NULL, 0}, + {"Toggle OBJ", GZMenuItemType_Bool, IsLayerEnabled, UpdateRegs, 12, NULL, 0}, }; -// pointer to the item list, number of items, pointer to the previous menu -GZMenu sMainMenu = {sMainMenuItems, ARRAY_LEN(sMainMenuItems), NULL}; -GZMenu sInventoryMenu = {sInventoryMenuItems, ARRAY_LEN(sInventoryMenuItems), &sMainMenu}; -GZMenu sAmountsMenu = {sAmountsMenuItems, ARRAY_LEN(sAmountsMenuItems), &sInventoryMenu}; -GZMenu sCollectionMenu = {sCollectionMenuItems, ARRAY_LEN(sCollectionMenuItems), &sMainMenu}; -GZMenu sSettingsMenu = {sSettingsMenuItems, ARRAY_LEN(sSettingsMenuItems), &sMainMenu}; -GZMenu sCommandsMenu = {sCommandsMenuItems, ARRAY_LEN(sCommandsMenuItems), &sMainMenu}; -GZMenu sAboutMenu = {sAboutMenuItems, ARRAY_LEN(sAboutMenuItems), &sMainMenu}; +// -- menu list -- -static void Quit(u32 params) { gMenuManager.Quit(); } +// pointer to parent menu, pointer to items, number of items, does it require adventure mode, internal value +GZMenu sMainMenu = {"Main Menu", NULL, sMainMenuItems, ARRAY_LEN(sMainMenuItems), false, 0}; +GZMenu sInventoryMenu = {"Inventory", &sMainMenu, sInventoryMenuItems, ARRAY_LEN(sInventoryMenuItems), true, 0}; +GZMenu sAmountsMenu = {"Inventory - Amounts", &sInventoryMenu, sAmountsMenuItems, ARRAY_LEN(sAmountsMenuItems), true, 0}; +GZMenu sCollectionMenu = {"Collection", &sMainMenu, sCollectionMenuItems, ARRAY_LEN(sCollectionMenuItems), true, 0}; +GZMenu sSettingsMenu = {"Settings", &sMainMenu, sSettingsMenuItems, ARRAY_LEN(sSettingsMenuItems), false, 0}; +GZMenu sAboutMenu = {"About", &sMainMenu, NULL, 0, false, 0}; +GZMenu sDebugMenu = {"Debug", &sMainMenu, sDebugMenuItems, ARRAY_LEN(sDebugMenuItems), false, 0}; +GZMenu sRegsMenu = {"Debug - Regs", &sDebugMenu, sRegsMenuItems, ARRAY_LEN(sRegsMenuItems), false, 0}; -static void Back(u32 params) { gMenuManager.AssignPrevMenu(); } +// clang-format on static void UpdateInventory(u32 params) { - GZMenuItem* pActiveMenuItem = gMenuManager.GetActiveMenuItem(); ItemFlag eFlag = params & 0xFF; if (data_027e0ce0 == NULL || data_027e0ce0->mUnk_28 == NULL) { return; } - switch (eFlag) { - case ItemFlag_Whirlwind: - case ItemFlag_Boomerang: - case ItemFlag_Whip: - case ItemFlag_Bow: - case ItemFlag_Bombs: - case ItemFlag_SandRod: - if (!GET_FLAG(data_027e0ce0->mUnk_28->mUnk_08, eFlag)) { - data_027e0ce0->mUnk_28->func_ov000_020a863c(eFlag); - } else { - data_027e0ce0->mUnk_28->func_ov000_020a865c(eFlag); - } - break; - default: - break; + if (!GET_FLAG(data_027e0ce0->mUnk_28->mUnk_08, eFlag)) { + data_027e0ce0->mUnk_28->func_ov000_020a863c(eFlag); + } else { + data_027e0ce0->mUnk_28->func_ov000_020a865c(eFlag); } } +static bool HasObtainedItem(int itemIndex) { + if (data_027e0ce0 == NULL || data_027e0ce0->mUnk_28 == NULL) { + return false; + } + + return GET_FLAG(data_027e0ce0->mUnk_28->mUnk_08, gMenuManager.mpActiveMenu->entries[itemIndex].params & 0xFF); +} + static void UpdateAmounts(u32 params) { GZMenuItem* pActiveMenuItem = gMenuManager.GetActiveMenuItem(); - InventoryAmountType eType = (InventoryAmountType)(params & 0xFF); + InventoryAmountType eType = params & 0xFF; - if (data_027e0ce0 == NULL || data_027e0ce0->mUnk_28 == NULL) { + if (pActiveMenuItem == NULL || data_027e0ce0 == NULL || data_027e0ce0->mUnk_28 == NULL) { return; } - gMenuManager.ValidateNewIncrement(); + gMenuManager.ValidateAmountIncrement(); switch (eType) { case InventoryAmountType_Bow: @@ -230,8 +244,6 @@ static void PrevProfile(u32 params) { } else { gSettings.mProfileHeader.curProfileIndex = 0; } - - gMenuManager.mState.requestRedraw = true; } static void NextProfile(u32 params) { @@ -240,25 +252,51 @@ static void NextProfile(u32 params) { if (gSettings.mProfileHeader.curProfileIndex >= ARRAY_LEN(gSettings.mProfiles)) { gSettings.mProfileHeader.curProfileIndex = ARRAY_LEN(gSettings.mProfiles) - 1; } - - gMenuManager.mState.requestRedraw = true; } static void LoadDefaultProfile(u32 params) { gSettings.LoadDefaultProfile(); gMenuManager.mState.successTimer = 90; - gMenuManager.mState.requestRedraw = true; } static void SaveSettings(u32 params) { gSettings.WriteSave(); gMenuManager.mState.successTimer = 90; - gMenuManager.mState.requestRedraw = true; } -static u32 prevDispCnt; +static void UpdateRegs(u32 params) { + static u32 dispCnt = 0xFF; + + if (params == 0xFF) { + REG_DISPCNT_SUB = dispCnt; + } else { + if (dispCnt == 0xFF) { + dispCnt = REG_DISPCNT_SUB; + } + + u32 value = 1 << params; + + if (REG_DISPCNT_SUB & value) { + REG_DISPCNT_SUB &= ~value; + } else { + REG_DISPCNT_SUB |= value; + } + } +} + +static bool IsLayerEnabled(int itemIndex) { + GZMenuItem* pActiveItem = &gMenuManager.mpActiveMenu->entries[itemIndex]; + u32 value = 1 << (pActiveItem->params & 0x0F); + return REG_DISPCNT_SUB & value; +} + static u32 prevDispCnt_Sub; -static u8 prevVRAM_CNT_B; +static vu16 prevBG0Cnt_Sub; + +//! TODO: find a better way to avoid display glitches +// for now we back up BG0 VRAM and palettes data and restore them when done +static u8 prevBG0VRAM[0x1430]; // size of "DbgFntM.NCGR" +static u8 prevBGPalettes[0x400]; // size of sub palettes space GZMenuManager gMenuManager; @@ -266,24 +304,28 @@ GZMenuManager::GZMenuManager() { this->mState.Init(); this->mpActiveMenu = &sMainMenu; this->mpButtons = &gGZ.mButtons; - memset(&data_0204d9d0[0], 0, sizeof(Screen)); - memset(&data_0204d9d0[1], 0, sizeof(Screen)); + memset(&data_0204d9d0[DRAW_TO_TOP_SCREEN], 0, sizeof(Screen)); } +GZMenu* GZMenuManager::GetMainMenu() { return &sMainMenu; } + +bool GZMenuManager::IsMainMenuActive() { return this->mpActiveMenu == &sMainMenu; } + bool GZMenuManager::IsInventoryMenuActive() { return this->mpActiveMenu == &sInventoryMenu; } bool GZMenuManager::IsAmountsMenuActive() { return this->mpActiveMenu == &sAmountsMenu; } -bool GZMenuManager::IsCommandsMenuActive() { return this->mpActiveMenu == &sCommandsMenu; } +bool GZMenuManager::IsCommandsMenuActive() { return this->mpActiveMenu == &gCommandManager.mMenu; } bool GZMenuManager::IsSettingsMenuActive() { return this->mpActiveMenu == &sSettingsMenu; } bool GZMenuManager::IsAboutMenuActive() { return this->mpActiveMenu == &sAboutMenu; } -void GZMenuManager::ValidateNewIncrement() { +void GZMenuManager::ValidateAmountIncrement() { GZMenuItem* pActiveMenuItem = this->GetActiveMenuItem(); - if (this->mState.itemIndex == 0) { + // redundant but whatever + if (pActiveMenuItem == NULL || this->mState.itemIndex == 0) { return; } @@ -338,8 +380,8 @@ void GZMenuManager::ValidateNewIncrement() { } void GZMenuManager::AssignPrevMenu() { - if (this->mpActiveMenu->mPrev != NULL) { - this->mpActiveMenu = this->mpActiveMenu->mPrev; + if (this->mpActiveMenu->parent != NULL) { + this->mpActiveMenu = this->mpActiveMenu->parent; this->mState.itemIndex = 0; this->mState.requestRedraw = true; } @@ -354,6 +396,7 @@ void GZMenuManager::Update() { this->SetupScreen(); this->StartDraw(); this->mState.isOpened = true; + this->mState.requestRedraw = true; } else { this->Quit(); } @@ -377,13 +420,13 @@ void GZMenuManager::Update() { } if (this->mControls.down.Executed(this->mpButtons)) { - if (this->mState.itemIndex + 1 < this->mpActiveMenu->mCount) { + if (this->mState.itemIndex + 1 < this->mpActiveMenu->mCount + 1) { this->mState.itemIndex++; this->mState.requestRedraw = true; } } - if (this->IsAmountsMenuActive()) { + if (pActiveMenuItem != NULL && pActiveMenuItem->eType == GZMenuItemType_Increment) { bool changed = false; if (this->mControls.decrease.Executed(this->mpButtons)) { @@ -394,8 +437,9 @@ void GZMenuManager::Update() { changed = true; } - if (changed && this->mState.itemIndex > 0 && pActiveMenuItem->mActionCallback != NULL) { - pActiveMenuItem->mActionCallback(pActiveMenuItem->params); + // for now only amounts is using increments + if (this->IsAmountsMenuActive() && changed && this->mState.itemIndex > 0 && pActiveMenuItem->action != NULL) { + pActiveMenuItem->action(pActiveMenuItem->params); this->mState.requestRedraw = true; } } @@ -403,19 +447,24 @@ void GZMenuManager::Update() { if (this->mControls.ok.Executed(this->mpButtons)) { // handle confirmation stuff - if (!pActiveMenuItem->needSaveFile || (pActiveMenuItem->needSaveFile && gGZ.IsAdventureMode())) { - if ((!this->IsAmountsMenuActive() || this->mState.itemIndex == 0) && - pActiveMenuItem->mActionCallback != NULL) { - pActiveMenuItem->mActionCallback(pActiveMenuItem->params); - - if (this->IsInventoryMenuActive()) { - this->mState.requestRedraw = true; + // null when "back" or "quit" is selected + if (pActiveMenuItem != NULL) { + if (!this->mpActiveMenu->needSaveFile || (this->mpActiveMenu->needSaveFile && gGZ.IsAdventureMode())) { + if ((!this->IsAmountsMenuActive() || this->mState.itemIndex == 0) && pActiveMenuItem->action != NULL) { + pActiveMenuItem->action(pActiveMenuItem->params); + } else if (pActiveMenuItem->submenu != NULL) { + this->mpActiveMenu = pActiveMenuItem->submenu; + this->mState.itemIndex = 0; } - } else if (pActiveMenuItem->mSubMenu != NULL) { - this->mpActiveMenu = pActiveMenuItem->mSubMenu; - this->mState.itemIndex = 0; + this->mState.requestRedraw = true; } + } else { + if (this->IsMainMenuActive()) { + this->Quit(); + } else { + this->AssignPrevMenu(); + } } } @@ -438,7 +487,7 @@ void GZMenuManager::Update() { } } -void GZMenuManager::SetAmountString(s16 index, Vec2b* pPos, bool selected) { +void GZMenuManager::SetAmountString(InventoryAmountType eType, Vec2b* pPos, bool selected) { u8 maxArrows = data_027e0ce0->mUnk_28->func_ov000_020a8728(); u8 maxBombs = data_027e0ce0->mUnk_28->func_ov000_020a8748(); @@ -449,34 +498,39 @@ void GZMenuManager::SetAmountString(s16 index, Vec2b* pPos, bool selected) { "Yellow Potion", // PotionType_Yellow }; - switch (index - 1) { + switch (eType) { case InventoryAmountType_Bow: if (data_027e0ce0 != NULL && data_027e0ce0->mUnk_28 != NULL) { - DisplayDebugTextF(0, pPos, 0, selected, " (%d/%d)", data_027e0ce0->mUnk_28->mArrowAmount, maxArrows); + DisplayDebugTextF(DRAW_TO_TOP_SCREEN, pPos, 0, selected, " (%d/%d)", + data_027e0ce0->mUnk_28->mArrowAmount, maxArrows); } break; case InventoryAmountType_Bombs: if (data_027e0ce0 != NULL && data_027e0ce0->mUnk_28 != NULL) { - DisplayDebugTextF(0, pPos, 0, selected, " (%d/%d)", data_027e0ce0->mUnk_28->mBombAmount, maxBombs); + DisplayDebugTextF(DRAW_TO_TOP_SCREEN, pPos, 0, selected, " (%d/%d)", + data_027e0ce0->mUnk_28->mBombAmount, maxBombs); } break; case InventoryAmountType_QuiverCapacity: - DisplayDebugTextF(0, pPos, 0, selected, " (%d)", maxArrows); + DisplayDebugTextF(DRAW_TO_TOP_SCREEN, pPos, 0, selected, " (%d)", maxArrows); break; case InventoryAmountType_BombCapacity: - DisplayDebugTextF(0, pPos, 0, selected, " (%d)", maxBombs); + DisplayDebugTextF(DRAW_TO_TOP_SCREEN, pPos, 0, selected, " (%d)", maxBombs); break; case InventoryAmountType_Potion1: - DisplayDebugTextF(0, pPos, 0, selected, " (%s)", szValueToPotion[data_027e0ce0->mUnk_28->mPotions[0]]); + DisplayDebugTextF(DRAW_TO_TOP_SCREEN, pPos, 0, selected, " (%s)", + szValueToPotion[data_027e0ce0->mUnk_28->mPotions[0]]); break; case InventoryAmountType_Potion2: - DisplayDebugTextF(0, pPos, 0, selected, " (%s)", szValueToPotion[data_027e0ce0->mUnk_28->mPotions[1]]); + DisplayDebugTextF(DRAW_TO_TOP_SCREEN, pPos, 0, selected, " (%s)", + szValueToPotion[data_027e0ce0->mUnk_28->mPotions[1]]); break; case InventoryAmountType_SmallKeys: - DisplayDebugTextF(0, pPos, 0, selected, " (%d/%d)", data_027e0ce0->mUnk_28->mKeyAmount, MAX_KEYS); + DisplayDebugTextF(DRAW_TO_TOP_SCREEN, pPos, 0, selected, " (%d/%d)", data_027e0ce0->mUnk_28->mKeyAmount, + MAX_KEYS); break; case InventoryAmountType_LightTears: - DisplayDebugTextF(0, pPos, 0, selected, " (%d/%d)", data_027e0ce0->mUnk_28->mTearsAmount, + DisplayDebugTextF(DRAW_TO_TOP_SCREEN, pPos, 0, selected, " (%d/%d)", data_027e0ce0->mUnk_28->mTearsAmount, MAX_TEARS_OF_LIGHT); break; default: @@ -485,125 +539,126 @@ void GZMenuManager::SetAmountString(s16 index, Vec2b* pPos, bool selected) { } void GZMenuManager::SetupScreen() { - // reset the top screen buffer - memset(&data_0204d9d0[0], 0, sizeof(Screen)); - - // send the menu item strings to the buffer Vec2b elemPos = this->mState.menuPos; - for (s16 i = 0; i < this->mpActiveMenu->mCount; i++) { - GZMenuItem* pActiveMenuItem = &this->mpActiveMenu->mpItems[i]; - const char* szName = pActiveMenuItem->mName; - Vec2b extraPos = elemPos; - bool selected = i == this->mState.itemIndex; - extraPos.x += strlen(szName); - // 0 = white, 1 = red, 2 = darker red, 3 = dark green - DisplayDebugText(0, &elemPos, 0, selected, szName); + // reset the top screen buffer then send the menu item strings to the buffer + memset(&data_0204d9d0[DRAW_TO_TOP_SCREEN], 0, sizeof(Screen)); - if (i > 0) { - if (this->IsAmountsMenuActive()) { - this->SetAmountString(i, &extraPos, selected); - } else if (this->IsInventoryMenuActive() && pActiveMenuItem->mSubMenu == NULL) { - bool hasItem = GET_FLAG(data_027e0ce0->mUnk_28->mUnk_08, pActiveMenuItem->params & 0xFF); - DisplayDebugText(0, &extraPos, 0, selected, hasItem ? " (obtained)" : " (not obtained)"); - } else if (pActiveMenuItem->needSaveFile && !gGZ.IsAdventureMode()) { - DisplayDebugText(0, &extraPos, 0, selected, " (disabled)"); - } - } + // current menu title + Vec2b titlePos = elemPos; + const char* titleStr = "stgz - "; + titlePos.x += (28 - strlen(titleStr) - strlen(this->mpActiveMenu->title)) / 2; + titlePos.y--; + DisplayDebugTextF(DRAW_TO_TOP_SCREEN, &titlePos, 0, 0, "%s%s", titleStr, this->mpActiveMenu->title); - elemPos.y++; - } + // return element + const char* retStr = this->IsMainMenuActive() ? "Quit" : "Back"; + DisplayDebugText(DRAW_TO_TOP_SCREEN, &elemPos, 0, this->mState.itemIndex == 0 ? 3 : 0, retStr); + elemPos.y++; + // menu items if (this->IsCommandsMenuActive()) { gCommandManager.Draw(&elemPos); + } else { + for (s16 i = 0; i < this->mpActiveMenu->mCount; i++) { + GZMenuItem* pActiveMenuItem = &this->mpActiveMenu->entries[i]; + const char* szName = pActiveMenuItem->name; + Vec2b extraPos = elemPos; + bool selected = i + 1 == this->mState.itemIndex; + extraPos.x += strlen(szName); + + if (pActiveMenuItem->eType == GZMenuItemType_Bool && pActiveMenuItem->checkCallback != NULL) { + Vec2b boolPos = elemPos; + DisplayDebugTextF(DRAW_TO_TOP_SCREEN, &boolPos, 0, selected, "[%s]%s", + pActiveMenuItem->checkCallback(i) ? "x" : " ", szName); + } else { + // 0 = white, 1 = red, 2 = darker red, 3 = dark green, seems to be palette indices? + DisplayDebugText(DRAW_TO_TOP_SCREEN, &elemPos, 0, selected, szName); + } + + if (this->IsAmountsMenuActive()) { + this->SetAmountString(pActiveMenuItem->params & 0xFF, &extraPos, selected); + } else if (this->mpActiveMenu->needSaveFile && !gGZ.IsAdventureMode()) { + DisplayDebugText(DRAW_TO_TOP_SCREEN, &extraPos, 0, selected, " (disabled)"); + } + + elemPos.y++; + } } - // send the arrow to the buffer + // current selection arrow Vec2b arrowPos = this->mState.menuPos; arrowPos.x--; arrowPos.y += this->mState.itemIndex; - DisplayDebugText(0, &arrowPos, 0, 1, ">"); + DisplayDebugText(DRAW_TO_TOP_SCREEN, &arrowPos, 0, this->mState.itemIndex == 0 ? 3 : 1, ">"); arrowPos.y++; + // about and settings screens (TODO: move to GZSettings) if (this->IsSettingsMenuActive()) { // special handling for the settings screen Vec2b settingsPos = this->mState.menuPos; settingsPos.y = elemPos.y + 1; - DisplayDebugTextF(0, &settingsPos, 0, 0, "Current Profile: %d", gSettings.mProfileHeader.curProfileIndex + 1); + DisplayDebugTextF(DRAW_TO_TOP_SCREEN, &settingsPos, 0, 0, "Current Profile: %d", + gSettings.mProfileHeader.curProfileIndex + 1); - settingsPos.y += 15; + settingsPos.y = 21; if (gSettings.error) { - DisplayDebugTextF(0, &settingsPos, 0, 1, "Error detected: 0x%X", gSettings.errorCode); + DisplayDebugTextF(DRAW_TO_TOP_SCREEN, &settingsPos, 0, 1, "Error detected: 0x%X", gSettings.errorCode); } else if (this->mState.successTimer > 0) { - DisplayDebugTextF(0, &settingsPos, 0, 0, "Success!", gSettings.errorCode); + DisplayDebugTextF(DRAW_TO_TOP_SCREEN, &settingsPos, 0, 0, "Success!", gSettings.errorCode); } } else if (this->IsAboutMenuActive()) { // special handling for the about screen Vec2b aboutPos = this->mState.menuPos; - aboutPos.y = elemPos.y + 1; // start wherever the item list ended - DisplayDebugTextF(0, &aboutPos, 0, 0, "Code Version: %s", gBuildGitVersion); + + aboutPos.y += 2; + DisplayDebugTextF(DRAW_TO_TOP_SCREEN, &aboutPos, 0, 0, "Code Version: %s", gBuildGitVersion); aboutPos.y++; - DisplayDebugTextF(0, &aboutPos, 0, 0, "Build Author: %s", gBuildAuthor); + DisplayDebugTextF(DRAW_TO_TOP_SCREEN, &aboutPos, 0, 0, "Build Author: %s", gBuildAuthor); aboutPos.y++; - DisplayDebugTextF(0, &aboutPos, 0, 0, "Commit Author: %s", gCommitAuthor); + DisplayDebugTextF(DRAW_TO_TOP_SCREEN, &aboutPos, 0, 0, "Commit Author: %s", gCommitAuthor); aboutPos.y++; - DisplayDebugTextF(0, &aboutPos, 0, 0, "Commit Name: %s", gCommitGitString); + DisplayDebugTextF(DRAW_TO_TOP_SCREEN, &aboutPos, 0, 0, "Commit Name: %s", gCommitGitString); - aboutPos.y += 16; - DisplayDebugText(0, &aboutPos, 0, 0, "Licensed under GPL-3.0"); + aboutPos.y = 21; + DisplayDebugText(DRAW_TO_TOP_SCREEN, &aboutPos, 0, 0, "Licensed under GPL-3.0"); aboutPos.y++; - DisplayDebugText(0, &aboutPos, 0, 0, "Made with <3 by Yanis2"); + DisplayDebugText(DRAW_TO_TOP_SCREEN, &aboutPos, 0, 0, "Made with <3 by Yanis2"); } } void GZMenuManager::StartDraw() { - // don't ask me I have no idea how this works, feel free to improve - - prevDispCnt = REG_DISPCNT; prevDispCnt_Sub = REG_DISPCNT_SUB; - prevVRAM_CNT_B = REG_VRAM_CNT_B; - - DC_FlushAll(); - func_020131ec(); - REG_POWER_CNT |= 0x8000; - func_02023770(2); // no corruption when commented but no text - GX_SetGraphicsMode(1, 0, 0); - GXS_SetGraphicsMode(0); - - REG_DISPCNT = ((REG_DISPCNT & ~0x1F00) | 0x100); - REG_DISPCNT_SUB = (REG_DISPCNT_SUB & ~0x1F00) | 0x100; - func_0201b180(true, true); // loads the font (participate in the corruption also?) -} + prevBG0Cnt_Sub = REG_BG0CNT_SUB; + Copy256((void*)0x06208000, prevBG0VRAM, sizeof(prevBG0VRAM)); + Copy256((void*)0x05000400, prevBGPalettes, sizeof(prevBGPalettes)); -void GZMenuManager::Draw() { - func_0201b278(true, true); // copy screen - func_020131ec(); - SetBrightColor((void*)®_MASTER_BRIGHT, 0); - SetBrightColor((void*)®_MASTER_BRIGHT_SUB, 0); + REG_DISPCNT_SUB = (REG_DISPCNT_SUB & ~0x0400) | 0x100; // disable BG2 and make sure BG0 is enabled + REG_BG0CNT_SUB &= ~3; // make BG0 on top of everything else - if (func_020147a8() != 0) { - data_ov000_020b50c0.func_ov000_02069f58(); + if (gGZ.IsAdventureMode() && !gGZ.IsOnLand()) { + //! TODO: fix issue where the font is displayed on the screen + REG_DISPCNT_SUB &= ~0x0200; // disable BG1 for the overworld } - while (this->mState.isOpened && !this->mState.requestRedraw) { - func_020131ec(); - gGZ.Update(); - this->Update(); - } + func_0201b180(false, true); // loads the font } -void GZMenuManager::StopDraw() { - if (gOverlayManager.mLoadedOverlays[OverlaySlot_4] == OverlayIndex_Title) { - GX_SetGraphicsMode(1, 0, 1); - GXS_SetGraphicsMode(5); - } +void GZMenuManager::Draw() { + // copy screen + func_02027654(data_0204d9d0[DRAW_TO_TOP_SCREEN].data, sizeof(data_0204d9d0[DRAW_TO_TOP_SCREEN].data)); + func_020252ec(data_0204d9d0[DRAW_TO_TOP_SCREEN].data, 0, sizeof(data_0204d9d0[DRAW_TO_TOP_SCREEN].data)); +} - memset((void*)0x068A0000, 0, 0x21A0); - REG_DISPCNT = prevDispCnt; +void GZMenuManager::StopDraw() { REG_DISPCNT_SUB = prevDispCnt_Sub; - REG_VRAM_CNT_B = prevVRAM_CNT_B; + REG_BG0CNT_SUB = prevBG0Cnt_Sub; + func_02027654(prevBG0VRAM, sizeof(prevBG0VRAM)); + Copy256(prevBG0VRAM, (void*)0x06208000, sizeof(prevBG0VRAM)); + func_02027654(prevBGPalettes, sizeof(prevBGPalettes)); + Copy256(prevBGPalettes, (void*)0x05000400, sizeof(prevBGPalettes)); } diff --git a/src/gz_settings.cpp b/src/gz_settings.cpp index 23dac38..92fbf28 100644 --- a/src/gz_settings.cpp +++ b/src/gz_settings.cpp @@ -33,32 +33,25 @@ void GZSettings::Update() { this->ProcessTitleScreen(); } void GZSettings::ProcessTitleScreen() { GZProfile* pProfile = this->GetProfile(); - if (!pProfile->mFasterTitleScreen && !pProfile->mSkipTitleScreen) { + if (data_027e0994 == NULL || (!pProfile->mFasterTitleScreen && !pProfile->mSkipTitleScreen)) { return; } - if (!gGZ.IsTitleScreen()) { - return; - } - - if (data_027e0994 == NULL && data_027e0994->mpTitleScreen == NULL) { - return; - } + TitleScreen* pTitleScreen = data_027e0994->GetTitleScreen(); - if (data_027e0994->mpTitleScreen->mShowUI) { + if (!gGZ.IsTitleScreen() || pTitleScreen == NULL || pTitleScreen->mShowUI) { return; } - data_027e0994->mpTitleScreen->func_ov025_020c4e54(); + pTitleScreen->func_ov025_020c4e54(); if (pProfile->mSkipTitleScreen) { data_ov000_020b5214.func_ov000_0206db44(0x0B); - data_027e0994->mpTitleScreen->func_ov025_020c4ea0(TitleScreenState_ToFileSelect); + pTitleScreen->func_ov025_020c4ea0(TitleScreenState_ToFileSelect); } } static GZProfile sDefaultProfile = { - .profileIndex = 0xF0, .mFasterTitleScreen = true, .mSkipTitleScreen = true, .mPositionIndex = 0,