From f99993af85c744eed8b298283178e8d9a87a043a Mon Sep 17 00:00:00 2001 From: GaryOderNichts <12049776+GaryOderNichts@users.noreply.github.com> Date: Sun, 16 Jun 2024 05:28:42 +0200 Subject: [PATCH] Reduce stack usage during static initialization (#4184) * Reduce stack usage during static initialization * Implement `ABS` macro for `TWO_ACTOR_PARAMS` --- soh/soh/ActorDB.cpp | 7 +++-- .../Enhancements/item-tables/ItemTableTypes.h | 2 +- .../Enhancements/randomizer/randomizer.cpp | 28 +++++++++---------- .../randomizer/randomizer_check_objects.cpp | 3 +- .../randomizer/randomizer_check_objects.h | 9 ++++-- .../randomizer/randomizer_check_tracker.cpp | 2 +- .../randomizer/randomizer_tricks.cpp | 3 +- .../randomizer/randomizer_tricks.h | 4 +-- 8 files changed, 32 insertions(+), 26 deletions(-) diff --git a/soh/soh/ActorDB.cpp b/soh/soh/ActorDB.cpp index ea8450ac4..de2538888 100644 --- a/soh/soh/ActorDB.cpp +++ b/soh/soh/ActorDB.cpp @@ -16,7 +16,7 @@ ActorDB* ActorDB::Instance; #undef DEFINE_ACTOR_UNSET struct AddPair { - std::string name; + const char* name; ActorInit& init; }; @@ -24,7 +24,7 @@ struct AddPair { #define DEFINE_ACTOR(name, _1, allocType) { #name, name##_InitVars }, #define DEFINE_ACTOR_UNSET(_0) -static const std::vector initialActorTable = { +static constexpr AddPair initialActorTable[] = { #include "tables/actor_table.h" }; @@ -33,7 +33,7 @@ static const std::vector initialActorTable = { #undef DEFINE_ACTOR // https://wiki.cloudmodding.com/oot/Actor_List_(Variables) -static std::unordered_map actorDescriptions = { +static constexpr std::pair actorDescriptionData[] = { { ACTOR_PLAYER, "Link" }, { ACTOR_EN_TEST, "Stalfos" }, { ACTOR_EN_GIRLA, "Shop Items" }, @@ -464,6 +464,7 @@ static std::unordered_map actorDescriptions = { { ACTOR_BG_JYA_BLOCK, "Silver Block (Child Era)" }, { ACTOR_OBJ_WARP2BLOCK, "Navi Infospot (Green, Time Block)" } }; +static std::unordered_map actorDescriptions = std::unordered_map(std::begin(actorDescriptionData), std::end(actorDescriptionData)); ActorDB::ActorDB() { db.reserve(ACTOR_NUMBER_MAX); // reserve size for all initial entries so we don't do it for each diff --git a/soh/soh/Enhancements/item-tables/ItemTableTypes.h b/soh/soh/Enhancements/item-tables/ItemTableTypes.h index 6282275b1..28e70dc95 100644 --- a/soh/soh/Enhancements/item-tables/ItemTableTypes.h +++ b/soh/soh/Enhancements/item-tables/ItemTableTypes.h @@ -59,4 +59,4 @@ typedef struct GetItemEntry { /* 0x10 */ uint16_t drawItemId; // Will be a copy of itemId unless the item is an ice trap. Needed for particles to function on ice traps. /* 0x11 */ uint16_t drawModIndex; // Will be a copy of modIndex unless the item is an ice trap. Needed for particles to function on ice traps. CustomDrawFunc drawFunc; -}; // size = 0x11 +} GetItemEntry; // size = 0x11 diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 107e23e83..5ea7293eb 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -4660,7 +4660,7 @@ void RandomizerSettingsWindow::DrawElement() { bool hasItems = false; for (auto& [randomizerCheck, rcObject] : rcObjects) { if (rcObject->visibleInImgui && !excludedLocations.count(rcObject->rc) && - locationSearch.PassFilter(rcObject->rcSpoilerName.c_str())) { + locationSearch.PassFilter(rcObject->rcSpoilerName)) { hasItems = true; break; @@ -4672,7 +4672,7 @@ void RandomizerSettingsWindow::DrawElement() { if (ImGui::TreeNode(RandomizerCheckObjects::GetRCAreaName(rcArea).c_str())) { for (auto& [randomizerCheck, rcObject] : rcObjects) { if (rcObject->visibleInImgui && !excludedLocations.count(rcObject->rc) && - locationSearch.PassFilter(rcObject->rcSpoilerName.c_str())) { + locationSearch.PassFilter(rcObject->rcSpoilerName)) { if (ImGui::ArrowButton(std::to_string(rcObject->rc).c_str(), ImGuiDir_Right)) { excludedLocations.insert(rcObject->rc); @@ -4686,7 +4686,7 @@ void RandomizerSettingsWindow::DrawElement() { Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } ImGui::SameLine(); - ImGui::Text("%s", rcObject->rcShortName.c_str()); + ImGui::Text("%s", rcObject->rcShortName); } } ImGui::TreePop(); @@ -4731,7 +4731,7 @@ void RandomizerSettingsWindow::DrawElement() { Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); } ImGui::SameLine(); - ImGui::Text("%s", rcObject->rcShortName.c_str()); + ImGui::Text("%s", rcObject->rcShortName); } } ImGui::TreePop(); @@ -4997,7 +4997,7 @@ void RandomizerSettingsWindow::DrawElement() { if (ImGui::Button("Enable Visible")) { for (auto [rtArea, rtObjects] : RandomizerTricks::GetAllRTObjectsByArea()) { for (auto [randomizerTrick, rtObject] : rtObjects) { - if (!rtObject.rtGlitch && !enabledTricks.count(rtObject.rt) && trickSearch.PassFilter(rtObject.rtShortName.c_str()) && areaTreeDisabled[rtArea] && RandomizerTricks::CheckRTTags(showTag, *rtObject.rtTags)) { + if (!rtObject.rtGlitch && !enabledTricks.count(rtObject.rt) && trickSearch.PassFilter(rtObject.rtShortName) && areaTreeDisabled[rtArea] && RandomizerTricks::CheckRTTags(showTag, *rtObject.rtTags)) { enabledTricks.insert(randomizerTrick); } } @@ -5017,7 +5017,7 @@ void RandomizerSettingsWindow::DrawElement() { bool hasTricks = false; for (auto [randomizerTrick, rtObject] : rtObjects) { if (rtObject.visibleInImgui && - trickSearch.PassFilter(rtObject.rtShortName.c_str()) && + trickSearch.PassFilter(rtObject.rtShortName) && !enabledTricks.count(rtObject.rt) && RandomizerTricks::CheckRTTags(showTag, *rtObject.rtTags) && !rtObject.rtGlitch) { @@ -5032,7 +5032,7 @@ void RandomizerSettingsWindow::DrawElement() { if (ImGui::TreeNode(RandomizerTricks::GetRTAreaName(rtArea).c_str())) { for (auto [randomizerTrick, rtObject] : rtObjects) { if (rtObject.visibleInImgui && - trickSearch.PassFilter(rtObject.rtShortName.c_str()) && + trickSearch.PassFilter(rtObject.rtShortName) && !enabledTricks.count(rtObject.rt) && RandomizerTricks::CheckRTTags(showTag, *rtObject.rtTags) && !rtObject.rtGlitch) { @@ -5048,8 +5048,8 @@ void RandomizerSettingsWindow::DrawElement() { } DrawTagChips(*rtObject.rtTags); ImGui::SameLine(); - ImGui::Text("%s", rtObject.rtShortName.c_str()); - UIWidgets::InsertHelpHoverText(rtObject.rtDesc.c_str()); + ImGui::Text("%s", rtObject.rtShortName); + UIWidgets::InsertHelpHoverText(rtObject.rtDesc); } } areaTreeDisabled[rtArea] = true; @@ -5107,7 +5107,7 @@ void RandomizerSettingsWindow::DrawElement() { for (auto [rtArea, rtObjects] : RandomizerTricks::GetAllRTObjectsByArea()) { for (auto [randomizerTrick, rtObject] : rtObjects) { auto etfound = enabledTricks.find(randomizerTrick); - if (!rtObject.rtGlitch && etfound != enabledTricks.end() && trickSearch.PassFilter(rtObject.rtShortName.c_str()) && areaTreeEnabled[rtArea] && RandomizerTricks::CheckRTTags(showTag, *rtObject.rtTags)) { + if (!rtObject.rtGlitch && etfound != enabledTricks.end() && trickSearch.PassFilter(rtObject.rtShortName) && areaTreeEnabled[rtArea] && RandomizerTricks::CheckRTTags(showTag, *rtObject.rtTags)) { enabledTricks.erase(etfound); } } @@ -5127,7 +5127,7 @@ void RandomizerSettingsWindow::DrawElement() { bool hasTricks = false; for (auto [randomizerTrick, rtObject] : rtObjects) { if (rtObject.visibleInImgui && - trickSearch.PassFilter(rtObject.rtShortName.c_str()) && + trickSearch.PassFilter(rtObject.rtShortName) && enabledTricks.count(rtObject.rt) && RandomizerTricks::CheckRTTags(showTag, *rtObject.rtTags) && !rtObject.rtGlitch) { @@ -5143,7 +5143,7 @@ void RandomizerSettingsWindow::DrawElement() { for (auto [randomizerTrick, rtObject] : rtObjects) { auto etfound = enabledTricks.find(rtObject.rt); if (rtObject.visibleInImgui && - trickSearch.PassFilter(rtObject.rtShortName.c_str()) && + trickSearch.PassFilter(rtObject.rtShortName) && etfound != enabledTricks.end() && RandomizerTricks::CheckRTTags(showTag, *rtObject.rtTags) && !rtObject.rtGlitch) { @@ -5164,8 +5164,8 @@ void RandomizerSettingsWindow::DrawElement() { } DrawTagChips(*rtObject.rtTags); ImGui::SameLine(); - ImGui::Text("%s", rtObject.rtShortName.c_str()); - UIWidgets::InsertHelpHoverText(rtObject.rtDesc.c_str()); + ImGui::Text("%s", rtObject.rtShortName); + UIWidgets::InsertHelpHoverText(rtObject.rtDesc); } } areaTreeEnabled[rtArea] = true; diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp index b97a6f335..e3dcf4673 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp @@ -6,7 +6,7 @@ #include "soh/OTRGlobals.h" // RandomizerCheck, RCVORMQ, RCTYPE, RCAREA, ActorId, SceneId, ActorParams, OG ItemID, "Short name", "Spoiler name", vanillaCompletion -std::map rcObjects = { +static constexpr std::pair rcObjectsData[] = { RC_OBJECT(RC_KF_KOKIRI_SWORD_CHEST, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_KOKIRI_FOREST, ACTOR_EN_BOX, SCENE_KOKIRI_FOREST, 1248, GI_SWORD_KOKIRI, "Kokiri Sword Chest", "KF Kokiri Sword Chest", true), RC_OBJECT(RC_KF_MIDOS_TOP_LEFT_CHEST, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_KOKIRI_FOREST, ACTOR_EN_BOX, SCENE_MIDOS_HOUSE, 22944, GI_RUPEE_BLUE, "Mido Top Left Chest", "KF Mido Top Left Chest", false), RC_OBJECT(RC_KF_MIDOS_TOP_RIGHT_CHEST, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_KOKIRI_FOREST, ACTOR_EN_BOX, SCENE_MIDOS_HOUSE, 22945, GI_RUPEE_BLUE, "Mido Top Right Chest", "KF Mido Top Right Chest", false), @@ -775,6 +775,7 @@ std::map rcObjects = { RC_OBJECT(RC_UNKNOWN_CHECK, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_INVALID, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, GI_NONE, "Invalid Check", "Invalid Check", false), }; +std::map rcObjects = std::map(std::begin(rcObjectsData), std::end(rcObjectsData)); std::map rcAreaNames = { { RCAREA_KOKIRI_FOREST, "Kokiri Forest"}, diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_objects.h b/soh/soh/Enhancements/randomizer/randomizer_check_objects.h index dc9bd2010..e2b784135 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_objects.h +++ b/soh/soh/Enhancements/randomizer/randomizer_check_objects.h @@ -7,7 +7,10 @@ enum ActorID : int; enum SceneID : int; -#define TWO_ACTOR_PARAMS(a, b) (abs(a) << 16) | abs(b) +// ABS macro to use since `std::abs` is not constexpr yet +#define ABS(x) ((x) < 0 ? -(x) : (x)) + +#define TWO_ACTOR_PARAMS(a, b) (ABS(a) << 16) | ABS(b) #define RC_OBJECT(rc, rc_v_or_mq, rc_type, rc_area, actor_id, scene_id, actor_params, og_item_id, rc_shortname, rc_spoilername, vanillaCompletion) \ { rc, {rc, rc_v_or_mq, rc_type, rc_area, actor_id, scene_id, actor_params, og_item_id, false, rc_shortname, rc_spoilername, vanillaCompletion} } @@ -22,8 +25,8 @@ typedef struct { int32_t actorParams; GetItemID ogItemId; bool visibleInImgui; - std::string rcShortName; - std::string rcSpoilerName; + const char* rcShortName; + const char* rcSpoilerName; bool vanillaCompletion; } RandomizerCheckObject; diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp index aca75ef93..02952a052 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp @@ -1089,7 +1089,7 @@ bool ShouldShowCheck(RandomizerCheckObject check) { IsVisibleInCheckTracker(check) && (checkSearch.Filters.Size == 0 || checkSearch.PassFilter(RandomizerCheckObjects::GetRCAreaName(check.rcArea).c_str()) || - checkSearch.PassFilter(check.rcShortName.c_str())) + checkSearch.PassFilter(check.rcShortName)) ); } diff --git a/soh/soh/Enhancements/randomizer/randomizer_tricks.cpp b/soh/soh/Enhancements/randomizer/randomizer_tricks.cpp index 8a397f840..4b704ccc0 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_tricks.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_tricks.cpp @@ -21,7 +21,7 @@ std::vector extremeBase{RTTAG_EXTREME}; // Experimental - not implemented; these tricks may let you put the game into a softlockable state // Please see https://www.youtube.com/playlist?list=PLqsXSioZwQyoa23_27l5NZq5IZdKRi5Sm for reference on performing several of these tricks // RandomizerTrick, RTVORMQ, RTAREA, rt_tags rt_glitch (is it a glitch) "Short name", "Description" -std::unordered_map rtObjects = { +static constexpr std::pair rtObjectsData[] = { RT_OBJECT(RT_ACUTE_ANGLE_CLIP, RTVORMQ_BOTH, RTAREA_GENERAL, &advancedBase, true, "Acute angle clip", "Enables locations requiring jumpslash clips through walls which meet at an acute angle."), RT_OBJECT(RT_ADVANCED_CLIPS, RTVORMQ_BOTH, RTAREA_GENERAL, &advancedBase, true, "Advanced clips", "Enables locations requiring clips through walls and objects requiring precise jumps or other tricks."), RT_OBJECT(RT_BLANK_A, RTVORMQ_BOTH, RTAREA_GENERAL, &advancedBase, true, "Blank A", "Enables locations requiring blank A button; NOTE: this requires the 'Quick Putaway' restoration."), @@ -208,6 +208,7 @@ std::unordered_map rtObjects = { RT_OBJECT(RT_GANON_MQ_SHADOW_TRIAL, RTVORMQ_MQ, RTAREA_GANONS_CASTLE, &noviceBase, false, "Shadow Trial MQ Torch with Bow", "You can light the torch in this room without a fire source by shooting an arrow through the lit torch at the beginning of the room. Because the room is so dark and the unlit torch is so far away, it can be difficult to aim the shot correctly."), RT_OBJECT(RT_GANON_MQ_LIGHT_TRIAL, RTVORMQ_MQ, RTAREA_GANONS_CASTLE, &intermediateBase, /*todo*/ false, "Light Trial MQ without Hookshot", "If you move quickly you can sneak past the edge of a flame wall before it can rise up to block you. In this case to do it without taking damage is especially precise.") }; +std::unordered_map rtObjects = std::unordered_map(std::begin(rtObjectsData), std::end(rtObjectsData)); std::unordered_map rtAreaNames = { { RTAREA_GENERAL, "General Tricks"}, diff --git a/soh/soh/Enhancements/randomizer/randomizer_tricks.h b/soh/soh/Enhancements/randomizer/randomizer_tricks.h index 6fb4a4341..5d1df34d4 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_tricks.h +++ b/soh/soh/Enhancements/randomizer/randomizer_tricks.h @@ -71,8 +71,8 @@ typedef struct { std::vector *rtTags; bool rtGlitch; bool visibleInImgui; - std::string rtShortName; - std::string rtDesc; + const char* rtShortName; + const char* rtDesc; } RandomizerTrickObject; namespace RandomizerTricks {