Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SceneDB [WIP Do not merge] #4460

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion soh/include/z64.h
Original file line number Diff line number Diff line change
Expand Up @@ -1675,7 +1675,8 @@ typedef struct PreNMIContext {
} PreNMIContext; // size = 0xAC

typedef enum {
/* 1 */ F_8F = 1,
/* 0 */ F_NA,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have deviated from decomp documentation to add a value to this enum. All dungeons have 8 floors and 0 is used to represent invalid/unused floors. Having an actual enum value saves a lot of static_casts for the scene table.

/* 1 */ F_8F,
/* 2 */ F_7F,
/* 3 */ F_6F,
/* 4 */ F_5F,
Expand Down
6 changes: 3 additions & 3 deletions soh/include/z64save.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,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;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are now dynamically sized to support any number of scenes. Fun side effect: all scenes can now have small keys, etc. This was easier and less invasive than restricting it to dungeons and making a mapping from scene id to dungeonItems index.

/* 0x48 */ s8* dungeonKeys;
/* 0x5B */ s8 defenseHearts;
/* 0x5C */ s16 gsTokens;
} Inventory; // size = 0x5E
Expand Down Expand Up @@ -189,7 +189,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];
Expand Down
2 changes: 1 addition & 1 deletion soh/soh/ActorDB.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,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 RetrieveId to get it.
// 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);

Expand Down
5 changes: 3 additions & 2 deletions soh/soh/Enhancements/randomizer/hook_handlers.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <libultraship/bridge.h>
#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"
Expand Down Expand Up @@ -835,15 +836,15 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l
case VB_BE_ELIGIBLE_FOR_LIGHT_ARROWS:
*should =
LINK_IS_ADULT &&
(gEntranceTable[gSaveContext.entranceIndex].scene == SCENE_TEMPLE_OF_TIME) &&
(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);
Expand Down
17 changes: 13 additions & 4 deletions soh/soh/Enhancements/randomizer/logic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <vector>

#include "soh/OTRGlobals.h"
#include "soh/SceneDB.h"
#include "dungeon.h"
#include "context.h"
#include "macros.h"
Expand Down Expand Up @@ -1785,6 +1786,7 @@ namespace Rando {
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;
}
Expand All @@ -1794,15 +1796,15 @@ namespace Rando {
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;
Expand Down Expand Up @@ -1882,9 +1884,16 @@ namespace Rando {

void Logic::NewSaveContext() {
if (mSaveContext != nullptr && mSaveContext != &gSaveContext) {
free(mSaveContext);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed free to delete as you should always match malloc/free, new/delete

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();
}

Expand Down
61 changes: 25 additions & 36 deletions soh/soh/Enhancements/randomizer/randomizer_entrance.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "randomizer_grotto.h"
#include "soh/OTRGlobals.h"
#include "soh/SaveManager.h"
#include "soh/SceneDB.h"
#include <string.h>

#include "global.h"
Expand Down Expand Up @@ -46,8 +47,6 @@ static s16 entranceOverrideTable[ENTRANCE_TABLE_SIZE] = {0};
static s16 bossSceneSaveDeathWarps[SHUFFLEABLE_BOSS_COUNT] = {0};
static ActorEntry modifiedLinkActorEntry = {0};

EntranceInfo originalEntranceTable[ENTRANCE_TABLE_SIZE] = {0};

typedef struct {
s16 entryway;
s16 exit;
Expand Down Expand Up @@ -84,15 +83,15 @@ 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);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note the order is reversed compared to assignment. This is to better match the verbiage of "copy from X to Y".

}
}

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);
}
}

Expand All @@ -101,53 +100,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();
Expand Down Expand Up @@ -240,9 +231,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;
}
}
}
Expand Down Expand Up @@ -310,8 +299,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
Expand Down
3 changes: 2 additions & 1 deletion soh/soh/Enhancements/timesaver_hook_handlers.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include <libultraship/bridge.h>
#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"
Expand Down Expand Up @@ -171,7 +172,7 @@ 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);
Expand Down
5 changes: 3 additions & 2 deletions soh/soh/Enhancements/tts/tts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@
#include <spdlog/fmt/fmt.h>

#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;
}
Expand Down Expand Up @@ -204,6 +204,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) {
Expand Down Expand Up @@ -452,7 +453,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) {
Expand Down
3 changes: 3 additions & 0 deletions soh/soh/OTRGlobals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
#include "SohGui.hpp"
#include "ActorDB.h"
#include "SaveManager.h"
#include "SceneDB.h"

#ifdef ENABLE_REMOTE_CONTROL
#include "soh/Network/CrowdControl/CrowdControl.h"
Expand Down Expand Up @@ -1150,6 +1151,8 @@ extern "C" void InitOTR() {
SohGui::SetupGuiElements();
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();
Expand Down
Loading