Port Proposed OoT Object Docs (#1361)

* port docs in z_scene

* undo accidental ctrl-f

* another fix

* expose Object_SpawnPersistent

---------

Co-authored-by: engineer124 <engineer124engineer124@gmail.com>
This commit is contained in:
fig02
2023-10-03 23:01:04 -04:00
committed by GitHub
parent d635b81ee6
commit f4a490bb6a
68 changed files with 279 additions and 269 deletions
+85 -72
View File
@@ -1,28 +1,41 @@
#include "global.h"
s32 Object_Spawn(ObjectContext* objectCtx, s16 id) {
/**
* Spawn 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
* 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 id) {
size_t size;
objectCtx->status[objectCtx->num].id = id;
objectCtx->slots[objectCtx->numEntries].id = id;
size = gObjectTable[id].vromEnd - gObjectTable[id].vromStart;
if (1) {}
if (size != 0) {
DmaMgr_SendRequest0(objectCtx->status[objectCtx->num].segment, gObjectTable[id].vromStart, size);
DmaMgr_SendRequest0(objectCtx->slots[objectCtx->numEntries].segment, gObjectTable[id].vromStart, size);
}
if (objectCtx->num < OBJECT_EXCHANGE_BANK_MAX - 1) {
objectCtx->status[objectCtx->num + 1].segment = ALIGN16((u32)objectCtx->status[objectCtx->num].segment + size);
if (objectCtx->numEntries < ARRAY_COUNT(objectCtx->slots) - 1) {
objectCtx->slots[objectCtx->numEntries + 1].segment =
ALIGN16((u32)objectCtx->slots[objectCtx->numEntries].segment + size);
}
objectCtx->num++;
objectCtx->spawnedObjectCount = objectCtx->num;
objectCtx->numEntries++;
objectCtx->numPersistentEntries = objectCtx->numEntries;
return objectCtx->num - 1;
return objectCtx->numEntries - 1;
}
void Object_InitBank(GameState* gameState, ObjectContext* objectCtx) {
void Object_InitContext(GameState* gameState, ObjectContext* objectCtx) {
PlayState* play = (PlayState*)gameState;
s32 pad;
u32 spaceSize;
@@ -30,66 +43,66 @@ void Object_InitBank(GameState* gameState, ObjectContext* objectCtx) {
if (play->sceneId == SCENE_CLOCKTOWER || play->sceneId == SCENE_TOWN || play->sceneId == SCENE_BACKTOWN ||
play->sceneId == SCENE_ICHIBA) {
spaceSize = OBJECT_SPACE_SIZE_CLOCK_TOWN;
spaceSize = 1530 * 1024;
} else if (play->sceneId == SCENE_MILK_BAR) {
spaceSize = OBJECT_SPACE_SIZE_MILK_BAR;
spaceSize = 1580 * 1024;
} else if (play->sceneId == SCENE_00KEIKOKU) {
spaceSize = OBJECT_SPACE_SIZE_TERMINA_FIELD;
spaceSize = 1470 * 1024;
} else {
spaceSize = OBJECT_SPACE_SIZE_DEFAULT;
spaceSize = 1380 * 1024;
}
objectCtx->num = 0;
objectCtx->spawnedObjectCount = 0;
objectCtx->mainKeepIndex = 0;
objectCtx->subKeepIndex = 0;
objectCtx->numEntries = 0;
objectCtx->numPersistentEntries = 0;
objectCtx->mainKeepSlot = 0;
objectCtx->subKeepSlot = 0;
// clang-format off
for (i = 0; i < OBJECT_EXCHANGE_BANK_MAX; i++) { objectCtx->status[i].id = 0; }
for (i = 0; i < ARRAY_COUNT(objectCtx->slots); i++) { objectCtx->slots[i].id = 0; }
// clang-format on
objectCtx->spaceStart = objectCtx->status[0].segment = THA_AllocTailAlign16(&gameState->tha, spaceSize);
objectCtx->spaceStart = objectCtx->slots[0].segment = THA_AllocTailAlign16(&gameState->tha, spaceSize);
objectCtx->spaceEnd = (void*)((u32)objectCtx->spaceStart + spaceSize);
objectCtx->mainKeepIndex = Object_Spawn(objectCtx, GAMEPLAY_KEEP);
objectCtx->mainKeepSlot = Object_SpawnPersistent(objectCtx, GAMEPLAY_KEEP);
gSegments[0x04] = VIRTUAL_TO_PHYSICAL(objectCtx->status[objectCtx->mainKeepIndex].segment);
gSegments[4] = VIRTUAL_TO_PHYSICAL(objectCtx->slots[objectCtx->mainKeepSlot].segment);
}
void Object_UpdateBank(ObjectContext* objectCtx) {
void Object_UpdateEntries(ObjectContext* objectCtx) {
s32 i;
ObjectStatus* status = &objectCtx->status[0];
ObjectEntry* entry = &objectCtx->slots[0];
RomFile* objectFile;
size_t size;
for (i = 0; i < objectCtx->num; i++) {
if (status->id < 0) {
s32 id = -status->id;
for (i = 0; i < objectCtx->numEntries; i++) {
if (entry->id < 0) {
s32 id = -entry->id;
if (status->dmaReq.vromAddr == 0) {
if (entry->dmaReq.vromAddr == 0) {
objectFile = &gObjectTable[id];
size = objectFile->vromEnd - objectFile->vromStart;
if (size == 0) {
status->id = 0;
entry->id = 0;
} else {
osCreateMesgQueue(&status->loadQueue, &status->loadMsg, 1);
DmaMgr_SendRequestImpl(&status->dmaReq, status->segment, objectFile->vromStart, size, 0,
&status->loadQueue, NULL);
osCreateMesgQueue(&entry->loadQueue, &entry->loadMsg, 1);
DmaMgr_SendRequestImpl(&entry->dmaReq, entry->segment, objectFile->vromStart, size, 0,
&entry->loadQueue, NULL);
}
} else if (!osRecvMesg(&status->loadQueue, NULL, OS_MESG_NOBLOCK)) {
status->id = id;
} else if (!osRecvMesg(&entry->loadQueue, NULL, OS_MESG_NOBLOCK)) {
entry->id = id;
}
}
status++;
entry++;
}
}
s32 Object_GetIndex(ObjectContext* objectCtx, s16 objectId) {
s32 Object_GetSlot(ObjectContext* objectCtx, s16 objectId) {
s32 i;
for (i = 0; i < objectCtx->num; i++) {
if (ABS_ALT(objectCtx->status[i].id) == objectId) {
for (i = 0; i < objectCtx->numEntries; i++) {
if (ABS_ALT(objectCtx->slots[i].id) == objectId) {
return i;
}
}
@@ -97,8 +110,8 @@ s32 Object_GetIndex(ObjectContext* objectCtx, s16 objectId) {
return -1;
}
s32 Object_IsLoaded(ObjectContext* objectCtx, s32 index) {
if (objectCtx->status[index].id > 0) {
s32 Object_IsLoaded(ObjectContext* objectCtx, s32 slot) {
if (objectCtx->slots[slot].id > 0) {
return true;
} else {
return false;
@@ -110,31 +123,31 @@ void Object_LoadAll(ObjectContext* objectCtx) {
s32 id;
uintptr_t vromSize;
for (i = 0; i < objectCtx->num; i++) {
id = objectCtx->status[i].id;
for (i = 0; i < objectCtx->numEntries; i++) {
id = objectCtx->slots[i].id;
vromSize = gObjectTable[id].vromEnd - gObjectTable[id].vromStart;
if (vromSize == 0) {
continue;
}
DmaMgr_SendRequest0(objectCtx->status[i].segment, gObjectTable[id].vromStart, vromSize);
DmaMgr_SendRequest0(objectCtx->slots[i].segment, gObjectTable[id].vromStart, vromSize);
}
}
void* func_8012F73C(ObjectContext* objectCtx, s32 iParm2, s16 id) {
void* func_8012F73C(ObjectContext* objectCtx, s32 slot, s16 id) {
u32 addr;
uintptr_t vromSize;
RomFile* fileTableEntry;
objectCtx->status[iParm2].id = -id;
objectCtx->status[iParm2].dmaReq.vromAddr = 0;
objectCtx->slots[slot].id = -id;
objectCtx->slots[slot].dmaReq.vromAddr = 0;
fileTableEntry = &gObjectTable[id];
vromSize = fileTableEntry->vromEnd - fileTableEntry->vromStart;
// TODO: UB to cast void to u32
addr = ((u32)objectCtx->status[iParm2].segment) + vromSize;
addr = ((u32)objectCtx->slots[slot].segment) + vromSize;
addr = ALIGN16(addr);
return (void*)addr;
@@ -152,19 +165,19 @@ void Scene_CommandSpawnList(PlayState* play, SceneCmd* cmd) {
((gSaveContext.respawnFlag == 2) &&
(gSaveContext.respawn[RESPAWN_MODE_RETURN].playerParams == PLAYER_PARAMS(0xFF, PLAYER_INITMODE_TELESCOPE)))) {
// Skull Kid Object
Object_Spawn(&play->objectCtx, OBJECT_STK);
Object_SpawnPersistent(&play->objectCtx, OBJECT_STK);
return;
}
loadedCount = Object_Spawn(&play->objectCtx, OBJECT_LINK_CHILD);
nextObject = play->objectCtx.status[play->objectCtx.num].segment;
play->objectCtx.num = loadedCount;
play->objectCtx.spawnedObjectCount = loadedCount;
loadedCount = Object_SpawnPersistent(&play->objectCtx, OBJECT_LINK_CHILD);
nextObject = play->objectCtx.slots[play->objectCtx.numEntries].segment;
play->objectCtx.numEntries = loadedCount;
play->objectCtx.numPersistentEntries = loadedCount;
playerObjectId = gPlayerFormObjectIndices[GET_PLAYER_FORM];
gActorOverlayTable[0].initInfo->objectId = playerObjectId;
Object_Spawn(&play->objectCtx, playerObjectId);
Object_SpawnPersistent(&play->objectCtx, playerObjectId);
play->objectCtx.status[play->objectCtx.num].segment = nextObject;
play->objectCtx.slots[play->objectCtx.numEntries].segment = nextObject;
}
// SceneTableEntry Header Command 0x01: Actor List
@@ -224,10 +237,10 @@ void Scene_CommandSpecialFiles(PlayState* play, SceneCmd* cmd) {
{ SEGMENT_ROM_START(elf_message_ydan), SEGMENT_ROM_END(elf_message_ydan) },
};
if (cmd->specialFiles.subKeepIndex != 0) {
play->objectCtx.subKeepIndex = Object_Spawn(&play->objectCtx, cmd->specialFiles.subKeepIndex);
if (cmd->specialFiles.subKeepId != 0) {
play->objectCtx.subKeepSlot = Object_SpawnPersistent(&play->objectCtx, cmd->specialFiles.subKeepId);
// TODO: Segment number enum?
gSegments[0x05] = VIRTUAL_TO_PHYSICAL(play->objectCtx.status[play->objectCtx.subKeepIndex].segment);
gSegments[0x05] = VIRTUAL_TO_PHYSICAL(play->objectCtx.slots[play->objectCtx.subKeepSlot].segment);
}
if (cmd->specialFiles.naviQuestHintFileId != NAVI_QUEST_HINTS_NONE) {
@@ -255,28 +268,28 @@ void Scene_CommandObjectList(PlayState* play, SceneCmd* cmd) {
s32 i;
s32 j;
s32 k;
ObjectStatus* firstObject;
ObjectStatus* status;
ObjectStatus* status2;
ObjectEntry* firstObject;
ObjectEntry* entry;
ObjectEntry* invalidatedEntry;
s16* objectEntry;
void* nextPtr;
objectEntry = Lib_SegmentedToVirtual(cmd->objectList.segment);
k = 0;
i = play->objectCtx.spawnedObjectCount;
status = &play->objectCtx.status[i];
firstObject = play->objectCtx.status;
i = play->objectCtx.numPersistentEntries;
entry = &play->objectCtx.slots[i];
firstObject = &play->objectCtx.slots[0];
while (i < play->objectCtx.num) {
if (status->id != *objectEntry) {
status2 = &play->objectCtx.status[i];
while (i < play->objectCtx.numEntries) {
if (entry->id != *objectEntry) {
invalidatedEntry = &play->objectCtx.slots[i];
for (j = i; j < play->objectCtx.num; j++) {
status2->id = 0;
status2++;
for (j = i; j < play->objectCtx.numEntries; j++) {
invalidatedEntry->id = 0;
invalidatedEntry++;
}
play->objectCtx.num = i;
play->objectCtx.numEntries = i;
Actor_KillAllWithMissingObject(play, &play->actorCtx);
continue;
@@ -285,13 +298,13 @@ void Scene_CommandObjectList(PlayState* play, SceneCmd* cmd) {
i++;
k++;
objectEntry++;
status++;
entry++;
}
while (k < cmd->objectList.num) {
nextPtr = func_8012F73C(&play->objectCtx, i, *objectEntry);
if (i < OBJECT_EXCHANGE_BANK_MAX - 1) {
if (i < ARRAY_COUNT(play->objectCtx.slots) - 1) {
firstObject[i + 1].segment = nextPtr;
}
@@ -300,7 +313,7 @@ void Scene_CommandObjectList(PlayState* play, SceneCmd* cmd) {
objectEntry++;
}
play->objectCtx.num = i;
play->objectCtx.numEntries = i;
}
// SceneTableEntry Header Command 0x0C: Light List