diff --git a/soh/include/z64.h b/soh/include/z64.h index 53b76e8fb..1640db4d4 100644 --- a/soh/include/z64.h +++ b/soh/include/z64.h @@ -1687,7 +1687,8 @@ typedef struct PreNMIContext { } PreNMIContext; // size = 0xAC typedef enum { - /* 1 */ F_8F = 1, + /* 0 */ F_NA, + /* 1 */ F_8F, /* 2 */ F_7F, /* 3 */ F_6F, /* 4 */ F_5F, diff --git a/soh/include/z64save.h b/soh/include/z64save.h index 63a9b1d10..6c0109c2f 100644 --- a/soh/include/z64save.h +++ b/soh/include/z64save.h @@ -47,8 +47,8 @@ typedef struct { /* 0x28 */ u16 equipment; // a mask where each nibble corresponds to a type of equipment `EquipmentType`, and each bit to an owned piece `EquipInv*` /* 0x2C */ u32 upgrades; /* 0x30 */ u32 questItems; - /* 0x34 */ u8 dungeonItems[20]; - /* 0x48 */ s8 dungeonKeys[19]; + /* 0x34 */ u8* dungeonItems; + /* 0x48 */ s8* dungeonKeys; /* 0x5B */ s8 defenseHearts; /* 0x5C */ s16 gsTokens; } Inventory; // size = 0x5E @@ -224,7 +224,7 @@ typedef struct { /* 0x0066 */ s16 savedSceneNum; // Upstream TODO: sceneId /* 0x0068 */ ItemEquips equips; /* 0x0074 */ Inventory inventory; - /* 0x00D4 */ SavedSceneFlags sceneFlags[124]; + /* 0x00D4 */ SavedSceneFlags* sceneFlags; /* 0x0E64 */ FaroresWindData fw; /* 0x0E8C */ char unk_E8C[0x10]; /* 0x0E9C */ s32 gsFlags[6]; diff --git a/soh/soh/ActorDB.cpp b/soh/soh/ActorDB.cpp index 70ea29675..61d1bd80d 100644 --- a/soh/soh/ActorDB.cpp +++ b/soh/soh/ActorDB.cpp @@ -514,7 +514,7 @@ ActorDB::Entry& ActorDB::AddEntry(const std::string& name, const std::string& de return entry; } -// Adds an actor with the new ActorDBInit struct. The id assigned to the actor is dynamic. Use the return Entry or +// Adds an actor with the new ActorDBInit struct. The id assigned to the actor is dynamic. Use the returned Entry or // RetrieveId to get it. ActorDB::Entry& ActorDB::AddEntry(const ActorDBInit& init) { Entry& entry = AddEntry(init.name, init.desc, nextFreeId); diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index 994e0fba6..425b00a12 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -1,6 +1,7 @@ #include #include "soh/OTRGlobals.h" #include "soh/ResourceManagerHelpers.h" +#include "soh/SceneDB.h" #include "soh/Enhancements/enhancementTypes.h" #include "soh/Enhancements/custom-message/CustomMessageTypes.h" #include "soh/Enhancements/item-tables/ItemTableManager.h" @@ -857,13 +858,16 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l *should = !Flags_GetRandomizerInf(RAND_INF_DARUNIAS_JOY); break; case VB_BE_ELIGIBLE_FOR_LIGHT_ARROWS: - *should = LINK_IS_ADULT && (gEntranceTable[gSaveContext.entranceIndex].scene == SCENE_TEMPLE_OF_TIME) && + *should = LINK_IS_ADULT && + (EntranceDB::Instance->RetrieveEntry(gSaveContext.entranceIndex).entry.sceneId == + SCENE_TEMPLE_OF_TIME) && !Flags_GetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS) && MeetsLACSRequirements(); break; case VB_BE_ELIGIBLE_FOR_NOCTURNE_OF_SHADOW: *should = !Flags_GetEventChkInf(EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL) && LINK_IS_ADULT && - gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_KAKARIKO_VILLAGE && + (EntranceDB::Instance->RetrieveEntry(gSaveContext.entranceIndex).entry.sceneId == + SCENE_KAKARIKO_VILLAGE) && CHECK_QUEST_ITEM(QUEST_MEDALLION_FOREST) && CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE) && CHECK_QUEST_ITEM(QUEST_MEDALLION_WATER); break; diff --git a/soh/soh/Enhancements/randomizer/logic.cpp b/soh/soh/Enhancements/randomizer/logic.cpp index ca52009ac..1ac7a6e69 100644 --- a/soh/soh/Enhancements/randomizer/logic.cpp +++ b/soh/soh/Enhancements/randomizer/logic.cpp @@ -8,6 +8,7 @@ #include #include "soh/OTRGlobals.h" +#include "soh/SceneDB.h" #include "dungeon.h" #include "context.h" #include "macros.h" @@ -2025,6 +2026,7 @@ void Logic::InitSaveContext() { mSaveContext->equips.equipment = 0; // Inventory + size_t numScenes = SceneDB::Instance->GetNumEntries(); for (int item = 0; item < ARRAY_COUNT(mSaveContext->inventory.items); item++) { mSaveContext->inventory.items[item] = ITEM_NONE; } @@ -2034,15 +2036,15 @@ void Logic::InitSaveContext() { mSaveContext->inventory.equipment = 0; mSaveContext->inventory.upgrades = 0; mSaveContext->inventory.questItems = 0; - for (int dungeon = 0; dungeon < ARRAY_COUNT(mSaveContext->inventory.dungeonItems); dungeon++) { + for (int dungeon = 0; dungeon < numScenes; dungeon++) { mSaveContext->inventory.dungeonItems[dungeon] = 0; } - for (int dungeon = 0; dungeon < ARRAY_COUNT(mSaveContext->inventory.dungeonKeys); dungeon++) { + for (int dungeon = 0; dungeon < numScenes; dungeon++) { mSaveContext->inventory.dungeonKeys[dungeon] = 0x0; } mSaveContext->inventory.defenseHearts = 0; mSaveContext->inventory.gsTokens = 0; - for (int scene = 0; scene < ARRAY_COUNT(mSaveContext->sceneFlags); scene++) { + for (int scene = 0; scene < numScenes; scene++) { mSaveContext->sceneFlags[scene].chest = 0; mSaveContext->sceneFlags[scene].swch = 0; mSaveContext->sceneFlags[scene].clear = 0; @@ -2121,9 +2123,16 @@ void Logic::InitSaveContext() { void Logic::NewSaveContext() { if (mSaveContext != nullptr && mSaveContext != &gSaveContext) { - free(mSaveContext); + delete[] mSaveContext->inventory.dungeonItems; + delete[] mSaveContext->inventory.dungeonKeys; + delete[] mSaveContext->sceneFlags; + delete mSaveContext; } + size_t numScenes = SceneDB::Instance->GetNumEntries(); mSaveContext = new SaveContext(); + mSaveContext->inventory.dungeonItems = new u8[numScenes]; + mSaveContext->inventory.dungeonKeys = new s8[numScenes]; + mSaveContext->sceneFlags = new SavedSceneFlags[numScenes]; InitSaveContext(); } diff --git a/soh/soh/Enhancements/randomizer/randomizer_entrance.c b/soh/soh/Enhancements/randomizer/randomizer_entrance.c index 11d17e621..eac431bba 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_entrance.c +++ b/soh/soh/Enhancements/randomizer/randomizer_entrance.c @@ -12,6 +12,7 @@ #include "randomizer_grotto.h" #include "soh/OTRGlobals.h" #include "soh/SaveManager.h" +#include "soh/SceneDB.h" #include #include "global.h" @@ -92,7 +93,7 @@ static void Entrance_SeparateOGCFairyFountainExit(void) { // Overwrite unused entrance 0x03E8 (ENTR_POTION_SHOP_KAKARIKO_1) with values from 0x0340 // (ENTR_CASTLE_GROUNDS_GREAT_FAIRY_EXIT) to use it as the exit from OGC Great Fairy Fountain -> Castle Grounds for (size_t i = 0; i < 4; ++i) { - gEntranceTable[ENTR_POTION_SHOP_KAKARIKO_1 + i] = gEntranceTable[ENTR_CASTLE_GROUNDS_GREAT_FAIRY_EXIT + i]; + EntranceDB_Copy(ENTR_CASTLE_GROUNDS_GREAT_FAIRY_EXIT + i, ENTR_POTION_SHOP_KAKARIKO_1 + i); } } @@ -100,7 +101,7 @@ static void Entrance_SeparateAdultSpawnAndPrelude() { // Overwrite unused entrance 0x0282 (ENTR_HYRULE_FIELD_10) with values from 0x05F4 (ENTR_TEMPLE_OF_TIME_WARP_PAD) to // use it as the Adult Spawn index and separate it from Prelude of Light for (size_t i = 0; i < 4; ++i) { - gEntranceTable[ENTR_HYRULE_FIELD_10 + i] = gEntranceTable[ENTR_TEMPLE_OF_TIME_WARP_PAD + i]; + EntranceDB_Copy(ENTR_TEMPLE_OF_TIME_WARP_PAD + i, ENTR_HYRULE_FIELD_10 + i); } } @@ -109,56 +110,45 @@ static void Entrance_ReplaceChildTempleWarps() { if (Randomizer_GetSettingValue(RSK_SHUFFLE_DUNGEON_ENTRANCES) != RO_DUNGEON_ENTRANCE_SHUFFLE_OFF || Randomizer_GetSettingValue(RSK_SHUFFLE_BOSS_ENTRANCES) != RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF) { // Forest Temple - gEntranceTable[ENTR_SACRED_FOREST_MEADOW_FOREST_TEMPLE_BLUE_WARP] = - gEntranceTable[ENTR_SACRED_FOREST_MEADOW_WARP_PAD]; - gEntranceTable[ENTR_SACRED_FOREST_MEADOW_3_1] = gEntranceTable[ENTR_SACRED_FOREST_MEADOW_2_1]; + EntranceDB_Copy(ENTR_SACRED_FOREST_MEADOW_WARP_PAD, ENTR_SACRED_FOREST_MEADOW_FOREST_TEMPLE_BLUE_WARP); + EntranceDB_Copy(ENTR_SACRED_FOREST_MEADOW_2_1, ENTR_SACRED_FOREST_MEADOW_3_1); // Fire Temple - gEntranceTable[ENTR_DEATH_MOUNTAIN_CRATER_FIRE_TEMPLE_BLUE_WARP] = - gEntranceTable[ENTR_DEATH_MOUNTAIN_CRATER_WARP_PAD]; - gEntranceTable[ENTR_DEATH_MOUNTAIN_CRATER_5_1] = gEntranceTable[ENTR_DEATH_MOUNTAIN_CRATER_4_1]; + EntranceDB_Copy(ENTR_DEATH_MOUNTAIN_CRATER_WARP_PAD, ENTR_DEATH_MOUNTAIN_CRATER_FIRE_TEMPLE_BLUE_WARP); + EntranceDB_Copy(ENTR_DEATH_MOUNTAIN_CRATER_4_1, ENTR_DEATH_MOUNTAIN_CRATER_5_1); // Water Temple - gEntranceTable[ENTR_LAKE_HYLIA_WATER_TEMPLE_BLUE_WARP] = gEntranceTable[ENTR_LAKE_HYLIA_WARP_PAD]; - gEntranceTable[ENTR_LAKE_HYLIA_9_1] = gEntranceTable[ENTR_LAKE_HYLIA_8_1]; + EntranceDB_Copy(ENTR_LAKE_HYLIA_WARP_PAD, ENTR_LAKE_HYLIA_WATER_TEMPLE_BLUE_WARP); + EntranceDB_Copy(ENTR_LAKE_HYLIA_8_1, ENTR_LAKE_HYLIA_9_1); // Shadow Temple - gEntranceTable[ENTR_GRAVEYARD_SHADOW_TEMPLE_BLUE_WARP] = gEntranceTable[ENTR_GRAVEYARD_WARP_PAD]; - gEntranceTable[ENTR_GRAVEYARD_8_1] = gEntranceTable[ENTR_GRAVEYARD_7_1]; + EntranceDB_Copy(ENTR_GRAVEYARD_WARP_PAD, ENTR_GRAVEYARD_SHADOW_TEMPLE_BLUE_WARP); + EntranceDB_Copy(ENTR_GRAVEYARD_7_1, ENTR_GRAVEYARD_8_1); // Spirit Temple - gEntranceTable[ENTR_DESERT_COLOSSUS_SPIRIT_TEMPLE_BLUE_WARP] = gEntranceTable[ENTR_DESERT_COLOSSUS_WARP_PAD]; - gEntranceTable[ENTR_DESERT_COLOSSUS_8_1] = gEntranceTable[ENTR_DESERT_COLOSSUS_5_1]; - } -} - -void Entrance_CopyOriginalEntranceTable(void) { - if (!hasCopiedEntranceTable) { - memcpy(originalEntranceTable, gEntranceTable, sizeof(EntranceInfo) * ENTRANCE_TABLE_SIZE); - hasCopiedEntranceTable = 1; + EntranceDB_Copy(ENTR_DESERT_COLOSSUS_WARP_PAD, ENTR_DESERT_COLOSSUS_SPIRIT_TEMPLE_BLUE_WARP); + EntranceDB_Copy(ENTR_DESERT_COLOSSUS_5_1, ENTR_DESERT_COLOSSUS_8_1); } } void Entrance_ResetEntranceTable(void) { - if (hasCopiedEntranceTable && hasModifiedEntranceTable) { - memcpy(gEntranceTable, originalEntranceTable, sizeof(EntranceInfo) * ENTRANCE_TABLE_SIZE); - hasModifiedEntranceTable = 0; - } + EntranceDB_ResetVanillaEntrances(); } void Entrance_Init(void) { EntranceOverride* entranceOverrides = Randomizer_GetEntranceOverrides(); s32 index; - Entrance_CopyOriginalEntranceTable(); - // Skip Child Stealth if given by settings if (Randomizer_GetSettingValue(RSK_SKIP_CHILD_STEALTH)) { - gEntranceTable[ENTR_CASTLE_COURTYARD_GUARDS_DAY_0].scene = SCENE_CASTLE_COURTYARD_ZELDA; - gEntranceTable[ENTR_CASTLE_COURTYARD_GUARDS_DAY_0].spawn = 0; - gEntranceTable[ENTR_CASTLE_COURTYARD_GUARDS_DAY_0].field = - ENTRANCE_INFO_FIELD(false, false, TRANS_TYPE_FADE_WHITE, TRANS_TYPE_FADE_WHITE); + EntranceDB_Copy(ENTR_CASTLE_COURTYARD_ZELDA_0, ENTR_CASTLE_COURTYARD_GUARDS_DAY_0); } // Delete the title card and add a fade in for Hyrule Field from Ocarina of Time cutscene for (index = ENTR_HYRULE_FIELD_16; index <= ENTR_HYRULE_FIELD_16_3; ++index) { - gEntranceTable[index].field = ENTRANCE_INFO_FIELD(false, false, TRANS_TYPE_FADE_BLACK, TRANS_TYPE_INSTANT); + // Normally modifying a EntranceDBEntry is not safe since it can mess up the internal tables, + // but since we are just changing the cosmetic stuff, it is fine + EntranceDBEntry* entry = EntranceDB_Retrieve(index); + entry->continueBgm = false; + entry->displayTitleCard = false; + entry->endTransition = TRANS_TYPE_FADE_BLACK; + entry->startTransition = TRANS_TYPE_INSTANT; } Entrance_SeparateOGCFairyFountainExit(); @@ -251,9 +241,7 @@ void Entrance_Init(void) { s16 override = indicesToSilenceBackgroundMusic[j]; for (s16 i = 0; i < 4; i++) { - // Zero out the bit in the field which tells the game to keep playing - // background music for all four scene setups at each index - gEntranceTable[override + i].field &= ~ENTRANCE_INFO_CONTINUE_BGM_FLAG; + EntranceDB_Retrieve(override + i)->continueBgm = false; } } } @@ -316,8 +304,8 @@ u32 Entrance_SceneAndSpawnAre(u8 scene, u8 spawn) { } } - EntranceInfo currentEntrance = gEntranceTable[entranceIndex]; - return currentEntrance.scene == scene && currentEntrance.spawn == spawn; + EntranceDBEntry* entry = EntranceDB_Retrieve(entranceIndex); + return entry->sceneId == scene && entry->spawn == spawn; } // Properly respawn the player after a game over, accounting for dungeon entrance randomizer diff --git a/soh/soh/Enhancements/timesaver_hook_handlers.cpp b/soh/soh/Enhancements/timesaver_hook_handlers.cpp index dd8185c1d..278e1f68a 100644 --- a/soh/soh/Enhancements/timesaver_hook_handlers.cpp +++ b/soh/soh/Enhancements/timesaver_hook_handlers.cpp @@ -1,5 +1,6 @@ #include #include "soh/OTRGlobals.h" +#include "soh/SceneDB.h" #include "soh/Enhancements/randomizer/randomizerTypes.h" #include "soh/Enhancements/game-interactor/GameInteractor.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" @@ -180,7 +181,8 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li // LACS u8 meetsLACSRequirements = LINK_IS_ADULT && - (gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_TEMPLE_OF_TIME) && + (EntranceDB::Instance->RetrieveEntry(gSaveContext.entranceIndex).entry.sceneId == + SCENE_TEMPLE_OF_TIME) && CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) && CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW) && !Flags_GetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS); if (GameInteractor_Should(VB_BE_ELIGIBLE_FOR_LIGHT_ARROWS, meetsLACSRequirements)) { diff --git a/soh/soh/Enhancements/tts/tts.cpp b/soh/soh/Enhancements/tts/tts.cpp index 978e5ca24..ca7e99141 100644 --- a/soh/soh/Enhancements/tts/tts.cpp +++ b/soh/soh/Enhancements/tts/tts.cpp @@ -9,13 +9,13 @@ #include #include "soh/OTRGlobals.h" +#include "soh/SceneDB.h" #include "message_data_static.h" #include "overlays/gamestates/ovl_file_choose/file_choose.h" #include "soh/Enhancements/boss-rush/BossRush.h" #include "soh/resource/type/SohResourceType.h" extern "C" { -extern MapData* gMapData; extern SaveContext gSaveContext; extern PlayState* gPlayState; } @@ -206,6 +206,7 @@ void RegisterOnKaleidoscopeUpdateHook() { PauseContext* pauseCtx = &gPlayState->pauseCtx; Input* input = &gPlayState->state.input[0]; + SceneDB::Entry& scene = SceneDB::Instance->RetrieveEntry(gSaveContext.mapIndex); // Save game prompt if (pauseCtx->state == 7) { @@ -454,8 +455,7 @@ void RegisterOnKaleidoscopeUpdateHook() { // Cursor is on a dungeon floor position if (cursorPoint >= 3 && cursorPoint < 11) { - int floorID = - gMapData->floorID[gPlayState->interfaceCtx.unk_25A][pauseCtx->dungeonMapSlot - 3]; + int floorID = scene.entry.dungeonData.floors[pauseCtx->dungeonMapSlot - 3].id; // Normalize so F1 == 0, and negative numbers are basement levels int normalizedFloor = (floorID * -1) + 8; if (normalizedFloor >= 0) { diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 9ac03b48e..075c26650 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -74,6 +74,7 @@ #include "soh/SohGui/ImGuiUtils.h" #include "ActorDB.h" #include "SaveManager.h" +#include "SceneDB.h" #ifdef ENABLE_REMOTE_CONTROL #include "soh/Network/CrowdControl/CrowdControl.h" @@ -1228,6 +1229,8 @@ extern "C" void InitOTR() { OTRGlobals::Instance->gRandoContext->AddExcludedOptions(); AudioCollection::Instance = new AudioCollection(); ActorDB::Instance = new ActorDB(); + SceneDB::Instance = new SceneDB(); + EntranceDB::Instance = new EntranceDB(); #ifdef __APPLE__ SpeechSynthesizer::Instance = new DarwinSpeechSynthesizer(); SpeechSynthesizer::Instance->Init(); diff --git a/soh/soh/SaveManager.cpp b/soh/soh/SaveManager.cpp index 0b0421fbe..ccea81286 100644 --- a/soh/soh/SaveManager.cpp +++ b/soh/soh/SaveManager.cpp @@ -16,6 +16,7 @@ #include "macros.h" #include #include +#include "soh/SceneDB.h" #include "soh/SohGui/SohGui.hpp" #define NOGDI // avoid various windows defines that conflict with things in z64.h @@ -24,6 +25,7 @@ #include #include #include +#include #include extern "C" SaveContext gSaveContext; @@ -117,7 +119,8 @@ SaveManager::SaveManager() { AddLoadFunction("base", 2, LoadBaseVersion2); AddLoadFunction("base", 3, LoadBaseVersion3); AddLoadFunction("base", 4, LoadBaseVersion4); - AddSaveFunction("base", 4, SaveBase, true, SECTION_PARENT_NONE); + AddLoadFunction("base", 5, LoadBaseVersion5); + AddSaveFunction("base", 5, SaveBase, true, SECTION_PARENT_NONE); AddLoadFunction("randomizer", 1, LoadRandomizerVersion1); AddLoadFunction("randomizer", 2, LoadRandomizerVersion2); @@ -736,6 +739,7 @@ void SaveManager::InitFile(bool isDebug) { } void SaveManager::InitFileImpl(bool isDebug) { + AllocateSceneData(); if (isDebug) { InitFileDebug(); } else { @@ -809,23 +813,11 @@ void SaveManager::InitFileNormal() { gSaveContext.inventory.equipment = 0x1100; gSaveContext.inventory.upgrades = 0; gSaveContext.inventory.questItems = 0; - for (int dungeon = 0; dungeon < ARRAY_COUNT(gSaveContext.inventory.dungeonItems); dungeon++) { - gSaveContext.inventory.dungeonItems[dungeon] = 0; - } - for (int dungeon = 0; dungeon < ARRAY_COUNT(gSaveContext.inventory.dungeonKeys); dungeon++) { - gSaveContext.inventory.dungeonKeys[dungeon] = 0xFF; - } + std::fill_n(gSaveContext.inventory.dungeonItems, SceneDB::Instance->GetNumEntries(), 0); + std::fill_n(gSaveContext.inventory.dungeonKeys, SceneDB::Instance->GetNumEntries(), -1); gSaveContext.inventory.defenseHearts = 0; gSaveContext.inventory.gsTokens = 0; - for (int scene = 0; scene < ARRAY_COUNT(gSaveContext.sceneFlags); scene++) { - gSaveContext.sceneFlags[scene].chest = 0; - gSaveContext.sceneFlags[scene].swch = 0; - gSaveContext.sceneFlags[scene].clear = 0; - gSaveContext.sceneFlags[scene].collect = 0; - gSaveContext.sceneFlags[scene].unk = 0; - gSaveContext.sceneFlags[scene].rooms = 0; - gSaveContext.sceneFlags[scene].floors = 0; - } + std::fill_n(gSaveContext.sceneFlags, SceneDB::Instance->GetNumEntries(), SavedSceneFlags{ 0, 0, 0, 0, 0, 0, 0 }); gSaveContext.fw.pos.x = 0; gSaveContext.fw.pos.y = 0; gSaveContext.fw.pos.z = 0; @@ -996,13 +988,12 @@ void SaveManager::InitFileDebug() { gSaveContext.inventory.equipment = 0x7777; gSaveContext.inventory.upgrades = 0x125249; gSaveContext.inventory.questItems = 0x1E3FFFF; - static std::array sDungeonItems = { 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - for (int dungeon = 0; dungeon < ARRAY_COUNT(gSaveContext.inventory.dungeonItems); dungeon++) { - gSaveContext.inventory.dungeonItems[dungeon] = sDungeonItems[dungeon]; - } - for (int dungeon = 0; dungeon < ARRAY_COUNT(gSaveContext.inventory.dungeonKeys); dungeon++) { - gSaveContext.inventory.dungeonKeys[dungeon] = 8; + std::fill_n(gSaveContext.inventory.dungeonItems, SceneDB::Instance->GetNumEntries(), 0); + for (int dungeon = 0; dungeon <= SCENE_ICE_CAVERN; dungeon++) { + gSaveContext.inventory.dungeonItems[dungeon] = 0b111; } + std::fill_n(gSaveContext.inventory.dungeonKeys, SceneDB::Instance->GetNumEntries(), 8); + gSaveContext.inventory.defenseHearts = 0; gSaveContext.inventory.gsTokens = 0; @@ -1117,13 +1108,8 @@ void SaveManager::InitFileMaxed() { gSaveContext.inventory.equipment = 0x7777; gSaveContext.inventory.upgrades = 3597531; gSaveContext.inventory.questItems = 33554431; - static std::array sDungeonItems = { 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 }; - for (int dungeon = 0; dungeon < ARRAY_COUNT(gSaveContext.inventory.dungeonItems); dungeon++) { - gSaveContext.inventory.dungeonItems[dungeon] = sDungeonItems[dungeon]; - } - for (int dungeon = 0; dungeon < ARRAY_COUNT(gSaveContext.inventory.dungeonKeys); dungeon++) { - gSaveContext.inventory.dungeonKeys[dungeon] = 9; - } + std::fill_n(gSaveContext.inventory.dungeonItems, SceneDB::Instance->GetNumEntries(), 0b111); + std::fill_n(gSaveContext.inventory.dungeonKeys, SceneDB::Instance->GetNumEntries(), 9); gSaveContext.inventory.defenseHearts = 20; gSaveContext.inventory.gsTokens = 100; @@ -1192,6 +1178,22 @@ void SaveManager::InitFileMaxed() { gSaveContext.sceneFlags[5].swch = 0x40000000; } +void SaveManager::AllocateSceneData() { + delete[] gSaveContext.inventory.dungeonItems; + delete[] gSaveContext.inventory.dungeonKeys; + delete[] gSaveContext.sceneFlags; + + size_t numScenes = SceneDB::Instance->GetNumEntries(); + + gSaveContext.inventory.dungeonItems = new u8[numScenes]; + gSaveContext.inventory.dungeonKeys = new s8[numScenes]; + gSaveContext.sceneFlags = new SavedSceneFlags[numScenes]; + + std::fill_n(gSaveContext.inventory.dungeonItems, numScenes, 0); + std::fill_n(gSaveContext.inventory.dungeonKeys, numScenes, -1); + std::fill_n(gSaveContext.sceneFlags, numScenes, SavedSceneFlags{ 0, 0, 0, 0, 0, 0, 0 }); +} + #if defined(__WIIU__) || defined(__SWITCH__) // std::filesystem::copy_file doesn't work properly with the Wii U's toolchain atm int copy_file(const char* src, const char* dst) { @@ -1568,16 +1570,16 @@ void SaveManager::LoadBaseVersion1() { SaveManager::Instance->LoadData("equipment", gSaveContext.inventory.equipment); SaveManager::Instance->LoadData("upgrades", gSaveContext.inventory.upgrades); SaveManager::Instance->LoadData("questItems", gSaveContext.inventory.questItems); - SaveManager::Instance->LoadArray( - "dungeonItems", ARRAY_COUNT(gSaveContext.inventory.dungeonItems), - [](size_t i) { SaveManager::Instance->LoadData("", gSaveContext.inventory.dungeonItems[i]); }); - SaveManager::Instance->LoadArray("dungeonKeys", ARRAY_COUNT(gSaveContext.inventory.dungeonKeys), [](size_t i) { + SaveManager::Instance->LoadArray("dungeonItems", 20, [](size_t i) { + SaveManager::Instance->LoadData("", gSaveContext.inventory.dungeonItems[i]); + }); + SaveManager::Instance->LoadArray("dungeonKeys", 19, [](size_t i) { SaveManager::Instance->LoadData("", gSaveContext.inventory.dungeonKeys[i]); }); SaveManager::Instance->LoadData("defenseHearts", gSaveContext.inventory.defenseHearts); SaveManager::Instance->LoadData("gsTokens", gSaveContext.inventory.gsTokens); }); - SaveManager::Instance->LoadArray("sceneFlags", ARRAY_COUNT(gSaveContext.sceneFlags), [](size_t i) { + SaveManager::Instance->LoadArray("sceneFlags", SCENE_ID_MAX, [](size_t i) { SaveManager::Instance->LoadStruct("", [&i]() { SaveManager::Instance->LoadData("chest", gSaveContext.sceneFlags[i].chest); SaveManager::Instance->LoadData("swch", gSaveContext.sceneFlags[i].swch); @@ -1712,10 +1714,10 @@ void SaveManager::LoadBaseVersion2() { SaveManager::Instance->LoadData("equipment", gSaveContext.inventory.equipment); SaveManager::Instance->LoadData("upgrades", gSaveContext.inventory.upgrades); SaveManager::Instance->LoadData("questItems", gSaveContext.inventory.questItems); - SaveManager::Instance->LoadArray( - "dungeonItems", ARRAY_COUNT(gSaveContext.inventory.dungeonItems), - [](size_t i) { SaveManager::Instance->LoadData("", gSaveContext.inventory.dungeonItems[i]); }); - SaveManager::Instance->LoadArray("dungeonKeys", ARRAY_COUNT(gSaveContext.inventory.dungeonKeys), [](size_t i) { + SaveManager::Instance->LoadArray("dungeonItems", 20, [](size_t i) { + SaveManager::Instance->LoadData("", gSaveContext.inventory.dungeonItems[i]); + }); + SaveManager::Instance->LoadArray("dungeonKeys", 19, [](size_t i) { SaveManager::Instance->LoadData("", gSaveContext.inventory.dungeonKeys[i]); }); SaveManager::Instance->LoadData("defenseHearts", gSaveContext.inventory.defenseHearts); @@ -1744,7 +1746,7 @@ void SaveManager::LoadBaseVersion2() { "entrancesDiscovered", ARRAY_COUNT(gSaveContext.ship.stats.entrancesDiscovered), [](size_t i) { SaveManager::Instance->LoadData("", gSaveContext.ship.stats.entrancesDiscovered[i]); }); }); - SaveManager::Instance->LoadArray("sceneFlags", ARRAY_COUNT(gSaveContext.sceneFlags), [](size_t i) { + SaveManager::Instance->LoadArray("sceneFlags", SCENE_ID_MAX, [](size_t i) { SaveManager::Instance->LoadStruct("", [&i]() { SaveManager::Instance->LoadData("chest", gSaveContext.sceneFlags[i].chest); SaveManager::Instance->LoadData("swch", gSaveContext.sceneFlags[i].swch); @@ -1928,10 +1930,10 @@ void SaveManager::LoadBaseVersion3() { SaveManager::Instance->LoadData("equipment", gSaveContext.inventory.equipment); SaveManager::Instance->LoadData("upgrades", gSaveContext.inventory.upgrades); SaveManager::Instance->LoadData("questItems", gSaveContext.inventory.questItems); - SaveManager::Instance->LoadArray( - "dungeonItems", ARRAY_COUNT(gSaveContext.inventory.dungeonItems), - [](size_t i) { SaveManager::Instance->LoadData("", gSaveContext.inventory.dungeonItems[i]); }); - SaveManager::Instance->LoadArray("dungeonKeys", ARRAY_COUNT(gSaveContext.inventory.dungeonKeys), [](size_t i) { + SaveManager::Instance->LoadArray("dungeonItems", 20, [](size_t i) { + SaveManager::Instance->LoadData("", gSaveContext.inventory.dungeonItems[i]); + }); + SaveManager::Instance->LoadArray("dungeonKeys", 19, [](size_t i) { SaveManager::Instance->LoadData("", gSaveContext.inventory.dungeonKeys[i]); }); SaveManager::Instance->LoadData("defenseHearts", gSaveContext.inventory.defenseHearts); @@ -1977,7 +1979,7 @@ void SaveManager::LoadBaseVersion3() { "entrancesDiscovered", ARRAY_COUNT(gSaveContext.ship.stats.entrancesDiscovered), [](size_t i) { SaveManager::Instance->LoadData("", gSaveContext.ship.stats.entrancesDiscovered[i]); }); }); - SaveManager::Instance->LoadArray("sceneFlags", ARRAY_COUNT(gSaveContext.sceneFlags), [](size_t i) { + SaveManager::Instance->LoadArray("sceneFlags", SCENE_ID_MAX, [](size_t i) { SaveManager::Instance->LoadStruct("", [&i]() { SaveManager::Instance->LoadData("chest", gSaveContext.sceneFlags[i].chest); SaveManager::Instance->LoadData("swch", gSaveContext.sceneFlags[i].swch); @@ -2148,16 +2150,16 @@ void SaveManager::LoadBaseVersion4() { SaveManager::Instance->LoadData("equipment", gSaveContext.inventory.equipment); SaveManager::Instance->LoadData("upgrades", gSaveContext.inventory.upgrades); SaveManager::Instance->LoadData("questItems", gSaveContext.inventory.questItems); - SaveManager::Instance->LoadArray( - "dungeonItems", ARRAY_COUNT(gSaveContext.inventory.dungeonItems), - [](size_t i) { SaveManager::Instance->LoadData("", gSaveContext.inventory.dungeonItems[i]); }); - SaveManager::Instance->LoadArray("dungeonKeys", ARRAY_COUNT(gSaveContext.inventory.dungeonKeys), [](size_t i) { + SaveManager::Instance->LoadArray("dungeonItems", 20, [](size_t i) { + SaveManager::Instance->LoadData("", gSaveContext.inventory.dungeonItems[i]); + }); + SaveManager::Instance->LoadArray("dungeonKeys", 19, [](size_t i) { SaveManager::Instance->LoadData("", gSaveContext.inventory.dungeonKeys[i]); }); SaveManager::Instance->LoadData("defenseHearts", gSaveContext.inventory.defenseHearts); SaveManager::Instance->LoadData("gsTokens", gSaveContext.inventory.gsTokens); }); - SaveManager::Instance->LoadArray("sceneFlags", ARRAY_COUNT(gSaveContext.sceneFlags), [](size_t i) { + SaveManager::Instance->LoadArray("sceneFlags", SCENE_ID_MAX, [](size_t i) { SaveManager::Instance->LoadStruct("", [&i]() { SaveManager::Instance->LoadData("chest", gSaveContext.sceneFlags[i].chest); SaveManager::Instance->LoadData("swch", gSaveContext.sceneFlags[i].swch); @@ -2255,6 +2257,187 @@ void SaveManager::LoadBaseVersion4() { SaveManager::Instance->LoadData("maskMemory", gSaveContext.ship.maskMemory); } +void SaveManager::LoadBaseVersion5() { + SaveManager::Instance->LoadData("entranceIndex", gSaveContext.entranceIndex); + SaveManager::Instance->LoadData("linkAge", gSaveContext.linkAge); + SaveManager::Instance->LoadData("cutsceneIndex", gSaveContext.cutsceneIndex); + SaveManager::Instance->LoadData("dayTime", gSaveContext.dayTime); + SaveManager::Instance->LoadData("nightFlag", gSaveContext.nightFlag); + SaveManager::Instance->LoadData("totalDays", gSaveContext.totalDays); + SaveManager::Instance->LoadData("bgsDayCount", gSaveContext.bgsDayCount); + SaveManager::Instance->LoadData("deaths", gSaveContext.deaths); + SaveManager::Instance->LoadArray("playerName", ARRAY_COUNT(gSaveContext.playerName), + [](size_t i) { SaveManager::Instance->LoadData("", gSaveContext.playerName[i]); }); + int isRando = 0; + SaveManager::Instance->LoadData("n64ddFlag", isRando); + if (isRando) { + gSaveContext.ship.quest.id = QUEST_RANDOMIZER; + } + SaveManager::Instance->LoadData("healthCapacity", gSaveContext.healthCapacity); + SaveManager::Instance->LoadData("health", gSaveContext.health); + SaveManager::Instance->LoadData("magicLevel", gSaveContext.magicLevel); + SaveManager::Instance->LoadData("magic", gSaveContext.magic); + SaveManager::Instance->LoadData("rupees", gSaveContext.rupees); + SaveManager::Instance->LoadData("swordHealth", gSaveContext.swordHealth); + SaveManager::Instance->LoadData("naviTimer", gSaveContext.naviTimer); + SaveManager::Instance->LoadData("isMagicAcquired", gSaveContext.isMagicAcquired); + SaveManager::Instance->LoadData("isDoubleMagicAcquired", gSaveContext.isDoubleMagicAcquired); + SaveManager::Instance->LoadData("isDoubleDefenseAcquired", gSaveContext.isDoubleDefenseAcquired); + SaveManager::Instance->LoadData("bgsFlag", gSaveContext.bgsFlag); + SaveManager::Instance->LoadData("ocarinaGameRoundNum", gSaveContext.ocarinaGameRoundNum); + SaveManager::Instance->LoadStruct("childEquips", []() { + SaveManager::Instance->LoadArray( + "buttonItems", ARRAY_COUNT(gSaveContext.childEquips.buttonItems), [](size_t i) { + SaveManager::Instance->LoadData("", gSaveContext.childEquips.buttonItems[i], + static_cast(ITEM_NONE)); + }); + SaveManager::Instance->LoadArray( + "cButtonSlots", ARRAY_COUNT(gSaveContext.childEquips.cButtonSlots), [](size_t i) { + SaveManager::Instance->LoadData("", gSaveContext.childEquips.cButtonSlots[i], + static_cast(SLOT_NONE)); + }); + SaveManager::Instance->LoadData("equipment", gSaveContext.childEquips.equipment); + }); + SaveManager::Instance->LoadStruct("adultEquips", []() { + SaveManager::Instance->LoadArray( + "buttonItems", ARRAY_COUNT(gSaveContext.adultEquips.buttonItems), [](size_t i) { + SaveManager::Instance->LoadData("", gSaveContext.adultEquips.buttonItems[i], + static_cast(ITEM_NONE)); + }); + SaveManager::Instance->LoadArray( + "cButtonSlots", ARRAY_COUNT(gSaveContext.adultEquips.cButtonSlots), [](size_t i) { + SaveManager::Instance->LoadData("", gSaveContext.adultEquips.cButtonSlots[i], + static_cast(SLOT_NONE)); + }); + SaveManager::Instance->LoadData("equipment", gSaveContext.adultEquips.equipment); + }); + SaveManager::Instance->LoadData("unk_54", gSaveContext.unk_54); + SaveManager::Instance->LoadData("savedSceneNum", gSaveContext.savedSceneNum); + SaveManager::Instance->LoadStruct("equips", []() { + SaveManager::Instance->LoadArray("buttonItems", ARRAY_COUNT(gSaveContext.equips.buttonItems), [](size_t i) { + SaveManager::Instance->LoadData("", gSaveContext.equips.buttonItems[i], static_cast(ITEM_NONE)); + }); + SaveManager::Instance->LoadArray("cButtonSlots", ARRAY_COUNT(gSaveContext.equips.cButtonSlots), [](size_t i) { + SaveManager::Instance->LoadData("", gSaveContext.equips.cButtonSlots[i], static_cast(SLOT_NONE)); + }); + SaveManager::Instance->LoadData("equipment", gSaveContext.equips.equipment); + }); + SaveManager::Instance->LoadStruct("inventory", []() { + SaveManager::Instance->LoadArray("items", ARRAY_COUNT(gSaveContext.inventory.items), [](size_t i) { + SaveManager::Instance->LoadData("", gSaveContext.inventory.items[i]); + }); + SaveManager::Instance->LoadArray("ammo", ARRAY_COUNT(gSaveContext.inventory.ammo), [](size_t i) { + SaveManager::Instance->LoadData("", gSaveContext.inventory.ammo[i]); + }); + SaveManager::Instance->LoadData("equipment", gSaveContext.inventory.equipment); + SaveManager::Instance->LoadData("upgrades", gSaveContext.inventory.upgrades); + SaveManager::Instance->LoadData("questItems", gSaveContext.inventory.questItems); + SaveManager::Instance->LoadData("defenseHearts", gSaveContext.inventory.defenseHearts); + SaveManager::Instance->LoadData("gsTokens", gSaveContext.inventory.gsTokens); + }); + SaveManager::Instance->LoadStruct("sceneData", []() { + for (size_t i = 0; i < SceneDB::Instance->GetNumEntries(); i++) { + const SceneDB::Entry& entry = SceneDB::Instance->RetrieveEntry(static_cast(i)); + SaveManager::Instance->LoadStruct(entry.name, [&i]() { + SaveManager::Instance->LoadData("chest", gSaveContext.sceneFlags[i].chest); + SaveManager::Instance->LoadData("swch", gSaveContext.sceneFlags[i].swch); + SaveManager::Instance->LoadData("clear", gSaveContext.sceneFlags[i].clear); + SaveManager::Instance->LoadData("collect", gSaveContext.sceneFlags[i].collect); + SaveManager::Instance->LoadData("unk", gSaveContext.sceneFlags[i].unk); + SaveManager::Instance->LoadData("rooms", gSaveContext.sceneFlags[i].rooms); + SaveManager::Instance->LoadData("floors", gSaveContext.sceneFlags[i].floors); + SaveManager::Instance->LoadData("dungeonKeys", gSaveContext.inventory.dungeonKeys[i]); + SaveManager::Instance->LoadData("dungeonItems", gSaveContext.inventory.dungeonItems[i]); + }); + } + }); + SaveManager::Instance->LoadStruct("fw", []() { + SaveManager::Instance->LoadStruct("pos", []() { + SaveManager::Instance->LoadData("x", gSaveContext.fw.pos.x); + SaveManager::Instance->LoadData("y", gSaveContext.fw.pos.y); + SaveManager::Instance->LoadData("z", gSaveContext.fw.pos.z); + }); + SaveManager::Instance->LoadData("yaw", gSaveContext.fw.yaw); + SaveManager::Instance->LoadData("playerParams", gSaveContext.fw.playerParams); + SaveManager::Instance->LoadData("entranceIndex", gSaveContext.fw.entranceIndex); + SaveManager::Instance->LoadData("roomIndex", gSaveContext.fw.roomIndex); + SaveManager::Instance->LoadData("set", gSaveContext.fw.set); + SaveManager::Instance->LoadData("tempSwchFlags", gSaveContext.fw.tempSwchFlags); + SaveManager::Instance->LoadData("tempCollectFlags", gSaveContext.fw.tempCollectFlags); + }); + SaveManager::Instance->LoadArray("gsFlags", ARRAY_COUNT(gSaveContext.gsFlags), + [](size_t i) { SaveManager::Instance->LoadData("", gSaveContext.gsFlags[i]); }); + SaveManager::Instance->LoadArray("highScores", ARRAY_COUNT(gSaveContext.highScores), + [](size_t i) { SaveManager::Instance->LoadData("", gSaveContext.highScores[i]); }); + SaveManager::Instance->LoadArray("eventChkInf", ARRAY_COUNT(gSaveContext.eventChkInf), [](size_t i) { + SaveManager::Instance->LoadData("", gSaveContext.eventChkInf[i]); + }); + SaveManager::Instance->LoadArray("itemGetInf", ARRAY_COUNT(gSaveContext.itemGetInf), + [](size_t i) { SaveManager::Instance->LoadData("", gSaveContext.itemGetInf[i]); }); + SaveManager::Instance->LoadArray("infTable", ARRAY_COUNT(gSaveContext.infTable), + [](size_t i) { SaveManager::Instance->LoadData("", gSaveContext.infTable[i]); }); + SaveManager::Instance->LoadData("worldMapAreaData", gSaveContext.worldMapAreaData); + SaveManager::Instance->LoadData("scarecrowLongSongSet", gSaveContext.scarecrowLongSongSet); + SaveManager::Instance->LoadArray("scarecrowLongSong", ARRAY_COUNT(gSaveContext.scarecrowLongSong), [](size_t i) { + SaveManager::Instance->LoadStruct("", [&i]() { + SaveManager::Instance->LoadData("noteIdx", gSaveContext.scarecrowLongSong[i].noteIdx); + SaveManager::Instance->LoadData("unk_01", gSaveContext.scarecrowLongSong[i].unk_01); + SaveManager::Instance->LoadData("unk_02", gSaveContext.scarecrowLongSong[i].unk_02); + SaveManager::Instance->LoadData("volume", gSaveContext.scarecrowLongSong[i].volume); + SaveManager::Instance->LoadData("vibrato", gSaveContext.scarecrowLongSong[i].vibrato); + SaveManager::Instance->LoadData("tone", gSaveContext.scarecrowLongSong[i].tone); + SaveManager::Instance->LoadData("semitone", gSaveContext.scarecrowLongSong[i].semitone); + }); + }); + SaveManager::Instance->LoadData("scarecrowSpawnSongSet", gSaveContext.scarecrowSpawnSongSet); + SaveManager::Instance->LoadArray("scarecrowSpawnSong", ARRAY_COUNT(gSaveContext.scarecrowSpawnSong), [](size_t i) { + SaveManager::Instance->LoadStruct("", [&i]() { + SaveManager::Instance->LoadData("noteIdx", gSaveContext.scarecrowSpawnSong[i].noteIdx); + SaveManager::Instance->LoadData("unk_01", gSaveContext.scarecrowSpawnSong[i].unk_01); + SaveManager::Instance->LoadData("unk_02", gSaveContext.scarecrowSpawnSong[i].unk_02); + SaveManager::Instance->LoadData("volume", gSaveContext.scarecrowSpawnSong[i].volume); + SaveManager::Instance->LoadData("vibrato", gSaveContext.scarecrowSpawnSong[i].vibrato); + SaveManager::Instance->LoadData("tone", gSaveContext.scarecrowSpawnSong[i].tone); + SaveManager::Instance->LoadData("semitone", gSaveContext.scarecrowSpawnSong[i].semitone); + }); + }); + SaveManager::Instance->LoadStruct("horseData", []() { + SaveManager::Instance->LoadData("scene", gSaveContext.horseData.scene); + SaveManager::Instance->LoadStruct("pos", []() { + SaveManager::Instance->LoadData("x", gSaveContext.horseData.pos.x); + SaveManager::Instance->LoadData("y", gSaveContext.horseData.pos.y); + SaveManager::Instance->LoadData("z", gSaveContext.horseData.pos.z); + }); + SaveManager::Instance->LoadData("angle", gSaveContext.horseData.angle); + }); + + SaveManager::Instance->LoadArray("randomizerInf", ARRAY_COUNT(gSaveContext.ship.randomizerInf), [](size_t i) { + SaveManager::Instance->LoadData("", gSaveContext.ship.randomizerInf[i]); + }); + int isMQ = 0; + SaveManager::Instance->LoadData("isMasterQuest", isMQ); + if (isMQ) { + gSaveContext.ship.quest.id = QUEST_MASTER; + } + SaveManager::Instance->LoadStruct("backupFW", []() { + SaveManager::Instance->LoadStruct("pos", []() { + SaveManager::Instance->LoadData("x", gSaveContext.ship.backupFW.pos.x); + SaveManager::Instance->LoadData("y", gSaveContext.ship.backupFW.pos.y); + SaveManager::Instance->LoadData("z", gSaveContext.ship.backupFW.pos.z); + }); + SaveManager::Instance->LoadData("yaw", gSaveContext.ship.backupFW.yaw); + SaveManager::Instance->LoadData("playerParams", gSaveContext.ship.backupFW.playerParams); + SaveManager::Instance->LoadData("entranceIndex", gSaveContext.ship.backupFW.entranceIndex); + SaveManager::Instance->LoadData("roomIndex", gSaveContext.ship.backupFW.roomIndex); + SaveManager::Instance->LoadData("set", gSaveContext.ship.backupFW.set); + SaveManager::Instance->LoadData("tempSwchFlags", gSaveContext.ship.backupFW.tempSwchFlags); + SaveManager::Instance->LoadData("tempCollectFlags", gSaveContext.ship.backupFW.tempCollectFlags); + }); + SaveManager::Instance->LoadData("dogParams", gSaveContext.dogParams); + SaveManager::Instance->LoadData("filenameLanguage", gSaveContext.ship.filenameLanguage); + SaveManager::Instance->LoadData("maskMemory", gSaveContext.ship.maskMemory); +} + void SaveManager::SaveBase(SaveContext* saveContext, int sectionID, bool fullSave) { SaveManager::Instance->SaveData("entranceIndex", saveContext->entranceIndex); SaveManager::Instance->SaveData("linkAge", saveContext->linkAge); @@ -2319,25 +2502,24 @@ void SaveManager::SaveBase(SaveContext* saveContext, int sectionID, bool fullSav SaveManager::Instance->SaveData("equipment", saveContext->inventory.equipment); SaveManager::Instance->SaveData("upgrades", saveContext->inventory.upgrades); SaveManager::Instance->SaveData("questItems", saveContext->inventory.questItems); - SaveManager::Instance->SaveArray( - "dungeonItems", ARRAY_COUNT(saveContext->inventory.dungeonItems), - [&](size_t i) { SaveManager::Instance->SaveData("", saveContext->inventory.dungeonItems[i]); }); - SaveManager::Instance->SaveArray("dungeonKeys", ARRAY_COUNT(saveContext->inventory.dungeonKeys), [&](size_t i) { - SaveManager::Instance->SaveData("", saveContext->inventory.dungeonKeys[i]); - }); SaveManager::Instance->SaveData("defenseHearts", saveContext->inventory.defenseHearts); SaveManager::Instance->SaveData("gsTokens", saveContext->inventory.gsTokens); }); - SaveManager::Instance->SaveArray("sceneFlags", ARRAY_COUNT(saveContext->sceneFlags), [&](size_t i) { - SaveManager::Instance->SaveStruct("", [&]() { - SaveManager::Instance->SaveData("chest", saveContext->sceneFlags[i].chest); - SaveManager::Instance->SaveData("swch", saveContext->sceneFlags[i].swch); - SaveManager::Instance->SaveData("clear", saveContext->sceneFlags[i].clear); - SaveManager::Instance->SaveData("collect", saveContext->sceneFlags[i].collect); - SaveManager::Instance->SaveData("unk", saveContext->sceneFlags[i].unk); - SaveManager::Instance->SaveData("rooms", saveContext->sceneFlags[i].rooms); - SaveManager::Instance->SaveData("floors", saveContext->sceneFlags[i].floors); - }); + SaveManager::Instance->SaveStruct("sceneData", [&]() { + for (size_t i = 0; i < SceneDB::Instance->GetNumEntries(); i++) { + const SceneDB::Entry& entry = SceneDB::Instance->RetrieveEntry(static_cast(i)); + SaveManager::Instance->SaveStruct(entry.name, [&]() { + SaveManager::Instance->SaveData("chest", saveContext->sceneFlags[i].chest); + SaveManager::Instance->SaveData("swch", saveContext->sceneFlags[i].swch); + SaveManager::Instance->SaveData("clear", saveContext->sceneFlags[i].clear); + SaveManager::Instance->SaveData("collect", saveContext->sceneFlags[i].collect); + SaveManager::Instance->SaveData("unk", saveContext->sceneFlags[i].unk); + SaveManager::Instance->SaveData("rooms", saveContext->sceneFlags[i].rooms); + SaveManager::Instance->SaveData("floors", saveContext->sceneFlags[i].floors); + SaveManager::Instance->SaveData("dungeonKeys", saveContext->inventory.dungeonKeys[i]); + SaveManager::Instance->SaveData("dungeonItems", saveContext->inventory.dungeonItems[i]); + }); + } }); SaveManager::Instance->SaveStruct("fw", [&]() { SaveManager::Instance->SaveStruct("pos", [&]() { @@ -2800,7 +2982,7 @@ void CopyV0Save(SaveContext_v0& src, SaveContext& dst) { } dst.inventory.defenseHearts = src.inventory.defenseHearts; dst.inventory.gsTokens = src.inventory.gsTokens; - for (size_t i = 0; i < ARRAY_COUNT(src.sceneFlags); i++) { + for (size_t i = 0; i < SCENE_ID_MAX; i++) { dst.sceneFlags[i].chest = src.sceneFlags[i].chest; dst.sceneFlags[i].swch = src.sceneFlags[i].swch; dst.sceneFlags[i].clear = src.sceneFlags[i].clear; diff --git a/soh/soh/SaveManager.h b/soh/soh/SaveManager.h index 3c4a31243..14bb11561 100644 --- a/soh/soh/SaveManager.h +++ b/soh/soh/SaveManager.h @@ -166,6 +166,8 @@ class SaveManager { static void InitFileDebug(); static void InitFileMaxed(); + static void AllocateSceneData(); + static void LoadRandomizerVersion1(); static void LoadRandomizerVersion2(); static void LoadRandomizerVersion3(); @@ -177,6 +179,7 @@ class SaveManager { static void LoadBaseVersion2(); static void LoadBaseVersion3(); static void LoadBaseVersion4(); + static void LoadBaseVersion5(); static void SaveBase(SaveContext* saveContext, int sectionID, bool fullSave); std::vector initFuncs; diff --git a/soh/soh/SceneDB.cpp b/soh/soh/SceneDB.cpp new file mode 100644 index 000000000..4d44e34d5 --- /dev/null +++ b/soh/soh/SceneDB.cpp @@ -0,0 +1,1190 @@ +#include "SceneDB.h" + +#include +#include +#include + +#include "variables.h" + +SceneDB* SceneDB::Instance; +EntranceDB* EntranceDB::Instance; + +extern const std::vector sceneDBInit; + +// We need a different struct than EntranceDB::Init (scene is a int not a string) because tables/entrance_table.h has +// the scene as an enum, which we do not have a compile-time way to convert to a string +struct EntranceTableInit { + std::string name; + std::string desc; + s32 scene; + s32 spawn; + bool continueBgm; + bool displayTitleCard; + u8 endTransition; + u8 startTransition; +}; + +#define DEFINE_ENTRANCE(enumName, sceneId, spawn, continueBgm, displayTitleCard, endTransType, startTransType) \ + { #enumName, "", sceneId, spawn, continueBgm, displayTitleCard, endTransType, startTransType }, + +static const EntranceTableInit entranceDBInit[] = { +#include "tables/entrance_table.h" +}; + +#undef DEFINE_ENTRANCE + +SceneDB::SceneDB() { + db.reserve(SCENE_ID_MAX); // reserve size for all initial entries so we don't do it for each + for (const Init& init : sceneDBInit) { + AddEntry(init); + } + + SceneDB::Entry& entry = RetrieveEntry(SCENE_BOTTOM_OF_THE_WELL); + entry.entry.epona.allowed = true; + entry.SetEponaSpawnPos({ { -630, 0, 53 } }); +} + +// Adds an scene at the given index. The name must be unique. +SceneDB::Entry& SceneDB::AddEntry(const std::string& name, const std::string& desc, size_t index) { + assert(!nameTable.contains(name)); // TODO this should maybe throw instead. We'll need to think about error handling + // for mods that try to declare the same scene. + + if (db.size() < (index + 1)) { + db.resize(index + 1); + } + Entry& newEntry = db.at(index); + newEntry.entry.id = index; + + assert(!newEntry.entry.valid); + + nextFreeId = std::max(nextFreeId, index + 1); + + nameTable[name] = newEntry.entry.id; + newEntry.SetName(name); + newEntry.SetDesc(desc); + + newEntry.entry.valid = true; + + return newEntry; +} + +// Adds an scene with the new SceneDBInit struct. The id assigned to the scene is dynamic. Use the returned Entry or +// RetrieveId to get it. +SceneDB::Entry& SceneDB::AddEntry(const Init& init) { + Entry& entry = AddEntry(init.name, init.desc, nextFreeId); + + entry.SetTitleCard(init.titleCard); + + entry.entry.sceneDrawConfig = init.sceneDrawConfig; + entry.entry.restrictions.hGauge = init.restrictions.hGauge; + entry.entry.restrictions.bButton = init.restrictions.bButton; + entry.entry.restrictions.aButton = init.restrictions.aButton; + entry.entry.restrictions.bottles = init.restrictions.bottles; + entry.entry.restrictions.tradeItems = init.restrictions.tradeItems; + entry.entry.restrictions.hookshot = init.restrictions.hookshot; + entry.entry.restrictions.ocarina = init.restrictions.ocarina; + entry.entry.restrictions.warpSongs = init.restrictions.warpSongs; + entry.entry.restrictions.sunsSong = init.restrictions.sunsSong; + entry.entry.restrictions.farores = init.restrictions.farores; + entry.entry.restrictions.dinsNayrus = init.restrictions.dinsNayrus; + entry.entry.restrictions.all = init.restrictions.all; + entry.entry.epona.allowed = init.epona.allowed; + entry.entry.epona.startingPos = init.epona.startingPos; + entry.entry.epona.angle = init.epona.angle; + entry.SetEponaSpawnPos(init.epona.spawnPos); + + entry.entry.compassInfo.scaleX = init.compassInfo.scaleX; + entry.entry.compassInfo.scaleY = init.compassInfo.scaleY; + entry.entry.compassInfo.x = init.compassInfo.x; + entry.entry.compassInfo.y = init.compassInfo.y; + + if (init.bossData.mapScene != "") { + int id = RetrieveId(init.bossData.mapScene); + assert(id != -1); // TODO error of some kind for invalid mods + entry.entry.bossData.mapScene = id; + } else { + entry.entry.bossData.mapScene = -1; + } + entry.entry.dungeonData.bossFloor = init.dungeonData.bossFloor; + entry.SetDungeonPalettes(init.dungeonData.palettes); + entry.SetDungeonNameTextures(init.dungeonData.nameEngTexture, init.dungeonData.nameGerTexture, + init.dungeonData.nameFraTexture); + entry.SetDungeonFloors(init.dungeonData.floors); + entry.SetDungeonRooms(init.dungeonData.rooms); + entry.SetDungeonIntraRoomTransitions(init.dungeonData.intraRoomTransitions); + + entry.entry.worldData.minimapX = init.worldData.minimapX; + entry.entry.worldData.minimapY = init.worldData.minimapY; + entry.entry.worldData.minimapWidth = init.worldData.minimapWidth; + entry.entry.worldData.minimapHeight = init.worldData.minimapHeight; + entry.entry.worldData.iconX = init.worldData.iconX; + entry.entry.worldData.iconY = init.worldData.iconY; + entry.entry.worldData.entranceFlag = init.worldData.entranceFlag; + entry.SetWorldMinimapTexture(init.worldData.minimapTexture); + + return entry; +} + +// Get the SceneDB::Entry for the given scene id. +SceneDB::Entry& SceneDB::RetrieveEntry(const int id) { + static Entry invalid; + if ((id < 0) || (id >= db.size())) { + return invalid; + } + return db[id]; +} + +// Get the id for a given scene by name. +int SceneDB::RetrieveId(const std::string& name) { + auto entry = nameTable.find(name); + if (entry == nameTable.end()) { + return -1; + } + + return entry->second; +} + +// Get the number of scene entries +size_t SceneDB::GetNumEntries() { + return db.size(); +} + +SceneDB::Entry::Entry() { + entry.name = nullptr; + entry.desc = nullptr; + entry.valid = false; + entry.id = 0; + entry.titleCard = nullptr; + entry.sceneDrawConfig = SDC_DEFAULT; + entry.restrictions.hGauge = false; + entry.restrictions.bButton = false; + entry.restrictions.aButton = false; + entry.restrictions.bottles = false; + entry.restrictions.tradeItems = false; + entry.restrictions.hookshot = false; + entry.restrictions.ocarina = false; + entry.restrictions.warpSongs = false; + entry.restrictions.sunsSong = false; + entry.restrictions.farores = false; + entry.restrictions.dinsNayrus = false; + entry.restrictions.all = false; + entry.epona.allowed = false; + entry.epona.startingPos = { 0, 0, 0 }; + entry.epona.spawnPos = {}; + entry.epona.angle = 0; + entry.compassInfo.scaleX = 0; + entry.compassInfo.scaleY = 0; + entry.compassInfo.x = 0; + entry.compassInfo.y = 0; + entry.bossData.mapScene = -1; + entry.dungeonData.bossFloor = -1; + entry.dungeonData.palettes = nullptr; + entry.dungeonData.numPalettes = 0; + for (size_t i = 0; i < 8; i++) { + entry.dungeonData.floors[i].id = static_cast(0); + entry.dungeonData.floors[i].height = 0.0f; + entry.dungeonData.floors[i].rooms = nullptr; + entry.dungeonData.floors[i].numRooms = 0; + entry.dungeonData.floors[i].mapLeftTexture = nullptr; + entry.dungeonData.floors[i].mapRightTexture = nullptr; + } + entry.dungeonData.rooms = nullptr; + entry.dungeonData.numRooms = 0; + entry.dungeonData.intraRoomTransitions = nullptr; + entry.dungeonData.numIntraRoomTransitions = 0; + entry.worldData.minimapX = 0; + entry.worldData.minimapY = 0; + entry.worldData.minimapWidth = 0; + entry.worldData.minimapHeight = 0; + entry.worldData.iconX = 0; + entry.worldData.iconY = 0; + entry.worldData.entranceFlag = 0; + entry.worldData.minimapTexture = nullptr; +} + +SceneDB::Entry::Entry(const Entry& other) { + entry = other.entry; + SetName(other.name); + SetDesc(other.desc); + SetTitleCard(other.titleCard); + SetEponaSpawnPos(other.eponaSpawnPos); + SetDungeonPalettes(other.dungeonPalettes); + SetDungeonNameTextures(other.nameEngTexture, other.nameGerTexture, other.nameFraTexture); + SetDungeonFloors(other.dungeonFloors, other.dungeonFloorInfo); + SetDungeonRooms(other.dungeonRooms, other.dungeonRoomInfo); + SetDungeonIntraRoomTransitions(other.dungeonIntraRoomTransitions); + SetWorldMinimapTexture(other.worldMinimapTexture); +} + +SceneDB::Entry& SceneDB::Entry::operator=(const Entry& other) { + entry = other.entry; + SetName(other.name); + SetDesc(other.desc); + SetTitleCard(other.titleCard); + SetEponaSpawnPos(other.eponaSpawnPos); + SetDungeonPalettes(other.dungeonPalettes); + SetDungeonNameTextures(other.nameEngTexture, other.nameGerTexture, other.nameFraTexture); + SetDungeonFloors(other.dungeonFloors, other.dungeonFloorInfo); + SetDungeonRooms(other.dungeonRooms, other.dungeonRoomInfo); + SetDungeonIntraRoomTransitions(other.dungeonIntraRoomTransitions); + SetWorldMinimapTexture(other.worldMinimapTexture); + return *this; +} + +void SceneDB::Entry::SetName(const std::string& newName) { + name = newName; + entry.name = name.c_str(); +} + +void SceneDB::Entry::SetDesc(const std::string& newDesc) { + desc = newDesc; + entry.desc = desc.c_str(); +} + +void SceneDB::Entry::SetTitleCard(const std::string& newTitleCard) { + titleCard = newTitleCard; + entry.titleCard = titleCard.c_str(); +} + +void SceneDB::Entry::SetEponaSpawnPos(const std::vector& newSpawnPos) { + eponaSpawnPos = newSpawnPos; + entry.epona.spawnPos = eponaSpawnPos.data(); + entry.epona.numSpawns = eponaSpawnPos.size(); +} + +void SceneDB::Entry::SetDungeonPalettes(const std::vector& newDungeonPalettes) { + dungeonPalettes = newDungeonPalettes; + entry.dungeonData.palettes = dungeonPalettes.data(); + entry.dungeonData.numPalettes = dungeonPalettes.size(); +} + +void SceneDB::Entry::SetDungeonNameTextures(const std::string& newNameEngTexture, const std::string& newNameGerTexture, + const std::string& newNameFraTexture) { + nameEngTexture = newNameEngTexture; + nameGerTexture = newNameGerTexture; + nameFraTexture = newNameFraTexture; + entry.dungeonData.nameEngTexture = nameEngTexture.c_str(); + entry.dungeonData.nameGerTexture = nameGerTexture.c_str(); + entry.dungeonData.nameFraTexture = nameFraTexture.c_str(); +} + +void SceneDB::Entry::SetDungeonFloors(const std::vector& newDungeonFloors) { + assert(newDungeonFloors.size() == 8 || newDungeonFloors.size() == 0); + + dungeonFloors.clear(); + dungeonFloorInfo.clear(); + + dungeonFloors.reserve(newDungeonFloors.size()); + dungeonFloorInfo.reserve(newDungeonFloors.size()); + + for (size_t i = 0; i < newDungeonFloors.size(); i++) { + dungeonFloors.push_back(SceneDBFloor{ static_cast(newDungeonFloors[i].id), newDungeonFloors[i].height, + nullptr, 0, nullptr, nullptr, nullptr, 0, nullptr, 0 }); + dungeonFloorInfo.push_back(FloorInfo{ newDungeonFloors[i].palettes, newDungeonFloors[i].mapLeftTexture, + newDungeonFloors[i].mapRightTexture, newDungeonFloors[i].chestMarks, + newDungeonFloors[i].bossMarks }); + } + + for (size_t i = 0; i < dungeonFloors.size(); i++) { + dungeonFloors[i].rooms = dungeonFloorInfo[i].rooms.data(); + dungeonFloors[i].numRooms = dungeonFloorInfo[i].rooms.size(); + dungeonFloors[i].mapLeftTexture = dungeonFloorInfo[i].mapLeftTexture.c_str(); + dungeonFloors[i].mapRightTexture = dungeonFloorInfo[i].mapRightTexture.c_str(); + dungeonFloors[i].numChestMarks = dungeonFloorInfo[i].chestMarks.size(); + dungeonFloors[i].chestMarks = dungeonFloorInfo[i].chestMarks.data(); + dungeonFloors[i].numBossMarks = dungeonFloorInfo[i].bossMarks.size(); + dungeonFloors[i].bossMarks = dungeonFloorInfo[i].bossMarks.data(); + } + std::copy(dungeonFloors.begin(), dungeonFloors.end(), entry.dungeonData.floors); +} + +void SceneDB::Entry::SetDungeonFloors(const std::vector& newDungeonFloors, + const std::vector& newDungeonFloorInfo) { + assert(newDungeonFloors.size() == 8 || newDungeonFloors.size() == 0); + assert(newDungeonFloorInfo.size() == 8 || newDungeonFloorInfo.size() == 0); + assert(newDungeonFloors.size() == newDungeonFloorInfo.size()); + dungeonFloors = newDungeonFloors; + dungeonFloorInfo = newDungeonFloorInfo; + for (size_t i = 0; i < dungeonFloors.size(); i++) { + dungeonFloors[i].rooms = dungeonFloorInfo[i].rooms.data(); + dungeonFloors[i].numRooms = dungeonFloorInfo[i].rooms.size(); + dungeonFloors[i].mapLeftTexture = dungeonFloorInfo[i].mapLeftTexture.c_str(); + dungeonFloors[i].mapRightTexture = dungeonFloorInfo[i].mapRightTexture.c_str(); + dungeonFloors[i].numChestMarks = dungeonFloorInfo[i].chestMarks.size(); + dungeonFloors[i].chestMarks = dungeonFloorInfo[i].chestMarks.data(); + dungeonFloors[i].numBossMarks = dungeonFloorInfo[i].bossMarks.size(); + dungeonFloors[i].bossMarks = dungeonFloorInfo[i].bossMarks.data(); + } + std::copy(dungeonFloors.begin(), dungeonFloors.end(), entry.dungeonData.floors); +} + +void SceneDB::Entry::SetDungeonRooms(const std::vector& newDungeonRooms) { + dungeonRooms.clear(); + dungeonRoomInfo.clear(); + + dungeonRooms.reserve(newDungeonRooms.size()); + dungeonRoomInfo.reserve(newDungeonRooms.size()); + + for (size_t i = 0; i < newDungeonRooms.size(); i++) { + dungeonRooms.push_back(SceneDBRoom{ newDungeonRooms[i].compassOffsetX, newDungeonRooms[i].compassOffsetY, + nullptr, nullptr, 0, nullptr, 0 }); + dungeonRoomInfo.push_back( + RoomInfo{ newDungeonRooms[i].minimapTexture, newDungeonRooms[i].chestMarks, newDungeonRooms[i].bossMarks }); + } + + for (size_t i = 0; i < dungeonRooms.size(); i++) { + dungeonRooms[i].minimapTexture = dungeonRoomInfo[i].minimapTexture.c_str(); + dungeonRooms[i].chestMarks = dungeonRoomInfo[i].chestMarks.data(); + dungeonRooms[i].numChestMarks = dungeonRoomInfo[i].chestMarks.size(); + dungeonRooms[i].bossMarks = dungeonRoomInfo[i].bossMarks.data(); + dungeonRooms[i].numBossMarks = dungeonRoomInfo[i].bossMarks.size(); + } + entry.dungeonData.rooms = dungeonRooms.data(); + entry.dungeonData.numRooms = dungeonRooms.size(); +} + +void SceneDB::Entry::SetDungeonRooms(const std::vector& newDungeonRooms, + const std::vector& newDungeonRoomInfo) { + dungeonRooms = newDungeonRooms; + dungeonRoomInfo = newDungeonRoomInfo; + for (size_t i = 0; i < dungeonRooms.size(); i++) { + dungeonRooms[i].minimapTexture = dungeonRoomInfo[i].minimapTexture.c_str(); + dungeonRooms[i].chestMarks = dungeonRoomInfo[i].chestMarks.data(); + dungeonRooms[i].numChestMarks = dungeonRoomInfo[i].chestMarks.size(); + dungeonRooms[i].bossMarks = dungeonRoomInfo[i].bossMarks.data(); + dungeonRooms[i].numBossMarks = dungeonRoomInfo[i].bossMarks.size(); + } + entry.dungeonData.rooms = dungeonRooms.data(); + entry.dungeonData.numRooms = dungeonRooms.size(); +} + +void SceneDB::Entry::SetDungeonIntraRoomTransitions( + const std::vector& newDungeonIntraRoomTransitions) { + dungeonIntraRoomTransitions.clear(); + + dungeonIntraRoomTransitions.reserve(newDungeonIntraRoomTransitions.size()); + + for (size_t i = 0; i < newDungeonIntraRoomTransitions.size(); i++) { + dungeonIntraRoomTransitions.push_back(SceneDBIntraRoomTransition{ newDungeonIntraRoomTransitions[i].fromRoom, + newDungeonIntraRoomTransitions[i].toRoom, + newDungeonIntraRoomTransitions[i].toFloor }); + } + entry.dungeonData.intraRoomTransitions = dungeonIntraRoomTransitions.data(); + entry.dungeonData.numIntraRoomTransitions = dungeonIntraRoomTransitions.size(); +} + +void SceneDB::Entry::SetDungeonIntraRoomTransitions( + const std::vector& newDungeonIntraRoomTransitions) { + dungeonIntraRoomTransitions = newDungeonIntraRoomTransitions; + entry.dungeonData.intraRoomTransitions = dungeonIntraRoomTransitions.data(); + entry.dungeonData.numIntraRoomTransitions = dungeonIntraRoomTransitions.size(); +} + +void SceneDB::Entry::SetWorldMinimapTexture(const std::string& newWorldMinimapTexture) { + worldMinimapTexture = newWorldMinimapTexture; + entry.worldData.minimapTexture = worldMinimapTexture.empty() ? nullptr : worldMinimapTexture.c_str(); +} + +struct MqMapMarkInit { + struct Room { + std::vector chestMarks; + std::vector bossMarks; + }; + + std::vector rooms; +}; + +std::vector mqMapMarkInit = { + // Deku Tree + { + { { { { 3, 71, 50 } }, {} }, + { {}, {} }, + { { { 1, 64, 62 } }, {} }, + { { { 4, 76, 37 } }, {} }, + { {}, {} }, + { { { 0, 46, 50 }, { 5, 76, 52 } }, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, { { -1, 50, 23 } } }, + { { { 2, 46, 50 }, { 6, 58, 60 } }, {} }, + { {}, {} }, + { {}, {} } }, + }, + // Dodongo's Cavern + { { + { { { 0, 69, 14 }, { 4, 69, 30 } }, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { { { 5, 54, 54 } }, {} }, + { { { 2, 69, 54 } }, {} }, + { {}, { { -1, 37, 49 } } }, + { {}, {} }, + { { { 3, 59, 53 } }, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { { { 1, 68, 54 } }, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + } }, + // Jabu-Jabu's Belly + { { + { { { 3, 66, 50 }, { 5, 72, 47 } }, {} }, + { { { 7, 72, 54 } }, {} }, + { {}, {} }, + { { { 4, 64, 62 }, { 8, 79, 38 } }, {} }, + { {}, {} }, + { { { 10, 64, 45 } }, { { -1, 67, 32 } } }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { { { 9, 68, 45 } }, {} }, + { {}, {} }, + { {}, {} }, + { { { 1, 79, 33 }, { 6, 61, 41 } }, {} }, + { { { 0, 48, 57 }, { 2, 77, 55 } }, {} }, + // Jabu-Jabu's Belly minimap 16 + // SoH [General] - This entry corresponds to Big Octorok's room and is missing in the MQ game + // N64 hardware does an OoB read and lands on MQ Forest Temple room 0 + // To avoid UB with OoB for SoH, the correct entry is now added below + { {}, {} }, + } }, + // Forest Temple + { { + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { { { 0, 72, 57 } }, {} }, + { { { 1, 69, 39 }, { 9, 62, 65 } }, {} }, + { {}, {} }, + { { { 9, 71, 59 } }, {} }, + { {}, {} }, + { {}, {} }, + { { { 13, 80, 53 } }, {} }, + { { { 15, 49, 50 } }, {} }, + { {}, {} }, + { { { 6, 65, 53 } }, {} }, + { {}, {} }, + { { { 11, 39, 35 } }, { { -1, 53, 5 } } }, + { { { 2, 65, 54 } }, {} }, + { { { 14, 64, 31 } }, {} }, + { {}, {} }, + { {}, {} }, + { { { 3, 75, 53 } }, {} }, + { { { 12, 69, 52 } }, {} }, + { { { 5, 58, 27 } }, {} }, + { {}, {} }, + { {}, {} }, + } }, + // Fire Temple + { { + { {}, {} }, + { {}, {} }, + { { { 7, 53, 70 } }, { { -1, 40, 47 } } }, + { {}, {} }, + { { { 11, 57, 48 } }, {} }, + { { { 3, 67, 73 }, { 6, 58, 76 } }, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { { { 2, 78, 62 }, { 12, 77, 58 } }, {} }, + { {}, {} }, + { { { 4, 60, 54 } }, {} }, + { {}, {} }, + { {}, {} }, + { { { 1, 72, 68 } }, {} }, + { { { 8, 66, 57 } }, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { { { 5, 51, 61 } }, {} }, + { {}, {} }, + { {}, {} }, + } }, + // Water Temple + { { + { {}, {} }, + { {}, {} }, + { { { 6, 81, 68 } }, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { { { 5, 75, 55 } }, {} }, + { {}, {} }, + { {}, { { -1, 77, 40 } } }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { { { 1, 74, 61 } }, {} }, + { { { 2, 73, 65 } }, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { { { 0, 73, 63 } }, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + } }, + // Spirit Temple + { { + { { { 26, 27, 35 }, { 27, 36, 35 }, { 30, 27, 28 }, { 31, 36, 28 } }, {} }, + { { { 29, 67, 63 } }, {} }, + { {}, {} }, + { { { 0, 71, 62 }, { 8, 71, 48 } }, {} }, + { {}, {} }, + { { { 3, 56, 54 }, { 15, 69, 42 } }, {} }, + { { { 28, 60, 54 } }, {} }, + { {}, {} }, + { { { 1, 76, 40 } }, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { { { 7, 70, 53 } }, {} }, + { {}, {} }, + { { { 4, 68, 42 } }, {} }, + { {}, {} }, + { {}, {} }, + { { { 25, 78, 58 } }, {} }, + { { { 24, 78, 58 } }, {} }, + { {}, {} }, + { {}, {} }, + { { { 5, 71, 55 } }, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { { { 18, 75, 54 } }, {} }, + { {}, {} }, + { { { 6, 78, 55 }, { 12, 70, 70 } }, {} }, + { { { 2, 76, 37 } }, { { -1, 57, 23 } } }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + } }, + // Shadow Temple + { { + { {}, {} }, + { { { 1, 77, 64 } }, {} }, + { {}, {} }, + { {}, { { -1, 77, 76 } } }, + { { { 7, 76, 65 } }, {} }, + { {}, {} }, + { { { 2, 83, 67 }, { 14, 84, 59 } }, {} }, + { { { 3, 76, 67 } }, {} }, + { {}, {} }, + { {}, {} }, + { { { 4, 78, 62 }, { 5, 74, 62 }, { 6, 71, 68 } }, {} }, + { { { 9, 77, 64 } }, {} }, + { {}, {} }, + { { { 10, 71, 65 }, { 11, 80, 65 } }, {} }, + { { { 16, 73, 64 } }, {} }, + { {}, {} }, + { { { 12, 87, 64 }, { 22, 87, 68 } }, {} }, + { { { 13, 77, 66 } }, {} }, + { {}, {} }, + { { { 21, 78, 66 } }, {} }, + { { { 8, 76, 66 }, { 20, 78, 68 } }, {} }, + { { { 14, 77, 62 } }, {} }, + { {}, {} }, + { { { 15, 56, 67 } }, {} }, + { {}, {} }, + { { { 16, 73, 64 } }, {} }, + { { { 14, 77, 62 } }, {} }, + } }, + // Bottom of the Well + { { + { { { 3, 60, 18 } }, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { { { 2, 73, 61 } }, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { { { 1, 74, 66 } }, {} }, + } }, + // Ice Cavern + { { + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { { { 2, 71, 59 } }, {} }, + { {}, {} }, + { { { 0, 48, 36 } }, {} }, + { {}, {} }, + { { { 1, 73, 67 } }, {} }, + } }, +}; + +// Sets a scene's dungeon map marks based on whether it should be MQ or not +void SceneDB::Entry::SetMapMarkData(const bool isMQ) { + if (isMQ) { + if (this->entry.id >= SCENE_DEKU_TREE && this->entry.id <= SCENE_ICE_CAVERN) { + s32 dungeonNum = this->entry.id - SCENE_DEKU_TREE; + for (size_t i = 0; i < mqMapMarkInit[dungeonNum].rooms.size(); i++) { + dungeonRoomInfo[i].chestMarks = mqMapMarkInit[dungeonNum].rooms[i].chestMarks; + dungeonRoomInfo[i].bossMarks = mqMapMarkInit[dungeonNum].rooms[i].bossMarks; + + dungeonRooms[i].chestMarks = dungeonRoomInfo[i].chestMarks.data(); + dungeonRooms[i].numChestMarks = dungeonRoomInfo[i].chestMarks.size(); + dungeonRooms[i].bossMarks = dungeonRoomInfo[i].bossMarks.data(); + dungeonRooms[i].numBossMarks = dungeonRoomInfo[i].bossMarks.size(); + } + } + } else { + SetDungeonRooms(sceneDBInit[this->entry.id].dungeonData.rooms); + } +} + +struct MqPauseMapMarkInit { + struct Floor { + std::vector chestMarks; + std::vector bossMarks; + }; + + Floor floors[8]; +}; + +std::vector mqPauseMapMarkInit = { + // Deku Tree + { { + { {}, {} }, + { {}, {} }, + { {}, {} }, + { { { 2, 40.0f, -33.0f }, { 6, 49.0f, -42.0f } }, {} }, // 3F + { { { 1, 48.0f, -63.0f } }, {} }, // 2F + { { { 3, 84.0f, -39.0f } }, {} }, // 1F + { { { 0, 46.0f, -59.0f }, { 4, 77.0f, -26.0f }, { 5, 65.0f, -61.0f } }, {} }, // B1 + { {}, { { -1, 55.0f, 0.0f } } }, // B2 + } }, + // Dodongo's Cavern + { { + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { { { 2, 55.0f, -36.0f }, { 3, 54.0f, -51.0f }, { 5, 13.0f, -61.0f } }, {} }, // 2F + { { { 0, 47.0f, -40.0f }, { 1, 51.0f, -3.0f }, { 4, 47.0f, -47.0f } }, { { -1, 23.0f, -25.0f } } }, // 1F + } }, + // Jabu-Jabu's Belly + { { + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { { { 3, 48.0f, -68.0f }, + { 5, 50.0f, -66.0f }, + { 7, 55.0f, -50.0f }, + { 9, 58.0f, 1.0f }, + { 10, 62.0f, -45.0f } }, + { { -1, 65.0f, -37.0f } } }, // 1F + { { { 0, 37.0f, -49.0f }, + { 1, 65.0f, -38.0f }, + { 2, 52.0f, -48.0f }, + { 4, 46.0f, -36.0f }, + { 6, 59.0f, -41.0f }, + { 8, 52.0f, -26.0f } }, + {} }, // B1 + } }, + // Forest Temple + { { + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { { { 3, 53.0f, -64.0f }, + { 5, 65.0f, -9.0f }, + { 12, 49.0f, -1.0f }, + { 13, 40.0f, 0.0f }, + { 14, 18.0f, -2.0f }, + { 15, 59.0f, 0.0f } }, + {} }, // 2F + { { { 0, 49.0f, -1.0f }, { 1, 71.0f, -13.0f }, { 2, 11.0f, -25.0f }, { 6, 84.0f, -16.0f } }, {} }, // 1F + { { { 9, 65.0f, -30.0f } }, {} }, // B1 + { { { 11, 41.0f, -24.0f } }, { { -1, 50.0f, -11.0f } } }, // B2 + } }, + // Fire Temple + { { + { {}, {} }, + { {}, {} }, + { {}, {} }, + { { { 5, 24.0f, -40.0f } }, {} }, // 5F + { {}, {} }, // 4F + { { { 3, 75.0f, -47.0f }, { 6, 72.0f, -51.0f }, { 8, 65.0f, -12.0f } }, {} }, // 3F + { { { 11, 78.0f, -35.0f } }, {} }, // 2F + { { { 1, 67.0f, -58.0f }, + { 2, 48.0f, -30.0f }, + { 4, 63.0f, -14.0f }, + { 7, 36.0f, -45.0f }, + { 12, 47.0f, -26.0f } }, + { { -1, 26.0f, -34.0f } } }, // 1F + } }, + // Water Temple + { { + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { { { 2, 88.0f, -60.0f } }, { { -1, 62.0f, -23.0f } } }, // 3F + { { { 0, 88.0f, -60.0f } }, {} }, // 2F + { { { 1, 88.0f, -60.0f }, { 5, 49.0f, -43.0f } }, {} }, // 1F + { { { 6, 75.0f, -65.0f } }, {} }, // B1 + } }, + // Spirit Temple + { { + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { { { 18, 46.0f, -30.0f } }, {} }, // 4F + { { { 1, 23.0f, -33.0f }, + { 2, 56.0f, -11.0f }, + { 5, 83.0f, -25.0f }, + { 24, 84.0f, -39.0f }, + { 25, 74.0f, -37.0f } }, + { { -1, 47.0f, 0.0f } } }, // 3F + { { { 3, 46.0f, -20.0f }, + { 6, 28.0f, -19.0f }, + { 12, 25.0f, -25.0f }, + { 15, 50.0f, -13.0f }, + { 28, 48.0f, -29.0f } }, + {} }, // 2F + { { { 0, 14.0f, -24.0f }, + { 4, 55.0f, -14.0f }, + { 7, 78.0f, -2.0f }, + { 8, 14.0f, -16.0f }, + { 26, 42.0f, -43.0f }, + { 27, 50.0f, -43.0f }, + { 29, 25.0f, -35.0f }, + { 30, 42.0f, -36.0f }, + { 31, 50.0f, -36.0f } }, + {} }, // 1F + } }, + // Shadow Temple + { { + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { { { 1, 41.0f, -17.0f }, { 7, 27.0f, -24.0f } }, {} }, // B1 + { { { 2, 81.0f, -20.0f }, { 3, 74.0f, -37.0f } }, {} }, // B2 + { { { 12, 96.0f, -51.0f }, { 16, 46.0f, -42.0f }, { 22, 96.0f, -55.0f } }, {} }, // B3 + { { { 4, 43.0f, -66.0f }, + { 5, 37.0f, -66.0f }, + { 6, 33.0f, -72.0f }, + { 8, 85.0f, -18.0f }, + { 9, 61.0f, -42.0f }, + { 10, 15.0f, -4.0f }, + { 11, 25.0f, -4.0f }, + { 13, 19.0f, -29.0f }, + { 14, 78.0f, -15.0f }, + { 15, 60.0f, -70.0f }, + { 21, 92.0f, -29.0f }, + { 20, 87.0f, -20.0f } }, + { { -1, 31.0f, -45.0f } } }, // B4 + } }, + // Bottom of the Well + { { + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { { { 2, 84.0f, -38.0f }, { 3, 57.0f, -18.0f } }, {} }, // B1 + { {}, {} }, // B2 + { { { 1, 72.0f, -32.0f } }, {} }, // B3 + } }, + // Ice Cavern + { { + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { {}, {} }, + { { { 0, 66.0f, -2.0f }, { 1, 77.0f, -46.0f }, { 2, 27.0f, -45.0f } }, {} }, // 1F + } }, +}; + +// Sets a scene's pause map marks based on whether it should be MQ or not +void SceneDB::Entry::SetPauseMapMarkData(const bool isMQ) { + if (isMQ) { + if (this->entry.id >= SCENE_DEKU_TREE && this->entry.id <= SCENE_ICE_CAVERN) { + s32 dungeonNum = this->entry.id - SCENE_DEKU_TREE; + for (size_t i = 0; i < 8; i++) { + dungeonFloorInfo[i].chestMarks = mqPauseMapMarkInit[dungeonNum].floors[i].chestMarks; + dungeonFloorInfo[i].bossMarks = mqPauseMapMarkInit[dungeonNum].floors[i].bossMarks; + + dungeonFloors[i].numChestMarks = dungeonFloorInfo[i].chestMarks.size(); + dungeonFloors[i].chestMarks = dungeonFloorInfo[i].chestMarks.data(); + dungeonFloors[i].numBossMarks = dungeonFloorInfo[i].bossMarks.size(); + dungeonFloors[i].bossMarks = dungeonFloorInfo[i].bossMarks.data(); + } + } + } else { + SetDungeonFloors(sceneDBInit[this->entry.id].dungeonData.floors); + } +} + +// Returns is a scene is a boss scene +// A scene is a boss scene if it has the scene in the bossData is != -1 +bool SceneDB::Entry::isBoss() { + return SCENEDB_ISBOSS(&this->entry); +} + +// Returns is a scene is a boss dungeon +// A scene is a dungeon scene if it's number of rooms is != 0 +bool SceneDB::Entry::isDungeon() { + return SCENEDB_ISDUNGEON(&this->entry); +} + +// Returns is a scene is a overworld scene +// A scene is a world scene if it has a texture for a world minimap +bool SceneDB::Entry::isOverworld() { + return SCENEDB_ISOVERWORLD(&this->entry); +} + +EntranceDB::EntranceDB() { + db.reserve(ENTR_MAX); // reserve size for all initial entries so we don't do it for each + for (const EntranceTableInit& init : entranceDBInit) { + Init nativeInit{ init.name, init.desc, SceneDB::Instance->RetrieveEntry(init.scene).name, + init.spawn, init.continueBgm, init.displayTitleCard, + init.endTransition, init.startTransition }; + + AddEntry(nativeInit); + } +} + +EntranceDB::Entry& EntranceDB::AddEntry(const Init& init) { + Entry& entry = AddEntry(init.name, init.desc, nextFreeId); + // TODO handle errors + entry.entry.sceneId = SceneDB::Instance->RetrieveEntry(SceneDB::Instance->RetrieveId(init.scene)).entry.id; + entry.entry.spawn = init.spawn; + entry.entry.continueBgm = init.continueBgm; + entry.entry.displayTitleCard = init.displayTitleCard; + entry.entry.endTransition = init.endTransition; + entry.entry.startTransition = init.startTransition; + + // Add this entrance to the list of layers for the scene and spawn + NextLayerLookupKey nextLayerKey{ entry.entry.sceneId, entry.entry.spawn }; + auto nextLayer = nextLayerLookupTable.find(nextLayerKey); + if (nextLayer == nextLayerLookupTable.end()) { + entry.entry.layer = 0; + nextLayerLookupTable.insert({ nextLayerKey, 1 }); + } else { + entry.entry.layer = nextLayer->second++; + } + + // Add the entrance to the lookup of scene, spawn, and layer -> base scene + idLookupTable.insert({ { entry.entry.sceneId, entry.entry.spawn, entry.entry.layer }, entry.entry.id }); + + return entry; +} + +EntranceDB::Entry& EntranceDB::RetrieveEntry(const int id) { + static Entry invalid; + if ((id < 0) || (id >= db.size())) { + return invalid; + } + return db[id]; +} + +EntranceDB::Entry& EntranceDB::RetrieveEntry(const int id, const int layer) { + Entry& entry = RetrieveEntry(id); + Entry& ret = RetrieveEntry(CalcId(entry.entry.sceneId, entry.entry.spawn, layer)); + assert(ret.entry.valid); + return ret; +} + +int EntranceDB::RetrieveId(const std::string& name) { + auto entry = nameTable.find(name); + if (entry == nameTable.end()) { + return -1; + } + + return entry->second; +} + +size_t EntranceDB::GetNumEntries() { + return db.size(); +} + +s32 EntranceDB::CalcId(const s32 sceneId, const s32 spawn, const s32 layer) { + auto entrance = idLookupTable.find({ sceneId, spawn, layer }); + + // If the entrance does not exist, assume it is a wrong warp + // TODO WW CVar to force error for mod debugging + if (entrance == idLookupTable.end()) { + auto wwEntrance = idLookupTable.find({ sceneId, spawn, 0 }); + // We need to make sure that at least the scene and spawn are correct, it's just the layer which is an OOB + assert(wwEntrance != idLookupTable.end()); + return wwEntrance->second + layer; + } + + return entrance->second; +} + +s32 EntranceDB::CalcId(const s32 entrance, const s32 newLayer) { + Entry& entry = RetrieveEntry(entrance); + auto newEntrance = idLookupTable.find({ entry.entry.sceneId, entry.entry.spawn, newLayer }); + + // If the entrance does not exist, assume it is a wrong warp + // TODO WW CVar to force error for mod debugging + if (newEntrance == idLookupTable.end()) { + auto wwEntrance = idLookupTable.find({ entry.entry.sceneId, entry.entry.spawn, 0 }); + // We need to make sure that at least the scene and spawn are correct, it's just the layer which is an OOB + assert(wwEntrance != idLookupTable.end()); + return wwEntrance->second + newLayer; + } + + return newEntrance->second; +} + +// Resets all vanilla entrances (mostly to restore all modifications rando makes) +void EntranceDB::ResetVanillaEntrances() { + // Erase all instances of vanilla entrances in the lookup tables + for (size_t i = 0; i < ENTR_MAX; i++) { + // For this entrance, reset the next layer. This will cause problems with mods that add a new layer (like for a + // cutscene) However, we will treat this as fine for now because we don't have such mods A more robust solution + // is to use a local nextLayerLookupTable to reestablish the vanilla layers + NextLayerLookupKey nextLayerKey{ entranceDBInit[i].scene, entranceDBInit[i].spawn }; + nextLayerLookupTable.erase(nextLayerKey); + + for (auto iter = idLookupTable.begin(); iter != idLookupTable.end();) { + if (iter->second == i) { + idLookupTable.erase(iter++); + } else { + iter++; + } + } + } + + for (size_t i = 0; i < ENTR_MAX; i++) { + // This entrance should already exist. Look it up and set its values to vanilla + Entry& entry = RetrieveEntry(i); + const EntranceTableInit& init = entranceDBInit[i]; + + entry.entry.sceneId = SceneDB::Instance->RetrieveEntry(init.scene).entry.id; + entry.entry.spawn = init.spawn; + entry.entry.continueBgm = init.continueBgm; + entry.entry.displayTitleCard = init.displayTitleCard; + entry.entry.endTransition = init.endTransition; + entry.entry.startTransition = init.startTransition; + + // Add this entrance to the list of layers for the scene and spawn + NextLayerLookupKey nextLayerKey{ entry.entry.sceneId, entry.entry.spawn }; + auto nextLayer = nextLayerLookupTable.find(nextLayerKey); + if (nextLayer == nextLayerLookupTable.end()) { + entry.entry.layer = 0; + nextLayerLookupTable.insert({ nextLayerKey, 1 }); + } else { + entry.entry.layer = nextLayer->second++; + } + + // Add the entrance to the lookup + idLookupTable.insert({ { entry.entry.sceneId, entry.entry.spawn, entry.entry.layer }, entry.entry.id }); + } +} + +// Copies an entrance. Needed by rando when making changes to the scene, spawn, or layer +void EntranceDB::Copy(s32 from, s32 to) { + Entry& entryFrom = RetrieveEntry(from); + Entry& entryTo = RetrieveEntry(to); + + // Remove entrance that is about to be overridden + for (auto iter = idLookupTable.begin(); iter != idLookupTable.end();) { + if (iter->second == to) { + idLookupTable.erase(iter++); + } else { + iter++; + } + } + + // Add a lookup so that the overridden entrance returns the new one + idLookupTable.insert({ { entryTo.entry.sceneId, entryTo.entry.spawn, entryTo.entry.layer }, entryFrom.entry.id }); + + // Replace the entrance + entryTo.entry.sceneId = entryFrom.entry.sceneId; + entryTo.entry.spawn = entryFrom.entry.spawn; + entryTo.entry.layer = entryFrom.entry.layer; + entryTo.entry.continueBgm = entryFrom.entry.continueBgm; + entryTo.entry.displayTitleCard = entryFrom.entry.displayTitleCard; + entryTo.entry.endTransition = entryFrom.entry.endTransition; + entryTo.entry.startTransition = entryFrom.entry.startTransition; +} + +EntranceDB::Entry& EntranceDB::AddEntry(const std::string& name, const std::string& desc, size_t index) { + assert(!nameTable.contains(name)); // TODO this should maybe throw instead. We'll need to think about error handling + // for mods that try to declare the same entrance. + + if (db.size() < (index + 1)) { + db.resize(index + 1); + } + Entry& newEntry = db.at(index); + newEntry.entry.id = index; + + assert(!newEntry.entry.valid); + + nextFreeId = std::max(nextFreeId, index + 1); + + nameTable[name] = newEntry.entry.id; + newEntry.SetName(name); + newEntry.SetDesc(desc); + + newEntry.entry.valid = true; + + return newEntry; +} + +EntranceDB::Entry::Entry() { + entry.name = nullptr; + entry.desc = nullptr; + entry.valid = false; + entry.id = 0; + entry.sceneId = 0; + entry.spawn = 0; + entry.layer = 0; + entry.continueBgm = false; + entry.displayTitleCard = false; + entry.endTransition = 0; + entry.startTransition = 0; +} + +EntranceDB::Entry::Entry(const Entry& other) { + entry = other.entry; + SetName(other.name); + SetDesc(other.desc); +} + +EntranceDB::Entry& EntranceDB::Entry::operator=(const Entry& other) { + entry = other.entry; + SetName(other.name); + SetDesc(other.desc); + return *this; +} + +void EntranceDB::Entry::SetName(const std::string& newName) { + name = newName; + entry.name = name.c_str(); +} + +void EntranceDB::Entry::SetDesc(const std::string& newDesc) { + desc = newDesc; + entry.desc = desc.c_str(); +} + +extern "C" SceneDBEntry* SceneDB_Retrieve(const int id) { + return &SceneDB::Instance->RetrieveEntry(id).entry; +} + +extern "C" int SceneDB_RetrieveId(const char* name) { + return SceneDB::Instance->RetrieveId(name); +} + +extern "C" int SceneDB_IsBoss(const int id) { + return SceneDB::Instance->RetrieveEntry(id).isBoss(); +} + +extern "C" int SceneDB_IsDungeon(const int id) { + return SceneDB::Instance->RetrieveEntry(id).isDungeon(); +} + +extern "C" int SceneDB_IsOverworld(const int id) { + return SceneDB::Instance->RetrieveEntry(id).isOverworld(); +} + +extern "C" void SceneDB_SetMapMarkData(const int id, const int isMQ) { + SceneDB::Instance->RetrieveEntry(id).SetMapMarkData(isMQ); +} + +extern "C" void SceneDB_SetPauseMapMarkData(const int id, const int isMQ) { + SceneDB::Instance->RetrieveEntry(id).SetPauseMapMarkData(isMQ); +} + +extern "C" EntranceDBEntry* EntranceDB_Retrieve(const int id) { + return &EntranceDB::Instance->RetrieveEntry(id).entry; +} + +extern "C" EntranceDBEntry* EntranceDB_RetrieveLayer(const int id, const int layer) { + return &EntranceDB::Instance->RetrieveEntry(id, layer).entry; +} + +extern "C" int EntranceDB_RetrieveId(const char* name) { + return EntranceDB::Instance->RetrieveId(name); +} + +extern "C" int EntranceDB_CalcId(const int sceneId, const int spawn, const int layer) { + return EntranceDB::Instance->CalcId(sceneId, spawn, layer); +} + +extern "C" int EntranceDB_CalcIdWithEntrance(const int entrance, const int newLayer) { + return EntranceDB::Instance->CalcId(entrance, newLayer); +} + +extern "C" void EntranceDB_ResetVanillaEntrances(void) { + return EntranceDB::Instance->ResetVanillaEntrances(); +} + +extern "C" void EntranceDB_Copy(const int from, const int to) { + return EntranceDB::Instance->Copy(from, to); +} diff --git a/soh/soh/SceneDB.h b/soh/soh/SceneDB.h new file mode 100644 index 000000000..7b85d03b4 --- /dev/null +++ b/soh/soh/SceneDB.h @@ -0,0 +1,374 @@ +#pragma once +#include +#include "z64scene.h" +#include "z64.h" + +typedef struct { + FloorID id; + f32 height; + s8* rooms; + u32 numRooms; + const char* mapLeftTexture; + const char* mapRightTexture; + PauseMapMarkPoint* chestMarks; + u32 numChestMarks; + PauseMapMarkPoint* bossMarks; + u32 numBossMarks; +} SceneDBFloor; + +typedef struct { + s16 compassOffsetX; + s16 compassOffsetY; + const char* minimapTexture; + MapMarkPoint* chestMarks; + u32 numChestMarks; + MapMarkPoint* bossMarks; + u32 numBossMarks; +} SceneDBRoom; + +typedef struct { + u8 fromRoom; + u8 toRoom; + u8 toFloor; +} SceneDBIntraRoomTransition; + +typedef struct { + const char* name; + const char* desc; + u32 valid; + s32 id; + const char* titleCard; + SceneDrawConfig sceneDrawConfig; + struct { + u8 hGauge; + u8 bButton; + u8 aButton; + u8 bottles; + u8 tradeItems; + u8 hookshot; + u8 ocarina; + u8 warpSongs; + u8 sunsSong; + u8 farores; + u8 dinsNayrus; + u8 all; + } restrictions; + struct { + u32 allowed; + Vec3s startingPos; + s16 angle; + Vec3s* spawnPos; + u32 numSpawns; + } epona; + struct { + s16 scaleX; + s16 scaleY; + s16 x; + s16 y; + } compassInfo; + struct { + s32 mapScene; + } bossData; + struct { + s32 bossFloor; + s16* palettes; + u32 numPalettes; + const char* nameEngTexture; + const char* nameGerTexture; + const char* nameFraTexture; + SceneDBFloor floors[8]; + SceneDBRoom* rooms; + u32 numRooms; + SceneDBIntraRoomTransition* intraRoomTransitions; + u32 numIntraRoomTransitions; + } dungeonData; + struct { + s16 minimapX; + s16 minimapY; + s16 minimapWidth; + s16 minimapHeight; + s16 iconX; + s16 iconY; + s16 entranceFlag; + const char* minimapTexture; + } worldData; +} SceneDBEntry; + +typedef struct { + const char* name; + const char* desc; + u32 valid; + s32 id; + s32 sceneId; + s32 spawn; + s32 layer; + u8 continueBgm; + u8 displayTitleCard; + u8 endTransition; + u8 startTransition; +} EntranceDBEntry; + +#define SCENEDB_ISBOSS(entry) ((entry)->bossData.mapScene != -1) +#define SCENEDB_ISDUNGEON(entry) ((entry)->dungeonData.numRooms != 0) +#define SCENEDB_ISOVERWORLD(entry) ((entry)->worldData.minimapTexture != NULL) + +#ifdef __cplusplus + +#include +#include +#include +#include + +class SceneDB { + public: + static SceneDB* Instance; + + struct Init { + struct FloorInit { + FloorID id = F_NA; + f32 height = 9999.0f; + std::vector palettes; + std::string mapLeftTexture; + std::string mapRightTexture; + std::vector chestMarks; + std::vector bossMarks; + }; + + struct RoomInit { + s16 compassOffsetX = 0; + s16 compassOffsetY = 0; + std::string minimapTexture; + std::vector chestMarks; + std::vector bossMarks; + }; + + struct IntraRoomTransitionInit { + u8 fromRoom = 0xFF; + u8 toRoom = 0xFF; + u8 toFloor = 0xFF; + }; + + std::string name; + std::string desc; + std::string titleCard; + SceneDrawConfig sceneDrawConfig = SDC_DEFAULT; + struct { + bool hGauge = false; + bool bButton = false; + bool aButton = false; + bool bottles = false; + bool tradeItems = false; + bool hookshot = false; + bool ocarina = false; + bool warpSongs = false; + bool sunsSong = false; + bool farores = false; + bool dinsNayrus = false; + bool all = false; + } restrictions; + struct { + bool allowed = false; + Vec3s startingPos = { 0, 0, 0 }; + s16 angle = 0; + std::vector spawnPos; + } epona; + struct { + s16 scaleX = 0; + s16 scaleY = 0; + s16 x = 0; + s16 y = 0; + } compassInfo; + struct { + std::string mapScene; + } bossData; + struct { + s32 bossFloor = -1; + std::vector palettes; + std::string nameEngTexture; + std::string nameGerTexture; + std::string nameFraTexture; + std::vector floors; + std::vector rooms; + std::vector intraRoomTransitions; + } dungeonData; + struct { + s16 minimapX = 0; + s16 minimapY = 0; + s16 minimapWidth = 0; + s16 minimapHeight = 0; + s16 iconX = 0; + s16 iconY = 0; + s16 entranceFlag = -1; + std::string minimapTexture; + } worldData; + }; + + SceneDB(); + + // Wrapper around SceneDBEntry so we get C++isms for the entries + struct Entry { + Entry(); + Entry(const Entry& other); + Entry& operator=(const Entry& other); + + struct FloorInfo { + std::vector rooms; + std::string mapLeftTexture; + std::string mapRightTexture; + std::vector chestMarks; + std::vector bossMarks; + }; + + struct RoomInfo { + std::string minimapTexture; + std::vector chestMarks; + std::vector bossMarks; + }; + + void SetName(const std::string& newName); + void SetDesc(const std::string& newDesc); + void SetTitleCard(const std::string& newTitleCard); + void SetEponaSpawnPos(const std::vector& newSpawnPos); + void SetDungeonPalettes(const std::vector& newDungeonPalettes); + void SetDungeonNameTextures(const std::string& newNameEngTexture, const std::string& newNameGerTexture, + const std::string& newNameFraTexture); + void SetDungeonFloors(const std::vector& newDungeonFloors); + void SetDungeonFloors(const std::vector& newDungeonFloors, + const std::vector& newDungeonFloorInfo); + void SetDungeonRooms(const std::vector& newDungeonRooms); + void SetDungeonRooms(const std::vector& newDungeonRooms, + const std::vector& newDungeonRoomInfo); + void SetDungeonIntraRoomTransitions( + const std::vector& newDungeonIntraRoomTransitions); + void + SetDungeonIntraRoomTransitions(const std::vector& newDungeonIntraRoomTransitions); + void SetWorldMinimapTexture(const std::string& newWorldMinimapTexture); + void SetMapMarkData(const bool isMQ); + void SetPauseMapMarkData(const bool isMQ); + + bool isBoss(); + bool isDungeon(); + bool isOverworld(); + + std::string name; + std::string desc; + std::string titleCard; + std::vector eponaSpawnPos; + std::vector dungeonPalettes; + std::string nameEngTexture; + std::string nameGerTexture; + std::string nameFraTexture; + std::vector dungeonFloorInfo; + std::vector dungeonFloors; + std::vector dungeonRoomInfo; + std::vector dungeonRooms; + std::vector dungeonIntraRoomTransitions; + std::string worldMinimapTexture; + SceneDBEntry entry; + }; + Entry& AddEntry(const Init& init); + + Entry& RetrieveEntry(const int id); + int RetrieveId(const std::string& name); + + size_t GetNumEntries(); + + private: + Entry& AddEntry(const std::string& name, const std::string& desc, size_t index); + + std::vector db; + std::unordered_map nameTable; + size_t nextFreeId = 0; +}; + +class EntranceDB { + public: + static EntranceDB* Instance; + + struct Init { + std::string name; + std::string desc; + std::string scene; + s32 spawn; + bool continueBgm; + bool displayTitleCard; + u8 endTransition; + u8 startTransition; + }; + + EntranceDB(); + + // Wrapper around EntranceDBEntry so we get C++isms for the entries + struct Entry { + Entry(); + Entry(const Entry& other); + Entry& operator=(const Entry& other); + + void SetName(const std::string& newName); + void SetDesc(const std::string& newDesc); + + std::string name; + std::string desc; + EntranceDBEntry entry; + }; + Entry& AddEntry(const Init& init); + + void ResetVanillaEntrances(); + + Entry& RetrieveEntry(const int id); + Entry& RetrieveEntry(const int id, const int layer); + int RetrieveId(const std::string& name); + + size_t GetNumEntries(); + + s32 CalcId(s32 sceneId, s32 spawn, s32 layer); + s32 CalcId(s32 entrance, s32 newLayer); + + void Copy(s32 from, s32 to); + + private: + Entry& AddEntry(const std::string& name, const std::string& desc, size_t index); + + std::vector db; + std::unordered_map nameTable; + size_t nextFreeId = 0; + + // This keeps a mapping of a scene, spawn, and layer to the resulting entrance ID, since we can assume no order + // about them + struct IdLookupKey { + s32 sceneId; + s32 spawn; + s32 layer; + auto operator<=>(const IdLookupKey&) const = default; + }; + std::map idLookupTable; + + // This keeps a mapping of a scene and spawn to the next avaliable layer + // When loading mods that add cutscenes, this will tell us the layer that cutscene's entrance is assigned + struct NextLayerLookupKey { + s32 sceneId; + s32 spawn; + auto operator<=>(const NextLayerLookupKey&) const = default; + }; + std::map nextLayerLookupTable; +}; + +#else + +SceneDBEntry* SceneDB_Retrieve(const int id); +int SceneDB_RetrieveId(const char* name); +int SceneDB_IsBoss(const int id); +int SceneDB_IsDungeon(const int id); +int SceneDB_IsOverworld(const int id); +void SceneDB_SetMapMarkData(const int id, const int isMQ); +void SceneDB_SetPauseMapMarkData(const int id, const int isMQ); + +EntranceDBEntry* EntranceDB_Retrieve(const int id); +EntranceDBEntry* EntranceDB_RetrieveLayer(const int id, const int layer); +int EntranceDB_RetrieveId(const char* name); +int EntranceDB_CalcId(const int sceneId, const int spawn, const int layer); +int EntranceDB_CalcIdWithEntrance(const int entrance, const int newLayer); +void EntranceDB_ResetVanillaEntrances(void); +void EntranceDB_Copy(const int from, const int to); + +#endif \ No newline at end of file diff --git a/soh/soh/SceneDB_Table.cpp b/soh/soh/SceneDB_Table.cpp new file mode 100644 index 000000000..3db6edc99 --- /dev/null +++ b/soh/soh/SceneDB_Table.cpp @@ -0,0 +1,3288 @@ +#include "SceneDB.h" + +#include "textures/map_48x85_static/map_48x85_static.h" +#include "textures/map_i_static/map_i_static.h" +#include "textures/icon_item_nes_static/icon_item_nes_static.h" +#include "textures/icon_item_ger_static/icon_item_ger_static.h" +#include "textures/icon_item_fra_static/icon_item_fra_static.h" +#include "textures/map_grand_static/map_grand_static.h" + +#include + +extern const std::vector sceneDBInit{ + { // SCENE_DEKU_TREE + "ydan_scene", + "Inside the Deku Tree", + "g_pn_06", + SDC_DEKU_TREE, + { false, false, false, false, false, false, false, false, false, false, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 3, 3, 1070, -690 }, + {}, + { + 7, + { 10, 1, 2, 10, 4, 5, 6, 7, 8, 10, 11 }, + std::string{ gPauseDekuTitleENGTex }, + std::string{ gPauseDekuTitleGERTex }, + std::string{ gPauseDekuTitleFRATex }, + { + { + F_NA, + 9999.0f, + {}, + std::string{}, + std::string{}, + {}, + {}, + }, + { + F_NA, + 9999.0f, + {}, + std::string{}, + std::string{}, + {}, + {}, + }, + { + F_NA, + 9999.0f, + {}, + std::string{}, + std::string{}, + {}, + {}, + }, + { + F_3F, + 760.0f, + { + 0, + 10, + }, + std::string{ gDekuTreePauseScreenMapFloor3LeftTex }, + std::string{ gDekuTreePauseScreenMapFloor3RightTex }, + { { 2, 40.0f, -33.0f }, { 6, 49.0f, -42.0f } }, + {}, + }, + { + F_2F, + 360.0f, + { + 0, + 1, + 2, + }, + std::string{ gDekuTreePauseScreenMapFloor2LeftTex }, + std::string{ gDekuTreePauseScreenMapFloor2RightTex }, + { { 1, 48.0f, -63.0f }, { 5, 52.0f, -68.0f } }, + {}, + }, + { + F_1F, + -40.0f, + { + 0, + }, + std::string{ gDekuTreePauseScreenMapFloor1LeftTex }, + std::string{ gDekuTreePauseScreenMapFloor1RightTex }, + { { 3, 84.0f, -39.0f } }, + {}, + }, + { + F_B1, + -1000.0f, + { + 3, + 4, + 5, + 6, + 7, + 8, + }, + std::string{ gDekuTreePauseScreenMapBasement1LeftTex }, + std::string{ gDekuTreePauseScreenMapBasement1RightTex }, + { { 4, 77.0f, -26.0f } }, + {}, + }, + { + F_B2, + -2000.0f, + { + 9, + }, + std::string{ gDekuTreePauseScreenMapBasement2LeftTex }, + std::string{ gDekuTreePauseScreenMapBasement2RightTex }, + {}, + { { -1, 55.0f, 0.0f } }, + }, + }, + { + { 1090, + -660, + std::string{ gDekuTreeRoom0Floor1MinimapTex }, + { + { 3, 71, 50 }, + }, + {} }, + { 1390, -570, std::string{ gDekuTreeRoom1MinimapTex }, {}, {} }, + { 1560, + -410, + std::string{ gDekuTreeRoom2MinimapTex }, + { + { 1, 64, 62 }, + { 5, 71, 69 }, + }, + {} }, + { 1220, + -690, + std::string{ gDekuTreeRoom3MinimapTex }, + { + { 4, 76, 37 }, + }, + {} }, + { 1200, -500, std::string{ gDekuTreeRoom4MinimapTex }, {}, {} }, + { 1390, -380, std::string{ gDekuTreeRoom5MinimapTex }, {}, {} }, + { 1770, -470, std::string{ gDekuTreeRoom6MinimapTex }, {}, {} }, + { 1610, -630, std::string{ gDekuTreeRoom7MinimapTex }, {}, {} }, + { 2000, -990, std::string{ gDekuTreeRoom8MinimapTex }, {}, {} }, + { 1290, + -870, + std::string{ gDekuTreeRoom9MinimapTex }, + {}, + { + { -1, 50, 23 }, + } }, + { 1420, + -720, + std::string{ gDekuTreeRoom10MinimapTex }, + { + { 2, 46, 50 }, + { 6, 58, 60 }, + }, + {} }, + { 1110, -630, std::string{ gDekuTreeRoom0Floor2MinimapTex }, {}, {} }, + { 1040, -660, std::string{ gDekuTreeRoom0Floor3MinimapTex }, {}, {} }, + }, + { + { 11, 12, 3 }, + { 0, 11, 4 }, + { 0, 12, 3 }, + { 12, 11, 4 }, + { 11, 0, 5 }, + }, + }, + {} }, + { // SCENE_DODONGOS_CAVERN + "ddan_scene", + "Dodongo's Cavern", + "g_pn_08", + SDC_DODONGOS_CAVERN, + { false, false, false, false, false, false, false, false, false, false, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 4, 4, 1070, -690 }, + {}, + { + 7, + { 1, 3, 5, 6, 10, 3, 9, 2, 4, 2, 4, 7, 7, 8, 13, 11 }, + std::string{ gPauseDodongoTitleENGTex }, + std::string{ gPauseDodongoTitleGERTex }, + std::string{ gPauseDodongoTitleFRATex }, + { + { + F_NA, + 9999.0f, + {}, + std::string{}, + std::string{}, + {}, + {}, + }, + { + F_NA, + 9999.0f, + {}, + std::string{}, + std::string{}, + {}, + {}, + }, + { + F_NA, + 9999.0f, + {}, + std::string{}, + std::string{}, + {}, + {}, + }, + { + F_NA, + 9999.0f, + {}, + std::string{}, + std::string{}, + {}, + {}, + }, + { + F_NA, + 9999.0f, + {}, + std::string{}, + std::string{}, + {}, + {}, + }, + { + F_NA, + 9999.0f, + {}, + std::string{}, + std::string{}, + {}, + {}, + }, + { + F_2F, + 280.0f, + { + 0, + 2, + 3, + 5, + 6, + 9, + 10, + 12, + }, + std::string{ gDodongosCavernPauseScreenMapFloor2LeftTex }, + std::string{ gDodongosCavernPauseScreenMapFloor2RightTex }, + { { 10, 25.0f, -41.0f }, { 4, 53.0f, -47.0f }, { 6, 58.0f, -59.0f } }, + {}, + }, + { + F_1F, + -440.0f, + { + 0, + 1, + 2, + 3, + 4, + 7, + 8, + 11, + 13, + 14, + 15, + }, + std::string{ gDodongosCavernPauseScreenMapFloor1LeftTex }, + std::string{ gDodongosCavernPauseScreenMapFloor1RightTex }, + { { 5, 13.0f, -60.0f }, { 8, 20.0f, -49.0f } }, + { { -1, 23.0f, -25.0f } }, + }, + }, + { + { 940, + -780, + std::string{ gDodongosCavernRoom0MinimapTex }, + { + { 8, 22, 32 }, + }, + {} }, + { 320, -800, std::string{ gDodongosCavernRoom1MinimapTex }, {}, {} }, + { 1500, -1090, std::string{ gDodongosCavernRoom2MinimapTex }, {}, {} }, + { 240, -1230, std::string{ gDodongosCavernRoom3MinimapTex }, {}, {} }, + { 580, -1140, std::string{ gDodongosCavernRoom4MinimapTex }, {}, {} }, + { 1510, -820, std::string{ gDodongosCavernRoom5MinimapTex }, {}, {} }, + { 720, -1210, std::string{ gDodongosCavernRoom6MinimapTex }, {}, {} }, + { 1030, + -1430, + std::string{ gDodongosCavernRoom7MinimapTex }, + {}, + { + { -1, 37, 49 }, + } }, + { 800, -1580, std::string{ gDodongosCavernRoom8MinimapTex }, {}, {} }, + { 660, + -920, + std::string{ gDodongosCavernRoom9MinimapTex }, + { + { 4, 58, 40 }, + { 6, 65, 64 }, + }, + {} }, + { 180, -830, std::string{ gDodongosCavernRoom10MinimapTex }, {}, {} }, + { 520, -730, std::string{ gDodongosCavernRoom11MinimapTex }, {}, {} }, + { 310, -950, std::string{ gDodongosCavernRoom12MinimapTex }, {}, {} }, + { 550, -1580, std::string{ gDodongosCavernRoom13MinimapTex }, {}, {} }, + { 790, -1910, std::string{ gDodongosCavernRoom14MinimapTex }, {}, {} }, + { 1650, + -950, + std::string{ gDodongosCavernRoom15MinimapTex }, + { + { 5, 68, 64 }, + }, + {} }, + { 1000, + -860, + std::string{ gDodongosCavernRoom0Floor3MinimapTex }, + { + { 10, 31, 27 }, + }, + {} }, + { 1570, -1070, std::string{ gDodongosCavernRoom2Floor3MinimapTex }, {}, {} }, + { 80, -1070, std::string{ gDodongosCavernRoom3Floor3MinimapTex }, {}, {} }, + }, + { + { 0, 16, 6 }, + { 2, 17, 6 }, + { 3, 18, 6 }, + { 16, 0, 7 }, + { 17, 2, 7 }, + { 18, 3, 7 }, + }, + }, + {} }, + { // SCENE_JABU_JABU + "bdan_scene", + "Inside Jabu-Jabu's Belly", + "g_pn_07", + SDC_JABU_JABU, + { false, false, false, false, false, false, false, false, false, false, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 3, 3, 1070, -690 }, + {}, + { + 6, + { 3, 1, 2, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 3 }, + std::string{ gPauseJabuTitleENGTex }, + std::string{ gPauseJabuTitleGERTex }, + std::string{ gPauseJabuTitleFRATex }, + { + { + F_NA, + 9999.0f, + {}, + std::string{}, + std::string{}, + {}, + {}, + }, + { + F_NA, + 9999.0f, + {}, + std::string{}, + std::string{}, + {}, + {}, + }, + { + F_NA, + 9999.0f, + {}, + std::string{}, + std::string{}, + {}, + {}, + }, + { + F_NA, + 9999.0f, + {}, + std::string{}, + std::string{}, + {}, + {}, + }, + { + F_NA, + 9999.0f, + {}, + std::string{}, + std::string{}, + {}, + {}, + }, + { + F_NA, + 9999.0f, + {}, + std::string{}, + std::string{}, + {}, + {}, + }, + { + F_1F, + -640.0f, + { + 0, + 1, + 2, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + }, + std::string{ gJabuPauseScreenMapFloor1LeftTex }, + std::string{ gJabuPauseScreenMapFloor1RightTex }, + { { 1, 67.0f, -13.0f }, { 2, 28.0f, -13.0f }, { 4, 38.0f, 0.0f } }, + { { -1, 65.0f, -37.0f } }, + }, + { + F_B1, + -3000.0f, + { + 1, + 3, + 6, + 13, + 14, + }, + std::string{ gJabuPauseScreenMapBasement1LeftTex }, + std::string{ gJabuPauseScreenMapBasement1RightTex }, + {}, + {}, + }, + }, + { + { 1130, -770, std::string{ gJabuRoom0MinimapTex }, {}, {} }, + { 1070, -1320, std::string{ gJabuRoom1MinimapTex }, {}, {} }, + { 1090, -1750, std::string{ gJabuRoom2MinimapTex }, {}, {} }, + { 1160, -1800, std::string{ gJabuRoom3MinimapTex }, {}, {} }, + { 1500, -1360, std::string{ gJabuRoom4MinimapTex }, {}, {} }, + { 690, + -1330, + std::string{ gJabuRoom5MinimapTex }, + {}, + { + { -1, 67, 32 }, + } }, + { 1540, -1700, std::string{ gJabuRoom6MinimapTex }, {}, {} }, + { 920, -2280, std::string{ gJabuRoom7MinimapTex }, {}, {} }, + { 1160, -2700, std::string{ gJabuRoom8MinimapTex }, {}, {} }, + { 700, + -2360, + std::string{ gJabuRoom9MinimapTex }, + { + { 1, 74, 57 }, + }, + {} }, + { 1650, + -2360, + std::string{ gJabuRoom10MinimapTex }, + { + { 2, 59, 57 }, + }, + {} }, + { 950, -2650, std::string{ gJabuRoom11MinimapTex }, {}, {} }, + { 1380, + -2650, + std::string{ gJabuRoom12MinimapTex }, + { + { 4, 68, 51 }, + }, + {} }, + { 1460, -1600, std::string{ gJabuRoom13MinimapTex }, {}, {} }, + { 830, -1445, std::string{ gJabuRoom14MinimapTex }, {}, {} }, + { 1170, -1370, std::string{ gJabuRoom1Basement1MinimapTex }, {}, {} }, + { 1620, -1910, std::string{ gJabuRoom6Basement1MinimapTex }, {}, {} }, + }, + { + { 1, 15, 7 }, + { 6, 16, 7 }, + { 15, 1, 6 }, + { 16, 6, 6 }, + }, + }, + {} }, + { // SCENE_FOREST_TEMPLE + "Bmori1_scene", + "Forest Temple", + "g_pn_01", + SDC_FOREST_TEMPLE, + { false, false, false, false, false, false, false, false, false, false, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 4, 4, 1070, -690 }, + {}, + { + 7, + { 9, 1, 2, 3, 6, 5, 6, 7, 8, 8, 5, 4, 3, 13, 11, 10, 11, 2, 13, 12, 10, 12, 13 }, + std::string{ gPauseForestTitleENGTex }, + std::string{ gPauseForestTitleGERTex }, + std::string{ gPauseForestTitleFRATex }, + { + { + F_NA, + 9999.0f, + {}, + std::string{}, + std::string{}, + {}, + {}, + }, + { + F_NA, + 9999.0f, + {}, + std::string{}, + std::string{}, + {}, + {}, + }, + { + F_NA, + 9999.0f, + {}, + std::string{}, + std::string{}, + {}, + {}, + }, + { + F_NA, + 9999.0f, + {}, + std::string{}, + std::string{}, + {}, + {}, + }, + { + F_2F, + 760.0f, + { + 0, + 6, + 7, + 8, + 10, + 11, + 12, + 13, + 14, + 19, + 20, + }, + std::string{ gForestTemplePauseScreenMapFloor2LeftTex }, + std::string{ gForestTemplePauseScreenMapFloor2RightTex }, + { { 0, 49.0f, -3.0f }, { 2, 12.0f, -26.0f }, { 5, 74.0f, -13.0f }, { 7, 82.0f, -22.0f } }, + {}, + }, + { + F_1F, + -40.0f, + { + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 11, + 15, + 16, + 18, + 21, + }, + std::string{ gForestTemplePauseScreenMapFloor1LeftTex }, + std::string{ gForestTemplePauseScreenMapFloor1RightTex }, + { { 0, 49.0f, -3.0f }, { 2, 12.0f, -26.0f }, { 5, 74.0f, -13.0f }, { 7, 82.0f, -22.0f } }, + {}, + }, + { + F_B1, + -440.0f, + { + 9, + }, + std::string{ gForestTemplePauseScreenMapBasement1LeftTex }, + std::string{ gForestTemplePauseScreenMapBasement1RightTex }, + { { 9, 31.0f, -29.0f } }, + {}, + }, + { + F_B2, + -3000.0f, + { + 17, + }, + std::string{ gForestTemplePauseScreenMapBasement2LeftTex }, + std::string{ gForestTemplePauseScreenMapBasement2RightTex }, + { { 11, 40.0f, -41.0f } }, + { { -1, 50.0f, -11.0f } }, + }, + }, + { + { 1130, -660, std::string{ gForestTempleRoom0Floor1MinimapTex }, {}, {} }, + { 1170, -900, std::string{ gForestTempleRoom1MinimapTex }, {}, {} }, + { 965, -1040, std::string{ gForestTempleRoom2MinimapTex }, {}, {} }, + { 890, -1210, std::string{ gForestTempleRoom3MinimapTex }, {}, {} }, + { 1170, -1520, std::string{ gForestTempleRoom4MinimapTex }, {}, {} }, + { 1460, -1190, std::string{ gForestTempleRoom5MinimapTex }, {}, {} }, + { 1170, + -1670, + std::string{ gForestTempleRoom6Floor1MinimapTex }, + { + { 0, 72, 60 }, + }, + {} }, + { 800, + -1320, + std::string{ gForestTempleRoom7Floor1MinimapTex }, + { + { 5, 76, 38 }, + }, + {} }, + { 1320, + -1310, + std::string{ gForestTempleRoom8Floor1MinimapTex }, + { + { 9, 59, 66 }, + }, + {} }, + { 880, + -1260, + std::string{ gForestTempleRoom9MinimapTex }, + { + { 9, 15, 58 }, + }, + {} }, + { 1130, + -1500, + std::string{ gForestTempleRoom10MinimapTex }, + { + { 1, 69, 56 }, + }, + {} }, + { 1590, -1080, std::string{ gForestTempleRoom11Floor1MinimapTex }, {}, {} }, + { 1390, + -1650, + std::string{ gForestTempleRoom12MinimapTex }, + { + { 13, 80, 54 }, + }, + {} }, + { 830, + -1620, + std::string{ gForestTempleRoom13MinimapTex }, + { + { 15, 49, 50 }, + }, + {} }, + { 610, -1090, std::string{ gForestTempleRoom14MinimapTex }, {}, {} }, + { 580, + -1390, + std::string{ gForestTempleRoom15MinimapTex }, + { + { 7, 61, 61 }, + }, + {} }, + { 710, -1220, std::string{ gForestTempleRoom16MinimapTex }, {}, {} }, + { 980, + -1090, + std::string{ gForestTempleRoom17MinimapTex }, + { + { 11, 39, 63 }, + }, + { + { -1, 53, 5 }, + } }, + { 1640, + -1290, + std::string{ gForestTempleRoom18MinimapTex }, + { + { 2, 66, 57 }, + }, + {} }, + { 1510, + -1410, + std::string{ gForestTempleRoom19MinimapTex }, + { + { 14, 64, 31 }, + }, + {} }, + { 590, -1390, std::string{ gForestTempleRoom20MinimapTex }, {}, {} }, + { 1610, -1600, std::string{ gForestTempleRoom21MinimapTex }, {}, {} }, + { 1130, + -660, + std::string{ gForestTempleRoom0Floor3MinimapTex }, + { + { 3, 63, 56 }, + }, + {} }, + { 1130, + -1630, + std::string{ gForestTempleRoom6Floor3MinimapTex }, + { + { 12, 69, 59 }, + }, + {} }, + { 820, -1290, std::string{ gForestTempleRoom7Floor3MinimapTex }, {}, {} }, + { 1320, -1290, std::string{ gForestTempleRoom8Floor3MinimapTex }, {}, {} }, + { 1620, + -1080, + std::string{ gForestTempleRoom11Floor3MinimapTex }, + { + { 4, 73, 54 }, + }, + {} }, + }, + { + { 0, 22, 4 }, + { 6, 23, 4 }, + { 7, 24, 4 }, + { 8, 25, 4 }, + { 11, 26, 4 }, + { 22, 0, 5 }, + { 23, 6, 5 }, + { 24, 7, 5 }, + { 25, 8, 5 }, + { 26, 11, 5 }, + }, + }, + {} }, + { // SCENE_FIRE_TEMPLE + "HIDAN_scene", + "Fire Temple", + "g_pn_03", + SDC_FIRE_TEMPLE, + { false, false, false, false, false, false, false, false, false, false, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 4, 4, 1070, -690 }, + {}, + { + 7, + { 1, 6, 7, 2, 3, 4, 6, 10, 6, 10, 7, 9, 11, 1, 12, 3, 11, 4, 5, 8, 9, 10, 11, 12, 13, 2 }, + std::string{ gPauseFireTitleENGTex }, + std::string{ gPauseFireTitleGERTex }, + std::string{ gPauseFireTitleFRATex }, + { + { + F_NA, + 9999.0f, + {}, + std::string{}, + std::string{}, + {}, + {}, + }, + { + F_NA, + 9999.0f, + {}, + std::string{}, + std::string{}, + {}, + {}, + }, + { + F_NA, + 9999.0f, + {}, + std::string{}, + std::string{}, + {}, + {}, + }, + { + F_5F, + 4360.0f, + { + 7, + 8, + 12, + 13, + }, + std::string{ gFireTemplePauseScreenMapFloor5LeftTex }, + std::string{ gFireTemplePauseScreenMapFloor5RightTex }, + { { 5, 22.0f, -41.0f }, { 13, 74.0f, -29.0f } }, + {}, + }, + { + F_4F, + 3640.0f, + { + 5, + 6, + 7, + 10, + 11, + 12, + 13, + 14, + 24, + }, + std::string{ gFireTemplePauseScreenMapFloor4LeftTex }, + std::string{ gFireTemplePauseScreenMapFloor4RightTex }, + {}, + {}, + }, + { + F_3F, + 2760.0f, + { + 4, + 5, + 6, + 9, + 10, + 11, + 16, + 23, + 24, + 25, + }, + std::string{ gFireTemplePauseScreenMapFloor3LeftTex }, + std::string{ gFireTemplePauseScreenMapFloor3RightTex }, + { { 3, 76.0f, -48.0f }, + { 6, 72.0f, -50.0f }, + { 7, 44.0f, -17.0f }, + { 8, 63.0f, -12.0f }, + { 9, 30.0f, -34.0f }, + { 10, 61.0f, -31.0f } }, + {}, + }, + { + F_2F, + 2020.0f, + { + 4, + 6, + 10, + 21, + }, + std::string{ gFireTemplePauseScreenMapFloor2LeftTex }, + std::string{ gFireTemplePauseScreenMapFloor2RightTex }, + { { 11, 78.0f, -34.0f } }, + {}, + }, + { + F_1F, + -140.0f, + { + 0, + 1, + 2, + 3, + 15, + 17, + 18, + 19, + 20, + 21, + 22, + }, + std::string{ gFireTemplePauseScreenMapFloor1LeftTex }, + std::string{ gFireTemplePauseScreenMapFloor1RightTex }, + { { 0, 48.0f, -17.0f }, + { 1, 35.0f, -45.0f }, + { 2, 67.0f, -58.0f }, + { 4, 74.0f, -15.0f }, + { 12, 47.0f, -27.0f } }, + { { -1, 26.0f, -34.0f } }, + }, + }, + { + { 1160, -580, std::string{ gFireTempleRoom0MinimapTex }, {}, {} }, + { 620, -620, std::string{ gFireTempleRoom1MinimapTex }, {}, {} }, + { 1330, + -700, + std::string{ gFireTempleRoom2MinimapTex }, + { + { 1, 53, 70 }, + }, + { + { -1, 40, 47 }, + } }, + { 1280, + -1150, + std::string{ gFireTempleRoom3MinimapTex }, + { + { 0, 71, 60 }, + }, + {} }, + { 440, + -710, + std::string{ gFireTempleRoom4Floor1MinimapTex }, + { + { 11, 59, 46 }, + }, + {} }, + { 600, + -670, + std::string{ gFireTempleRoom5Floor1MinimapTex }, + { + { 6, 57, 73 }, + { 3, 66, 71 }, + }, + {} }, + { 810, -850, std::string{ gFireTempleRoom6Floor1MinimapTex }, {}, {} }, + { 830, -1000, std::string{ gFireTempleRoom7Floor1MinimapTex }, {}, {} }, + { 720, + -720, + std::string{ gFireTempleRoom8MinimapTex }, + { + { 13, 72, 38 }, + }, + {} }, + { 1170, -840, std::string{ gFireTempleRoom9MinimapTex }, {}, {} }, + { 1490, -870, std::string{ gFireTempleRoom10Floor1MinimapTex }, {}, {} }, + { 1640, + -840, + std::string{ gFireTempleRoom11Floor1MinimapTex }, + { + { 9, 80, 61 }, + }, + {} }, + { 1870, -790, std::string{ gFireTempleRoom12Floor1MinimapTex }, {}, {} }, + { 1800, -1000, std::string{ gFireTempleRoom13Floor1MinimapTex }, {}, {} }, + { 1610, -980, std::string{ gFireTempleRoom14MinimapTex }, {}, {} }, + { 1130, -900, std::string{ gFireTempleRoom15MinimapTex }, {}, {} }, + { 860, + -660, + std::string{ gFireTempleRoom16MinimapTex }, + { + { 10, 71, 36 }, + }, + {} }, + { 1310, + -910, + std::string{ gFireTempleRoom17MinimapTex }, + { + { 12, 77, 58 }, + }, + {} }, + { 1140, -1130, std::string{ gFireTempleRoom18MinimapTex }, {}, {} }, + { 850, -1230, std::string{ gFireTempleRoom19MinimapTex }, {}, {} }, + { 760, + -1300, + std::string{ gFireTempleRoom20MinimapTex }, + { + { 4, 78, 59 }, + }, + {} }, + { 380, -810, std::string{ gFireTempleRoom21Floor1MinimapTex }, {}, {} }, + { 800, + -380, + std::string{ gFireTempleRoom22MinimapTex }, + { + { 2, 71, 68 }, + }, + {} }, + { 800, + -1270, + std::string{ gFireTempleRoom23MinimapTex }, + { + { 8, 66, 58 }, + }, + {} }, + { 1930, -820, std::string{ gFireTempleRoom24Floor1MinimapTex }, {}, {} }, + { 1410, + -1120, + std::string{ gFireTempleRoom25MinimapTex }, + { + { 7, 77, 54 }, + }, + {} }, + { 640, -880, std::string{ gFireTempleRoom4Floor3MinimapTex }, {}, {} }, + { 845, -1070, std::string{ gFireTempleRoom5Floor3MinimapTex }, {}, {} }, + { 810, -850, std::string{ gFireTempleRoom6Floor2MinimapTex }, {}, {} }, + { 810, -850, std::string{ gFireTempleRoom6Floor3MinimapTex }, {}, {} }, + { 850, -1060, std::string{ gFireTempleRoom7Floor3MinimapTex }, {}, {} }, + { 1390, -640, std::string{ gFireTempleRoom10Floor2MinimapTex }, {}, {} }, + { 1540, -900, std::string{ gFireTempleRoom10Floor3MinimapTex }, {}, {} }, + { 1650, -850, std::string{ gFireTempleRoom11Floor3MinimapTex }, {}, {} }, + { 1880, -890, std::string{ gFireTempleRoom12Floor3MinimapTex }, {}, {} }, + { 1530, + -740, + std::string{ gFireTempleRoom13Floor3MinimapTex }, + { + { 5, 49, 62 }, + }, + {} }, + { 420, -880, std::string{ gFireTempleRoom21Floor3MinimapTex }, {}, {} }, + { 1950, -840, std::string{ gFireTempleRoom24Floor3MinimapTex }, {}, {} }, + }, + { + { 21, 36, 6 }, { 4, 26, 5 }, { 6, 28, 5 }, { 10, 31, 5 }, { 5, 27, 4 }, { 11, 33, 4 }, { 24, 37, 4 }, + { 28, 29, 4 }, { 31, 32, 4 }, { 10, 32, 4 }, { 7, 30, 3 }, { 12, 34, 3 }, { 13, 35, 3 }, { 30, 7, 4 }, + { 34, 12, 4 }, { 35, 13, 4 }, { 27, 5, 5 }, { 33, 11, 5 }, { 37, 24, 5 }, { 29, 28, 5 }, { 32, 31, 5 }, + { 26, 4, 6 }, { 28, 6, 6 }, { 31, 10, 6 }, { 36, 21, 7 }, + }, + }, + {} }, + { // SCENE_WATER_TEMPLE + "MIZUsin_scene", + "Water Temple", + "g_pn_04", + SDC_WATER_TEMPLE, + { false, false, false, false, false, false, false, false, false, false, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 4, 4, 900, -640 }, + {}, + { + 4, + { 1, 2, 10, 3, 3, 4, 5, 13, 5, 6, 7, 8, 7, 9, 8, 9, 11, 10, 12, 11, 12, 13, 9, 7, 8, 12 }, + std::string{ gPauseWaterTitleENGTex }, + std::string{ gPauseWaterTitleGERTex }, + std::string{ gPauseWaterTitleFRATex }, + { + { + F_NA, + 9999.0f, + {}, + std::string{}, + std::string{}, + {}, + {}, + }, + { + F_NA, + 9999.0f, + {}, + std::string{}, + std::string{}, + {}, + {}, + }, + { + F_NA, + 9999.0f, + {}, + std::string{}, + std::string{}, + {}, + {}, + }, + { + F_NA, + 9999.0f, + {}, + std::string{}, + std::string{}, + {}, + {}, + }, + { + F_3F, + 690.0f, + { + 0, + 1, + 4, + 5, + 6, + 7, + 10, + 11, + 13, + 17, + 19, + 20, + }, + std::string{ gWaterTemplePauseScreenMapFloor3LeftTex }, + std::string{ gWaterTemplePauseScreenMapFloor3RightTex }, + { { 2, 88.0f, -60.0f }, { 7, 23.0f, -2.0f }, { 9, 84.0f, -45.0f } }, + { { -1, 62.0f, -23.0f } }, + }, + { + F_2F, + 330.0f, + { + 0, + 1, + 4, + 5, + 6, + 10, + 17, + 20, + 21, + }, + std::string{ gWaterTemplePauseScreenMapFloor2LeftTex }, + std::string{ gWaterTemplePauseScreenMapFloor2RightTex }, + { { 0, 86.0f, -60.0f }, { 8, 76.0f, -72.0f } }, + {}, + }, + { + F_1F, + -160.0f, + { + 0, + 1, + 3, + 5, + 8, + 9, + 12, + 14, + 15, + 16, + 17, + 18, + 21, + }, + std::string{ gWaterTemplePauseScreenMapFloor1LeftTex }, + std::string{ gWaterTemplePauseScreenMapFloor1RightTex }, + { { 1, 88.0f, -60.0f }, { 3, 42.0f, -21.0f }, { 5, 47.0f, -15.0f }, { 10, 33.0f, -31.0f } }, + {}, + }, + { + F_B1, + -3000.0f, + { + 0, + 1, + 2, + 3, + 5, + 8, + 9, + 12, + 14, + 15, + }, + std::string{ gWaterTemplePauseScreenMapBasement1LeftTex }, + std::string{ gWaterTemplePauseScreenMapBasement1RightTex }, + { { 6, 77.0f, -66.0f } }, + {}, + }, + }, + { + { 1120, -610, std::string{ gWaterTempleRoom0Floor3MinimapTex }, {}, {} }, + { 1290, -930, std::string{ gWaterTempleRoom1Floor3MinimapTex }, {}, {} }, + { 1120, + -770, + std::string{ gWaterTempleRoom2MinimapTex }, + { + { 6, 79, 68 }, + }, + {} }, + { 1380, -680, std::string{ gWaterTempleRoom3Floor3MinimapTex }, {}, {} }, + { 930, + -1060, + std::string{ gWaterTempleRoom4Floor3MinimapTex }, + { + { 9, 81, 62 }, + }, + {} }, + { 1520, -930, std::string{ gWaterTempleRoom5Floor3MinimapTex }, {}, {} }, + { 1980, -980, std::string{ gWaterTempleRoom6MinimapTex }, {}, {} }, + { 2010, + -1860, + std::string{ gWaterTempleRoom7MinimapTex }, + { + { 7, 74, 62 }, + }, + {} }, + { 1590, + -1380, + std::string{ gWaterTempleRoom8Floor3MinimapTex }, + { + { 10, 57, 66 }, + }, + {} }, + { 1510, -1050, std::string{ gWaterTempleRoom9Floor3MinimapTex }, {}, {} }, + { 1500, -830, std::string{ gWaterTempleRoom10Floor3MinimapTex }, {}, {} }, + { 1300, + -1230, + std::string{ gWaterTempleRoom11MinimapTex }, + {}, + { + { -1, 77, 40 }, + } }, + { 1240, -1380, std::string{ gWaterTempleRoom12Floor3MinimapTex }, {}, {} }, + { 1800, -1330, std::string{ gWaterTempleRoom13MinimapTex }, {}, {} }, + { 1290, -1750, std::string{ gWaterTempleRoom14Floor3MinimapTex }, {}, {} }, + { 1450, -1610, std::string{ gWaterTempleRoom15Floor3MinimapTex }, {}, {} }, + { 1560, + -1600, + std::string{ gWaterTempleRoom16MinimapTex }, + { + { 5, 76, 64 }, + }, + {} }, + { 880, -830, std::string{ gWaterTempleRoom17Floor3MinimapTex }, {}, {} }, + { 820, + -800, + std::string{ gWaterTempleRoom18MinimapTex }, + { + { 1, 74, 61 }, + }, + {} }, + { 820, + -820, + std::string{ gWaterTempleRoom19MinimapTex }, + { + { 2, 74, 63 }, + }, + {} }, + { 1060, -690, std::string{ gWaterTempleRoom20Floor3MinimapTex }, {}, {} }, + { 1670, -1540, std::string{ gWaterTempleRoom21Floor3MinimapTex }, {}, {} }, + { 1120, -620, std::string{ gWaterTempleRoom0Floor2MinimapTex }, {}, {} }, + { 1130, -790, std::string{ gWaterTempleRoom0Floor1MinimapTex }, {}, {} }, + { 1130, -780, std::string{ gWaterTempleRoom0Basement1MinimapTex }, {}, {} }, + { 1290, -930, std::string{ gWaterTempleRoom1Floor2MinimapTex }, {}, {} }, + { 1290, -930, std::string{ gWaterTempleRoom1Floor1MinimapTex }, {}, {} }, + { 1280, -870, std::string{ gWaterTempleRoom1Basement1MinimapTex }, {}, {} }, + { 1390, -690, std::string{ gWaterTempleRoom3Basement1MinimapTex }, {}, {} }, + { 940, -1050, std::string{ gWaterTempleRoom4Floor2MinimapTex }, {}, {} }, + { 1520, -930, std::string{ gWaterTempleRoom5Floor2MinimapTex }, {}, {} }, + { 1520, -930, std::string{ gWaterTempleRoom5Floor1MinimapTex }, {}, {} }, + { 1980, -980, std::string{ gWaterTempleRoom6Floor2MinimapTex }, {}, {} }, + { 1620, -1370, std::string{ gWaterTempleRoom8Basement1MinimapTex }, {}, {} }, + { 1510, -1050, std::string{ gWaterTempleRoom9Basement1MinimapTex }, {}, {} }, + { 1490, -800, std::string{ gWaterTempleRoom10Floor2MinimapTex }, {}, {} }, + { 1240, -1380, std::string{ gWaterTempleRoom12Basement1MinimapTex }, {}, {} }, + { 1290, -1750, std::string{ gWaterTempleRoom14Basement1MinimapTex }, {}, {} }, + { 1450, -1610, std::string{ gWaterTempleRoom15Basement1MinimapTex }, {}, {} }, + { 880, + -840, + std::string{ gWaterTempleRoom17Floor2MinimapTex }, + { + { 0, 74, 64 }, + }, + {} }, + { 880, -830, std::string{ gWaterTempleRoom17Floor1MinimapTex }, {}, {} }, + { 1060, + -690, + std::string{ gWaterTempleRoom20Floor2MinimapTex }, + { + { 8, 75, 67 }, + }, + {} }, + { 1670, + -1540, + std::string{ gWaterTempleRoom21Floor1MinimapTex }, + { + { 3, 82, 65 }, + }, + {} }, + { 1520, -930, std::string{ gWaterTempleRoom5Basement1MinimapTex }, {}, {} }, + }, + { + { 0, 22, 5 }, { 1, 25, 5 }, { 4, 29, 5 }, { 5, 30, 5 }, { 6, 32, 5 }, { 10, 35, 5 }, { 17, 39, 5 }, + { 20, 41, 5 }, { 0, 23, 6 }, { 1, 26, 6 }, { 22, 23, 6 }, { 25, 26, 6 }, { 30, 31, 6 }, { 39, 40, 6 }, + { 21, 42, 6 }, { 17, 40, 6 }, { 0, 24, 7 }, { 1, 27, 7 }, { 23, 24, 7 }, { 26, 27, 7 }, { 3, 28, 7 }, + { 9, 34, 7 }, { 12, 36, 7 }, { 14, 37, 7 }, { 15, 38, 7 }, { 31, 43, 7 }, { 8, 33, 7 }, { 24, 23, 6 }, + { 27, 26, 6 }, { 28, 3, 6 }, { 33, 8, 6 }, { 36, 12, 6 }, { 37, 14, 6 }, { 38, 15, 6 }, { 43, 31, 6 }, + { 34, 9, 6 }, { 23, 22, 5 }, { 26, 25, 5 }, { 31, 30, 5 }, { 40, 39, 5 }, { 42, 21, 5 }, { 17, 39, 5 }, + { 22, 0, 4 }, { 25, 1, 4 }, { 29, 4, 4 }, { 30, 5, 4 }, { 32, 6, 4 }, { 35, 10, 4 }, { 39, 17, 4 }, + { 41, 20, 4 }, + }, + }, + {} }, + { // SCENE_SPIRIT_TEMPLE + "jyasinzou_scene", + "Spirit Temple", + "g_pn_05", + SDC_SPIRIT_TEMPLE, + { false, false, false, false, false, false, false, false, false, false, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 3, 3, 900, -640 }, + {}, + { + 5, + { 10, 1, 2, 3, 4, 5, 10, 7, 8, 9, 10, 6, 12, 13, 11, 8, 13, 1, 2, 3, 4, 11, 6, 12, 8, 5, 10, 9, 6 }, + std::string{ gPauseSpiritTitleENGTex }, + std::string{ gPauseSpiritTitleGERTex }, + std::string{ gPauseSpiritTitleFRATex }, + { + { + F_NA, + 9999.0f, + {}, + std::string{}, + std::string{}, + {}, + {}, + }, + { + F_NA, + 9999.0f, + {}, + std::string{}, + std::string{}, + {}, + {}, + }, + { + F_NA, + 9999.0f, + {}, + std::string{}, + std::string{}, + {}, + {}, + }, + { + F_NA, + 9999.0f, + {}, + std::string{}, + std::string{}, + {}, + {}, + }, + { + F_4F, + 1480.0f, + { + 22, + 23, + 24, + 25, + 26, + }, + std::string{ gSpiritTemplePauseScreenMapFloor4LeftTex }, + std::string{ gSpiritTemplePauseScreenMapFloor4RightTex }, + { { 10, 59.0f, -9.0f }, { 18, 32.0f, -20.0f } }, + {}, + }, + { + F_3F, + 760.0f, + { + 5, + 7, + 8, + 9, + 10, + 11, + 16, + 17, + 18, + 19, + 20, + 21, + 23, + }, + std::string{ gSpiritTemplePauseScreenMapFloor3LeftTex }, + std::string{ gSpiritTemplePauseScreenMapFloor3RightTex }, + { { 1, 20.0f, -43.0f }, + { 5, 83.0f, -26.0f }, + { 15, 57.0f, -14.0f }, + { 20, 81.0f, -55.0f }, + { 21, 87.0f, -55.0f } }, + { { -1, 47.0f, 0.0f } }, + }, + { + F_2F, + 280.0f, + { + 4, + 5, + 6, + 15, + }, + std::string{ gSpiritTemplePauseScreenMapFloor2LeftTex }, + std::string{ gSpiritTemplePauseScreenMapFloor2RightTex }, + { { 2, 41.0f, -16.0f }, + { 3, 47.0f, -17.0f }, + { 6, 27.0f, -16.0f }, + { 12, 29.0f, -20.0f }, + { 13, 70.0f, -22.0f }, + { 14, 70.0f, -25.0f } }, + {}, + }, + { + F_1F, + -3000.0f, + { + 0, + 1, + 2, + 3, + 4, + 12, + 13, + 14, + 15, + 27, + }, + std::string{ gSpiritTemplePauseScreenMapFloor1LeftTex }, + std::string{ gSpiritTemplePauseScreenMapFloor1RightTex }, + { { 0, 38.0f, -17.0f }, { 4, 55.0f, -14.0f }, { 8, 15.0f, -14.0f }, { 7, 78.0f, -3.0f } }, + {}, + }, + }, + { + { 800, -570, std::string{ gSpiritTempleRoom0MinimapTex }, {}, {} }, + { 1500, -900, std::string{ gSpiritTempleRoom1MinimapTex }, {}, {} }, + { 1370, + -1070, + std::string{ gSpiritTempleRoom2MinimapTex }, + { + { 0, 78, 43 }, + }, + {} }, + { 1730, + -1090, + std::string{ gSpiritTempleRoom3MinimapTex }, + { + { 8, 69, 40 }, + }, + {} }, + { 1590, -1280, std::string{ gSpiritTempleRoom4Floor1MinimapTex }, {}, {} }, + { 1020, + -1160, + std::string{ gSpiritTempleRoom5Floor2MinimapTex }, + { + { 2, 43, 50 }, + { 3, 56, 54 }, + }, + {} }, + { 1060, -920, std::string{ gSpiritTempleRoom6MinimapTex }, {}, {} }, + { 1470, -980, std::string{ gSpiritTempleRoom7MinimapTex }, {}, {} }, + { 1600, + -780, + std::string{ gSpiritTempleRoom8MinimapTex }, + { + { 1, 70, 67 }, + }, + {} }, + { 1830, -530, std::string{ gSpiritTempleRoom9MinimapTex }, {}, {} }, + { 1630, -350, std::string{ gSpiritTempleRoom10MinimapTex }, {}, {} }, + { 2000, -1000, std::string{ gBlankSpiritTempleRoom11MinimapTex }, {}, {} }, + { 650, + -1440, + std::string{ gSpiritTempleRoom12MinimapTex }, + { + { 7, 70, 58 }, + }, + {} }, + { 660, -1080, std::string{ gSpiritTempleRoom13MinimapTex }, {}, {} }, + { 1020, + -1100, + std::string{ gSpiritTempleRoom14MinimapTex }, + { + { 4, 68, 42 }, + }, + {} }, + { 880, -1110, std::string{ gSpiritTempleRoom15Floor1MinimapTex }, {}, {} }, + { 940, -980, std::string{ gSpiritTempleRoom16MinimapTex }, {}, {} }, + { 720, -860, std::string{ gSpiritTempleRoom17MinimapTex }, {}, {} }, + { 570, -790, std::string{ gSpiritTempleRoom18MinimapTex }, {}, {} }, + { 620, + -540, + std::string{ gSpiritTempleRoom19MinimapTex }, + { + { 20, 75, 58 }, + { 21, 83, 58 }, + }, + {} }, + { 570, -350, std::string{ gSpiritTempleRoom20MinimapTex }, {}, {} }, + { 550, + -1000, + std::string{ gSpiritTempleRoom21MinimapTex }, + { + { 5, 71, 55 }, + }, + {} }, + { 970, + -1250, + std::string{ gSpiritTempleRoom22MinimapTex }, + { + { 10, 72, 49 }, + }, + {} }, + { 920, -820, std::string{ gSpiritTempleRoom23Floor3MinimapTex }, {}, {} }, + { 1040, -1070, std::string{ gSpiritTempleRoom24MinimapTex }, {}, {} }, + { 1150, -1180, std::string{ gSpiritTempleRoom25MinimapTex }, {}, {} }, + { 1200, + -950, + std::string{ gSpiritTempleRoom26MinimapTex }, + { + { 18, 50, 41 }, + }, + {} }, + { 1550, -1380, std::string{ gSpiritTempleRoom27MinimapTex }, {}, {} }, + { 1520, + -1160, + std::string{ gSpiritTempleRoom4Floor2MinimapTex }, + { + { 6, 73, 49 }, + { 12, 79, 55 }, + }, + {} }, + { 1020, + -1100, + std::string{ gSpiritTempleRoom5Floor3MinimapTex }, + { + { 15, 77, 42 }, + }, + { + { -1, 57, 23 }, + } }, + { 820, + -1150, + std::string{ gSpiritTempleRoom15Floor2MinimapTex }, + { + { 13, 77, 63 }, + { 14, 77, 68 }, + }, + {} }, + { 1010, -830, std::string{ gSpiritTempleRoom23Floor4MinimapTex }, {}, {} }, + }, + { + { 4, 28, 6 }, + { 15, 30, 6 }, + { 5, 29, 5 }, + { 23, 31, 4 }, + { 31, 23, 5 }, + { 29, 5, 6 }, + { 28, 4, 7 }, + { 30, 15, 7 }, + }, + }, + {} }, + { // SCENE_SHADOW_TEMPLE + "HAKAdan_scene", + "Shadow Temple", + "g_pn_02", + SDC_SHADOW_TEMPLE_AND_WELL, + { false, false, false, false, false, false, false, false, false, false, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 10, 10, 900, -640 }, + {}, + { + 7, + { 13, 1, 5, 4, 4, 5, 3, 7, 8, 9, 10, 11, 12, 13, 2, 5, 1, 1, 6, 7, 8, 3, 9, 7, 8, 12 }, + std::string{ gPauseShadowTitleENGTex }, + std::string{ gPauseShadowTitleGERTex }, + std::string{ gPauseShadowTitleFRATex }, + { + { + F_NA, + 9999.0f, + {}, + std::string{}, + std::string{}, + {}, + {}, + }, + { + F_NA, + 9999.0f, + {}, + std::string{}, + std::string{}, + {}, + {}, + }, + { + F_NA, + 9999.0f, + {}, + std::string{}, + std::string{}, + {}, + {}, + }, + { + F_NA, + 9999.0f, + {}, + std::string{}, + std::string{}, + {}, + {}, + }, + { + F_B1, + -343.3f, + { + 0, + 1, + 2, + 4, + }, + std::string{ gShadowTemplePauseScreenMapBasement1LeftTex }, + std::string{ gShadowTemplePauseScreenMapBasement1RightTex }, + { { 1, 41.0f, -17.0f }, { 7, 27.0f, -24.0f } }, + {}, + }, + { + F_B2, + -863.3f, + { + 5, + 6, + 7, + 8, + }, + std::string{ gShadowTemplePauseScreenMapBasement2LeftTex }, + std::string{ gShadowTemplePauseScreenMapBasement2RightTex }, + { { 2, 81.0f, -20.0f }, { 3, 74.0f, -37.0f } }, + {}, + }, + { + F_B3, + -1143.3f, + { + 8, + 9, + 12, + 14, + 16, + 21, + }, + std::string{ gShadowTemplePauseScreenMapBasement3LeftTex }, + std::string{ gShadowTemplePauseScreenMapBasement3RightTex }, + { { 12, 96.0f, -51.0f }, { 22, 96.0f, -55.0f } }, + {}, + }, + { + F_B4, + -3000.0f, + { + 3, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 17, + 18, + 19, + 20, + 21, + }, + std::string{ gShadowTemplePauseScreenMapBasement4LeftTex }, + std::string{ gShadowTemplePauseScreenMapBasement4RightTex }, + { { 4, 43.0f, -66.0f }, + { 5, 37.0f, -66.0f }, + { 6, 33.0f, -72.0f }, + { 8, 85.0f, -18.0f }, + { 9, 61.0f, -42.0f }, + { 10, 15.0f, -4.0f }, + { 11, 25.0f, -4.0f }, + { 13, 19.0f, -29.0f }, + { 21, 92.0f, -29.0f }, + { 20, 87.0f, -20.0f } }, + { { -1, 31.0f, -45.0f } }, + }, + }, + { + { 1320, -940, std::string{ gShadowTempleRoom0MinimapTex }, {}, {} }, + { 1320, + -960, + std::string{ gShadowTempleRoom1MinimapTex }, + { + { 1, 77, 64 }, + }, + {} }, + { 1090, -860, std::string{ gShadowTempleRoom2MinimapTex }, {}, {} }, + { 1510, + -870, + std::string{ gShadowTempleRoom3MinimapTex }, + {}, + { + { -1, 77, 76 }, + } }, + { 1480, + -920, + std::string{ gShadowTempleRoom4MinimapTex }, + { + { 7, 76, 65 }, + }, + {} }, + { 940, -870, std::string{ gShadowTempleRoom5MinimapTex }, {}, {} }, + { 920, + -980, + std::string{ gShadowTempleRoom6MinimapTex }, + { + { 2, 83, 67 }, + }, + {} }, + { 910, + -820, + std::string{ gShadowTempleRoom7MinimapTex }, + { + { 3, 76, 67 }, + }, + {} }, + { 800, -860, std::string{ gShadowTempleRoom8Basement2MinimapTex }, {}, {} }, + { 820, -520, std::string{ gShadowTempleRoom9Basement3MinimapTex }, {}, {} }, + { 1150, + -500, + std::string{ gShadowTempleRoom10MinimapTex }, + { + { 4, 78, 62 }, + { 5, 74, 62 }, + { 6, 71, 68 }, + }, + {} }, + { 1000, + -780, + std::string{ gShadowTempleRoom11MinimapTex }, + { + { 9, 77, 64 }, + }, + {} }, + { 1800, -1050, std::string{ gShadowTempleRoom12Basement3MinimapTex }, {}, {} }, + { 1660, + -1130, + std::string{ gShadowTempleRoom13MinimapTex }, + { + { 10, 71, 65 }, + { 11, 80, 65 }, + }, + {} }, + { 1090, -770, std::string{ gShadowTempleRoom14Basement3MinimapTex }, {}, {} }, + { 1630, -1010, std::string{ gShadowTempleRoom15MinimapTex }, {}, {} }, + { 710, + -680, + std::string{ gShadowTempleRoom16MinimapTex }, + { + { 12, 87, 64 }, + { 22, 87, 68 }, + }, + {} }, + { 1670, + -930, + std::string{ gShadowTempleRoom17MinimapTex }, + { + { 13, 77, 66 }, + }, + {} }, + { 830, -880, std::string{ gShadowTempleRoom18MinimapTex }, {}, {} }, + { 770, + -900, + std::string{ gShadowTempleRoom19MinimapTex }, + { + { 21, 78, 66 }, + }, + {} }, + { 800, + -980, + std::string{ gShadowTempleRoom20MinimapTex }, + { + { 8, 76, 66 }, + { 20, 78, 68 }, + }, + {} }, + { 850, -990, std::string{ gShadowTempleRoom21Basement3MinimapTex }, {}, {} }, + { 830, -770, std::string{ gShadowTempleRoom8Basement3MinimapTex }, {}, {} }, + { 820, -520, std::string{ gShadowTempleRoom9Basement4MinimapTex }, {}, {} }, + { 1800, -1050, std::string{ gShadowTempleRoom12Basement4MinimapTex }, {}, {} }, + { 1090, -770, std::string{ gShadowTempleRoom14Basement4MinimapTex }, {}, {} }, + { 850, -990, std::string{ gShadowTempleRoom21Basement4MinimapTex }, {}, {} }, + }, + { + { 8, 22, 6 }, + { 9, 23, 7 }, + { 12, 24, 7 }, + { 14, 25, 7 }, + { 21, 26, 7 }, + { 23, 9, 6 }, + { 24, 12, 6 }, + { 25, 14, 6 }, + { 26, 21, 6 }, + { 22, 8, 5 }, + }, + }, + {} }, + { // SCENE_BOTTOM_OF_THE_WELL + "HAKAdanCH_scene", + "Bottom of the Well", + "g_pn_54", + SDC_SHADOW_TEMPLE_AND_WELL, + { false, false, false, false, false, false, false, false, false, false, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 5, 5, 900, -640 }, + {}, + { + -1, + { 13, 1, 2, 3, 4, 5, 6 }, + std::string{ gPauseBotWTitleENGTex }, + std::string{ gPauseBotWTitleGERTex }, + std::string{ gPauseBotWTitleFRATex }, + { + { + F_NA, + 9999.0f, + {}, + std::string{}, + std::string{}, + {}, + {}, + }, + { + F_NA, + 9999.0f, + {}, + std::string{}, + std::string{}, + {}, + {}, + }, + { + F_NA, + 9999.0f, + {}, + std::string{}, + std::string{}, + {}, + {}, + }, + { + F_NA, + 9999.0f, + {}, + std::string{}, + std::string{}, + {}, + {}, + }, + { + F_NA, + 9999.0f, + {}, + std::string{}, + std::string{}, + {}, + {}, + }, + { + F_B1, + -100.0f, + { + 0, + 1, + 2, + 3, + 4, + 5, + 6, + }, + std::string{ gBottomOfTheWellPauseScreenMapBasement1LeftTex }, + std::string{ gBottomOfTheWellPauseScreenMapBasement1RightTex }, + { { 1, 51.0f, -24.0f }, + { 3, 84.0f, -38.0f }, + { 4, 31.0f, -2.0f }, + { 5, 67.0f, -27.0f }, + { 8, 46.0f, -27.0f }, + { 10, 82.0f, -12.0f }, + { 12, 80.0f, -16.0f }, + { 14, 62.0f, -24.0f }, + { 20, 89.0f, -38.0f } }, + {}, + }, + { + F_B2, + -520.0f, + { + 0, + 1, + }, + std::string{ gBottomOfTheWellPauseScreenMapBasement2LeftTex }, + std::string{ gBottomOfTheWellPauseScreenMapBasement2RightTex }, + { { 2, 54.0f, -27.0f }, { 9, 28.0f, -17.0f }, { 16, 56.0f, -38.0f } }, + {}, + }, + { + F_B3, + -3000.0f, + { + 1, + }, + std::string{ gBottomOfTheWellPauseScreenMapBasement3LeftTex }, + std::string{ gBottomOfTheWellPauseScreenMapBasement3RightTex }, + { { 7, 71.0f, -33.0f } }, + {}, + }, + }, + { + { 1080, + -570, + std::string{ gBottomOfTheWellRoom0Basement1MinimapTex }, + { + { 1, 56, 26 }, + { 4, 39, 3 }, + { 5, 69, 30 }, + { 8, 53, 30 }, + { 12, 83, 16 }, + { 14, 67, 26 }, + }, + {} }, + { 1420, -930, std::string{ gBottomOfTheWellRoom1Basement1MinimapTex }, {}, {} }, + { 1620, -1040, std::string{ gBottomOfTheWellRoom2MinimapTex }, {}, {} }, + { 1040, + -1100, + std::string{ gBottomOfTheWellRoom3MinimapTex }, + { + { 10, 79, 67 }, + }, + {} }, + { 940, + -800, + std::string{ gBottomOfTheWellRoom4MinimapTex }, + { + { 3, 73, 62 }, + { 20, 81, 62 }, + }, + {} }, + { 1190, -1100, std::string{ gBottomOfTheWellRoom5MinimapTex }, {}, {} }, + { 1310, -1100, std::string{ gBottomOfTheWellRoom6MinimapTex }, {}, {} }, + { 1090, + -570, + std::string{ gBottomOfTheWellRoom0Basement2MinimapTex }, + { + { 2, 59, 28 }, + { 9, 36, 19 }, + { 16, 62, 38 }, + }, + {} }, + { 1380, -930, std::string{ gBottomOfTheWellRoom1Basement2MinimapTex }, {}, {} }, + { 1080, + -890, + std::string{ gBottomOfTheWellRoom1Basement3MinimapTex }, + { + { 7, 75, 66 }, + }, + {} }, + }, + { + { 0, 7, 6 }, + { 1, 8, 6 }, + { 8, 9, 7 }, + { 9, 8, 6 }, + { 7, 0, 5 }, + { 8, 1, 5 }, + }, + }, + {} }, + { // SCENE_ICE_CAVERN + "ice_doukutu_scene", + "Ice Cavern", + "g_pn_10", + SDC_ICE_CAVERN, + { false, false, false, false, false, false, false, false, true, false, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 3, 3, 900, -640 }, + {}, + { + -1, + { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }, + std::string{ gPauseIceCavernTitleENGTex }, + std::string{ gPauseIceCavernTitleGERTex }, + std::string{ gPauseIceCavernTitleFRATex }, + { + { + F_NA, + 9999.0f, + {}, + std::string{}, + std::string{}, + {}, + {}, + }, + { + F_NA, + 9999.0f, + {}, + std::string{}, + std::string{}, + {}, + {}, + }, + { + F_NA, + 9999.0f, + {}, + std::string{}, + std::string{}, + {}, + {}, + }, + { + F_NA, + 9999.0f, + {}, + std::string{}, + std::string{}, + {}, + {}, + }, + { + F_NA, + 9999.0f, + {}, + std::string{}, + std::string{}, + {}, + {}, + }, + { + F_NA, + 9999.0f, + {}, + std::string{}, + std::string{}, + {}, + {}, + }, + { + F_NA, + 9999.0f, + {}, + std::string{}, + std::string{}, + {}, + {}, + }, + { + F_1F, + -3000.0f, + { + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + }, + std::string{ gIceCavernPauseScreenMapFloor1LeftTex }, + std::string{ gIceCavernPauseScreenMapFloor1RightTex }, + { { 0, 66.0f, -2.0f }, { 1, 77.0f, -46.0f }, { 2, 27.0f, -45.0f } }, + {}, + }, + }, + { + { 1070, 100, std::string{ gIceCavernRoom0MinimapTex }, {}, {} }, + { 1180, -280, std::string{ gIceCavernRoom1MinimapTex }, {}, {} }, + { 1270, -690, std::string{ gIceCavernRoom2MinimapTex }, {}, {} }, + { 990, -840, std::string{ gIceCavernRoom3MinimapTex }, {}, {} }, + { 1280, -1010, std::string{ gIceCavernRoom4MinimapTex }, {}, {} }, + { 1450, -950, std::string{ gIceCavernRoom5MinimapTex }, {}, {} }, + { 1680, -730, std::string{ gIceCavernRoom6MinimapTex }, {}, {} }, + { 1530, + -470, + std::string{ gIceCavernRoom7MinimapTex }, + { + { 2, 71, 59 }, + }, + {} }, + { 760, -1130, std::string{ gIceCavernRoom8MinimapTex }, {}, {} }, + { 860, + -1440, + std::string{ gIceCavernRoom9MinimapTex }, + { + { 0, 48, 36 }, + }, + {} }, + { 1500, -420, std::string{ gIceCavernRoom10MinimapTex }, {}, {} }, + { 800, + -700, + std::string{ gIceCavernRoom11MinimapTex }, + { + { 1, 73, 67 }, + }, + {} }, + }, + {}, + }, + {} }, + { // SCENE_GANONS_TOWER + "ganon_scene", + "Ganon's Tower", + "none", + SDC_DEFAULT, + { false, false, false, false, false, false, false, false, false, false, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_GERUDO_TRAINING_GROUND + "men_scene", + "Gerudo Training Ground", + "g_pn_11", + SDC_GERUDO_TRAINING_GROUND, + { false, false, false, false, false, false, false, true, false, true, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_THIEVES_HIDEOUT + "gerudoway_scene", + "Thieves' Hideout", + "g_pn_49", + SDC_THIEVES_HIDEOUT, + { false, false, false, false, false, false, false, false, false, true, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_INSIDE_GANONS_CASTLE + "ganontika_scene", + "Inside Ganon's Castle", + "g_pn_09", + SDC_INSIDE_GANONS_CASTLE, + { false, false, false, false, false, false, false, true, false, true, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_GANONS_TOWER_COLLAPSE_INTERIOR + "ganon_sonogo_scene", + "Ganon's Tower (Collapsing)", + "none", + SDC_GANONS_TOWER_COLLAPSE_INTERIOR, + { false, false, false, false, false, false, true, false, false, true, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_INSIDE_GANONS_CASTLE_COLLAPSE + "ganontikasonogo_scene", + "Inside Ganon's Castle (Collapsing)", + "none", + SDC_INSIDE_GANONS_CASTLE_COLLAPSE, + { false, false, false, false, false, false, true, false, false, true, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_TREASURE_BOX_SHOP + "takaraya_scene", + "Treasure Box Shop", + "g_pn_51", + SDC_DEFAULT, + { false, true, false, false, false, true, true, false, false, true, true, true }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_DEKU_TREE_BOSS + "ydan_boss_scene", + "Gohma's Lair", + "none", + SDC_DEKU_TREE_BOSS, + { false, false, false, false, true, false, true, false, false, true, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + { "ydan_scene" }, + {}, + {} }, + { // SCENE_DODONGOS_CAVERN_BOSS + "ddan_boss_scene", + "King Dodongo's Lair", + "none", + SDC_DEFAULT, + { false, false, false, false, true, false, true, false, false, true, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + { "ddan_scene" }, + {}, + {} }, + { // SCENE_JABU_JABU_BOSS + "bdan_boss_scene", + "Barinade's Lair", + "none", + SDC_JABU_JABU, + { false, false, false, false, true, false, true, false, false, true, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + { "bdan_scene" }, + {}, + {} }, + { // SCENE_FOREST_TEMPLE_BOSS + "moribossroom_scene", + "Phantom Ganon's Lair", + "none", + SDC_DEFAULT, + { false, false, false, false, true, false, true, false, false, true, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + { "Bmori1_scene" }, + {}, + {} }, + { // SCENE_FIRE_TEMPLE_BOSS + "FIRE_bs_scene", + "Volvagia's Lair", + "none", + SDC_FIRE_TEMPLE, + { false, false, false, false, true, false, true, false, false, true, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + { "HIDAN_scene" }, + {}, + {} }, + { // SCENE_WATER_TEMPLE_BOSS + "MIZUsin_bs_scene", + "Morpha's Lair", + "none", + SDC_WATER_TEMPLE_BOSS, + { false, false, false, false, true, false, true, false, false, true, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + { "MIZUsin_scene" }, + {}, + {} }, + { // SCENE_SPIRIT_TEMPLE_BOSS + "jyasinboss_scene", + "Twinrova's Lair & Nabooru's Mini-Boss Room", + "none", + SDC_DEFAULT, + { false, false, false, false, true, false, true, false, false, true, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + { "jyasinzou_scene" }, + {}, + {} }, + { // SCENE_SHADOW_TEMPLE_BOSS + "HAKAdan_bs_scene", + "Bongo Bongo's Lair", + "none", + SDC_SHADOW_TEMPLE_AND_WELL, + { false, false, false, false, true, false, true, false, false, true, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + { "HAKAdan_scene" }, + {}, + {} }, + { // SCENE_GANONDORF_BOSS + "ganon_boss_scene", + "Ganondorf's Lair", + "none", + SDC_DEFAULT, + { false, false, false, false, true, false, true, false, false, true, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + { "" }, + {}, + {} }, + { // SCENE_GANONS_TOWER_COLLAPSE_EXTERIOR + "ganon_final_scene", + "Tower Collapse Exterior", + "none", + SDC_GANONS_TOWER_COLLAPSE_EXTERIOR, + { false, false, false, false, false, false, true, false, false, true, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + { "" }, + {}, + {} }, + { // SCENE_MARKET_ENTRANCE_DAY + "entra_scene", + "Market Entrance (Child - Day)", + "none", + SDC_DEFAULT, + { false, false, false, false, false, true, false, false, false, true, true, true }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_MARKET_ENTRANCE_NIGHT + "entra_n_scene", + "Market Entrance (Child - Night)", + "none", + SDC_DEFAULT, + { false, false, false, false, false, true, false, false, false, true, true, true }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_MARKET_ENTRANCE_RUINS + "enrui_scene", + "Market Entrance (Ruins)", + "none", + SDC_DEFAULT, + { false, false, false, false, false, true, false, false, true, true, true, true }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_BACK_ALLEY_DAY + "market_alley_scene", + "Back Alley (Child - Day)", + "g_pn_18", + SDC_DEFAULT, + { false, false, false, false, false, true, false, false, false, true, true, true }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_BACK_ALLEY_NIGHT + "market_alley_n_scene", + "Back Alley (Child - Night)", + "g_pn_18", + SDC_DEFAULT, + { false, false, false, false, false, true, false, false, false, true, true, true }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_MARKET_DAY + "market_day_scene", + "Market (Child - Day)", + "g_pn_17", + SDC_DEFAULT, + { false, false, false, false, false, true, false, false, false, true, true, true }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_MARKET_NIGHT + "market_night_scene", + "Market (Child - Night)", + "g_pn_17", + SDC_DEFAULT, + { false, false, false, false, false, true, false, false, false, true, true, true }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_MARKET_RUINS + "market_ruins_scene", + "Market (Ruins)", + "g_pn_17", + SDC_DEFAULT, + { false, false, false, false, false, true, false, false, true, true, true, true }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_TEMPLE_OF_TIME_EXTERIOR_DAY + "shrine_scene", + "Temple of Time Exterior (Child - Day)", + "none", + SDC_DEFAULT, + { false, false, false, false, false, true, false, false, false, true, true, true }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_TEMPLE_OF_TIME_EXTERIOR_NIGHT + "shrine_n_scene", + "Temple of Time Exterior (Child - Night)", + "none", + SDC_DEFAULT, + { false, false, false, false, false, true, false, false, false, true, true, true }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_TEMPLE_OF_TIME_EXTERIOR_RUINS + "shrine_r_scene", + "Temple of Time Exterior (Ruins)", + "none", + SDC_DEFAULT, + { false, false, false, false, false, true, false, false, true, true, true, true }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_KNOW_IT_ALL_BROS_HOUSE + "kokiri_home_scene", + "Know-It-All Brothers' House", + "none", + SDC_DEFAULT, + { false, true, false, false, false, true, false, false, false, true, true, true }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_TWINS_HOUSE + "kokiri_home3_scene", + "House of Twins", + "none", + SDC_DEFAULT, + { false, true, false, false, false, true, false, false, false, true, true, true }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_MIDOS_HOUSE + "kokiri_home4_scene", + "Mido's House", + "none", + SDC_DEFAULT, + { false, true, false, false, false, true, false, false, false, true, true, true }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_SARIAS_HOUSE + "kokiri_home5_scene", + "Saria's House", + "none", + SDC_DEFAULT, + { false, true, false, false, false, true, false, false, false, true, true, true }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_KAKARIKO_CENTER_GUEST_HOUSE + "kakariko_scene", + "Carpenter Boss's House", + "none", + SDC_DEFAULT, + { false, true, false, false, false, true, false, false, false, true, true, true }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_BACK_ALLEY_HOUSE + "kakariko3_scene", + "Back Alley House (Man in Green)", + "none", + SDC_DEFAULT, + { false, true, false, false, false, true, false, false, false, true, true, true }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_BAZAAR + "shop1_scene", + "Bazaar", + "g_pn_23", + SDC_DEFAULT, + { false, true, false, false, false, true, false, false, false, true, true, true }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_KOKIRI_SHOP + "kokiri_shop_scene", + "Kokiri Shop", + "g_pn_19", + SDC_DEFAULT, + { false, true, false, false, false, true, false, false, false, true, true, true }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_GORON_SHOP + "golon_scene", + "Goron Shop", + "g_pn_20", + SDC_DEFAULT, + { false, true, false, false, false, true, false, false, false, true, true, true }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_ZORA_SHOP + "zoora_scene", + "Zora Shop", + "g_pn_21", + SDC_DEFAULT, + { false, true, false, false, false, true, false, false, false, true, true, true }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_POTION_SHOP_KAKARIKO + "drag_scene", + "Kakariko Potion Shop", + "g_pn_24", + SDC_DEFAULT, + { false, true, false, false, false, true, false, false, false, true, true, true }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_POTION_SHOP_MARKET + "alley_shop_scene", + "Market Potion Shop", + "g_pn_24", + SDC_DEFAULT, + { false, true, false, false, false, true, false, false, false, true, true, true }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_BOMBCHU_SHOP + "night_shop_scene", + "Bombchu Shop", + "g_pn_56", + SDC_DEFAULT, + { false, true, false, false, false, true, false, false, false, true, true, true }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_HAPPY_MASK_SHOP + "face_shop_scene", + "Happy Mask Shop", + "g_pn_50", + SDC_DEFAULT, + { false, true, false, false, false, true, false, false, false, true, true, true }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_LINKS_HOUSE + "link_home_scene", + "Link's House", + "none", + SDC_DEFAULT, + { false, true, false, false, false, true, false, false, false, true, true, true }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_DOG_LADY_HOUSE + "impa_scene", + "Back Alley House (Dog Lady)", + "none", + SDC_DEFAULT, + { false, true, false, false, false, true, false, false, false, true, true, true }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_STABLE + "malon_stable_scene", + "Stable", + "g_pn_48", + SDC_DEFAULT, + { false, true, false, false, false, true, false, false, false, true, true, true }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_IMPAS_HOUSE + "labo_scene", + "Impa's House", + "none", + SDC_DEFAULT, + { false, true, false, false, false, true, false, false, false, true, true, true }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_LAKESIDE_LABORATORY + "hylia_labo_scene", + "Lakeside Laboratory", + "g_pn_26", + SDC_LAKESIDE_LABORATORY, + { false, false, false, false, false, true, false, false, false, true, true, true }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_CARPENTERS_TENT + "tent_scene", + "Carpenters' Tent", + "none", + SDC_DEFAULT, + { false, true, false, false, false, true, false, false, false, true, true, true }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_GRAVEKEEPERS_HUT + "hut_scene", + "Gravekeeper's Hut", + "g_pn_25", + SDC_DEFAULT, + { false, true, false, false, false, true, false, false, false, true, true, true }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC + "daiyousei_izumi_scene", + "Great Fairy's Fountain (Upgrades)", + "g_pn_13", + SDC_GREAT_FAIRYS_FOUNTAIN, + { false, false, false, false, false, false, false, false, false, true, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_FAIRYS_FOUNTAIN + "yousei_izumi_tate_scene", + "Fairy's Fountain", + "g_pn_45", + SDC_FAIRYS_FOUNTAIN, + { false, false, false, false, false, false, false, false, true, true, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_GREAT_FAIRYS_FOUNTAIN_SPELLS + "yousei_izumi_yoko_scene", + "Great Fairy's Fountain (Spells)", + "g_pn_13", + SDC_GREAT_FAIRYS_FOUNTAIN, + { false, false, false, false, false, false, false, false, false, true, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_GROTTOS + "kakusiana_scene", + "Grottos", + "none", + SDC_GROTTOS, + { false, false, false, false, false, false, false, false, true, true, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_REDEAD_GRAVE + "hakaana_scene", + "Grave (Redead)", + "none", + SDC_GRAVE_EXIT_LIGHT_SHINING, + { false, false, false, false, false, false, false, false, true, true, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_GRAVE_WITH_FAIRYS_FOUNTAIN + "hakaana2_scene", + "Grave (Fairy's Fountain)", + "none", + SDC_FAIRYS_FOUNTAIN, + { false, false, false, false, false, false, false, false, true, true, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_ROYAL_FAMILYS_TOMB + "hakaana_ouke_scene", + "Royal Family's Tomb", + "g_pn_44", + SDC_ROYAL_FAMILYS_TOMB, + { false, false, false, false, false, false, false, false, true, true, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_SHOOTING_GALLERY + "syatekijyou_scene", + "Shooting Gallery", + "g_pn_15", + SDC_SHOOTING_GALLERY, + { false, true, false, true, true, true, true, false, false, true, true, true }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_TEMPLE_OF_TIME + "tokinoma_scene", + "Temple of Time", + "g_pn_16", + SDC_TEMPLE_OF_TIME, + { false, false, false, false, false, true, false, false, false, true, true, true }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_CHAMBER_OF_THE_SAGES + "kenjyanoma_scene", + "Chamber of the Sages", + "g_pn_14", + SDC_CHAMBER_OF_THE_SAGES, + { true, true, false, true, true, true, true, false, false, true, true, true }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_CASTLE_COURTYARD_GUARDS_DAY + "hairal_niwa_scene", + "Castle Hedge Maze (Day)", + "g_pn_12", + SDC_CASTLE_COURTYARD_GUARDS, + { false, true, false, true, true, true, true, false, false, true, true, true }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_CASTLE_COURTYARD_GUARDS_NIGHT + "hairal_niwa_n_scene", + "Castle Hedge Maze (Night)", + "g_pn_12", + SDC_CASTLE_COURTYARD_GUARDS, + { false, true, false, true, true, true, true, false, false, true, true, true }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_CUTSCENE_MAP + "hiral_demo_scene", + "Cutscene Map", + "none", + SDC_DEFAULT, + { false, false, false, false, false, false, false, false, false, false, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_WINDMILL_AND_DAMPES_GRAVE + "hakasitarelay_scene", + "Damp's Grave & Windmill", + "g_pn_57", + SDC_GRAVE_EXIT_LIGHT_SHINING, + { false, false, false, false, false, false, false, true, false, true, true, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_FISHING_POND + "turibori_scene", + "Fishing Pond", + "g_pn_46", + SDC_FISHING_POND, + { false, true, false, true, true, true, true, false, false, true, true, true }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_CASTLE_COURTYARD_ZELDA + "nakaniwa_scene", + "Castle Courtyard", + "g_pn_12", + SDC_CALM_WATER, + { false, false, false, false, false, false, true, false, false, true, true, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_BOMBCHU_BOWLING_ALLEY + "bowling_scene", + "Bombchu Bowling Alley", + "g_pn_47", + SDC_BOMBCHU_BOWLING_ALLEY, + { false, true, false, true, true, true, true, false, false, true, true, true }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_LON_LON_BUILDINGS + "souko_scene", + "Ranch House & Silo", + "none", + SDC_LON_LON_BUILDINGS, + { false, false, false, false, false, true, false, false, false, true, true, true }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_MARKET_GUARD_HOUSE + "miharigoya_scene", + "Guard House", + "none", + SDC_MARKET_GUARD_HOUSE, + { false, false, false, false, false, true, false, false, false, true, true, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_POTION_SHOP_GRANNY + "mahouya_scene", + "Granny's Potion Shop", + "g_pn_24", + SDC_POTION_SHOP_GRANNY, + { false, true, false, false, false, true, true, false, false, true, true, true }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_GANON_BOSS + "ganon_demo_scene", + "Ganon's Tower Collapse & Battle Arena", + "none", + SDC_OUTSIDE_GANONS_CASTLE, + { false, false, false, false, true, false, true, false, false, true, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_HOUSE_OF_SKULLTULA + "kinsuta_scene", + "House of Skulltula", + "g_pn_22", + SDC_DEFAULT, + { false, false, false, false, false, true, false, false, false, true, true, true }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_HYRULE_FIELD + "spot00_scene", + "Spot 00 - Hyrule Field", + "g_pn_27", + SDC_HYRULE_FIELD, + { false, false, false, false, false, false, false, false, false, true, false, false }, + { true, + { -460, 100, 6640 }, + 0, + { { 16, 0, 1341 }, { -1297, 0, 1459 }, { -5416, -300, 1296 }, { -4667, -300, 3620 }, + { -3837, 81, 5537 }, { -5093, -226, 6661 }, { -6588, -79, 5053 }, { -7072, -500, 7538 }, + { -6139, -500, 8910 }, { -8497, -300, 7802 }, { -5481, -499, 12127 }, { -4808, -700, 13583 }, + { -3416, -490, 12092 }, { -2915, 100, 8339 }, { -2277, -500, 13247 }, { -1026, -500, 12101 }, + { 1427, -500, 13341 }, { -200, -486, 10205 }, { -1469, 100, 7496 }, { -995, 168, 5652 }, + { 1938, 89, 6232 }, { 1387, -105, 9206 }, { 1571, -223, 7701 }, { 3893, -121, 7068 }, + { 3179, 373, 5221 }, { 4678, -20, 3869 }, { 3460, 246, 4207 }, { 3686, 128, 2366 }, + { 1791, 18, 152 }, { 3667, -16, 1399 }, { 1827, -15, 983 }, { 1574, 399, 4318 }, + { 716, 95, 3391 }, { -1189, -41, 4739 }, { -1976, -171, 4172 }, { 1314, 391, 5665 }, + { 112, 0, 1959 }, { -3011, -111, 9397 }, { -5674, -270, 8585 }, { -8861, -300, 7836 }, + { -6056, -500, 7810 }, { -7306, -500, 5994 }, { -7305, -500, 7605 }, { -7439, -300, 7600 }, + { -7464, -300, 6268 }, { -8080, -300, 7553 }, { -8091, -300, 7349 }, { -8785, -300, 7383 }, + { -8745, -300, 7508 }, { -8777, -300, 7788 }, { -8048, -299, 7738 }, { -7341, -184, 7730 }, + { -6410, -288, 7824 }, { -6326, -290, 8205 }, { -6546, -292, 8400 }, { -7533, -180, 8459 }, + { -8024, -295, 7903 }, { -8078, -308, 7994 }, { -9425, -287, 7696 }, { -9322, -292, 7577 }, + { -9602, -199, 7160 }, { -9307, -300, 7758 }, { -9230, -300, 7642 }, { -7556, -499, 8695 }, + { -6438, -500, 8606 }, { -6078, -500, 8258 }, { -6233, -500, 7613 }, { -5035, -205, 7814 }, + { -5971, -500, 8501 }, { -5724, -498, 10123 }, { -5094, -392, 11106 }, { -5105, -393, 11312 }, + { -4477, -314, 11132 }, { -3867, -380, 11419 }, { -2952, -500, 11944 }, { -2871, -488, 11743 }, + { -3829, -372, 11327 }, { -4439, -293, 10989 }, { -5014, -381, 11086 }, { -5113, -188, 10968 }, + { -5269, -188, 11156 }, { -5596, -178, 9972 }, { -5801, -288, 8518 }, { -4910, -178, 7931 }, + { -3586, 73, 8140 }, { -4487, -106, 9362 }, { -4339, -112, 6412 }, { -3417, 105, 8194 }, + { -4505, -20, 6608 }, { -5038, -199, 6603 }, { -4481, 1, 6448 }, { -5032, -168, 6418 }, + { -5256, -700, 14329 }, { -5749, -820, 15380 }, { -3122, -700, 13608 }, { -3758, -525, 13228 }, + { -3670, -500, 13123 }, { -2924, -500, 13526 }, { 1389, -115, 9370 }, { 548, -116, 8889 }, + { -106, -107, 8530 }, { -1608, 85, 7646 }, { -5300, -700, 13772 }, { -5114, -700, 13400 }, + { -4561, -700, 13700 }, { -4762, -700, 14084 }, { -2954, 100, 8216 }, { 1460, -104, 9246 }, + { 629, -105, 8791 }, { -10, -90, 8419 }, { -1462, 100, 7504 }, { -3018, -500, 12493 }, + { -2994, -311, 10331 }, { -4006, -700, 14152 }, { -4341, -500, 12743 }, { -5879, -497, 6799 }, + { 22, -473, 10103 }, { -1389, -192, 8874 }, { -4, 92, 6866 }, { 483, 104, 6637 }, + { 1580, 183, 5987 }, { 1548, 308, 5077 }, { 1511, 399, 4267 }, { 1358, 385, 4271 }, + { 1379, 395, 5063 }, { 1360, 394, 5870 }, { 813, 283, 6194 }, { -57, 101, 6743 }, + { 91, 325, 5143 }, { 1425, -214, 7659 }, { 3487, -19, 880 }, { 2933, 152, 2094 }, + { 2888, -145, 6862 }, { 1511, 67, 6471 }, { 4051, -47, 1722 }, { -7335, -500, 8627 }, + { -7728, -462, 8498 }, { -7791, -446, 8832 }, { -2915, -435, 11334 }, { 165, -278, 3352 } } }, + { 25, 25, 1080, -360 }, + {}, + {}, + { 216, 150, 80, 73, 1, 0, -1, std::string{ gHyruleFieldMinimapTex } } }, + { // SCENE_KAKARIKO_VILLAGE + "spot01_scene", + "Spot 01 - Kakariko Village", + "g_pn_28", + SDC_KAKARIKO_VILLAGE, + { false, false, false, false, false, false, false, false, false, true, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 7, 6, 1000, -650 }, + {}, + {}, + { 216, 158, 80, 64, 269, -833, 8, std::string{ gKakarikoVillageMinimapTex } } }, + { // SCENE_GRAVEYARD + "spot02_scene", + "Spot 02 - Graveyard", + "g_pn_29", + SDC_DEFAULT, + { false, false, false, false, false, false, false, false, false, true, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 6, 6, 890, -800 }, + {}, + {}, + { 218, 184, 80, 39, 1, 0, 7, std::string{ gGraveyardMinimapTex } } }, + { // SCENE_ZORAS_RIVER + "spot03_scene", + "Spot 03 - Zora's River", + "g_pn_30", + SDC_ZORAS_RIVER, + { false, false, false, false, false, false, false, false, false, true, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 7, 7, 720, -730 }, + {}, + {}, + { 202, 164, 96, 58, 1, 0, -1, std::string{ gZorasRiverMinimapTex } } }, + { // SCENE_KOKIRI_FOREST + "spot04_scene", + "Spot 04 - Kokiri Forest", + "g_pn_31", + SDC_KOKIRI_FOREST, + { false, false, false, false, false, false, false, false, false, true, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 8, 8, 660, -730 }, + {}, + {}, + { 202, 160, 96, 62, 273, -850, 0, std::string{ gKokiriForestMinimapTex } } }, + { // SCENE_SACRED_FOREST_MEADOW + "spot05_scene", + "Spot 05 - Sacred Forest Meadow", + "g_pn_52", + SDC_CALM_WATER, + { false, false, false, false, false, false, false, false, false, true, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 5, 7, 1220, -660 }, + {}, + {}, + { 250, 138, 48, 85, 279, -889, 3, std::string{ gSacredMeadowMinimapTex } } }, + { // SCENE_LAKE_HYLIA + "spot06_scene", + "Spot 06 - Lake Hylia", + "g_pn_32", + SDC_LAKE_HYLIA, + { false, false, false, false, false, false, false, false, false, true, false, false }, + { true, { -1929, -1025, 768 }, 0, { { -2109, -882, 1724 }, { -328, -1238, 2705 }, { -3092, -1033, 3527 } } }, + { 13, 13, 1080, -260 }, + {}, + {}, + { 216, 140, 80, 81, 259, -829, 5, std::string{ gLakeHyliaMinimapTex } } }, + { // SCENE_ZORAS_DOMAIN + "spot07_scene", + "Spot 07 - Zora's Domain", + "g_pn_33", + SDC_ZORAS_DOMAIN, + { false, false, false, false, false, false, false, false, false, true, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 5, 5, 1120, -880 }, + {}, + {}, + { 234, 150, 64, 73, 1, 0, -1, std::string{ gZorasDomainMinimapTex } } }, + { // SCENE_ZORAS_FOUNTAIN + "spot08_scene", + "Spot 08 - Zora's Fountain", + "g_pn_34", + SDC_ZORAS_FOUNTAIN, + { false, false, false, false, false, false, false, false, false, true, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 8, 8, 1150, -630 }, + {}, + {}, + { 234, 156, 64, 65, 260, -844, 2, std::string{ gZorasFountainMinimapTex } } }, + { // SCENE_GERUDO_VALLEY + "spot09_scene", + "Spot 09 - Gerudo Valley", + "g_pn_35", + SDC_GERUDO_VALLEY, + { false, false, false, false, false, false, false, false, false, true, false, false }, + { true, + { 2566, -259, 767 }, + 0, + { { 2687, -269, 753 }, + { 2066, -132, 317 }, + { 523, -8, 635 }, + { 558, 36, -323 }, + { 615, 51, -839 }, + { -614, 32, 29 }, + { -639, -3, 553 }, + { -540, 10, -889 }, + { -1666, 58, 378 }, + { -3044, 210, -648 } } }, + { 11, 11, 1060, -680 }, + {}, + {}, + { 216, 158, 80, 65, 1, 0, -1, std::string{ gGerudoValleyMinimapTex } } }, + { // SCENE_LOST_WOODS + "spot10_scene", + "Spot 10 - Lost Woods", + "g_pn_36", + SDC_LOST_WOODS, + { false, false, false, false, false, false, false, false, false, true, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 12, 12, 1100, -720 }, + {}, + {}, + { 234, 168, 64, 56, 1, 0, -1, std::string{ gHauntedWastelandMinimapTex } } }, + { // SCENE_DESERT_COLOSSUS + "spot11_scene", + "Spot 11 - Desert Colossus", + "g_pn_55", + SDC_DESERT_COLOSSUS, + { false, false, false, false, false, false, false, false, false, true, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 11, 11, 930, -710 }, + {}, + {}, + { 234, 162, 64, 59, 235, -836, 6, std::string{ gDesertColossusMinimapTex } } }, + { // SCENE_GERUDOS_FORTRESS + "spot12_scene", + "Spot 12 - Gerudo's Fortress", + "g_pn_53", + SDC_GERUDOS_FORTRESS, + { false, false, false, false, false, false, false, false, false, true, false, false }, + { true, + { -328, 10, 953 }, + 0, + { { -678, 21, -623 }, + { 149, 333, -2499 }, + { 499, 581, -547 }, + { 3187, 1413, -3775 }, + { 3198, 1413, 307 }, + { 3380, 1413, -1200 }, + { -966, 1, -56 }, + { -966, 24, -761 }, + { -694, 174, -2820 } } }, + { 9, 9, 850, -830 }, + {}, + {}, + { 216, 138, 80, 85, 1, 0, 11, std::string{ gGerudosFortessMinimapTex } } }, + { // SCENE_HAUNTED_WASTELAND + "spot13_scene", + "Spot 13 - Haunted Wasteland", + "g_pn_37", + SDC_HAUNTED_WASTELAND, + { false, false, false, false, false, false, false, false, false, true, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 15, 15, 1100, -780 }, + {}, + {}, + { 234, 168, 64, 56, 1, 0, -1, std::string{ gLostWoodsMinimapTex } } }, + { // SCENE_HYRULE_CASTLE + "spot15_scene", + "Spot 15 - Hyrule Castle", + "g_pn_38", + SDC_HYRULE_CASTLE, + { false, false, false, false, false, false, false, false, false, true, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 10, 10, 1030, -540 }, + {}, + {}, + { 234, 162, 64, 59, 1, 0, -1, std::string{ gHyruleCastleAreaMinimapTex } } }, + { // SCENE_DEATH_MOUNTAIN_TRAIL + "spot16_scene", + "Spot 16 - Death Mountain Trail", + "g_pn_39", + SDC_DEATH_MOUNTAIN_TRAIL, + { false, false, false, false, false, false, false, false, false, true, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 10, 9, 1240, -700 }, + {}, + {}, + { 250, 138, 48, 85, 267, -852, 1, std::string{ gDeathMountainTrailMinimapTex } } }, + { // SCENE_DEATH_MOUNTAIN_CRATER + "spot17_scene", + "Spot 17 - Death Mountain Crater", + "g_pn_40", + SDC_DEATH_MOUNTAIN_CRATER, + { false, false, false, false, false, false, false, false, false, true, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 6, 6, 1030, -620 }, + {}, + {}, + { 216, 146, 80, 78, 261, -873, 4, std::string{ gDeathMountainCraterMinimapTex } } }, + { // SCENE_GORON_CITY + "spot18_scene", + "Spot 18 - Goron City", + "g_pn_41", + SDC_GORON_CITY, + { false, false, false, false, false, false, false, false, false, true, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 5, 5, 1100, -660 }, + {}, + {}, + { 234, 150, 64, 72, 1, 0, -1, std::string{ gGoronCityMinimapTex } } }, + { // SCENE_LON_LON_RANCH + "spot20_scene", + "Spot 20 - Lon Lon Ranch", + "g_pn_42", + SDC_LON_LON_RANCH, + { false, false, false, false, false, false, false, false, false, true, false, false }, + { true, + { 928, 0, -2280 }, + 0, + { { 1039, 0, 2051 }, + { -1443, 0, 1429 }, + { 856, 0, -918 }, + { 882, 0, -2256 }, + { -1003, 0, -755 }, + { -2254, 0, -629 }, + { 907, 0, -2336 } } }, + { 11, 11, 1120, -750 }, + {}, + {}, + { 234, 154, 64, 68, 1, 0, -1, std::string{ gLonLonRanchMinimapTex } } }, + { // SCENE_OUTSIDE_GANONS_CASTLE + "ganon_tou_scene", + "Ganon's Castle Exterior", + "g_pn_43", + SDC_OUTSIDE_GANONS_CASTLE, + { false, false, false, false, false, false, false, false, false, true, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 10, 10, 1070, -580 }, + {}, + {}, + {} }, + { // SCENE_TEST01 + "test01_scene", + "Jungle Gym", + "none", + SDC_CALM_WATER, + { false, false, false, false, false, false, false, false, false, false, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_BESITU + "besitu_scene", + "Ganondorf Test Room", + "none", + SDC_BESITU, + { false, false, false, false, false, false, false, false, false, false, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_DEPTH_TEST + "depth_test_scene", + "Depth Test", + "none", + SDC_DEFAULT, + { false, false, false, false, false, false, false, false, false, false, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_SYOTES + "syotes_scene", + "Stalfos Mini-Boss Room", + "none", + SDC_DEFAULT, + { false, false, false, false, false, false, false, false, false, false, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_SYOTES2 + "syotes2_scene", + "Stalfos Boss Room", + "none", + SDC_DEFAULT, + { false, false, false, false, false, false, false, false, false, false, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_SUTARU + "sutaru_scene", + "Sutaru", + "none", + SDC_DEFAULT, + { false, false, false, false, false, false, false, false, false, false, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_HAIRAL_NIWA2 + "hairal_niwa2_scene", + "Castle Hedge Maze (Early)", + "g_pn_12", + SDC_CASTLE_COURTYARD_GUARDS, + { false, false, false, false, false, false, false, false, false, false, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_SASATEST + "sasatest_scene", + "Sasa Test", + "none", + SDC_DEFAULT, + { false, false, false, false, false, false, false, false, false, false, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // SCENE_TESTROOM + "testroom_scene", + "Treasure Chest Room", + "none", + SDC_DEFAULT, + { false, false, false, false, false, false, false, false, false, false, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, + { // The entrance table has an entrance for a scene that does not exist. This entry makes a scene that they can be + // accounted to it. + "SCENE_UNUSED_6E", + "Unused scene that has an entrance for it", + "none", + SDC_DEFAULT, + { false, false, false, false, false, false, false, false, false, false, false, false }, + { false, { 0, 0, 0 }, 0, {} }, + { 0, 0, 0, 0 }, + {}, + {}, + {} }, +}; \ No newline at end of file diff --git a/soh/soh/z_play_otr.cpp b/soh/soh/z_play_otr.cpp index 23e61261c..1e46ce1e7 100644 --- a/soh/soh/z_play_otr.cpp +++ b/soh/soh/z_play_otr.cpp @@ -4,6 +4,7 @@ #include "soh/resource/type/Scene.h" #include #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/SceneDB.h" #include "global.h" #include "vt.h" #include @@ -20,14 +21,10 @@ Ship::IResource* OTRPlay_LoadFile(PlayState* play, const char* fileName) { } extern "C" void OTRPlay_SpawnScene(PlayState* play, s32 sceneId, s32 spawn) { - SceneTableEntry* scene = &gSceneTable[sceneId]; + SceneDB::Entry& entry = SceneDB::Instance->RetrieveEntry(sceneId); - scene->unk_13 = 0; - play->loadedScene = scene; play->sceneNum = sceneId; - play->sceneConfig = scene->config; - - // osSyncPrintf("\nSCENE SIZE %fK\n", (scene->sceneFile.vromEnd - scene->sceneFile.vromStart) / 1024.0f); + play->sceneConfig = entry.entry.sceneDrawConfig; // Scenes considered "dungeon" with a MQ variant int16_t inNonSharedScene = (sceneId >= SCENE_DEKU_TREE && sceneId <= SCENE_ICE_CAVERN) || @@ -37,8 +34,8 @@ extern "C" void OTRPlay_SpawnScene(PlayState* play, s32 sceneId, s32 spawn) { if (inNonSharedScene) { sceneVersion = ResourceMgr_IsGameMasterQuest() ? "mq" : "nonmq"; } - std::string scenePath = StringHelper::Sprintf("scenes/%s/%s/%s", sceneVersion.c_str(), scene->sceneFile.fileName, - scene->sceneFile.fileName); + std::string scenePath = + StringHelper::Sprintf("scenes/%s/%s/%s", sceneVersion.c_str(), entry.name.c_str(), entry.name.c_str()); play->sceneSegment = OTRPlay_LoadFile(play, scenePath.c_str()); @@ -50,12 +47,8 @@ extern "C" void OTRPlay_SpawnScene(PlayState* play, s32 sceneId, s32 spawn) { return; } - scene->unk_13 = 0; - - // gSegments[2] = VIRTUAL_TO_PHYSICAL(play->sceneSegment); - OTRPlay_InitScene(play, spawn); - auto roomSize = func_80096FE8(play, &play->roomCtx); + uint32_t roomSize = func_80096FE8(play, &play->roomCtx); osSyncPrintf("ROOM SIZE=%fK\n", roomSize / 1024.0f); diff --git a/soh/src/code/z_actor.c b/soh/src/code/z_actor.c index 3933f263d..82eabb0fc 100644 --- a/soh/src/code/z_actor.c +++ b/soh/src/code/z_actor.c @@ -875,6 +875,7 @@ void TitleCard_InitBossName(PlayState* play, TitleCardContext* titleCtx, void* t titleCtx->delayTimer = 0; } +// SceneDB TODO: this needs to be parameterized with a good multi-language solution for the textures void TitleCard_InitPlaceName(PlayState* play, TitleCardContext* titleCtx, void* texture, s32 x, s32 y, s32 width, s32 height, s32 delay) { SceneTableEntry* loadedScene = play->loadedScene; diff --git a/soh/src/code/z_demo.c b/soh/src/code/z_demo.c index b6ccedc7c..815cce272 100644 --- a/soh/src/code/z_demo.c +++ b/soh/src/code/z_demo.c @@ -35,6 +35,7 @@ #include "soh/OTRGlobals.h" #include "soh/ResourceManagerHelpers.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/SceneDB.h" u16 D_8011E1C0 = 0; u16 D_8011E1C4 = 0; @@ -2218,6 +2219,7 @@ void Cutscene_HandleConditionalTriggers(PlayState* play) { return; } + s32 scene = EntranceDB_Retrieve(gSaveContext.entranceIndex)->sceneId; if ((gSaveContext.gameMode == GAMEMODE_NORMAL) && (gSaveContext.respawnFlag <= 0) && (gSaveContext.cutsceneIndex < 0xFFF0)) { if ((gSaveContext.entranceIndex == ENTR_DESERT_COLOSSUS_OUTSIDE_TEMPLE) && @@ -2247,12 +2249,12 @@ void Cutscene_HandleConditionalTriggers(PlayState* play) { (CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) && CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW) && LINK_IS_ADULT && !Flags_GetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS) && - (gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_TEMPLE_OF_TIME)))) { + (scene == SCENE_TEMPLE_OF_TIME)))) { Flags_SetEventChkInf(EVENTCHKINF_RETURNED_TO_TEMPLE_OF_TIME_WITH_ALL_MEDALLIONS); gSaveContext.entranceIndex = ENTR_TEMPLE_OF_TIME_ENTRANCE; gSaveContext.cutsceneIndex = 0xFFF8; } else if (!Flags_GetEventChkInf(EVENTCHKINF_WATCHED_GANONS_CASTLE_COLLAPSE_CAUGHT_BY_GERUDO) && - (gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_GANON_BOSS)) { + (scene == SCENE_GANON_BOSS)) { Flags_SetEventChkInf(EVENTCHKINF_WATCHED_GANONS_CASTLE_COLLAPSE_CAUGHT_BY_GERUDO); gSaveContext.entranceIndex = ENTR_GANON_BOSS_0; gSaveContext.cutsceneIndex = 0xFFF0; diff --git a/soh/src/code/z_horse.c b/soh/src/code/z_horse.c index ef4b7ec50..40f145e35 100644 --- a/soh/src/code/z_horse.c +++ b/soh/src/code/z_horse.c @@ -3,10 +3,11 @@ #include #include "soh/Enhancements/game-interactor/GameInteractor.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/SceneDB.h" s32 func_8006CFC0(s32 scene) { - s32 validScenes[] = { SCENE_HYRULE_FIELD, SCENE_LAKE_HYLIA, SCENE_GERUDO_VALLEY, SCENE_GERUDOS_FORTRESS, - SCENE_LON_LON_RANCH }; +#if 0 + s32 validScenes[] = { SCENE_HYRULE_FIELD, SCENE_LAKE_HYLIA, SCENE_GERUDO_VALLEY, SCENE_GERUDOS_FORTRESS, SCENE_LON_LON_RANCH }; s32 i; for (i = 0; i < ARRAY_COUNT(validScenes); i++) { @@ -16,6 +17,8 @@ s32 func_8006CFC0(s32 scene) { } return 0; +#endif + return SceneDB_Retrieve(scene)->epona.allowed; } void func_8006D074(PlayState* play) { @@ -108,19 +111,13 @@ void func_8006D0EC(PlayState* play, Player* player) { Actor* horseActor = Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, 0.0f, 0.0f, -500.0f, 0, 0, 0, 1, true); assert(horseActor != NULL); } else if (Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) || (DREG(1) != 0)) { - for (i = 0; i < ARRAY_COUNT(horseSpawns); i++) { - HorseSpawn* horseSpawn = &horseSpawns[i]; - if (horseSpawn->scene == play->sceneNum) { - Actor* horseActor = - Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, horseSpawn->pos.x, horseSpawn->pos.y, - horseSpawn->pos.z, 0, horseSpawn->angle, 0, horseSpawn->type, true); - assert(horseActor != NULL); - if (play->sceneNum == SCENE_GERUDOS_FORTRESS) { - horseActor->room = -1; - } - - break; - } + SceneDBEntry* entry = SceneDB_Retrieve(play->sceneNum); + Actor* horseActor = + Actor_Spawn(&play->actorCtx, play, ACTOR_EN_HORSE, entry->epona.startingPos.x, entry->epona.startingPos.y, + entry->epona.startingPos.z, 0, entry->epona.angle, 0, 2, true); + assert(horseActor != NULL); + if (play->sceneNum == SCENE_GERUDOS_FORTRESS) { + horseActor->room = -1; } } else if (!Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED)) { if ((DREG(1) == 0) && (play->sceneNum == SCENE_LON_LON_BUILDINGS) && !IS_DAY) { diff --git a/soh/src/code/z_kaleido_setup.c b/soh/src/code/z_kaleido_setup.c index 8d92d7c32..0554554b4 100644 --- a/soh/src/code/z_kaleido_setup.c +++ b/soh/src/code/z_kaleido_setup.c @@ -1,4 +1,6 @@ #include "global.h" +#include "soh/ResourceManagerHelpers.h" +#include "soh/SceneDB.h" s16 sKaleidoSetupKscpPos0[] = { PAUSE_QUEST, PAUSE_EQUIP, PAUSE_ITEM, PAUSE_MAP }; f32 sKaleidoSetupEyeX0[] = { 0.0f, 64.0f, 0.0f, -64.0f }; @@ -124,6 +126,10 @@ void KaleidoSetup_Init(PlayState* play) { pauseCtx->randoQuestMode = 0; View_Init(&pauseCtx->view, play->state.gfxCtx); + + if (SceneDB_IsDungeon(play->sceneNum)) { + SceneDB_SetPauseMapMarkData(play->sceneNum, ResourceMgr_IsGameMasterQuest()); + } } void KaleidoSetup_Destroy(PlayState* play) { diff --git a/soh/src/code/z_map_data.c b/soh/src/code/z_map_data.c index 48507ce0e..47b5da862 100644 --- a/soh/src/code/z_map_data.c +++ b/soh/src/code/z_map_data.c @@ -132,25 +132,32 @@ static s16 sPaletteRoom[10][8][14] = { }, }; -static s16 sRoomCompassOffsetX[10][44] = { - { 1090, 1390, 1560, 1220, 1200, 1390, 1770, 1610, 2000, 1290, 1420, - 1110, 1040, 470, 790, 1570, 720, 1000, 1580, 70, 0 }, - { 940, 320, 1500, 240, 580, 1510, 720, 1030, 800, 660, 180, 520, 310, 550, 790, 1650, 1000, 1570, 80, 70 }, - { 1130, 1070, 1090, 1160, 1500, 690, 1540, 920, 1160, 700, 1650, 950, 1380, 1460, 830, 1170, 1620 }, - { 1130, 1170, 965, 890, 1170, 1460, 1170, 800, 1320, 880, 1130, 1590, 1390, 830, 610, 580, 710, - 980, 1640, 1510, 590, 1610, 1130, 1130, 820, 1320, 1620, 0, 0, 0, 0, 1300, 1270 }, - { 1160, 620, 1330, 1280, 440, 600, 810, 830, 720, 1170, 1490, 1640, 1870, 1800, 1610, 1130, 860, 1310, 1140, - 850, 760, 380, 800, 800, 1930, 1410, 640, 845, 810, 810, 850, 1390, 1540, 1650, 1880, 1530, 420, 1950 }, - { 1120, 1290, 1120, 1380, 930, 1520, 1980, 2010, 1590, 1510, 1500, 1300, 1240, 1800, 1290, - 1450, 1560, 880, 820, 820, 1060, 1670, 1120, 1130, 1130, 1290, 1290, 1280, 1390, 940, - 1520, 1520, 1980, 1620, 1510, 1490, 1240, 1290, 1450, 880, 880, 1060, 1670, 1520 }, - { 800, 1500, 1370, 1730, 1590, 1020, 1060, 1470, 1600, 1830, 1630, 2000, 650, 660, 1020, 880, - 940, 720, 570, 620, 570, 550, 970, 920, 1040, 1150, 1200, 1550, 1520, 1020, 820, 1010 }, - { 1320, 1320, 1090, 1510, 1480, 940, 920, 910, 800, 820, 1150, 1000, 1800, 1660, - 1090, 1630, 710, 1670, 830, 770, 800, 850, 830, 820, 1800, 1090, 850 }, - { 1080, 1420, 1620, 1040, 940, 1190, 1310, 1090, 1380, 1080 }, - { 1070, 1180, 1270, 990, 1280, 1450, 1680, 1530, 760, 860, 1500, 800 }, -}; +static s16 sRoomCompassOffsetX[10] + [44] = { + { 1090, 1390, 1560, 1220, 1200, 1390, 1770, 1610, 2000, 1290, + 1420, 1110, 1040, 470, 790, 1570, 720, 1000, 1580, 70 }, + { 940, 320, 1500, 240, 580, 1510, 720, 1030, 800, 660, + 180, 520, 310, 550, 790, 1650, 1000, 1570, 80, 70 }, + { 1130, 1070, 1090, 1160, 1500, 690, 1540, 920, 1160, 700, 1650, 950, 1380, 1460, 830, + 1170, 1620 }, + { 1130, 1170, 965, 890, 1170, 1460, 1170, 800, 1320, 880, 1130, + 1590, 1390, 830, 610, 580, 710, 980, 1640, 1510, 590, 1610, + 1130, 1130, 820, 1320, 1620, 0, 0, 0, 0, 1300, 1270 }, + { 1160, 620, 1330, 1280, 440, 600, 810, 830, 720, 1170, 1490, 1640, 1870, + 1800, 1610, 1130, 860, 1310, 1140, 850, 760, 380, 800, 800, 1930, 1410, + 640, 845, 810, 810, 850, 1390, 1540, 1650, 1880, 1530, 420, 1950 }, + { 1120, 1290, 1120, 1380, 930, 1520, 1980, 2010, 1590, 1510, 1500, + 1300, 1240, 1800, 1290, 1450, 1560, 880, 820, 820, 1060, 1670, + 1120, 1130, 1130, 1290, 1290, 1280, 1390, 940, 1520, 1520, 1980, + 1620, 1510, 1490, 1240, 1290, 1450, 880, 880, 1060, 1670, 1520 }, + { 800, 1500, 1370, 1730, 1590, 1020, 1060, 1470, 1600, 1830, 1630, + 2000, 650, 660, 1020, 880, 940, 720, 570, 620, 570, 550, + 970, 920, 1040, 1150, 1200, 1550, 1520, 1020, 820, 1010 }, + { 1320, 1320, 1090, 1510, 1480, 940, 920, 910, 800, 820, 1150, 1000, 1800, 1660, + 1090, 1630, 710, 1670, 830, 770, 800, 850, 830, 820, 1800, 1090, 850 }, + { 1080, 1420, 1620, 1040, 940, 1190, 1310, 1090, 1380, 1080 }, + { 1070, 1180, 1270, 990, 1280, 1450, 1680, 1530, 760, 860, 1500, 800 }, + }; static s16 sRoomCompassOffsetY[10][44] = { { -660, -570, -410, -690, -500, -380, -470, -630, -990, -870, @@ -277,7 +284,7 @@ static u8 sSwitchFromFloor[10][51] = { }; static u8 sSwitchToRoom[10][51] = { - { 12, 11, 12, 11 }, + { 12, 11, 12, 11, 0 }, { 16, 17, 18, 0, 2, 3 }, { 15, 16, 1, 6 }, { 22, 23, 24, 25, 26, 0, 6, 7, 8, 11 }, diff --git a/soh/src/code/z_map_exp.c b/soh/src/code/z_map_exp.c index 44b5b43b5..2a0c90d99 100644 --- a/soh/src/code/z_map_exp.c +++ b/soh/src/code/z_map_exp.c @@ -4,6 +4,8 @@ #include "textures/parameter_static/parameter_static.h" #include "textures/map_i_static/map_i_static.h" #include "textures/map_grand_static/map_grand_static.h" +#include "soh/ResourceManagerHelpers.h" +#include "soh/SceneDB.h" #include #include "soh/OTRGlobals.h" #include "soh/Enhancements/cosmetics/cosmeticsTypes.h" @@ -14,6 +16,8 @@ s16 sPlayerInitialPosX = 0; s16 sPlayerInitialPosZ = 0; s16 sPlayerInitialDirection = 0; s16 sEntranceIconMapIndex = 0; +s16 sOwEntranceIconPosX = 0; +s16 sOwEntranceIconPosY = 0; s16 Top_MM_Margin = 0; s16 Left_MM_Margin = 0; @@ -31,7 +35,8 @@ void Map_SavePlayerInitialInfo(PlayState* play) { void Map_SetPaletteData(PlayState* play, s16 room) { s32 mapIndex = gSaveContext.mapIndex; InterfaceContext* interfaceCtx = &play->interfaceCtx; - s16 paletteIndex = gMapData->roomPalette[mapIndex][room]; + SceneDBEntry* entry = SceneDB_Retrieve(mapIndex); + s16 paletteIndex = entry->dungeonData.palettes[room]; if (interfaceCtx->mapRoomNum == room) { interfaceCtx->mapPaletteIndex = paletteIndex; @@ -52,6 +57,7 @@ void Map_SetFloorPalettesData(PlayState* play, s16 floor) { InterfaceContext* interfaceCtx = &play->interfaceCtx; s16 room; s16 i; + SceneDBEntry* entry = SceneDB_Retrieve(mapIndex); for (i = 0; i < 16; i++) { interfaceCtx->mapPalette[i] = 0; @@ -63,32 +69,13 @@ void Map_SetFloorPalettesData(PlayState* play, s16 floor) { interfaceCtx->mapPalette[31] = 1; } - switch (play->sceneNum) { - case SCENE_DEKU_TREE: - case SCENE_DODONGOS_CAVERN: - case SCENE_JABU_JABU: - case SCENE_FOREST_TEMPLE: - case SCENE_FIRE_TEMPLE: - case SCENE_WATER_TEMPLE: - case SCENE_SPIRIT_TEMPLE: - case SCENE_SHADOW_TEMPLE: - case SCENE_BOTTOM_OF_THE_WELL: - case SCENE_ICE_CAVERN: - case SCENE_DEKU_TREE_BOSS: - case SCENE_DODONGOS_CAVERN_BOSS: - case SCENE_JABU_JABU_BOSS: - case SCENE_FOREST_TEMPLE_BOSS: - case SCENE_FIRE_TEMPLE_BOSS: - case SCENE_WATER_TEMPLE_BOSS: - case SCENE_SPIRIT_TEMPLE_BOSS: - case SCENE_SHADOW_TEMPLE_BOSS: - for (i = 0; i < gMapData->maxPaletteCount[mapIndex]; i++) { - room = gMapData->paletteRoom[mapIndex][floor][i]; - if ((room != 0xFF) && (gSaveContext.sceneFlags[mapIndex].rooms & gBitFlags[room])) { - Map_SetPaletteData(play, room); - } + if (SCENEDB_ISDUNGEON(entry)) { + for (i = 0; i < entry->dungeonData.floors[floor].numRooms; i++) { + room = entry->dungeonData.floors[floor].rooms[i]; + if ((room != 0xFF) && (gSaveContext.sceneFlags[mapIndex].rooms & gBitFlags[room])) { + Map_SetPaletteData(play, room); } - break; + } } } @@ -365,101 +352,50 @@ void Map_InitData(PlayState* play, s16 room) { s32 mapIndex = gSaveContext.mapIndex; InterfaceContext* interfaceCtx = &play->interfaceCtx; s16 extendedMapIndex; + SceneDBEntry* entry = SceneDB_Retrieve(mapIndex); - switch (play->sceneNum) { - case SCENE_HYRULE_FIELD: - case SCENE_KAKARIKO_VILLAGE: - case SCENE_GRAVEYARD: - case SCENE_ZORAS_RIVER: - case SCENE_KOKIRI_FOREST: - case SCENE_SACRED_FOREST_MEADOW: - case SCENE_LAKE_HYLIA: - case SCENE_ZORAS_DOMAIN: - case SCENE_ZORAS_FOUNTAIN: - case SCENE_GERUDO_VALLEY: - case SCENE_LOST_WOODS: - case SCENE_DESERT_COLOSSUS: - case SCENE_GERUDOS_FORTRESS: - case SCENE_HAUNTED_WASTELAND: - case SCENE_HYRULE_CASTLE: - case SCENE_DEATH_MOUNTAIN_TRAIL: - case SCENE_DEATH_MOUNTAIN_CRATER: - case SCENE_GORON_CITY: - case SCENE_LON_LON_RANCH: - case SCENE_OUTSIDE_GANONS_CASTLE: - extendedMapIndex = mapIndex; - if (play->sceneNum == SCENE_GRAVEYARD) { - if (CHECK_QUEST_ITEM(QUEST_SONG_NOCTURNE)) { - extendedMapIndex = 0x14; - } - } else if (play->sceneNum == SCENE_LAKE_HYLIA) { - if ((LINK_AGE_IN_YEARS == YEARS_ADULT) && - ((!IS_RANDO && !CHECK_QUEST_ITEM(QUEST_MEDALLION_WATER)) || - (IS_RANDO && !Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP)))) { - extendedMapIndex = 0x15; - } - } else if (play->sceneNum == SCENE_GERUDO_VALLEY) { - if ((LINK_AGE_IN_YEARS == YEARS_ADULT) && !GET_EVENTCHKINF_CARPENTERS_FREE_ALL()) { - extendedMapIndex = 0x16; - } - } else if (play->sceneNum == SCENE_GERUDOS_FORTRESS) { - if ((!IS_RANDO && GET_EVENTCHKINF_CARPENTERS_FREE_ALL()) || - (IS_RANDO && CHECK_QUEST_ITEM(QUEST_GERUDO_CARD))) { - extendedMapIndex = 0x17; - } - } - osSyncPrintf(VT_FGCOL(BLUE)); - osSyncPrintf("KKK=%d\n", extendedMapIndex); - osSyncPrintf(VT_RST); - sEntranceIconMapIndex = extendedMapIndex; - // DmaMgr_SendRequest1(interfaceCtx->mapSegment, - //(uintptr_t)_map_grand_staticSegmentRomStart + gMapData->owMinimapTexOffset[extendedMapIndex], - // gMapData->owMinimapTexSize[mapIndex], __FILE__, __LINE__); + if (SCENEDB_ISOVERWORLD(entry)) { + if (play->sceneNum == SCENE_GRAVEYARD && CHECK_QUEST_ITEM(QUEST_SONG_NOCTURNE)) { + sOwEntranceIconPosX = 294; + sOwEntranceIconPosY = -825; + play->interfaceCtx.mapSegmentName[0] = gExploredShadowGraveyardMinimapTex; + } else if (play->sceneNum == SCENE_LAKE_HYLIA && (LINK_AGE_IN_YEARS == YEARS_ADULT) && + ((!IS_RANDO && !CHECK_QUEST_ITEM(QUEST_MEDALLION_WATER)) || + (IS_RANDO && !Flags_GetEventChkInf(EVENTCHKINF_USED_WATER_TEMPLE_BLUE_WARP)))) { + sOwEntranceIconPosX = 259; + sOwEntranceIconPosY = -829; + play->interfaceCtx.mapSegmentName[0] = gDrainedLakeHyliaMinimapTex; + } else if (play->sceneNum == SCENE_GERUDO_VALLEY && (LINK_AGE_IN_YEARS == YEARS_ADULT) && + !GET_EVENTCHKINF_CARPENTERS_FREE_ALL()) { + sOwEntranceIconPosX = 1; + sOwEntranceIconPosY = 0; + play->interfaceCtx.mapSegmentName[0] = gGerudoValleyWithBrokenBridgeMinimapTex; + } else if (play->sceneNum == SCENE_GERUDOS_FORTRESS && (!IS_RANDO && GET_EVENTCHKINF_CARPENTERS_FREE_ALL()) || + (IS_RANDO && CHECK_QUEST_ITEM(QUEST_GERUDO_CARD))) { + sOwEntranceIconPosX = 243; + sOwEntranceIconPosY = -833; + play->interfaceCtx.mapSegmentName[0] = gGerudosFortressMinimapTex; + } else { + sOwEntranceIconPosX = entry->worldData.iconX; + sOwEntranceIconPosY = entry->worldData.iconY; + play->interfaceCtx.mapSegmentName[0] = entry->worldData.minimapTexture; + } + play->interfaceCtx.mapSegment[0] = ResourceGetDataByName(play->interfaceCtx.mapSegmentName[0]); - if (sEntranceIconMapIndex < 24) { - play->interfaceCtx.mapSegment[0] = ResourceGetDataByName(minimapTableOW[sEntranceIconMapIndex]); - play->interfaceCtx.mapSegmentName[0] = minimapTableOW[sEntranceIconMapIndex]; - } + interfaceCtx->unk_258 = mapIndex; + } else if (SCENEDB_ISDUNGEON(entry)) { + osSyncPrintf(VT_FGCOL(YELLOW)); + // "Deku Tree Dungeon MAP Texture DMA" + osSyncPrintf("デクの樹ダンジョンMAP テクスチャDMA(%x) scene_id_offset=%d VREG(30)=%d\n", room, mapIndex, + VREG(30)); + osSyncPrintf(VT_RST); - interfaceCtx->unk_258 = mapIndex; - break; - case SCENE_DEKU_TREE: - case SCENE_DODONGOS_CAVERN: - case SCENE_JABU_JABU: - case SCENE_FOREST_TEMPLE: - case SCENE_FIRE_TEMPLE: - case SCENE_WATER_TEMPLE: - case SCENE_SPIRIT_TEMPLE: - case SCENE_SHADOW_TEMPLE: - case SCENE_BOTTOM_OF_THE_WELL: - case SCENE_ICE_CAVERN: - case SCENE_DEKU_TREE_BOSS: - case SCENE_DODONGOS_CAVERN_BOSS: - case SCENE_JABU_JABU_BOSS: - case SCENE_FOREST_TEMPLE_BOSS: - case SCENE_FIRE_TEMPLE_BOSS: - case SCENE_WATER_TEMPLE_BOSS: - case SCENE_SPIRIT_TEMPLE_BOSS: - case SCENE_SHADOW_TEMPLE_BOSS: - osSyncPrintf(VT_FGCOL(YELLOW)); - // "Deku Tree Dungeon MAP Texture DMA" - osSyncPrintf("デクの樹ダンジョンMAP テクスチャDMA(%x) scene_id_offset=%d VREG(30)=%d\n", room, - mapIndex, VREG(30)); - osSyncPrintf(VT_RST); - // DmaMgr_SendRequest1(play->interfaceCtx.mapSegment, - //(uintptr_t)_map_i_staticSegmentRomStart + - //((gMapData->dgnMinimapTexIndexOffset[mapIndex] + room) * 0xFF0), - // 0xFF0, __FILE__, __LINE__); - - play->interfaceCtx.mapSegment[0] = - ResourceGetDataByName(minimapTableDangeon[gMapData->dgnMinimapTexIndexOffset[mapIndex] + room]); - play->interfaceCtx.mapSegmentName[0] = - minimapTableDangeon[gMapData->dgnMinimapTexIndexOffset[mapIndex] + room]; - R_COMPASS_OFFSET_X = gMapData->roomCompassOffsetX[mapIndex][room]; - R_COMPASS_OFFSET_Y = gMapData->roomCompassOffsetY[mapIndex][room]; - Map_SetFloorPalettesData(play, VREG(30)); - osSyncPrintf("MAP 各階ONチェック\n"); // "MAP Individual Floor ON Check" - break; + play->interfaceCtx.mapSegmentName[0] = entry->dungeonData.rooms[room].minimapTexture; + play->interfaceCtx.mapSegment[0] = ResourceGetDataByName(play->interfaceCtx.mapSegmentName[0]); + R_COMPASS_OFFSET_X = entry->dungeonData.rooms[room].compassOffsetX; + R_COMPASS_OFFSET_Y = entry->dungeonData.rooms[room].compassOffsetY; + Map_SetFloorPalettesData(play, VREG(30)); + osSyncPrintf("MAP 各階ONチェック\n"); // "MAP Individual Floor ON Check" } } @@ -470,37 +406,16 @@ void Map_InitRoomData(PlayState* play, s16 room) { osSyncPrintf("*******\n*******\nroom_no=%d (%d)(%d)\n*******\n*******\n", room, mapIndex, play->sceneNum); - if (room >= 0) { - switch (play->sceneNum) { - case SCENE_DEKU_TREE: - case SCENE_DODONGOS_CAVERN: - case SCENE_JABU_JABU: - case SCENE_FOREST_TEMPLE: - case SCENE_FIRE_TEMPLE: - case SCENE_WATER_TEMPLE: - case SCENE_SPIRIT_TEMPLE: - case SCENE_SHADOW_TEMPLE: - case SCENE_BOTTOM_OF_THE_WELL: - case SCENE_ICE_CAVERN: - case SCENE_DEKU_TREE_BOSS: - case SCENE_DODONGOS_CAVERN_BOSS: - case SCENE_JABU_JABU_BOSS: - case SCENE_FOREST_TEMPLE_BOSS: - case SCENE_FIRE_TEMPLE_BOSS: - case SCENE_WATER_TEMPLE_BOSS: - case SCENE_SPIRIT_TEMPLE_BOSS: - case SCENE_SHADOW_TEMPLE_BOSS: - gSaveContext.sceneFlags[mapIndex].rooms |= gBitFlags[room]; - osSyncPrintf("ROOM_INF=%d\n", gSaveContext.sceneFlags[mapIndex].rooms); - interfaceCtx->mapRoomNum = room; - interfaceCtx->unk_25A = mapIndex; - Map_SetPaletteData(play, room); - osSyncPrintf(VT_FGCOL(YELLOW)); - osSyncPrintf("部屋部屋=%d\n", room); // "Room Room = %d" - osSyncPrintf(VT_RST); - Map_InitData(play, room); - break; - } + if ((room >= 0) && (SceneDB_IsDungeon(play->sceneNum) || SceneDB_IsBoss(play->sceneNum))) { + gSaveContext.sceneFlags[mapIndex].rooms |= gBitFlags[room]; + osSyncPrintf("ROOM_INF=%d\n", gSaveContext.sceneFlags[mapIndex].rooms); + interfaceCtx->mapRoomNum = room; + interfaceCtx->unk_25A = mapIndex; + Map_SetPaletteData(play, room); + osSyncPrintf(VT_FGCOL(YELLOW)); + osSyncPrintf("部屋部屋=%d\n", room); // "Room Room = %d" + osSyncPrintf(VT_RST); + Map_InitData(play, room); } else { interfaceCtx->mapRoomNum = 0; } @@ -521,6 +436,8 @@ void Map_Init(PlayState* play) { gMapData = &gMapDataTable; + SceneDB_SetMapMarkData(play->sceneNum, ResourceMgr_IsGameMasterQuest()); + interfaceCtx->unk_258 = -1; interfaceCtx->unk_25A = -1; @@ -530,75 +447,29 @@ void Map_Init(PlayState* play) { interfaceCtx->mapSegment, play); assert(interfaceCtx->mapSegment != NULL); - switch (play->sceneNum) { - case SCENE_HYRULE_FIELD: - case SCENE_KAKARIKO_VILLAGE: - case SCENE_GRAVEYARD: - case SCENE_ZORAS_RIVER: - case SCENE_KOKIRI_FOREST: - case SCENE_SACRED_FOREST_MEADOW: - case SCENE_LAKE_HYLIA: - case SCENE_ZORAS_DOMAIN: - case SCENE_ZORAS_FOUNTAIN: - case SCENE_GERUDO_VALLEY: - case SCENE_LOST_WOODS: - case SCENE_DESERT_COLOSSUS: - case SCENE_GERUDOS_FORTRESS: - case SCENE_HAUNTED_WASTELAND: - case SCENE_HYRULE_CASTLE: - case SCENE_DEATH_MOUNTAIN_TRAIL: - case SCENE_DEATH_MOUNTAIN_CRATER: - case SCENE_GORON_CITY: - case SCENE_LON_LON_RANCH: - case SCENE_OUTSIDE_GANONS_CASTLE: - mapIndex = play->sceneNum - SCENE_HYRULE_FIELD; - R_MAP_INDEX = gSaveContext.mapIndex = mapIndex; - R_COMPASS_SCALE_X = gMapData->owCompassInfo[mapIndex][0]; - R_COMPASS_SCALE_Y = gMapData->owCompassInfo[mapIndex][1]; - R_COMPASS_OFFSET_X = gMapData->owCompassInfo[mapIndex][2]; - R_COMPASS_OFFSET_Y = gMapData->owCompassInfo[mapIndex][3]; - Map_InitData(play, mapIndex); - R_OW_MINIMAP_X = gMapData->owMinimapPosX[mapIndex]; - R_OW_MINIMAP_Y = gMapData->owMinimapPosY[mapIndex]; - break; - case SCENE_DEKU_TREE: - case SCENE_DODONGOS_CAVERN: - case SCENE_JABU_JABU: - case SCENE_FOREST_TEMPLE: - case SCENE_FIRE_TEMPLE: - case SCENE_WATER_TEMPLE: - case SCENE_SPIRIT_TEMPLE: - case SCENE_SHADOW_TEMPLE: - case SCENE_BOTTOM_OF_THE_WELL: - case SCENE_ICE_CAVERN: - case SCENE_GANONS_TOWER: - case SCENE_GERUDO_TRAINING_GROUND: - case SCENE_THIEVES_HIDEOUT: - case SCENE_INSIDE_GANONS_CASTLE: - case SCENE_GANONS_TOWER_COLLAPSE_INTERIOR: - case SCENE_INSIDE_GANONS_CASTLE_COLLAPSE: - case SCENE_TREASURE_BOX_SHOP: - case SCENE_DEKU_TREE_BOSS: - case SCENE_DODONGOS_CAVERN_BOSS: - case SCENE_JABU_JABU_BOSS: - case SCENE_FOREST_TEMPLE_BOSS: - case SCENE_FIRE_TEMPLE_BOSS: - case SCENE_WATER_TEMPLE_BOSS: - case SCENE_SPIRIT_TEMPLE_BOSS: - case SCENE_SHADOW_TEMPLE_BOSS: - mapIndex = - (play->sceneNum >= SCENE_DEKU_TREE_BOSS) ? play->sceneNum - SCENE_DEKU_TREE_BOSS : play->sceneNum; - R_MAP_INDEX = gSaveContext.mapIndex = mapIndex; - if ((play->sceneNum <= SCENE_ICE_CAVERN) || (play->sceneNum >= SCENE_DEKU_TREE_BOSS)) { - R_COMPASS_SCALE_X = gMapData->dgnCompassInfo[mapIndex][0]; - R_COMPASS_SCALE_Y = gMapData->dgnCompassInfo[mapIndex][1]; - R_COMPASS_OFFSET_X = gMapData->dgnCompassInfo[mapIndex][2]; - R_COMPASS_OFFSET_Y = gMapData->dgnCompassInfo[mapIndex][3]; - R_MAP_TEX_INDEX = R_MAP_TEX_INDEX_BASE = gMapData->dgnMinimapTexIndexBase[mapIndex]; - Map_InitRoomData(play, play->roomCtx.curRoom.num); - MapMark_Init(play); - } - break; + SceneDBEntry* entry = SceneDB_Retrieve(play->sceneNum); + + if (SCENEDB_ISBOSS(entry)) { + gSaveContext.mapIndex = entry->bossData.mapScene; + } else { + gSaveContext.mapIndex = play->sceneNum; + } + + if (SCENEDB_ISOVERWORLD(entry)) { + R_COMPASS_SCALE_X = entry->compassInfo.scaleX; + R_COMPASS_SCALE_Y = entry->compassInfo.scaleY; + R_COMPASS_OFFSET_X = entry->compassInfo.x; + R_COMPASS_OFFSET_Y = entry->compassInfo.y; + Map_InitData(play, 0); + R_OW_MINIMAP_X = sOwEntranceIconPosX; + R_OW_MINIMAP_Y = sOwEntranceIconPosY; + } else if (SCENEDB_ISDUNGEON(entry) || SCENEDB_ISBOSS(entry)) { + R_COMPASS_SCALE_X = entry->compassInfo.scaleX; + R_COMPASS_SCALE_Y = entry->compassInfo.scaleY; + R_COMPASS_OFFSET_X = entry->compassInfo.x; + R_COMPASS_OFFSET_Y = entry->compassInfo.y; + Map_InitRoomData(play, play->roomCtx.curRoom.num); + MapMark_Init(play); } } @@ -607,6 +478,7 @@ void Minimap_DrawCompassIcons(PlayState* play) { Player* player = GET_PLAYER(play); s16 tempX, tempZ; Color_RGB8 lastEntranceColor = { 200, 0, 0 }; + SceneDBEntry* entry = SceneDB_Retrieve(play->sceneNum); if (CVarGetInteger(CVAR_COSMETIC("HUD.MinimapEntrance.Changed"), 0)) { lastEntranceColor = CVarGetColor24(CVAR_COSMETIC("HUD.MinimapEntrance.Value"), lastEntranceColor); } @@ -640,10 +512,10 @@ void Minimap_DrawCompassIcons(PlayState* play) { s16 mapWidth = 0; s16 mapStartPosX = 0; - if (play->sceneNum >= SCENE_HYRULE_FIELD && play->sceneNum <= SCENE_OUTSIDE_GANONS_CASTLE) { // Overworld - mapStartPosX = R_OW_MINIMAP_X; - mapWidth = gMapData->owMinimapWidth[R_MAP_INDEX]; - } else if (play->sceneNum >= SCENE_DEKU_TREE && play->sceneNum <= SCENE_ICE_CAVERN) { // Dungeons + if (SCENEDB_ISOVERWORLD(entry)) { + mapStartPosX = entry->worldData.minimapX; + mapWidth = entry->worldData.minimapWidth; + } else if (SCENEDB_ISDUNGEON(entry)) { mapStartPosX = R_DGN_MINIMAP_X; mapWidth = 96; } @@ -767,6 +639,7 @@ void Minimap_Draw(PlayState* play) { s32 pad[2]; InterfaceContext* interfaceCtx = &play->interfaceCtx; s32 mapIndex = gSaveContext.mapIndex; + SceneDBEntry* entry = SceneDB_Retrieve(play->sceneNum); Color_RGB8 minimapColor = { 0, 255, 255 }; if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.Changed"), 0)) { minimapColor = CVarGetColor24(CVAR_COSMETIC("HUD.Minimap.Value"), minimapColor); @@ -793,256 +666,181 @@ void Minimap_Draw(PlayState* play) { Y_Margins_Minimap = 0; } - switch (play->sceneNum) { - case SCENE_DEKU_TREE: - case SCENE_DODONGOS_CAVERN: - case SCENE_JABU_JABU: - case SCENE_FOREST_TEMPLE: - case SCENE_FIRE_TEMPLE: - case SCENE_WATER_TEMPLE: - case SCENE_SPIRIT_TEMPLE: - case SCENE_SHADOW_TEMPLE: - case SCENE_BOTTOM_OF_THE_WELL: - case SCENE_ICE_CAVERN: - if (!R_MINIMAP_DISABLED && CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) != HIDDEN) { - Gfx_SetupDL_39Overlay(play->state.gfxCtx); - gDPSetCombineLERP(OVERLAY_DISP++, 1, 0, PRIMITIVE, 0, TEXEL0, 0, PRIMITIVE, 0, 1, 0, PRIMITIVE, 0, - TEXEL0, 0, PRIMITIVE, 0); + if (SCENEDB_ISDUNGEON(entry)) { + if (!R_MINIMAP_DISABLED && + CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) != HIDDEN) { // Not Hidden + Gfx_SetupDL_39Overlay(play->state.gfxCtx); + gDPSetCombineLERP(OVERLAY_DISP++, 1, 0, PRIMITIVE, 0, TEXEL0, 0, PRIMITIVE, 0, 1, 0, PRIMITIVE, 0, + TEXEL0, 0, PRIMITIVE, 0); - if (CHECK_DUNGEON_ITEM(DUNGEON_MAP, mapIndex)) { - gDPSetPrimColor(OVERLAY_DISP++, 0, 0, minimapColor.r, minimapColor.g, minimapColor.b, - interfaceCtx->minimapAlpha); - - u8 mirrorMode = - CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? G_TX_MIRROR : G_TX_NOMIRROR; - gDPLoadTextureBlock_4b(OVERLAY_DISP++, interfaceCtx->mapSegmentName[0], G_IM_FMT_I, 96, 85, 0, - mirrorMode | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, - G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); - - s16 dgnMiniMapX = OTRGetRectDimensionFromRightEdge(R_DGN_MINIMAP_X + X_Margins_Minimap); - s16 dgnMiniMapY = R_DGN_MINIMAP_Y + Y_Margins_Minimap; - if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) != ORIGINAL_LOCATION) { - dgnMiniMapY = R_DGN_MINIMAP_Y + CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosY"), 0) + - Y_Margins_Minimap; - if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == ANCHOR_LEFT) { - if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.UseMargins"), 0) != 0) { - X_Margins_Minimap = Left_MM_Margin; - }; - dgnMiniMapX = OTRGetDimensionFromLeftEdge( - R_DGN_MINIMAP_X + CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0) + - X_Margins_Minimap); - } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == ANCHOR_RIGHT) { - if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.UseMargins"), 0) != 0) { - X_Margins_Minimap = Right_MM_Margin; - }; - dgnMiniMapX = OTRGetDimensionFromRightEdge( - R_DGN_MINIMAP_X + CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0) + - X_Margins_Minimap); - } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == ANCHOR_NONE) { - dgnMiniMapX = CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0); - } - } - - s32 sValue = 0; - if (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0)) { - // Flip the minimap on the x-axis (s-axis) by setting s to the textures mirror boundary - sValue = 96 << 5; - } - - gSPWideTextureRectangle(OVERLAY_DISP++, dgnMiniMapX << 2, dgnMiniMapY << 2, - (dgnMiniMapX + 96) << 2, (dgnMiniMapY + 85) << 2, G_TX_RENDERTILE, - sValue, 0, 1 << 10, 1 << 10); - } - - if (CHECK_DUNGEON_ITEM(DUNGEON_COMPASS, mapIndex)) { - Minimap_DrawCompassIcons(play); // Draw icons for the player spawn and current position - Gfx_SetupDL_39Overlay(play->state.gfxCtx); - MapMark_Draw(play); - } - } - - if (CHECK_BTN_ALL(play->state.input[0].press.button, BTN_L) && !Play_InCsMode(play) && - enableMapToggle) { - osSyncPrintf("Game_play_demo_mode_check=%d\n", Play_InCsMode(play)); - // clang-format off - if (!R_MINIMAP_DISABLED) { Audio_PlaySoundGeneral(NA_SE_SY_CAMERA_ZOOM_UP, &gSfxDefaultPos, 4, - &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); } - else { Audio_PlaySoundGeneral(NA_SE_SY_CAMERA_ZOOM_DOWN, &gSfxDefaultPos, 4, - &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); } - // clang-format on - R_MINIMAP_DISABLED ^= 1; - } - - break; - case SCENE_HYRULE_FIELD: - case SCENE_KAKARIKO_VILLAGE: - case SCENE_GRAVEYARD: - case SCENE_ZORAS_RIVER: - case SCENE_KOKIRI_FOREST: - case SCENE_SACRED_FOREST_MEADOW: - case SCENE_LAKE_HYLIA: - case SCENE_ZORAS_DOMAIN: - case SCENE_ZORAS_FOUNTAIN: - case SCENE_GERUDO_VALLEY: - case SCENE_LOST_WOODS: - case SCENE_DESERT_COLOSSUS: - case SCENE_GERUDOS_FORTRESS: - case SCENE_HAUNTED_WASTELAND: - case SCENE_HYRULE_CASTLE: - case SCENE_DEATH_MOUNTAIN_TRAIL: - case SCENE_DEATH_MOUNTAIN_CRATER: - case SCENE_GORON_CITY: - case SCENE_LON_LON_RANCH: - case SCENE_OUTSIDE_GANONS_CASTLE: - if (!R_MINIMAP_DISABLED && CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) != 4) { // Not Hidden - Gfx_SetupDL_39Overlay(play->state.gfxCtx); - - gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM); + if (CHECK_DUNGEON_ITEM(DUNGEON_MAP, mapIndex)) { gDPSetPrimColor(OVERLAY_DISP++, 0, 0, minimapColor.r, minimapColor.g, minimapColor.b, interfaceCtx->minimapAlpha); u8 mirrorMode = CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? G_TX_MIRROR : G_TX_NOMIRROR; - gDPLoadTextureBlock_4b(OVERLAY_DISP++, interfaceCtx->mapSegmentName[0], G_IM_FMT_IA, - gMapData->owMinimapWidth[mapIndex], gMapData->owMinimapHeight[mapIndex], 0, + gDPLoadTextureBlock_4b(OVERLAY_DISP++, interfaceCtx->mapSegmentName[0], G_IM_FMT_I, 96, 85, 0, mirrorMode | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); - s16 oWMiniMapX = OTRGetRectDimensionFromRightEdge(R_OW_MINIMAP_X + X_Margins_Minimap); - s16 oWMiniMapY = R_OW_MINIMAP_Y + Y_Margins_Minimap; + s16 dgnMiniMapX = OTRGetRectDimensionFromRightEdge(R_DGN_MINIMAP_X + X_Margins_Minimap); + s16 dgnMiniMapY = R_DGN_MINIMAP_Y + Y_Margins_Minimap; if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) != ORIGINAL_LOCATION) { - oWMiniMapY = - R_OW_MINIMAP_Y + CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosY"), 0) + Y_Margins_Minimap; + dgnMiniMapY = + R_DGN_MINIMAP_Y + CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosY"), 0) + Y_Margins_Minimap; if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == ANCHOR_LEFT) { if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.UseMargins"), 0) != 0) { X_Margins_Minimap = Left_MM_Margin; }; - oWMiniMapX = OTRGetDimensionFromLeftEdge( - R_OW_MINIMAP_X + CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0) + + dgnMiniMapX = OTRGetDimensionFromLeftEdge( + R_DGN_MINIMAP_X + CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0) + X_Margins_Minimap); } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == ANCHOR_RIGHT) { if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.UseMargins"), 0) != 0) { X_Margins_Minimap = Right_MM_Margin; }; - oWMiniMapX = OTRGetDimensionFromRightEdge( - R_OW_MINIMAP_X + CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0) + + dgnMiniMapX = OTRGetDimensionFromRightEdge( + R_DGN_MINIMAP_X + CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0) + X_Margins_Minimap); } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == ANCHOR_NONE) { - oWMiniMapX = CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0); + dgnMiniMapX = CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0); } } s32 sValue = 0; if (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0)) { // Flip the minimap on the x-axis (s-axis) by setting s to the textures mirror boundary - sValue = gMapData->owMinimapWidth[mapIndex] << 5; + sValue = 96 << 5; } - gSPWideTextureRectangle(OVERLAY_DISP++, oWMiniMapX << 2, oWMiniMapY << 2, - (oWMiniMapX + gMapData->owMinimapWidth[mapIndex]) << 2, - (oWMiniMapY + gMapData->owMinimapHeight[mapIndex]) << 2, G_TX_RENDERTILE, - sValue, 0, 1 << 10, 1 << 10); + gSPWideTextureRectangle(OVERLAY_DISP++, dgnMiniMapX << 2, dgnMiniMapY << 2, (dgnMiniMapX + 96) << 2, + (dgnMiniMapY + 85) << 2, G_TX_RENDERTILE, sValue, 0, 1 << 10, 1 << 10); + } - gDPSetPrimColor(OVERLAY_DISP++, 0, 0, minimapColor.r, minimapColor.g, minimapColor.b, - interfaceCtx->minimapAlpha); + if (CHECK_DUNGEON_ITEM(DUNGEON_COMPASS, mapIndex)) { + Minimap_DrawCompassIcons(play); // Draw icons for the player spawn and current position + Gfx_SetupDL_39Overlay(play->state.gfxCtx); + MapMark_Draw(play); + } + } - s16 iconSize = 8; + if (CHECK_BTN_ALL(play->state.input[0].press.button, BTN_L) && !Play_InCsMode(play) && enableMapToggle) { + osSyncPrintf("Game_play_demo_mode_check=%d\n", Play_InCsMode(play)); + // clang-format off + if (!R_MINIMAP_DISABLED) { Audio_PlaySoundGeneral(NA_SE_SY_CAMERA_ZOOM_UP, &gSfxDefaultPos, 4, + &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); } + else { Audio_PlaySoundGeneral(NA_SE_SY_CAMERA_ZOOM_DOWN, &gSfxDefaultPos, 4, + &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); } + // clang-format on + R_MINIMAP_DISABLED ^= 1; + } + } else if (SCENEDB_ISOVERWORLD(entry)) { + if (!R_MINIMAP_DISABLED && CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) != 4) { // Not Hidden + Gfx_SetupDL_39Overlay(play->state.gfxCtx); - if (((play->sceneNum != SCENE_KAKARIKO_VILLAGE) && (play->sceneNum != SCENE_KOKIRI_FOREST) && - (play->sceneNum != SCENE_ZORAS_FOUNTAIN)) || - (LINK_AGE_IN_YEARS != YEARS_ADULT)) { - s16 origX = gMapData->owEntranceIconPosX[sEntranceIconMapIndex]; + gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM); + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, minimapColor.r, minimapColor.g, minimapColor.b, + interfaceCtx->minimapAlpha); - // Compute the distance of the center of the original texture location to the center of the map - // Then duplicate that and right-align the texture (extra 2 pixels are due to the texture being - // a 6px left-aligned in a 8px tex) - s16 distFromCenter = - (R_OW_MINIMAP_X + (gMapData->owMinimapWidth[mapIndex] / 2)) - (origX + (iconSize / 2)); - s16 mirrorOffset = distFromCenter * 2 + (iconSize / 2) - 2; - s16 newX = origX + (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? mirrorOffset : 0); + u8 mirrorMode = CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? G_TX_MIRROR : G_TX_NOMIRROR; + gDPLoadTextureBlock_4b(OVERLAY_DISP++, interfaceCtx->mapSegmentName[0], G_IM_FMT_IA, + entry->worldData.minimapWidth, entry->worldData.minimapHeight, 0, + mirrorMode | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, + G_TX_NOLOD, G_TX_NOLOD); - // The game authentically uses larger negative values for the entrance icon Y pos value. - // Normally only the first 12 bits would be read when the final value is passed into - // `gSPTextureRectangle`, but our cosmetic hud placements requires using - // `gSPWideTextureRectangle` which reads the first 24 bits instead. This caused the icon to be - // placed off screen. To address this, we take only the first 10 bits (which are later - // left-shifted by 2 to get our final 12 bits) to fix the entrance icon position when used with - // `gSPWideTextureRectangle` - s16 newY = gMapData->owEntranceIconPosY[sEntranceIconMapIndex] & 0x3FF; - - s16 entranceX = OTRGetRectDimensionFromRightEdge(newX + X_Margins_Minimap); - s16 entranceY = newY + Y_Margins_Minimap; - if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) != ORIGINAL_LOCATION) { - entranceY = newY + CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosY"), 0) + Y_Margins_Minimap; - if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == ANCHOR_LEFT) { - if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.UseMargins"), 0) != 0) { - X_Margins_Minimap = Left_MM_Margin; - }; - entranceX = OTRGetRectDimensionFromLeftEdge( - newX + X_Margins_Minimap + CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0)); - } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == ANCHOR_RIGHT) { - if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.UseMargins"), 0) != 0) { - X_Margins_Minimap = Right_MM_Margin; - }; - entranceX = OTRGetRectDimensionFromRightEdge( - newX + X_Margins_Minimap + CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0)); - } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == ANCHOR_NONE) { - entranceX = - newX + X_Margins_Minimap + CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0); - } - } - - // For icons that normally would be placed in 0,0 leave them there based on the left edge - // dimension or hide them entirely if the fix is applied - if (gMapData->owEntranceIconPosY[sEntranceIconMapIndex] == 0) { - entranceY = 0; - entranceX = CVarGetInteger(CVAR_ENHANCEMENT("FixDungeonMinimapIcon"), 0) - ? -9999 - : OTRGetRectDimensionFromLeftEdge(0); - } - - //! @bug UB: sEntranceIconMapIndex can be up to 23 and is accessing owEntranceFlag which is size - //! 20 - if ((gMapData->owEntranceFlag[sEntranceIconMapIndex] == 0xFFFF) || - ((gMapData->owEntranceFlag[sEntranceIconMapIndex] != 0xFFFF) && - ((gSaveContext.infTable[26] & gBitFlags[gMapData->owEntranceFlag[mapIndex]]) || - CVarGetInteger(CVAR_ENHANCEMENT("AlwaysShowDungeonMinimapIcon"), 0)))) { - gDPLoadTextureBlock(OVERLAY_DISP++, gMapDungeonEntranceIconTex, G_IM_FMT_RGBA, G_IM_SIZ_16b, - iconSize, iconSize, 0, G_TX_NOMIRROR | G_TX_WRAP, - G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, - G_TX_NOLOD); - gSPWideTextureRectangle(OVERLAY_DISP++, entranceX << 2, entranceY << 2, - (entranceX + iconSize) << 2, (entranceY + iconSize) << 2, - G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10); - } + s16 oWMiniMapX = OTRGetRectDimensionFromRightEdge(entry->worldData.minimapX + X_Margins_Minimap); + s16 oWMiniMapY = entry->worldData.minimapY + Y_Margins_Minimap; + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) != ORIGINAL_LOCATION) { + oWMiniMapY = entry->worldData.minimapY + CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosY"), 0) + + Y_Margins_Minimap; + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == ANCHOR_LEFT) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.UseMargins"), 0) != 0) { + X_Margins_Minimap = Left_MM_Margin; + }; + oWMiniMapX = OTRGetDimensionFromLeftEdge(entry->worldData.minimapX + + CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0) + + X_Margins_Minimap); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == ANCHOR_RIGHT) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.UseMargins"), 0) != 0) { + X_Margins_Minimap = Right_MM_Margin; + }; + oWMiniMapX = OTRGetDimensionFromRightEdge(entry->worldData.minimapX + + CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0) + + X_Margins_Minimap); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == ANCHOR_NONE) { + oWMiniMapX = CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0); } + } - s16 origX = CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? 256 : 270; - s16 entranceX = OTRGetRectDimensionFromRightEdge(origX + X_Margins_Minimap); - s16 entranceY = 154 + Y_Margins_Minimap; + s32 sValue = 0; + if (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0)) { + // Flip the minimap on the x-axis (s-axis) by setting s to the textures mirror boundary + sValue = entry->worldData.minimapWidth << 5; + } + + gSPWideTextureRectangle( + OVERLAY_DISP++, oWMiniMapX << 2, oWMiniMapY << 2, (oWMiniMapX + entry->worldData.minimapWidth) << 2, + (oWMiniMapY + entry->worldData.minimapHeight) << 2, G_TX_RENDERTILE, sValue, 0, 1 << 10, 1 << 10); + + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, minimapColor.r, minimapColor.g, minimapColor.b, + interfaceCtx->minimapAlpha); + + s16 iconSize = 8; + + if (((play->sceneNum != SCENE_KAKARIKO_VILLAGE) && (play->sceneNum != SCENE_KOKIRI_FOREST) && + (play->sceneNum != SCENE_ZORAS_FOUNTAIN)) || + (LINK_AGE_IN_YEARS != YEARS_ADULT)) { + s16 origX = R_OW_MINIMAP_X; + + // Compute the distance of the center of the original texture location to the center of the map + // Then duplicate that and right-align the texture (extra 2 pixels are due to the texture being a + // 6px left-aligned in a 8px tex) + s16 distFromCenter = + (entry->worldData.minimapX + (entry->worldData.minimapWidth / 2)) - (origX + (iconSize / 2)); + s16 mirrorOffset = distFromCenter * 2 + (iconSize / 2) - 2; + s16 newX = origX + (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? mirrorOffset : 0); + + // The game authentically uses larger negative values for the entrance icon Y pos value. Normally + // only the first 12 bits would be read when the final value is passed into `gSPTextureRectangle`, + // but our cosmetic hud placements requires using `gSPWideTextureRectangle` which reads the first 24 + // bits instead. This caused the icon to be placed off screen. To address this, we take only the + // first 10 bits (which are later left-shifted by 2 to get our final 12 bits) to fix the entrance + // icon position when used with `gSPWideTextureRectangle` + s16 newY = R_OW_MINIMAP_Y & 0x3FF; + + s16 entranceX = OTRGetRectDimensionFromRightEdge(newX + X_Margins_Minimap); + s16 entranceY = newY + Y_Margins_Minimap; if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) != ORIGINAL_LOCATION) { - entranceY = 154 + Y_Margins_Minimap + CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosY"), 0); + entranceY = newY + CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosY"), 0) + Y_Margins_Minimap; if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == ANCHOR_LEFT) { if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.UseMargins"), 0) != 0) { X_Margins_Minimap = Left_MM_Margin; }; entranceX = OTRGetRectDimensionFromLeftEdge( - origX + X_Margins_Minimap + CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0)); + newX + X_Margins_Minimap + CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0)); } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == ANCHOR_RIGHT) { if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.UseMargins"), 0) != 0) { X_Margins_Minimap = Right_MM_Margin; }; entranceX = OTRGetRectDimensionFromRightEdge( - origX + X_Margins_Minimap + CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0)); + newX + X_Margins_Minimap + CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0)); } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == ANCHOR_NONE) { - entranceX = - origX + X_Margins_Minimap + CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0); + entranceX = newX + X_Margins_Minimap + CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0); } } - // Ice Cavern entrance icon - if ((play->sceneNum == SCENE_ZORAS_FOUNTAIN) && - ((gSaveContext.infTable[26] & gBitFlags[9]) || - CVarGetInteger(CVAR_ENHANCEMENT("AlwaysShowDungeonMinimapIcon"), 0))) { + // For icons that normally would be placed in 0,0 leave them there based on the left edge dimension + // or hide them entirely if the fix is applied + if (R_OW_MINIMAP_Y == 0) { + entranceY = 0; + entranceX = CVarGetInteger(CVAR_ENHANCEMENT("FixDungeonMinimapIcon"), 0) + ? -9999 + : OTRGetRectDimensionFromLeftEdge(0); + } + + if ((entry->worldData.entranceFlag == -1) || + ((entry->worldData.entranceFlag != -1) && + ((gSaveContext.infTable[26] & gBitFlags[entry->worldData.entranceFlag]) || + CVarGetInteger(CVAR_ENHANCEMENT("AlwaysShowDungeonMinimapIcon"), 0)))) { gDPLoadTextureBlock(OVERLAY_DISP++, gMapDungeonEntranceIconTex, G_IM_FMT_RGBA, G_IM_SIZ_16b, iconSize, iconSize, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); @@ -1050,22 +848,53 @@ void Minimap_Draw(PlayState* play) { (entranceX + iconSize) << 2, (entranceY + iconSize) << 2, G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10); } - - Minimap_DrawCompassIcons(play); // Draw icons for the player spawn and current position } - if (CHECK_BTN_ALL(play->state.input[0].press.button, BTN_L) && !Play_InCsMode(play) && - enableMapToggle) { - // clang-format off - if (!R_MINIMAP_DISABLED) { Audio_PlaySoundGeneral(NA_SE_SY_CAMERA_ZOOM_UP, &gSfxDefaultPos, 4, - &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); } - else { Audio_PlaySoundGeneral(NA_SE_SY_CAMERA_ZOOM_DOWN, &gSfxDefaultPos, 4, - &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); } - // clang-format on - R_MINIMAP_DISABLED ^= 1; + s16 origX = CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? 256 : 270; + s16 entranceX = OTRGetRectDimensionFromRightEdge(origX + X_Margins_Minimap); + s16 entranceY = 154 + Y_Margins_Minimap; + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) != ORIGINAL_LOCATION) { + entranceY = 154 + Y_Margins_Minimap + CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosY"), 0); + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == ANCHOR_LEFT) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.UseMargins"), 0) != 0) { + X_Margins_Minimap = Left_MM_Margin; + }; + entranceX = OTRGetRectDimensionFromLeftEdge( + origX + X_Margins_Minimap + CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0)); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == ANCHOR_RIGHT) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.UseMargins"), 0) != 0) { + X_Margins_Minimap = Right_MM_Margin; + }; + entranceX = OTRGetRectDimensionFromRightEdge( + origX + X_Margins_Minimap + CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0)); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == ANCHOR_NONE) { + entranceX = origX + X_Margins_Minimap + CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0); + } } - break; + // Ice Cavern entrance icon + if ((play->sceneNum == SCENE_ZORAS_FOUNTAIN) && + ((gSaveContext.infTable[26] & gBitFlags[9]) || + CVarGetInteger(CVAR_ENHANCEMENT("AlwaysShowDungeonMinimapIcon"), 0))) { + gDPLoadTextureBlock(OVERLAY_DISP++, gMapDungeonEntranceIconTex, G_IM_FMT_RGBA, G_IM_SIZ_16b, + iconSize, iconSize, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, + G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); + gSPWideTextureRectangle(OVERLAY_DISP++, entranceX << 2, entranceY << 2, (entranceX + iconSize) << 2, + (entranceY + iconSize) << 2, G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10); + } + + Minimap_DrawCompassIcons(play); // Draw icons for the player spawn and current position + } + + if (CHECK_BTN_ALL(play->state.input[0].press.button, BTN_L) && !Play_InCsMode(play) && enableMapToggle) { + // clang-format off + if (!R_MINIMAP_DISABLED) { Audio_PlaySoundGeneral(NA_SE_SY_CAMERA_ZOOM_UP, &gSfxDefaultPos, 4, + &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); } + else { Audio_PlaySoundGeneral(NA_SE_SY_CAMERA_ZOOM_DOWN, &gSfxDefaultPos, 4, + &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); } + // clang-format on + R_MINIMAP_DISABLED ^= 1; + } } } @@ -1083,6 +912,7 @@ void Map_Update(PlayState* play) { InterfaceContext* interfaceCtx = &play->interfaceCtx; s16 floor; s16 i; + SceneDBEntry* entry = SceneDB_Retrieve(play->sceneNum); Top_MM_Margin = CVarGetInteger(CVAR_COSMETIC("HUD.Margin.T"), 0); Left_MM_Margin = CVarGetInteger(CVAR_COSMETIC("HUD.Margin.L"), 0); @@ -1090,71 +920,47 @@ void Map_Update(PlayState* play) { Bottom_MM_Margin = CVarGetInteger(CVAR_COSMETIC("HUD.Margin.B"), 0); if ((play->pauseCtx.state == 0) && (play->pauseCtx.debugState == 0)) { - switch (play->sceneNum) { - case SCENE_DEKU_TREE: - case SCENE_DODONGOS_CAVERN: - case SCENE_JABU_JABU: - case SCENE_FOREST_TEMPLE: - case SCENE_FIRE_TEMPLE: - case SCENE_WATER_TEMPLE: - case SCENE_SPIRIT_TEMPLE: - case SCENE_SHADOW_TEMPLE: - case SCENE_BOTTOM_OF_THE_WELL: - case SCENE_ICE_CAVERN: - interfaceCtx->mapPalette[30] = 0; - if (CHECK_DUNGEON_ITEM(DUNGEON_MAP, mapIndex)) { - interfaceCtx->mapPalette[31] = 1; - } else { - interfaceCtx->mapPalette[31] = 0; - } + if (SCENEDB_ISDUNGEON(entry)) { + interfaceCtx->mapPalette[30] = 0; + if (CHECK_DUNGEON_ITEM(DUNGEON_MAP, play->sceneNum)) { + interfaceCtx->mapPalette[31] = 1; + } else { + interfaceCtx->mapPalette[31] = 0; + } - for (floor = 0; floor < 8; floor++) { - if (player->actor.world.pos.y > gMapData->floorCoordY[mapIndex][floor]) { - break; - } + for (floor = 0; floor < 8; floor++) { + if (player->actor.world.pos.y > entry->dungeonData.floors[floor].height) { + break; } + } - gSaveContext.sceneFlags[mapIndex].floors |= gBitFlags[floor]; - VREG(30) = floor; - if (R_MAP_TEX_INDEX != (R_MAP_TEX_INDEX_BASE + Map_GetFloorTextIndexOffset(mapIndex, floor))) { - R_MAP_TEX_INDEX = R_MAP_TEX_INDEX_BASE + Map_GetFloorTextIndexOffset(mapIndex, floor); + gSaveContext.sceneFlags[play->sceneNum].floors |= gBitFlags[floor]; + VREG(30) = floor; + + if (interfaceCtx->mapRoomNum != sLastRoomNum) { + // "Current floor = %d Current room = %x Number of rooms = %d" + osSyncPrintf("現在階=%d 現在部屋=%x 部屋数=%d\n", floor, interfaceCtx->mapRoomNum, + entry->dungeonData.numRooms); + sLastRoomNum = interfaceCtx->mapRoomNum; + } + + for (i = 0; i < entry->dungeonData.numIntraRoomTransitions; i++) { + if ((interfaceCtx->mapRoomNum == entry->dungeonData.intraRoomTransitions[i].fromRoom) && + (floor == entry->dungeonData.intraRoomTransitions[i].toFloor)) { + interfaceCtx->mapRoomNum = entry->dungeonData.intraRoomTransitions[i].toRoom; + osSyncPrintf(VT_FGCOL(YELLOW)); + // "Layer switching = %x" + osSyncPrintf("階層切替=%x\n", interfaceCtx->mapRoomNum); + osSyncPrintf(VT_RST); + Map_InitData(play, interfaceCtx->mapRoomNum); + gSaveContext.sunsSongState = SUNSSONG_INACTIVE; + Map_SavePlayerInitialInfo(play); } + } - if (interfaceCtx->mapRoomNum != sLastRoomNum) { - // "Current floor = %d Current room = %x Number of rooms = %d" - osSyncPrintf("現在階=%d 現在部屋=%x 部屋数=%d\n", floor, interfaceCtx->mapRoomNum, - gMapData->switchEntryCount[mapIndex]); - sLastRoomNum = interfaceCtx->mapRoomNum; - } - - for (i = 0; i < gMapData->switchEntryCount[mapIndex]; i++) { - if ((interfaceCtx->mapRoomNum == gMapData->switchFromRoom[mapIndex][i]) && - (floor == gMapData->switchFromFloor[mapIndex][i])) { - interfaceCtx->mapRoomNum = gMapData->switchToRoom[mapIndex][i]; - osSyncPrintf(VT_FGCOL(YELLOW)); - // "Layer switching = %x" - osSyncPrintf("階層切替=%x\n", interfaceCtx->mapRoomNum); - osSyncPrintf(VT_RST); - Map_InitData(play, interfaceCtx->mapRoomNum); - gSaveContext.sunsSongState = SUNSSONG_INACTIVE; - Map_SavePlayerInitialInfo(play); - } - } - - VREG(10) = interfaceCtx->mapRoomNum; - break; - case SCENE_DEKU_TREE_BOSS: - case SCENE_DODONGOS_CAVERN_BOSS: - case SCENE_JABU_JABU_BOSS: - case SCENE_FOREST_TEMPLE_BOSS: - case SCENE_FIRE_TEMPLE_BOSS: - case SCENE_WATER_TEMPLE_BOSS: - case SCENE_SPIRIT_TEMPLE_BOSS: - case SCENE_SHADOW_TEMPLE_BOSS: - VREG(30) = gMapData->bossFloor[play->sceneNum - SCENE_DEKU_TREE_BOSS]; - R_MAP_TEX_INDEX = R_MAP_TEX_INDEX_BASE + - gMapData->floorTexIndexOffset[play->sceneNum - SCENE_DEKU_TREE_BOSS][VREG(30)]; - break; + VREG(10) = interfaceCtx->mapRoomNum; + } else if (SCENEDB_ISBOSS(entry)) { + VREG(30) = SceneDB_Retrieve(entry->bossData.mapScene)->dungeonData.bossFloor; } } } diff --git a/soh/src/code/z_map_mark.c b/soh/src/code/z_map_mark.c index 4d1496fb4..4d62bf9e2 100644 --- a/soh/src/code/z_map_mark.c +++ b/soh/src/code/z_map_mark.c @@ -1,5 +1,6 @@ #include "global.h" #include "vt.h" +#include "soh/SceneDB.h" #include "textures/parameter_static/parameter_static.h" #include "soh/OTRGlobals.h" #include "soh/ResourceManagerHelpers.h" @@ -95,138 +96,112 @@ void MapMark_DrawForDungeon(PlayState* play) { interfaceCtx = &play->interfaceCtx; - if ((gMapData != NULL) && (play->interfaceCtx.mapRoomNum >= gMapData->dgnMinimapCount[dungeon])) { - // "Room number exceeded, yikes %d/%d MapMarkDraw processing interrupted" - osSyncPrintf(VT_COL(RED, WHITE) "部屋番号がオーバーしてるで,ヤバイで %d/%d \nMapMarkDraw の処理を中断します\n", - VT_RST, play->interfaceCtx.mapRoomNum, gMapData->dgnMinimapCount[dungeon]); - return; - } + SceneDBEntry* entry = SceneDB_Retrieve(dungeon); + SceneDBRoom* room = &entry->dungeonData.rooms[interfaceCtx->mapRoomNum]; - mapMarkIconData = &sLoadedMarkDataTable[dungeon][interfaceCtx->mapRoomNum][0]; + s32 Top_MC_Margin = CVarGetInteger(CVAR_COSMETIC("HUD.Margin.T"), 0); + s32 Left_MC_Margin = CVarGetInteger(CVAR_COSMETIC("HUD.Margin.L"), 0); + s32 Right_MC_Margin = CVarGetInteger(CVAR_COSMETIC("HUD.Margin.R"), 0); + s32 Bottom_MC_Margin = CVarGetInteger(CVAR_COSMETIC("HUD.Margin.B"), 0); + + s32 X_Margins_Minimap_ic; + s32 Y_Margins_Minimap_ic; + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.UseMargins"), 0) != 0) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == ORIGINAL_LOCATION) { + X_Margins_Minimap_ic = Right_MC_Margin; + }; + Y_Margins_Minimap_ic = Bottom_MC_Margin; + } else { + X_Margins_Minimap_ic = 0; + Y_Margins_Minimap_ic = 0; + } OPEN_DISPS(play->state.gfxCtx); - while (true) { - if (mapMarkIconData->markType == MAP_MARK_NONE) { - break; + gDPPipeSync(OVERLAY_DISP++); + gDPSetTextureLUT(OVERLAY_DISP++, G_TT_NONE); + gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 255, 255, interfaceCtx->minimapAlpha); + gDPSetEnvColor(OVERLAY_DISP++, 0, 0, 0, interfaceCtx->minimapAlpha); + + // Chest and boss icon code is nearly identical, so let's draw them in the same loop + for (i = 0; i < room->numChestMarks + room->numBossMarks; i++) { + if (i < room->numChestMarks) { + if (Flags_GetTreasure(play, markPoint->chestFlag)) { + continue; + } + + markPoint = &room->chestMarks[i]; + markInfo = &sMapMarkInfoTable[MAP_MARK_CHEST]; + } else { // This is a boss icon + markPoint = &room->bossMarks[i - room->numChestMarks]; + markInfo = &sMapMarkInfoTable[MAP_MARK_BOSS]; + } + + int height = markInfo->textureHeight * 1.0f; // Adjust Height with scale + int width = markInfo->textureWidth * 1.0f; // Adjust Width with scale + int height_factor = (1 << 10) * markInfo->textureHeight / height; + int width_factor = (1 << 10) * markInfo->textureWidth / width; + + // The original mark point X originates from the left edge of the map + // For mirror mode, we compute the new mark point X by subtracting it from the right side of the + // dungeon map and the textures width + s16 markPointX = + CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? 96 - markPoint->x - width : markPoint->x; + + // Minimap chest / boss icon + const s32 PosX_Minimap_ori = + GREG(94) + OTRGetRectDimensionFromRightEdge(markPointX + X_Margins_Minimap_ic) + 204; + const s32 PosY_Minimap_ori = GREG(95) + markPoint->y + Y_Margins_Minimap_ic + 140; + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) != ORIGINAL_LOCATION) { + rectTop = + (markPoint->y + Y_Margins_Minimap_ic + 140 + CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosY"), 0)); + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == ANCHOR_LEFT) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.UseMargins"), 0) != 0) { + X_Margins_Minimap_ic = Left_MC_Margin; + }; + if (play->sceneNum == SCENE_DEKU_TREE || play->sceneNum == SCENE_DODONGOS_CAVERN || + play->sceneNum == SCENE_JABU_JABU || play->sceneNum == SCENE_FOREST_TEMPLE || + play->sceneNum == SCENE_FIRE_TEMPLE || play->sceneNum == SCENE_WATER_TEMPLE || + play->sceneNum == SCENE_SPIRIT_TEMPLE || play->sceneNum == SCENE_SHADOW_TEMPLE || + play->sceneNum == SCENE_BOTTOM_OF_THE_WELL || play->sceneNum == SCENE_ICE_CAVERN) { + rectLeft = OTRGetRectDimensionFromLeftEdge( + markPointX + CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0) + 204 + X_Margins_Minimap_ic); + } else { + rectLeft = OTRGetRectDimensionFromLeftEdge( + markPointX + CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0) + 204 + X_Margins_Minimap_ic); + } + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == ANCHOR_RIGHT) { + if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.UseMargins"), 0) != 0) { + X_Margins_Minimap_ic = Right_MC_Margin; + }; + rectLeft = OTRGetRectDimensionFromRightEdge( + markPointX + CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0) + 204 + X_Margins_Minimap_ic); + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == ANCHOR_NONE) { + rectLeft = + markPointX + CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0) + 204 + X_Margins_Minimap_ic; + } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == HIDDEN) { + rectLeft = -9999; + } + } else { + rectLeft = PosX_Minimap_ori; + rectTop = PosY_Minimap_ori; } gDPPipeSync(OVERLAY_DISP++); - gDPSetTextureLUT(OVERLAY_DISP++, G_TT_NONE); - gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 255, 255, interfaceCtx->minimapAlpha); - gDPSetEnvColor(OVERLAY_DISP++, 0, 0, 0, interfaceCtx->minimapAlpha); - s32 Top_MC_Margin = CVarGetInteger(CVAR_COSMETIC("HUD.Margin.T"), 0); - s32 Left_MC_Margin = CVarGetInteger(CVAR_COSMETIC("HUD.Margin.L"), 0); - s32 Right_MC_Margin = CVarGetInteger(CVAR_COSMETIC("HUD.Margin.R"), 0); - s32 Bottom_MC_Margin = CVarGetInteger(CVAR_COSMETIC("HUD.Margin.B"), 0); - - s32 X_Margins_Minimap_ic; - s32 Y_Margins_Minimap_ic; - if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.UseMargins"), 0) != 0) { - if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == ORIGINAL_LOCATION) { - X_Margins_Minimap_ic = Right_MC_Margin; - }; - Y_Margins_Minimap_ic = Bottom_MC_Margin; - } else { - X_Margins_Minimap_ic = 0; - Y_Margins_Minimap_ic = 0; - } - - markPoint = &mapMarkIconData->points[0]; - // Place each chest / boss room icon - for (i = 0; i < mapMarkIconData->count; i++) { - if ((mapMarkIconData->markType != MAP_MARK_CHEST) || !Flags_GetTreasure(play, markPoint->chestFlag)) { - markInfo = &sMapMarkInfoTable[mapMarkIconData->markType]; - int height = markInfo->textureHeight * 1.0f; // Adjust Height with scale - int width = markInfo->textureWidth * 1.0f; // Adjust Width with scale - int height_factor = (1 << 10) * markInfo->textureHeight / height; - int width_factor = (1 << 10) * markInfo->textureWidth / width; - - // The original mark point X originates from the left edge of the map - // For mirror mode, we compute the new mark point X by subtracting it from the right side of the - // dungeon map and the textures width - s16 markPointX = - CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? 96 - markPoint->x - width : markPoint->x; - - // Minimap chest / boss icon - const s32 PosX_Minimap_ori = - GREG(94) + OTRGetRectDimensionFromRightEdge(markPointX + X_Margins_Minimap_ic) + 204; - const s32 PosY_Minimap_ori = GREG(95) + markPoint->y + Y_Margins_Minimap_ic + 140; - if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) != ORIGINAL_LOCATION) { - rectTop = (markPoint->y + Y_Margins_Minimap_ic + 140 + - CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosY"), 0)); - if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == ANCHOR_LEFT) { - if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.UseMargins"), 0) != 0) { - X_Margins_Minimap_ic = Left_MC_Margin; - }; - if (play->sceneNum == SCENE_DEKU_TREE || play->sceneNum == SCENE_DODONGOS_CAVERN || - play->sceneNum == SCENE_JABU_JABU || play->sceneNum == SCENE_FOREST_TEMPLE || - play->sceneNum == SCENE_FIRE_TEMPLE || play->sceneNum == SCENE_WATER_TEMPLE || - play->sceneNum == SCENE_SPIRIT_TEMPLE || play->sceneNum == SCENE_SHADOW_TEMPLE || - play->sceneNum == SCENE_BOTTOM_OF_THE_WELL || play->sceneNum == SCENE_ICE_CAVERN) { - rectLeft = OTRGetRectDimensionFromLeftEdge( - markPointX + CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0) + 204 + - X_Margins_Minimap_ic); - } else { - rectLeft = OTRGetRectDimensionFromLeftEdge( - markPointX + CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0) + 204 + - X_Margins_Minimap_ic); - } - } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == ANCHOR_RIGHT) { - if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.UseMargins"), 0) != 0) { - X_Margins_Minimap_ic = Right_MC_Margin; - }; - rectLeft = OTRGetRectDimensionFromRightEdge( - markPointX + CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0) + 204 + - X_Margins_Minimap_ic); - } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == ANCHOR_NONE) { - rectLeft = markPointX + CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosX"), 0) + 204 + - X_Margins_Minimap_ic; - } else if (CVarGetInteger(CVAR_COSMETIC("HUD.Minimap.PosType"), 0) == HIDDEN) { - rectLeft = -9999; - } - } else { - rectLeft = PosX_Minimap_ori; - rectTop = PosY_Minimap_ori; - } - - gDPPipeSync(OVERLAY_DISP++); - - gDPLoadTextureBlock(OVERLAY_DISP++, markInfo->texture, markInfo->imageFormat, G_IM_SIZ_MARK, - markInfo->textureWidth, markInfo->textureHeight, 0, G_TX_NOMIRROR | G_TX_WRAP, - G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); - // Changed to a Wide texture to support Left anchor. - gSPWideTextureRectangle(OVERLAY_DISP++, rectLeft << 2, rectTop << 2, rectLeft + width << 2, - rectTop + height << 2, G_TX_RENDERTILE, 0, 0, width_factor, height_factor); - } - - markPoint++; - } - mapMarkIconData++; + gDPLoadTextureBlock(OVERLAY_DISP++, markInfo->texture, markInfo->imageFormat, G_IM_SIZ_MARK, + markInfo->textureWidth, markInfo->textureHeight, 0, G_TX_NOMIRROR | G_TX_WRAP, + G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); + // Changed to a Wide texture to support Left anchor. + gSPWideTextureRectangle(OVERLAY_DISP++, rectLeft << 2, rectTop << 2, rectLeft + width << 2, + rectTop + height << 2, G_TX_RENDERTILE, 0, 0, width_factor, height_factor); } CLOSE_DISPS(play->state.gfxCtx); } void MapMark_Draw(PlayState* play) { - switch (play->sceneNum) { - case SCENE_DEKU_TREE: - case SCENE_DODONGOS_CAVERN: - case SCENE_JABU_JABU: - case SCENE_FOREST_TEMPLE: - case SCENE_FIRE_TEMPLE: - case SCENE_WATER_TEMPLE: - case SCENE_SPIRIT_TEMPLE: - case SCENE_SHADOW_TEMPLE: - case SCENE_BOTTOM_OF_THE_WELL: - case SCENE_ICE_CAVERN: - case SCENE_DEKU_TREE_BOSS: - case SCENE_DODONGOS_CAVERN_BOSS: - case SCENE_JABU_JABU_BOSS: - case SCENE_FOREST_TEMPLE_BOSS: - case SCENE_FIRE_TEMPLE_BOSS: - MapMark_DrawForDungeon(play); - break; + if (SceneDB_IsDungeon(play->sceneNum) || SceneDB_IsBoss(play->sceneNum)) { + MapMark_DrawForDungeon(play); } } diff --git a/soh/src/code/z_message_PAL.c b/soh/src/code/z_message_PAL.c index fc63f96c8..d9d37b7b7 100644 --- a/soh/src/code/z_message_PAL.c +++ b/soh/src/code/z_message_PAL.c @@ -3765,7 +3765,7 @@ void Message_DrawMain(PlayState* play, Gfx** p) { if (msgCtx->lastPlayedSong < OCARINA_SONG_SARIAS && (msgCtx->ocarinaAction < OCARINA_ACTION_PLAYBACK_MINUET || msgCtx->ocarinaAction >= OCARINA_ACTION_PLAYBACK_SARIA)) { - if (msgCtx->disableWarpSongs || (interfaceCtx->restrictions.warpSongs == 3 && !IS_RANDO)) { + if (msgCtx->disableWarpSongs || (interfaceCtx->restrictions.warpSongs && !IS_RANDO)) { Message_StartTextbox(play, 0x88C, NULL); // "You can't warp here!" play->msgCtx.ocarinaMode = OCARINA_MODE_04; } else if ((gSaveContext.eventInf[0] & 0xF) != 1) { diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index 0fc923070..6b258a107 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -7,6 +7,7 @@ #include "soh/Enhancements/randomizer/randomizer_entrance.h" #include "libultraship/bridge.h" +#include "soh/SceneDB.h" #include "soh/Enhancements/gameplaystats.h" #include "soh/Enhancements/boss-rush/BossRushTypes.h" #include "soh/Enhancements/custom-message/CustomMessageInterfaceAddon.h" @@ -1068,7 +1069,7 @@ void func_80083108(PlayState* play) { Interface_ChangeAlpha(50); } else { - if (interfaceCtx->restrictions.bButton == 0) { + if (!interfaceCtx->restrictions.bButton) { if ((gSaveContext.equips.buttonItems[0] == ITEM_SLINGSHOT) || (gSaveContext.equips.buttonItems[0] == ITEM_BOW) || (gSaveContext.equips.buttonItems[0] == ITEM_BOMBCHU) || @@ -1095,7 +1096,7 @@ void func_80083108(PlayState* play) { gSaveContext.equips.buttonItems[0] = gSaveContext.buttonStatus[0] & 0xFF; } } - } else if (interfaceCtx->restrictions.bButton == 1) { + } else { if ((gSaveContext.equips.buttonItems[0] == ITEM_SLINGSHOT) || (gSaveContext.equips.buttonItems[0] == ITEM_BOW) || (gSaveContext.equips.buttonItems[0] == ITEM_BOMBCHU) || @@ -1133,7 +1134,7 @@ void func_80083108(PlayState* play) { } } - if (interfaceCtx->restrictions.bottles != 0) { + if (interfaceCtx->restrictions.bottles) { for (i = 1; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { if ((gSaveContext.equips.buttonItems[i] >= ITEM_BOTTLE) && (gSaveContext.equips.buttonItems[i] <= ITEM_POE)) { @@ -1144,7 +1145,7 @@ void func_80083108(PlayState* play) { gSaveContext.buttonStatus[BUTTON_STATUS_INDEX(i)] = BTN_DISABLED; } } - } else if (interfaceCtx->restrictions.bottles == 0) { + } else { for (i = 1; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { if ((gSaveContext.equips.buttonItems[i] >= ITEM_BOTTLE) && (gSaveContext.equips.buttonItems[i] <= ITEM_POE)) { @@ -1157,7 +1158,7 @@ void func_80083108(PlayState* play) { } } - if (interfaceCtx->restrictions.tradeItems != 0) { + if (interfaceCtx->restrictions.tradeItems) { for (i = 1; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { if ((CVarGetInteger(CVAR_ENHANCEMENT("MMBunnyHood"), BUNNY_HOOD_VANILLA) != BUNNY_HOOD_VANILLA) && @@ -1173,7 +1174,7 @@ void func_80083108(PlayState* play) { gSaveContext.buttonStatus[BUTTON_STATUS_INDEX(i)] = BTN_DISABLED; } } - } else if (interfaceCtx->restrictions.tradeItems == 0) { + } else { for (i = 1; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { if ((gSaveContext.equips.buttonItems[i] >= ITEM_WEIRD_EGG) && (gSaveContext.equips.buttonItems[i] <= ITEM_CLAIM_CHECK)) { @@ -1186,7 +1187,7 @@ void func_80083108(PlayState* play) { } } - if (interfaceCtx->restrictions.hookshot != 0) { + if (interfaceCtx->restrictions.hookshot) { for (i = 1; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { if ((gSaveContext.equips.buttonItems[i] == ITEM_HOOKSHOT) || (gSaveContext.equips.buttonItems[i] == ITEM_LONGSHOT)) { @@ -1197,7 +1198,7 @@ void func_80083108(PlayState* play) { gSaveContext.buttonStatus[BUTTON_STATUS_INDEX(i)] = BTN_DISABLED; } } - } else if (interfaceCtx->restrictions.hookshot == 0) { + } else { for (i = 1; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { if ((gSaveContext.equips.buttonItems[i] == ITEM_HOOKSHOT) || (gSaveContext.equips.buttonItems[i] == ITEM_LONGSHOT)) { @@ -1210,7 +1211,7 @@ void func_80083108(PlayState* play) { } } - if (interfaceCtx->restrictions.ocarina != 0) { + if (interfaceCtx->restrictions.ocarina) { for (i = 1; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { if ((gSaveContext.equips.buttonItems[i] == ITEM_OCARINA_FAIRY) || (gSaveContext.equips.buttonItems[i] == ITEM_OCARINA_TIME)) { @@ -1221,7 +1222,7 @@ void func_80083108(PlayState* play) { gSaveContext.buttonStatus[BUTTON_STATUS_INDEX(i)] = BTN_DISABLED; } } - } else if (interfaceCtx->restrictions.ocarina == 0) { + } else { for (i = 1; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { if ((gSaveContext.equips.buttonItems[i] == ITEM_OCARINA_FAIRY) || (gSaveContext.equips.buttonItems[i] == ITEM_OCARINA_TIME)) { @@ -1234,7 +1235,7 @@ void func_80083108(PlayState* play) { } } - if (interfaceCtx->restrictions.farores != 0) { + if (interfaceCtx->restrictions.farores) { for (i = 1; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { if (gSaveContext.equips.buttonItems[i] == ITEM_FARORES_WIND) { if (gSaveContext.buttonStatus[BUTTON_STATUS_INDEX(i)] == BTN_ENABLED) { @@ -1245,7 +1246,7 @@ void func_80083108(PlayState* play) { osSyncPrintf("***(i=%d)*** ", i); } } - } else if (interfaceCtx->restrictions.farores == 0) { + } else { for (i = 1; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { if (gSaveContext.equips.buttonItems[i] == ITEM_FARORES_WIND) { if (gSaveContext.buttonStatus[BUTTON_STATUS_INDEX(i)] == BTN_DISABLED) { @@ -1257,7 +1258,7 @@ void func_80083108(PlayState* play) { } } - if (interfaceCtx->restrictions.dinsNayrus != 0) { + if (interfaceCtx->restrictions.dinsNayrus) { for (i = 1; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { if ((gSaveContext.equips.buttonItems[i] == ITEM_DINS_FIRE) || (gSaveContext.equips.buttonItems[i] == ITEM_NAYRUS_LOVE)) { @@ -1268,7 +1269,7 @@ void func_80083108(PlayState* play) { gSaveContext.buttonStatus[BUTTON_STATUS_INDEX(i)] = BTN_DISABLED; } } - } else if (interfaceCtx->restrictions.dinsNayrus == 0) { + } else { for (i = 1; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { if ((gSaveContext.equips.buttonItems[i] == ITEM_DINS_FIRE) || (gSaveContext.equips.buttonItems[i] == ITEM_NAYRUS_LOVE)) { @@ -1281,7 +1282,7 @@ void func_80083108(PlayState* play) { } } - if (interfaceCtx->restrictions.all != 0) { + if (interfaceCtx->restrictions.all) { for (i = 1; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { if ((gSaveContext.equips.buttonItems[i] != ITEM_OCARINA_FAIRY) && (gSaveContext.equips.buttonItems[i] != ITEM_OCARINA_TIME) && @@ -1308,7 +1309,7 @@ void func_80083108(PlayState* play) { } } } - } else if (interfaceCtx->restrictions.all == 0) { + } else { for (i = 1; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { if ((gSaveContext.equips.buttonItems[i] != ITEM_DINS_FIRE) && (gSaveContext.equips.buttonItems[i] != ITEM_HOOKSHOT) && @@ -1346,61 +1347,26 @@ void func_80083108(PlayState* play) { void Interface_SetSceneRestrictions(PlayState* play) { InterfaceContext* interfaceCtx = &play->interfaceCtx; - s16 i; - u8 currentScene; - // clang-format off - interfaceCtx->restrictions.hGauge = interfaceCtx->restrictions.bButton = - interfaceCtx->restrictions.aButton = interfaceCtx->restrictions.bottles = - interfaceCtx->restrictions.tradeItems = interfaceCtx->restrictions.hookshot = - interfaceCtx->restrictions.ocarina = interfaceCtx->restrictions.warpSongs = - interfaceCtx->restrictions.sunsSong = interfaceCtx->restrictions.farores = - interfaceCtx->restrictions.dinsNayrus = interfaceCtx->restrictions.all = 0; - // clang-format on + SceneDBEntry* entry = SceneDB_Retrieve(play->sceneNum); + interfaceCtx->restrictions.hGauge = entry->restrictions.hGauge; + interfaceCtx->restrictions.bButton = entry->restrictions.bButton; + interfaceCtx->restrictions.aButton = entry->restrictions.aButton; + interfaceCtx->restrictions.bottles = entry->restrictions.bottles; + interfaceCtx->restrictions.tradeItems = entry->restrictions.tradeItems; + interfaceCtx->restrictions.hookshot = entry->restrictions.hookshot; + interfaceCtx->restrictions.ocarina = entry->restrictions.ocarina; + interfaceCtx->restrictions.warpSongs = entry->restrictions.warpSongs; + interfaceCtx->restrictions.sunsSong = entry->restrictions.sunsSong; + interfaceCtx->restrictions.farores = entry->restrictions.farores; + interfaceCtx->restrictions.dinsNayrus = entry->restrictions.dinsNayrus; + interfaceCtx->restrictions.all = entry->restrictions.all; - i = 0; - - // "Data settings related to button display scene_data_ID=%d\n" - osSyncPrintf("ボタン表示関係データ設定 scene_data_ID=%d\n", play->sceneNum); - - do { - currentScene = (u8)play->sceneNum; - if (sRestrictionFlags[i].scene == currentScene) { - interfaceCtx->restrictions.hGauge = (sRestrictionFlags[i].flags1 & 0xC0) >> 6; - interfaceCtx->restrictions.bButton = (sRestrictionFlags[i].flags1 & 0x30) >> 4; - interfaceCtx->restrictions.aButton = (sRestrictionFlags[i].flags1 & 0x0C) >> 2; - interfaceCtx->restrictions.bottles = (sRestrictionFlags[i].flags1 & 0x03) >> 0; - interfaceCtx->restrictions.tradeItems = (sRestrictionFlags[i].flags2 & 0xC0) >> 6; - interfaceCtx->restrictions.hookshot = (sRestrictionFlags[i].flags2 & 0x30) >> 4; - interfaceCtx->restrictions.ocarina = (sRestrictionFlags[i].flags2 & 0x0C) >> 2; - interfaceCtx->restrictions.warpSongs = (sRestrictionFlags[i].flags2 & 0x03) >> 0; - interfaceCtx->restrictions.sunsSong = (sRestrictionFlags[i].flags3 & 0xC0) >> 6; - interfaceCtx->restrictions.farores = (sRestrictionFlags[i].flags3 & 0x30) >> 4; - interfaceCtx->restrictions.dinsNayrus = (sRestrictionFlags[i].flags3 & 0x0C) >> 2; - interfaceCtx->restrictions.all = (sRestrictionFlags[i].flags3 & 0x03) >> 0; - - osSyncPrintf(VT_FGCOL(YELLOW)); - osSyncPrintf("parameter->button_status = %x,%x,%x\n", sRestrictionFlags[i].flags1, - sRestrictionFlags[i].flags2, sRestrictionFlags[i].flags3); - osSyncPrintf("h_gage=%d, b_button=%d, a_button=%d, c_bottle=%d\n", interfaceCtx->restrictions.hGauge, - interfaceCtx->restrictions.bButton, interfaceCtx->restrictions.aButton, - interfaceCtx->restrictions.bottles); - osSyncPrintf("c_warasibe=%d, c_hook=%d, c_ocarina=%d, c_warp=%d\n", interfaceCtx->restrictions.tradeItems, - interfaceCtx->restrictions.hookshot, interfaceCtx->restrictions.ocarina, - interfaceCtx->restrictions.warpSongs); - osSyncPrintf("c_sunmoon=%d, m_wind=%d, m_magic=%d, another=%d\n", interfaceCtx->restrictions.sunsSong, - interfaceCtx->restrictions.farores, interfaceCtx->restrictions.dinsNayrus, - interfaceCtx->restrictions.all); - osSyncPrintf(VT_RST); - if (CVarGetInteger(CVAR_ENHANCEMENT("BetterFarore"), 0)) { - if (currentScene == SCENE_GERUDO_TRAINING_GROUND || currentScene == SCENE_INSIDE_GANONS_CASTLE) { - interfaceCtx->restrictions.farores = 0; - } - } - return; + if (CVarGetInteger(CVAR_ENHANCEMENT("BetterFarore"), 0)) { + if (play->sceneNum == SCENE_GERUDO_TRAINING_GROUND || play->sceneNum == SCENE_INSIDE_GANONS_CASTLE) { + interfaceCtx->restrictions.farores = 0; } - i++; - } while (sRestrictionFlags[i].scene != 0xFF); + } } Gfx* Gfx_TextureIA8(Gfx* displayListHead, void* texture, s16 textureWidth, s16 textureHeight, s16 rectLeft, s16 rectTop, @@ -1427,6 +1393,141 @@ Gfx* Gfx_TextureI8(Gfx* displayListHead, void* texture, s16 textureWidth, s16 te return displayListHead; } +void Inventory_DoBA(u8 cRight) { + if (cRight >= ITEM_STICK && cRight <= ITEM_POTION_BLUE) { + gSaveContext.equips.buttonItems[0] = gSaveContext.inventory.items[cRight]; + } else if (cRight >= ITEM_FAIRY && cRight <= ITEM_MASK_BUNNY) { + gSaveContext.equips.buttonItems[0] = gSaveContext.inventory.ammo[cRight - ITEM_FAIRY]; + } else if (cRight == ITEM_MASK_GORON) { + gSaveContext.equips.buttonItems[0] = (gSaveContext.inventory.equipment >> 8) & 0xFF; + } else if (cRight == ITEM_MASK_ZORA) { + gSaveContext.equips.buttonItems[0] = gSaveContext.inventory.equipment & 0xFF; + } else if (cRight == ITEM_MASK_GERUDO || cRight == ITEM_MASK_TRUTH) { + // ITEM_MASK_GERUDO and ITEM_MASK_TRUTH land in padding bytes + gSaveContext.equips.buttonItems[0] = 0; + } else if (cRight == ITEM_SOLD_OUT) { + gSaveContext.equips.buttonItems[0] = (gSaveContext.inventory.upgrades >> 24) & 0xFF; + } else if (cRight == ITEM_POCKET_EGG) { + gSaveContext.equips.buttonItems[0] = (gSaveContext.inventory.upgrades >> 16) & 0xFF; + } else if (cRight == ITEM_POCKET_CUCCO) { + gSaveContext.equips.buttonItems[0] = (gSaveContext.inventory.upgrades >> 8) & 0xFF; + } else if (cRight == ITEM_COJIRO) { + gSaveContext.equips.buttonItems[0] = gSaveContext.inventory.upgrades & 0xFF; + } else if (cRight == ITEM_ODD_MUSHROOM) { + gSaveContext.equips.buttonItems[0] = (gSaveContext.inventory.questItems >> 24) & 0xFF; + } else if (cRight == ITEM_ODD_POTION) { + gSaveContext.equips.buttonItems[0] = (gSaveContext.inventory.questItems >> 16) & 0xFF; + } else if (cRight == ITEM_SAW) { + gSaveContext.equips.buttonItems[0] = (gSaveContext.inventory.questItems >> 8) & 0xFF; + } else if (cRight == ITEM_SWORD_BROKEN) { + gSaveContext.equips.buttonItems[0] = gSaveContext.inventory.questItems & 0xFF; + } else if (cRight >= ITEM_PRESCRIPTION && cRight <= ITEM_BULLET_BAG_30) { + gSaveContext.equips.buttonItems[0] = gSaveContext.inventory.dungeonItems[cRight - ITEM_PRESCRIPTION]; + } else if (cRight >= ITEM_BULLET_BAG_40 && cRight <= ITEM_SWORD_KNIFE) { + gSaveContext.equips.buttonItems[0] = gSaveContext.inventory.dungeonKeys[cRight - ITEM_BULLET_BAG_40]; + } else if (cRight == ITEM_SONG_BOLERO) { + gSaveContext.equips.buttonItems[0] = gSaveContext.inventory.defenseHearts; + } else if (cRight == ITEM_SONG_SERENADE) { + gSaveContext.equips.buttonItems[0] = (gSaveContext.inventory.gsTokens >> 8) & 0xFF; + } else if (cRight == ITEM_SONG_REQUIEM) { + gSaveContext.equips.buttonItems[0] = gSaveContext.inventory.gsTokens & 0xFF; + } else if (cRight == ITEM_SONG_NOCTURNE || cRight == ITEM_SONG_PRELUDE) { + // ITEM_SONG_NOCTURNE and ITEM_SONG_PRELUDE land in padding bytes + gSaveContext.equips.buttonItems[0] = 0; + } else if (cRight >= ITEM_SONG_LULLABY) { + // The rest of the items fall into the saved scene flags. Let's calculate the scene and which field it pulls + // from + u32 offset = cRight - ITEM_SONG_LULLABY; + u32 scene = offset / sizeof(SavedSceneFlags); + switch (offset % sizeof(SavedSceneFlags)) { + case 0: + gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].chest >> 24) & 0xFF; + break; + case 1: + gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].chest >> 16) & 0xFF; + break; + case 2: + gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].chest >> 8) & 0xFF; + break; + case 3: + gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].chest & 0xFF; + break; + case 4: + gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].swch >> 24) & 0xFF; + break; + case 5: + gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].swch >> 16) & 0xFF; + break; + case 6: + gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].swch >> 8) & 0xFF; + break; + case 7: + gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].swch & 0xFF; + break; + case 8: + gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].clear >> 24) & 0xFF; + break; + case 9: + gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].clear >> 16) & 0xFF; + break; + case 10: + gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].clear >> 8) & 0xFF; + break; + case 11: + gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].clear & 0xFF; + break; + case 12: + gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].collect >> 24) & 0xFF; + break; + case 13: + gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].collect >> 16) & 0xFF; + break; + case 14: + gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].collect >> 8) & 0xFF; + break; + case 15: + gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].collect & 0xFF; + break; + case 16: + gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].unk >> 24) & 0xFF; + break; + case 17: + gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].unk >> 16) & 0xFF; + break; + case 18: + gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].unk >> 8) & 0xFF; + break; + case 19: + gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].unk & 0xFF; + break; + case 20: + gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].rooms >> 24) & 0xFF; + break; + case 21: + gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].rooms >> 16) & 0xFF; + break; + case 22: + gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].rooms >> 8) & 0xFF; + break; + case 23: + gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].rooms & 0xFF; + break; + case 24: + gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].floors >> 24) & 0xFF; + break; + case 25: + gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].floors >> 16) & 0xFF; + break; + case 26: + gSaveContext.equips.buttonItems[0] = (gSaveContext.sceneFlags[scene].floors >> 8) & 0xFF; + break; + case 27: + gSaveContext.equips.buttonItems[0] = gSaveContext.sceneFlags[scene].floors & 0xFF; + break; + } + } +} + void Rando_Inventory_SwapAgeEquipment(void) { s16 i; u16 shieldEquipValue; @@ -6864,7 +6965,7 @@ void Interface_Update(PlayState* play) { play->msgCtx.ocarinaMode = OCARINA_MODE_04; } } else if ((play->roomCtx.curRoom.behaviorType1 != ROOM_BEHAVIOR_TYPE1_1) && - (interfaceCtx->restrictions.sunsSong != 3)) { + (!interfaceCtx->restrictions.sunsSong)) { if ((gSaveContext.dayTime >= 0x4555) && (gSaveContext.dayTime < 0xC001)) { gSaveContext.nextDayTime = 0; play->transitionType = TRANS_TYPE_FADE_BLACK_FAST; diff --git a/soh/src/code/z_play.c b/soh/src/code/z_play.c index dfc832fc7..1859769fd 100644 --- a/soh/src/code/z_play.c +++ b/soh/src/code/z_play.c @@ -15,6 +15,7 @@ #include "soh/ResourceManagerHelpers.h" #include "soh/SaveManager.h" #include "soh/framebuffer_effects.h" +#include "soh/SceneDB.h" #include @@ -478,23 +479,21 @@ void Play_Init(GameState* thisx) { // save the base scene layer (before accounting for the special cases below) to use later for the transition type baseSceneLayer = gSaveContext.sceneSetupIndex; - - if ((gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_HYRULE_FIELD) && !LINK_IS_ADULT && - !IS_CUTSCENE_LAYER) { + EntranceDBEntry* entrance = EntranceDB_Retrieve(gSaveContext.entranceIndex); + if ((entrance->sceneId == SCENE_HYRULE_FIELD) && !LINK_IS_ADULT && !IS_CUTSCENE_LAYER) { if (CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD) && CHECK_QUEST_ITEM(QUEST_GORON_RUBY) && CHECK_QUEST_ITEM(QUEST_ZORA_SAPPHIRE)) { gSaveContext.sceneSetupIndex = 1; } else { gSaveContext.sceneSetupIndex = 0; } - } else if ((gEntranceTable[((void)0, gSaveContext.entranceIndex)].scene == SCENE_KOKIRI_FOREST) && LINK_IS_ADULT && - !IS_CUTSCENE_LAYER) { + } else if ((entrance->sceneId == SCENE_KOKIRI_FOREST) && LINK_IS_ADULT && !IS_CUTSCENE_LAYER) { gSaveContext.sceneSetupIndex = (Flags_GetEventChkInf(EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP)) ? 3 : 2; } - Play_SpawnScene( - play, gEntranceTable[((void)0, gSaveContext.entranceIndex) + ((void)0, gSaveContext.sceneSetupIndex)].scene, - gEntranceTable[((void)0, gSaveContext.sceneSetupIndex) + ((void)0, gSaveContext.entranceIndex)].spawn); + EntranceDBEntry* adjustedEntrance = + EntranceDB_RetrieveLayer(gSaveContext.entranceIndex, gSaveContext.sceneSetupIndex); + Play_SpawnScene(play, adjustedEntrance->sceneId, adjustedEntrance->spawn); osSyncPrintf("\nSCENE_NO=%d COUNTER=%d\n", ((void)0, gSaveContext.entranceIndex), gSaveContext.sceneSetupIndex); @@ -549,8 +548,8 @@ void Play_Init(GameState* thisx) { if (gSaveContext.gameMode != GAMEMODE_TITLE_SCREEN) { if (gSaveContext.nextTransitionType == TRANS_NEXT_TYPE_DEFAULT) { - play->transitionType = ENTRANCE_INFO_END_TRANS_TYPE( - gEntranceTable[((void)0, gSaveContext.entranceIndex) + baseSceneLayer].field); // Fade In + EntranceDBEntry* transEntrance = EntranceDB_RetrieveLayer(gSaveContext.entranceIndex, baseSceneLayer); + play->transitionType = transEntrance->endTransition; // Fade In } else { play->transitionType = gSaveContext.nextTransitionType; gSaveContext.nextTransitionType = TRANS_NEXT_TYPE_DEFAULT; @@ -819,8 +818,7 @@ void Play_Update(PlayState* play) { } // fade out bgm if "continue bgm" flag is not set - if (!(gEntranceTable[play->nextEntranceIndex + sceneLayer].field & - ENTRANCE_INFO_CONTINUE_BGM_FLAG)) { + if (!EntranceDB_RetrieveLayer(play->nextEntranceIndex, sceneLayer)->continueBgm) { // "Sound initalized. 111" osSyncPrintf("\n\n\nサウンドイニシャル来ました。111"); if ((play->transitionType < TRANS_TYPE_MAX) && !Environment_IsForcedSequenceDisabled()) { diff --git a/soh/src/code/z_room.c b/soh/src/code/z_room.c index 60fa3f0ff..b8d9b2370 100644 --- a/soh/src/code/z_room.c +++ b/soh/src/code/z_room.c @@ -7,6 +7,7 @@ #include "soh/Enhancements/game-interactor/GameInteractor.h" #include #include +#include #include "public/bridge/gfxbridge.h" #include "soh/OTRGlobals.h" @@ -646,7 +647,7 @@ void func_80097534(PlayState* play, RoomContext* roomCtx) { func_80031B14(play, &play->actorCtx); // kills all actors without room num set to -1 Actor_SpawnTransitionActors(play, &play->actorCtx); Map_InitRoomData(play, roomCtx->curRoom.num); - if (!((play->sceneNum >= SCENE_HYRULE_FIELD) && (play->sceneNum <= SCENE_LON_LON_RANCH))) { + if (!SceneDB_IsOverworld(play->sceneNum)) { Map_SavePlayerInitialInfo(play); } Audio_SetEnvReverb(play->roomCtx.curRoom.echo); diff --git a/soh/src/code/z_scene_table.c b/soh/src/code/z_scene_table.c index 7c28253fd..b571c413a 100644 --- a/soh/src/code/z_scene_table.c +++ b/soh/src/code/z_scene_table.c @@ -26,6 +26,7 @@ #include "soh/mq_asset_hacks.h" #include "soh/OTRGlobals.h" #include "soh/ResourceManagerHelpers.h" +#include "soh/SceneDB.h" // Entrance Table definition #define DEFINE_ENTRANCE(_0, sceneId, spawn, continueBgm, displayTitleCard, endTransType, startTransType) \ @@ -87,23 +88,23 @@ Gfx sDefaultDisplayList[] = { // Computes next entrance index based on age and day time to set the fade out transition void Scene_SetTransitionForNextEntrance(PlayState* play) { - s16 entranceIndex; + s16 layer = 0; if (!IS_DAY) { if (!LINK_IS_ADULT) { - entranceIndex = play->nextEntranceIndex + 1; + layer = 1; } else { - entranceIndex = play->nextEntranceIndex + 3; + layer = 3; } } else { if (!LINK_IS_ADULT) { - entranceIndex = play->nextEntranceIndex; + layer = 0; } else { - entranceIndex = play->nextEntranceIndex + 2; + layer = 2; } } - play->transitionType = ENTRANCE_INFO_START_TRANS_TYPE(gEntranceTable[entranceIndex].field); // Fade out + play->transitionType = EntranceDB_RetrieveLayer(play->nextEntranceIndex, layer)->startTransition; // Fade out } // Scene Draw Config 0 diff --git a/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c b/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c index 96a9297b9..820a3e3cb 100644 --- a/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c +++ b/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c @@ -1413,11 +1413,11 @@ void func_80A053F0(Actor* thisx, PlayState* play) { } else { this->actionFunc(this, play); thisx->shape.rot.y = this->unk_2BC; - nREG(80) = gSaveContext.sceneFlags[127].chest; + nREG(80) = HIGH_SCORE(HS_HBA); if (nREG(81) != 0) { - if (gSaveContext.sceneFlags[127].chest) { - LOG_NUM("z_common_data.memory.information.room_inf[127][ 0 ]", gSaveContext.sceneFlags[127].chest); + if (HIGH_SCORE(HS_HBA)) { + LOG_NUM("z_common_data.memory.information.room_inf[127][ 0 ]", HIGH_SCORE(HS_HBA)); } } diff --git a/soh/src/overlays/actors/ovl_En_Horse/z_en_horse.c b/soh/src/overlays/actors/ovl_En_Horse/z_en_horse.c index c4d46035d..2611d555e 100644 --- a/soh/src/overlays/actors/ovl_En_Horse/z_en_horse.c +++ b/soh/src/overlays/actors/ovl_En_Horse/z_en_horse.c @@ -10,6 +10,7 @@ #include "objects/object_hni/object_hni.h" #include "scenes/overworld/spot09/spot09_scene.h" #include +#include "soh/SceneDB.h" #define FLAGS ACTOR_FLAG_UPDATE_CULLING_DISABLED @@ -679,35 +680,39 @@ s32 EnHorse_Spawn(EnHorse* this, PlayState* play) { Player* player; Vec3f spawnPos; - for (i = 0; i < 169; i++) { - if (sHorseSpawns[i].scene == play->sceneNum) { - player = GET_PLAYER(play); - if (play->sceneNum != SCENE_LON_LON_RANCH || - //! Same flag checked twice - (Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) && - ((gSaveContext.eventInf[0] & 0xF) != 6 || Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED))) || - // always load two spawns inside lon lon - ((sHorseSpawns[i].pos.x == 856 && sHorseSpawns[i].pos.y == 0 && sHorseSpawns[i].pos.z == -918) || - (sHorseSpawns[i].pos.x == -1003 && sHorseSpawns[i].pos.y == 0 && sHorseSpawns[i].pos.z == -755))) { + SceneDBEntry* entry = SceneDB_Retrieve(play->sceneNum); + if (!entry->epona.allowed) { + return false; + } - spawnPos.x = sHorseSpawns[i].pos.x; - spawnPos.y = sHorseSpawns[i].pos.y; - spawnPos.z = sHorseSpawns[i].pos.z; - dist = Math3D_Vec3f_DistXYZ(&player->actor.world.pos, &spawnPos); + for (i = 0; i < entry->epona.numSpawns; i++) { + player = GET_PLAYER(play); + if (play->sceneNum != SCENE_LON_LON_RANCH || + //! Same flag checked twice + (Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED) && + ((gSaveContext.eventInf[0] & 0xF) != 6 || Flags_GetEventChkInf(EVENTCHKINF_EPONA_OBTAINED))) || + // always load two spawns inside lon lon + ((entry->epona.spawnPos[i].x == 856 && entry->epona.spawnPos[i].y == 0 && + entry->epona.spawnPos[i].z == -918) || + (entry->epona.spawnPos[i].x == -1003 && entry->epona.spawnPos[i].y == 0 && + entry->epona.spawnPos[i].z == -755))) { - if (play->sceneNum) {} - if (!(minDist < dist) && !func_80A5BBBC(play, this, &spawnPos)) { - minDist = dist; - this->actor.world.pos.x = sHorseSpawns[i].pos.x; - this->actor.world.pos.y = sHorseSpawns[i].pos.y; - this->actor.world.pos.z = sHorseSpawns[i].pos.z; - this->actor.prevPos = this->actor.world.pos; - this->actor.world.rot.y = sHorseSpawns[i].angle; - this->actor.shape.rot.y = Actor_WorldYawTowardActor(&this->actor, &GET_PLAYER(play)->actor); - spawn = true; - SkinMatrix_Vec3fMtxFMultXYZW(&play->viewProjectionMtxF, &this->actor.world.pos, - &this->actor.projectedPos, &this->actor.projectedW); - } + spawnPos.x = entry->epona.spawnPos[i].x; + spawnPos.y = entry->epona.spawnPos[i].y; + spawnPos.z = entry->epona.spawnPos[i].z; + dist = Math3D_Vec3f_DistXYZ(&player->actor.world.pos, &spawnPos); + + if (!(minDist < dist) && !func_80A5BBBC(play, this, &spawnPos)) { + minDist = dist; + this->actor.world.pos.x = entry->epona.spawnPos[i].x; + this->actor.world.pos.y = entry->epona.spawnPos[i].y; + this->actor.world.pos.z = entry->epona.spawnPos[i].z; + this->actor.prevPos = this->actor.world.pos; + this->actor.world.rot.y = 0; + this->actor.shape.rot.y = Actor_WorldYawTowardActor(&this->actor, &GET_PLAYER(play)->actor); + spawn = true; + SkinMatrix_Vec3fMtxFMultXYZW(&play->viewProjectionMtxF, &this->actor.world.pos, + &this->actor.projectedPos, &this->actor.projectedW); } } } diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index 6cc57ca22..4c94ec631 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -33,6 +33,7 @@ #include "soh/frame_interpolation.h" #include "soh/OTRGlobals.h" #include "soh/ResourceManagerHelpers.h" +#include "soh/SceneDB.h" #include #include @@ -10866,11 +10867,9 @@ void Player_Init(Actor* thisx, PlayState* play2) { } if ((respawnFlag == 0) || (respawnFlag < -1)) { - titleFileSize = scene->titleFile.vromEnd - scene->titleFile.vromStart; if (GameInteractor_Should(VB_SHOW_TITLE_CARD, gSaveContext.showTitleCard)) { if ((gSaveContext.sceneSetupIndex < 4) && - (gEntranceTable[((void)0, gSaveContext.entranceIndex) + ((void)0, gSaveContext.sceneSetupIndex)].field & - ENTRANCE_INFO_DISPLAY_TITLE_CARD_FLAG) && + EntranceDB_RetrieveLayer(gSaveContext.entranceIndex, gSaveContext.sceneSetupIndex)->displayTitleCard && ((play->sceneNum != SCENE_DODONGOS_CAVERN) || (Flags_GetEventChkInf(EVENTCHKINF_ENTERED_DODONGOS_CAVERN))) && ((play->sceneNum != SCENE_BOMBCHU_SHOP) || diff --git a/soh/src/overlays/gamestates/ovl_select/z_select.c b/soh/src/overlays/gamestates/ovl_select/z_select.c index e08ba7c97..49eaba7c8 100644 --- a/soh/src/overlays/gamestates/ovl_select/z_select.c +++ b/soh/src/overlays/gamestates/ovl_select/z_select.c @@ -13,6 +13,7 @@ #include "soh/Enhancements/randomizer/randomizer_grotto.h" #include "soh/OTRGlobals.h" #include "soh/ResourceManagerHelpers.h" +#include "soh/SceneDB.h" void Select_SwitchBetterWarpMode(SelectContext* this, u8 isBetterWarpMode); void Sram_InitDebugSave(void); @@ -57,7 +58,7 @@ void Select_LoadGame(SelectContext* this, s32 entranceIndex) { this->betterScenes[this->currentScene].entrancePairs[this->pageDownIndex]; // Check to see if the scene/entrance we just picked can be MQ'd if (entrancePair.canBeMQ) { - s16 scene = gEntranceTable[entrancePair.entranceIndex].scene; + s16 scene = EntranceDB_Retrieve(entrancePair.entranceIndex)->sceneId; u8 isEntranceDefaultMQ = ResourceMgr_IsSceneMasterQuest(scene); if (!isEntranceDefaultMQ && this->opt) { // Force vanilla for default MQ scene CVarSetInteger(CVAR_GENERAL("BetterDebugWarpScreenMQMode"), WARP_MODE_OVERRIDE_MQ_AS_VANILLA); @@ -1212,7 +1213,8 @@ void Better_Select_UpdateMenu(SelectContext* this) { BetterSceneSelectEntrancePair entrancePair = this->betterScenes[this->currentScene].entrancePairs[this->pageDownIndex]; // Update the MQ status to match the new scene - if (entrancePair.canBeMQ && ResourceMgr_IsSceneMasterQuest(gEntranceTable[entrancePair.entranceIndex].scene)) { + if (entrancePair.canBeMQ && + ResourceMgr_IsSceneMasterQuest(EntranceDB_Retrieve(entrancePair.entranceIndex)->sceneId)) { this->opt = 1; } else { this->opt = 0; @@ -1795,7 +1797,7 @@ void Select_SwitchBetterWarpMode(SelectContext* this, u8 isBetterWarpMode) { BetterSceneSelectEntrancePair entrancePair = this->betterScenes[this->currentScene].entrancePairs[this->pageDownIndex]; if (entrancePair.canBeMQ && - ResourceMgr_IsSceneMasterQuest(gEntranceTable[entrancePair.entranceIndex].scene)) { + ResourceMgr_IsSceneMasterQuest(EntranceDB_Retrieve(entrancePair.entranceIndex)->sceneId)) { this->opt = 1; } } diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_map_PAL.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_map_PAL.c index 3ff61d783..20e0dc996 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_map_PAL.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_map_PAL.c @@ -1,4 +1,5 @@ #include "z_kaleido_scope.h" +#include "soh/SceneDB.h" #include "textures/icon_item_24_static/icon_item_24_static.h" #include "textures/icon_item_nes_static/icon_item_nes_static.h" #include "textures/icon_item_ger_static/icon_item_ger_static.h" @@ -60,6 +61,7 @@ void KaleidoScope_DrawDungeonMap(PlayState* play, GraphicsContext* gfxCtx) { s16 stepB; u16 rgba16; bool dpad = CVarGetInteger(CVAR_SETTING("DPadOnPause"), 0); + SceneDBEntry* entry = SceneDB_Retrieve(gSaveContext.mapIndex); OPEN_DISPS(gfxCtx); @@ -91,9 +93,6 @@ void KaleidoScope_DrawDungeonMap(PlayState* play, GraphicsContext* gfxCtx) { pauseCtx->cursorX[PAUSE_MAP] = 0; pauseCtx->cursorPoint[PAUSE_MAP] = pauseCtx->dungeonMapSlot; osSyncPrintf("kscope->cursor_point=%d\n", pauseCtx->cursorPoint[PAUSE_MAP]); - R_MAP_TEX_INDEX = - R_MAP_TEX_INDEX_BASE + - gMapData->floorTexIndexOffset[gSaveContext.mapIndex][pauseCtx->cursorPoint[PAUSE_MAP] - 3]; KaleidoScope_UpdateDungeonMap(play); } } @@ -121,12 +120,13 @@ void KaleidoScope_DrawDungeonMap(PlayState* play, GraphicsContext* gfxCtx) { } } } else { + s16 oldFloor = pauseCtx->dungeonMapSlot; if ((pauseCtx->stickRelY > 30) || (dpad && CHECK_BTN_ALL(input->press.button, BTN_DUP))) { if (pauseCtx->cursorPoint[PAUSE_MAP] >= 4) { for (i = pauseCtx->cursorPoint[PAUSE_MAP] - 3 - 1; i >= 0; i--) { if ((gSaveContext.sceneFlags[gSaveContext.mapIndex].floors & gBitFlags[i]) || (CHECK_DUNGEON_ITEM(DUNGEON_MAP, gSaveContext.mapIndex) && - (gMapData->floorID[interfaceCtx->unk_25A][i] != 0))) { + (entry->dungeonData.floors[i].id != F_NA))) { pauseCtx->cursorPoint[PAUSE_MAP] = i + 3; break; } @@ -137,20 +137,15 @@ void KaleidoScope_DrawDungeonMap(PlayState* play, GraphicsContext* gfxCtx) { for (i = pauseCtx->cursorPoint[PAUSE_MAP] - 3 + 1; i < 11; i++) { if ((gSaveContext.sceneFlags[gSaveContext.mapIndex].floors & gBitFlags[i]) || (CHECK_DUNGEON_ITEM(DUNGEON_MAP, gSaveContext.mapIndex) && - (gMapData->floorID[interfaceCtx->unk_25A][i] != 0))) { + (entry->dungeonData.floors[i].id != F_NA))) { pauseCtx->cursorPoint[PAUSE_MAP] = i + 3; break; } } } } - - i = R_MAP_TEX_INDEX; - R_MAP_TEX_INDEX = - R_MAP_TEX_INDEX_BASE + - gMapData->floorTexIndexOffset[gSaveContext.mapIndex][pauseCtx->cursorPoint[PAUSE_MAP] - 3]; pauseCtx->dungeonMapSlot = pauseCtx->cursorPoint[PAUSE_MAP]; - if (i != R_MAP_TEX_INDEX) { + if (pauseCtx->dungeonMapSlot != oldFloor) { KaleidoScope_UpdateDungeonMap(play); } } @@ -179,10 +174,6 @@ void KaleidoScope_DrawDungeonMap(PlayState* play, GraphicsContext* gfxCtx) { pauseCtx->cursorX[PAUSE_MAP] = 0; pauseCtx->cursorSlot[PAUSE_MAP] = pauseCtx->cursorPoint[PAUSE_MAP] = pauseCtx->dungeonMapSlot; - R_MAP_TEX_INDEX = - R_MAP_TEX_INDEX_BASE + - gMapData - ->floorTexIndexOffset[gSaveContext.mapIndex][pauseCtx->cursorPoint[PAUSE_MAP] - 3]; KaleidoScope_UpdateDungeonMap(play); } } @@ -263,9 +254,9 @@ void KaleidoScope_DrawDungeonMap(PlayState* play, GraphicsContext* gfxCtx) { if ((gSaveContext.sceneFlags[gSaveContext.mapIndex].floors & gBitFlags[i]) || CHECK_DUNGEON_ITEM(DUNGEON_MAP, gSaveContext.mapIndex)) { if (i != (pauseCtx->dungeonMapSlot - 3)) { - gDPLoadTextureBlock(POLY_OPA_DISP++, floorIconTexs[gMapData->floorID[interfaceCtx->unk_25A][i]], - G_IM_FMT_IA, G_IM_SIZ_8b, 24, 16, 0, G_TX_WRAP | G_TX_NOMIRROR, - G_TX_WRAP | G_TX_NOMIRROR, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); + gDPLoadTextureBlock(POLY_OPA_DISP++, floorIconTexs[entry->dungeonData.floors[i].id], G_IM_FMT_IA, + G_IM_SIZ_8b, 24, 16, 0, G_TX_WRAP | G_TX_NOMIRROR, G_TX_WRAP | G_TX_NOMIRROR, + G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); gSP1Quadrangle(POLY_OPA_DISP++, j, j + 2, j + 3, j + 1, 0); } @@ -277,8 +268,7 @@ void KaleidoScope_DrawDungeonMap(PlayState* play, GraphicsContext* gfxCtx) { gDPPipeSync(POLY_OPA_DISP++); gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 150, 150, 255, pauseCtx->alpha); - gDPLoadTextureBlock(POLY_OPA_DISP++, - floorIconTexs[gMapData->floorID[interfaceCtx->unk_25A][pauseCtx->dungeonMapSlot - 3]], + gDPLoadTextureBlock(POLY_OPA_DISP++, floorIconTexs[entry->dungeonData.floors[pauseCtx->dungeonMapSlot - 3].id], G_IM_FMT_IA, G_IM_SIZ_8b, 24, 16, 0, G_TX_WRAP | G_TX_NOMIRROR, G_TX_WRAP | G_TX_NOMIRROR, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); @@ -303,10 +293,9 @@ void KaleidoScope_DrawDungeonMap(PlayState* play, GraphicsContext* gfxCtx) { gSP1Quadrangle(POLY_OPA_DISP++, 0, 2, 3, 1, 0); - if (CHECK_DUNGEON_ITEM(DUNGEON_COMPASS, gSaveContext.mapIndex) && - (gMapData->skullFloorIconY[gSaveContext.mapIndex] != -99)) { - pauseCtx->mapPageVtx[120].v.ob[1] = pauseCtx->mapPageVtx[121].v.ob[1] = - gMapData->skullFloorIconY[gSaveContext.mapIndex] + pauseCtx->offsetY; + if (CHECK_DUNGEON_ITEM(DUNGEON_COMPASS, gSaveContext.mapIndex) && (entry->dungeonData.bossFloor != -1)) { + s16 skullFloorIconY = 51 - 14 * entry->dungeonData.bossFloor; + pauseCtx->mapPageVtx[120].v.ob[1] = pauseCtx->mapPageVtx[121].v.ob[1] = skullFloorIconY + pauseCtx->offsetY; pauseCtx->mapPageVtx[122].v.ob[1] = pauseCtx->mapPageVtx[123].v.ob[1] = pauseCtx->mapPageVtx[120].v.ob[1] - 16; gDPLoadTextureBlock(POLY_OPA_DISP++, gDungeonMapSkullTex, G_IM_FMT_RGBA, G_IM_SIZ_16b, 16, 16, 0, diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c index 14f749d43..46cd38eeb 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c @@ -22,6 +22,7 @@ #include "soh/ResourceManagerHelpers.h" #include "soh/SaveManager.h" #include "soh/Enhancements/kaleido.h" +#include "soh/SceneDB.h" static void* sEquipmentFRATexs[] = { gPauseEquipment00FRATex, gPauseEquipment01Tex, gPauseEquipment02Tex, gPauseEquipment03Tex, gPauseEquipment04Tex, @@ -3680,6 +3681,7 @@ static uint8_t mapBlendMask[MAP_48x85_TEX_WIDTH * MAP_48x85_TEX_HEIGHT]; // SoH [General] - Modified to account for our resource system and HD textures void KaleidoScope_LoadDungeonMap(PlayState* play) { InterfaceContext* interfaceCtx = &play->interfaceCtx; + SceneDBEntry* entry = SceneDB_Retrieve(gSaveContext.mapIndex); // Free old textures if (mapLeftTexModifiedRaw != NULL) { @@ -3691,12 +3693,13 @@ void KaleidoScope_LoadDungeonMap(PlayState* play) { mapRightTexModifiedRaw = NULL; } + s16 floor = play->pauseCtx.cursorPoint[PAUSE_MAP] - 3; // Unload original textures to bypass cache result for lookups - ResourceMgr_UnloadOriginalWhenAltExists(sDungeonMapTexs[R_MAP_TEX_INDEX]); - ResourceMgr_UnloadOriginalWhenAltExists(sDungeonMapTexs[R_MAP_TEX_INDEX + 1]); + ResourceMgr_UnloadOriginalWhenAltExists(entry->dungeonData.floors[floor].mapLeftTexture); + ResourceMgr_UnloadOriginalWhenAltExists(entry->dungeonData.floors[floor].mapRightTexture); - interfaceCtx->mapSegmentName[0] = sDungeonMapTexs[R_MAP_TEX_INDEX]; - interfaceCtx->mapSegmentName[1] = sDungeonMapTexs[R_MAP_TEX_INDEX + 1]; + interfaceCtx->mapSegmentName[0] = entry->dungeonData.floors[floor].mapLeftTexture; + interfaceCtx->mapSegmentName[1] = entry->dungeonData.floors[floor].mapRightTexture; // When the texture is HD (raw) we need to copy a dynamic amount of data // Otherwise the original asset has a static size diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_lmap_mark.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_lmap_mark.c index 3209a6c5c..b319db42a 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_lmap_mark.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_lmap_mark.c @@ -1,4 +1,5 @@ #include "z_kaleido_scope.h" +#include "soh/SceneDB.h" #include "textures/parameter_static/parameter_static.h" #include "soh/ResourceManagerHelpers.h" @@ -36,12 +37,21 @@ static const u32 sLineBytesImageSizes[] = { 0, 1, 2, 2 }; extern PauseMapMarksData gPauseMapMarkDataTable[]; extern PauseMapMarksData gPauseMapMarkDataTableMasterQuest[]; +static const Vtx sMarkBossVtx[] = { + VTX(-4, 4, 0, 0, 0, 255, 255, 255, 255), + VTX(-4, -4, 0, 0, 256, 255, 255, 255, 255), + VTX(4, 4, 0, 256, 0, 255, 255, 255, 255), + VTX(4, -4, 0, 256, 256, 255, 255, 255, 255), +}; + +static const Vtx sMarkChestVtx[] = { + VTX(-4, 4, 0, 0, 0, 255, 255, 255, 255), + VTX(-4, -4, 0, 0, 256, 255, 255, 255, 255), + VTX(4, 4, 0, 256, 0, 255, 255, 255, 255), + VTX(4, -4, 0, 256, 256, 255, 255, 255, 255), +}; + void PauseMapMark_Init(PlayState* play) { - if (ResourceMgr_IsGameMasterQuest()) { - gLoadedPauseMarkDataTable = gPauseMapMarkDataTableMasterQuest; - } else { - gLoadedPauseMarkDataTable = gPauseMapMarkDataTable; - } } void PauseMapMark_Clear(PlayState* play) { @@ -54,138 +64,102 @@ void PauseMapMark_DrawForDungeon(PlayState* play) { PauseMapMarkInfo* markInfo; f32 scale; s32 i = 0; + SceneDBEntry* entry = SceneDB_Retrieve(gSaveContext.mapIndex); + SceneDBFloor* floor = &entry->dungeonData.floors[play->pauseCtx.dungeonMapSlot - 3]; - mapMarkData = &gLoadedPauseMarkDataTable[R_MAP_TEX_INDEX >> 1][i]; + if (SceneDB_IsBoss(play->sceneNum)) { + if (gBossMarkState == 0) { + Math_ApproachF(&gBossMarkScale, 1.5f, 1.0f, 0.041f); + if (gBossMarkScale == 1.5f) { + gBossMarkState = 1; + } + } else { + Math_ApproachF(&gBossMarkScale, 1.0f, 1.0f, 0.041f); + if (gBossMarkScale == 1.0f) { + gBossMarkState = 0; + } + } + scale = gBossMarkScale; + } else { + scale = 1.0f; + } OPEN_DISPS(play->state.gfxCtx); - while (true) { - if (mapMarkData->markType == PAUSE_MAP_MARK_NONE) { - break; + gDPPipeSync(POLY_OPA_DISP++); + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, 255); + gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 255); + + Matrix_Push(); + + if ((play->pauseCtx.state == 4) || (play->pauseCtx.state >= 0x12)) { + Matrix_Translate(-36.0f, 101.0f, 0.0f, MTXMODE_APPLY); + } else { + Matrix_Translate(-36.0f, 21.0f, 0.0f, MTXMODE_APPLY); + } + + markInfo = &sMapMarkInfoTable[MAP_MARK_CHEST]; + gDPLoadTextureBlock(POLY_OPA_DISP++, markInfo->texture, markInfo->imageFormat, G_IM_SIZ_MARK, + markInfo->textureWidth, markInfo->textureHeight, 0, G_TX_NOMIRROR | G_TX_WRAP, + G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); + for (s32 i = 0; i < floor->numChestMarks; i++) { + s32 display; + + if (Flags_GetTreasure(play, floor->chestMarks[i].chestFlag)) { + display = false; + } else { + display = SceneDB_IsDungeon(play->sceneNum); } - if ((mapMarkData->markType == PAUSE_MAP_MARK_BOSS) && (play->sceneNum >= SCENE_DEKU_TREE_BOSS) && - (play->sceneNum <= SCENE_GANONS_TOWER_COLLAPSE_EXTERIOR)) { - if (gBossMarkState == 0) { - Math_ApproachF(&gBossMarkScale, 1.5f, 1.0f, 0.041f); - if (gBossMarkScale == 1.5f) { - gBossMarkState = 1; - } - } else { - Math_ApproachF(&gBossMarkScale, 1.0f, 1.0f, 0.041f); - if (gBossMarkScale == 1.0f) { - gBossMarkState = 0; - } - } - scale = gBossMarkScale; - } else { - scale = 1.0f; + if (display) { + // Compute the offset to mirror icons over the map center (48) as an axis line + s16 mirrorOffset = + CVarGetInteger("gMirroredWorld", 0) ? mirrorOffset = (48 - floor->chestMarks[i].x) * 2 + 1 : 0; + + Matrix_Push(); + Matrix_Translate(GREG(92) + floor->chestMarks[i].x + mirrorOffset, GREG(93) + floor->chestMarks[i].y, 0.0f, + MTXMODE_APPLY); + Matrix_Scale(1.0f, 1.0f, 1.0f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + Matrix_Pop(); + + gSPVertex(POLY_OPA_DISP++, sMarkChestVtx, 4, 0); + gSP1Quadrangle(POLY_OPA_DISP++, 1, 3, 2, 0, 0); } + } + + markInfo = &sMapMarkInfoTable[MAP_MARK_BOSS]; + gDPLoadTextureBlock(POLY_OPA_DISP++, markInfo->texture, markInfo->imageFormat, G_IM_SIZ_MARK, + markInfo->textureWidth, markInfo->textureHeight, 0, G_TX_NOMIRROR | G_TX_WRAP, + G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); + for (s32 i = 0; i < floor->numBossMarks; i++) { + // Compute the offset to mirror icons over the map center (48) as an axis line + s16 mirrorOffset = CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) + ? mirrorOffset = (48 - floor->bossMarks[i].x) * 2 + 1 + : 0; Matrix_Push(); - - if ((play->pauseCtx.state == 4) || (play->pauseCtx.state >= 0x12)) { - Matrix_Translate(-36.0f, 101.0f, 0.0f, MTXMODE_APPLY); - } else { - Matrix_Translate(-36.0f, 21.0f, 0.0f, MTXMODE_APPLY); - } - - gDPPipeSync(POLY_OPA_DISP++); - gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, 255); - gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 255); - - markPoint = &mapMarkData->points[0]; - for (i = 0; i < mapMarkData->count; i++) { - s32 display; - - if (mapMarkData->markType == PAUSE_MAP_MARK_CHEST) { - if (Flags_GetTreasure(play, markPoint->chestFlag)) { - display = false; - } else { - switch (play->sceneNum) { - case SCENE_DEKU_TREE_BOSS: - case SCENE_DODONGOS_CAVERN_BOSS: - case SCENE_JABU_JABU_BOSS: - case SCENE_FOREST_TEMPLE_BOSS: - case SCENE_FIRE_TEMPLE_BOSS: - case SCENE_WATER_TEMPLE_BOSS: - case SCENE_SPIRIT_TEMPLE_BOSS: - case SCENE_SHADOW_TEMPLE_BOSS: - display = false; - break; - default: - display = true; - break; - } - } - } else { - display = true; - } - - if (display) { - markInfo = &sMapMarkInfoTable[mapMarkData->markType]; - - gDPPipeSync(POLY_OPA_DISP++); - gDPLoadTextureBlock(POLY_OPA_DISP++, markInfo->texture, markInfo->imageFormat, G_IM_SIZ_MARK, - markInfo->textureWidth, markInfo->textureHeight, 0, G_TX_NOMIRROR | G_TX_WRAP, - G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); - - // Compute the offset to mirror icons over the map center (48) as an axis line - s16 mirrorOffset = CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) - ? mirrorOffset = (48 - markPoint->x) * 2 + 1 - : 0; - - Matrix_Push(); - Matrix_Translate(GREG(92) + markPoint->x + mirrorOffset, GREG(93) + markPoint->y, 0.0f, MTXMODE_APPLY); - Matrix_Scale(scale, scale, scale, MTXMODE_APPLY); - gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), - G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - Matrix_Pop(); - - gSPVertex(POLY_OPA_DISP++, mapMarkData->vtx, mapMarkData->vtxCount, 0); - gSP1Quadrangle(POLY_OPA_DISP++, 1, 3, 2, 0, 0); - } - - markPoint++; - } - - mapMarkData++; + Matrix_Translate(GREG(92) + floor->bossMarks[i].x + mirrorOffset, GREG(93) + floor->bossMarks[i].y, 0.0f, + MTXMODE_APPLY); + Matrix_Scale(scale, scale, scale, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); Matrix_Pop(); + + gSPVertex(POLY_OPA_DISP++, sMarkBossVtx, 4, 0); + gSP1Quadrangle(POLY_OPA_DISP++, 1, 3, 2, 0, 0); } + Matrix_Pop(); + CLOSE_DISPS(play->state.gfxCtx); } void PauseMapMark_Draw(PlayState* play) { PauseMapMark_Init(play); - switch (play->sceneNum) { - case SCENE_DEKU_TREE: - case SCENE_DODONGOS_CAVERN: - case SCENE_JABU_JABU: - case SCENE_FOREST_TEMPLE: - case SCENE_FIRE_TEMPLE: - case SCENE_WATER_TEMPLE: - case SCENE_SPIRIT_TEMPLE: - case SCENE_SHADOW_TEMPLE: - case SCENE_BOTTOM_OF_THE_WELL: - case SCENE_ICE_CAVERN: - PauseMapMark_DrawForDungeon(play); - break; - case SCENE_DEKU_TREE_BOSS: - case SCENE_DODONGOS_CAVERN_BOSS: - case SCENE_JABU_JABU_BOSS: - case SCENE_FOREST_TEMPLE_BOSS: - case SCENE_FIRE_TEMPLE_BOSS: - case SCENE_WATER_TEMPLE_BOSS: - case SCENE_SPIRIT_TEMPLE_BOSS: - case SCENE_SHADOW_TEMPLE_BOSS: - case SCENE_GANONDORF_BOSS: - case SCENE_GANONS_TOWER_COLLAPSE_EXTERIOR: - if (CVarGetInteger(CVAR_ENHANCEMENT("PulsateBossIcon"), 0) != 0) { - PauseMapMark_DrawForDungeon(play); - } - break; + if (SceneDB_IsDungeon(play->sceneNum) || + (CVarGetInteger(CVAR_ENHANCEMENT("PulsateBossIcon"), 0) != 0 && SceneDB_IsBoss(play->sceneNum))) { + PauseMapMark_DrawForDungeon(play); } PauseMapMark_Clear(play);