z_scene Some comments and function names (#2808)

* z_scene Some comments and function names

* review changes

* further fixing from comments

* vromAddr

---------

Co-authored-by: djevangelia <djevangelia>
This commit is contained in:
djevangelia
2026-09-02 18:59:35 +02:00
committed by GitHub
parent 6c29db8fa6
commit 749e232dc3
3 changed files with 48 additions and 13 deletions
+1 -1
View File
@@ -41,7 +41,7 @@ void Object_InitContext(struct PlayState* play, ObjectContext* objectCtx);
void Object_UpdateEntries(ObjectContext* objectCtx);
s32 Object_GetSlot(ObjectContext* objectCtx, s16 objectId);
s32 Object_IsLoaded(ObjectContext* objectCtx, s32 slot);
void func_800981B8(ObjectContext* objectCtx);
void Object_ReloadAll(ObjectContext* objectCtx);
extern u32 gObjectTableSize;
extern RomFile gObjectTable[OBJECT_ID_MAX];
+45 -10
View File
@@ -20,18 +20,18 @@ SceneCmdHandlerFunc sSceneCmdHandlers[SCENE_CMD_ID_MAX];
RomFile sNaviQuestHintFiles[];
/**
* Spawn an object file of a specified ID that will persist through room changes.
* Loads an object file of a specified ID that will persist through room changes.
*
* This waits for the file to be fully loaded, the data is available when the function returns.
*
* @return The new object slot corresponding to the requested object ID.
*
* @note This function is not meant to be called externally to spawn object files on the fly.
* When an object is spawned with this function, all objects that come before it in the entry list will be treated as
* @note This function is not meant to be called externally to load object files on the fly.
* When an object is loaded with this function, all objects that come before it in the entry list will be treated as
* persistent, which will likely cause either the amount of free slots or object space memory to run out.
* This function is only meant to be called internally on scene load, before the object list from any room is processed.
*/
s32 Object_SpawnPersistent(ObjectContext* objectCtx, s16 objectId) {
s32 Object_LoadPersistent(ObjectContext* objectCtx, s16 objectId) {
u32 size;
objectCtx->slots[objectCtx->numEntries].id = objectId;
@@ -109,10 +109,14 @@ void Object_InitContext(PlayState* play, ObjectContext* objectCtx) {
GAME_STATE_ALLOC(&play->state, spaceSize, "../z_scene.c", 219);
objectCtx->spaceEnd = (void*)((uintptr_t)objectCtx->spaceStart + spaceSize);
objectCtx->mainKeepSlot = Object_SpawnPersistent(objectCtx, OBJECT_GAMEPLAY_KEEP);
objectCtx->mainKeepSlot = Object_LoadPersistent(objectCtx, OBJECT_GAMEPLAY_KEEP);
gSegments[4] = OS_K0_TO_PHYSICAL(objectCtx->slots[objectCtx->mainKeepSlot].segment);
}
/**
* Run every frame. Loads non-persistent objects on scene init/room change, whose data have
* been added to the object slot array by `func_800982FC`. Unloaded status is marked by negative object id.
*/
void Object_UpdateEntries(ObjectContext* objectCtx) {
s32 i;
ObjectEntry* entry = &objectCtx->slots[0];
@@ -120,7 +124,7 @@ void Object_UpdateEntries(ObjectContext* objectCtx) {
u32 size;
for (i = 0; i < objectCtx->numEntries; i++) {
if (entry->id < 0) {
if (entry->id < 0) { // Not yet loaded object
if (entry->dmaRequest.vromAddr == 0) {
osCreateMesgQueue(&entry->loadQueue, &entry->loadMsg, 1);
objectFile = &gObjectTable[-entry->id];
@@ -131,17 +135,22 @@ void Object_UpdateEntries(ObjectContext* objectCtx) {
DMA_REQUEST_ASYNC(&entry->dmaRequest, entry->segment, objectFile->vromStart, size, 0, &entry->loadQueue,
NULL, "../z_scene.c", 266);
} else if (osRecvMesg(&entry->loadQueue, NULL, OS_MESG_NOBLOCK) == 0) {
entry->id = -entry->id;
entry->id = -entry->id; // Object now loaded
}
}
entry++;
}
}
/**
* Get object slot for a given object id.
* @return object slot for given id, or -1 if not in any slot
*/
s32 Object_GetSlot(ObjectContext* objectCtx, s16 objectId) {
s32 i;
for (i = 0; i < objectCtx->numEntries; i++) {
// ABS is necessary because object might not yet be loaded
if (ABS(objectCtx->slots[i].id) == objectId) {
return i;
}
@@ -150,6 +159,10 @@ s32 Object_GetSlot(ObjectContext* objectCtx, s16 objectId) {
return -1;
}
/**
* Check if the object in a given slot is loaded.
* @return true if loaded, else false
*/
s32 Object_IsLoaded(ObjectContext* objectCtx, s32 slot) {
if (objectCtx->slots[slot].id > 0) {
return true;
@@ -158,7 +171,12 @@ s32 Object_IsLoaded(ObjectContext* objectCtx, s32 slot) {
}
}
void func_800981B8(ObjectContext* objectCtx) {
/**
* Run when exiting the pause menu (either to continue play or due to game over).
* Sync DMA loads all objects for current room.
* (Collision header data is restored by `func_800418D0`)
*/
void Object_ReloadAll(ObjectContext* objectCtx) {
s32 i;
s32 id;
u32 size;
@@ -173,6 +191,14 @@ void func_800981B8(ObjectContext* objectCtx) {
}
}
/**
* Prepares a given slot to be filled with data of given object id. Called by `Scene_CommandObjectList`
* for every non-persistent object to be added. The data is used by `Object_UpdateEntries` to load the
* objects.
* @note There is an assert to ensure that the next object slot address is within the object memory space,
* but in non-debug builds this is not included, and no other bounds check is done.
* @return start address of the next object slot's memory in object space
*/
void* func_800982FC(ObjectContext* objectCtx, s32 slot, s16 objectId) {
ObjectEntry* entry = &objectCtx->slots[slot];
RomFile* objectFile = &gObjectTable[objectId];
@@ -195,6 +221,10 @@ void* func_800982FC(ObjectContext* objectCtx, s32 slot, s16 objectId) {
return nextPtr;
}
/**
* Executes all the scene commands for the current scene/room upon loading. The commands to be run
* for a particular scene/room is found in the scene/room file's data.
*/
s32 Scene_ExecuteCommands(PlayState* play, SceneCmd* sceneCmd) {
while (true) {
u32 cmdCode = sceneCmd->base.code;
@@ -230,7 +260,7 @@ BAD_RETURN(s32) Scene_CommandPlayerEntryList(PlayState* play, SceneCmd* cmd) {
linkObjectId = gLinkObjectIds[((void)0, gSaveContext.save.linkAge)];
gActorOverlayTable[playerEntry->id].profile->objectId = linkObjectId;
Object_SpawnPersistent(&play->objectCtx, linkObjectId);
Object_LoadPersistent(&play->objectCtx, linkObjectId);
}
BAD_RETURN(s32) Scene_CommandActorEntryList(PlayState* play, SceneCmd* cmd) {
@@ -265,7 +295,7 @@ BAD_RETURN(s32) Scene_CommandSpawnList(PlayState* play, SceneCmd* cmd) {
BAD_RETURN(s32) Scene_CommandSpecialFiles(PlayState* play, SceneCmd* cmd) {
if (cmd->specialFiles.keepObjectId != OBJECT_INVALID) {
play->objectCtx.subKeepSlot = Object_SpawnPersistent(&play->objectCtx, cmd->specialFiles.keepObjectId);
play->objectCtx.subKeepSlot = Object_LoadPersistent(&play->objectCtx, cmd->specialFiles.keepObjectId);
gSegments[5] = OS_K0_TO_PHYSICAL(play->objectCtx.slots[play->objectCtx.subKeepSlot].segment);
}
@@ -300,6 +330,10 @@ BAD_RETURN(s32) Scene_CommandObjectList(PlayState* play, SceneCmd* cmd) {
entries = play->objectCtx.slots;
entry = &play->objectCtx.slots[i];
// On room load (room change/scene init), go through all current loaded non-persistent
// object slots and new objects to be loaded in those slots.
// If a slot's object id is not the same for both rooms, invalidate that object slot
// and every following slot. Also kill any actors dependent on those objects.
while (i < play->objectCtx.numEntries) {
if (entry->id != *objectListEntry) {
@@ -325,6 +359,7 @@ BAD_RETURN(s32) Scene_CommandObjectList(PlayState* play, SceneCmd* cmd) {
"scene_info->object_bank.num <= OBJECT_EXCHANGE_BANK_MAX", "../z_scene.c", 705);
while (k < cmd->objectList.length) {
// Add object from new object list at `nextPtr` (next start address in object memory space)
nextPtr = func_800982FC(&play->objectCtx, i, *objectListEntry);
if (i < (ARRAY_COUNT(play->objectCtx.slots) - 1)) {
entries[i + 1].segment = nextPtr;
@@ -4643,7 +4643,7 @@ void KaleidoScope_Update(PlayState* play) {
pauseCtx->state = PAUSE_STATE_OFF;
R_UPDATE_RATE = 3;
R_PAUSE_BG_PRERENDER_STATE = PAUSE_BG_PRERENDER_OFF;
func_800981B8(&play->objectCtx);
Object_ReloadAll(&play->objectCtx);
func_800418D0(&play->colCtx, play);
if (pauseCtx->promptChoice == 0) {
Play_TriggerRespawn(play);
@@ -4704,7 +4704,7 @@ void KaleidoScope_Update(PlayState* play) {
R_UPDATE_RATE = 3;
R_PAUSE_BG_PRERENDER_STATE = PAUSE_BG_PRERENDER_OFF;
func_800981B8(&play->objectCtx);
Object_ReloadAll(&play->objectCtx);
func_800418D0(&play->colCtx, play);
switch (play->sceneId) {