diff options
| author | mzxrules <mzxrules@gmail.com> | 2024-09-06 12:45:30 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-09-06 12:45:30 -0400 |
| commit | 629584b1bc5a3573bcc12a21029a6e6c53559d75 (patch) | |
| tree | 1fe6f3c7637eb660a690a4005af133100a7502b4 /src/code | |
| parent | e111552e73beda569c5b840e4164154fd4ec4c0d (diff) | |
Update Room Documentation (#1678)
* Implement Room Documentation
* nit
* Resolve Dragorn fixes (OoT)
* Resolve Fig suggestions, fix comment wording (OoT)
* hensldm nit
Diffstat (limited to 'src/code')
| -rw-r--r-- | src/code/z_map_disp.c | 4 | ||||
| -rw-r--r-- | src/code/z_play.c | 7 | ||||
| -rw-r--r-- | src/code/z_room.c | 99 | ||||
| -rw-r--r-- | src/code/z_scene.c | 4 |
4 files changed, 78 insertions, 36 deletions
diff --git a/src/code/z_map_disp.c b/src/code/z_map_disp.c index 7fbae707d..5718e1c84 100644 --- a/src/code/z_map_disp.c +++ b/src/code/z_map_disp.c @@ -509,7 +509,7 @@ void MapDisp_Init(PlayState* play) { sMapDisp.swapAnimTimer = 0; if (!Map_IsInBossScene(play)) { - sSceneNumRooms = play->numRooms; + sSceneNumRooms = play->roomList.count; } sMapDisp.texBuff0 = THA_AllocTailAlign16(&play->state.tha, 0x4000); sMapDisp.texBuff1 = THA_AllocTailAlign16(&play->state.tha, 0x4000); @@ -691,7 +691,7 @@ void MapDisp_InitMapData(PlayState* play, void* segmentAddress) { s32 i; if (!Map_IsInBossScene(play)) { - sSceneNumRooms = play->numRooms; + sSceneNumRooms = play->roomList.count; mapDataScene = Lib_SegmentedToVirtual(segmentAddress); sMapDataScene = *mapDataScene; mapDataRooms = Lib_SegmentedToVirtual(mapDataScene->rooms); diff --git a/src/code/z_play.c b/src/code/z_play.c index 188336c00..1c63b6a4b 100644 --- a/src/code/z_play.c +++ b/src/code/z_play.c @@ -993,7 +993,7 @@ void Play_UpdateMain(PlayState* this) { this->envCtx.fillScreen = false; } } else { - Room_HandleLoadCallbacks(this, &this->roomCtx); + Room_ProcessRoomRequest(this, &this->roomCtx); CollisionCheck_AT(this, &this->colChkCtx); CollisionCheck_OC(this, &this->colChkCtx); CollisionCheck_Damage(this, &this->colChkCtx); @@ -1597,7 +1597,7 @@ void Play_SpawnScene(PlayState* this, s32 sceneId, s32 spawn) { scene->unk_D = 0; gSegments[0x02] = OS_K0_TO_PHYSICAL(this->sceneSegment); Play_InitScene(this, spawn); - Room_AllocateAndLoad(this, &this->roomCtx); + Room_SetupFirstRoom(this, &this->roomCtx); } void Play_GetScreenPos(PlayState* this, Vec3f* worldPos, Vec3f* screenPos) { @@ -2311,7 +2311,8 @@ void Play_Init(GameState* thisx) { Actor_InitContext(this, &this->actorCtx, this->linkActorEntry); - while (!Room_HandleLoadCallbacks(this, &this->roomCtx)) {} + // Busyloop until the room loads + while (!Room_ProcessRoomRequest(this, &this->roomCtx)) {} if ((CURRENT_DAY != 0) && ((this->roomCtx.curRoom.behaviorType1 == ROOM_BEHAVIOR_TYPE1_1) || (this->roomCtx.curRoom.behaviorType1 == ROOM_BEHAVIOR_TYPE1_5))) { diff --git a/src/code/z_room.c b/src/code/z_room.c index 347844630..70573b0c8 100644 --- a/src/code/z_room.c +++ b/src/code/z_room.c @@ -481,8 +481,13 @@ void Room_Init(PlayState* play, RoomContext* roomCtx) { } } -size_t Room_AllocateAndLoad(PlayState* play, RoomContext* roomCtx) { - size_t maxRoomSize = 0; +/** + * Allocates memory for rooms and fetches the first room that the player will spawn into. + * + * @return u32 size of the buffer reserved for room data + */ +size_t Room_SetupFirstRoom(PlayState* play, RoomContext* roomCtx) { + size_t roomBufferSize = 0; size_t roomSize; s32 i; s32 j; @@ -493,17 +498,19 @@ size_t Room_AllocateAndLoad(PlayState* play, RoomContext* roomCtx) { size_t cumulRoomSize; s32 pad[2]; + // Set roomBufferSize to the largest room { - RomFile* roomList = play->roomList; + RomFile* roomList = play->roomList.romFiles; - for (i = 0; i < play->numRooms; i++) { + for (i = 0; i < play->roomList.count; i++) { roomSize = roomList[i].vromEnd - roomList[i].vromStart; - maxRoomSize = MAX(roomSize, maxRoomSize); + roomBufferSize = MAX(roomSize, roomBufferSize); } } + // If there any rooms are connected, find their combined size and update roomBufferSize if larger if ((u32)play->transitionActors.count != 0) { - RomFile* roomList = play->roomList; + RomFile* roomList = play->roomList.romFiles; TransitionActorEntry* transitionActor = &play->transitionActors.list[0]; for (j = 0; j < play->transitionActors.count; j++) { @@ -513,17 +520,17 @@ size_t Room_AllocateAndLoad(PlayState* play, RoomContext* roomCtx) { backRoomSize = (backRoom < 0) ? 0 : roomList[backRoom].vromEnd - roomList[backRoom].vromStart; cumulRoomSize = (frontRoom != backRoom) ? frontRoomSize + backRoomSize : frontRoomSize; - maxRoomSize = MAX(cumulRoomSize, maxRoomSize); + roomBufferSize = MAX(cumulRoomSize, roomBufferSize); transitionActor++; } } - roomCtx->roomMemPages[0] = THA_AllocTailAlign16(&play->state.tha, maxRoomSize); - if (roomCtx->roomMemPages[0] == NULL) { + roomCtx->bufPtrs[0] = THA_AllocTailAlign16(&play->state.tha, roomBufferSize); + if (roomCtx->bufPtrs[0] == NULL) { _dbg_hungup("../z_room.c", 1078); } - roomCtx->roomMemPages[1] = (void*)((uintptr_t)roomCtx->roomMemPages[0] + maxRoomSize); - roomCtx->activeMemPage = 0; + roomCtx->bufPtrs[1] = (void*)((uintptr_t)roomCtx->bufPtrs[0] + roomBufferSize); + roomCtx->activeBufPage = 0; roomCtx->status = 0; if ((gSaveContext.respawnFlag != 0) && (gSaveContext.respawnFlag != -2) && (gSaveContext.respawnFlag != -7)) { @@ -542,12 +549,31 @@ size_t Room_AllocateAndLoad(PlayState* play, RoomContext* roomCtx) { frontRoom = play->setupEntranceList[play->curSpawn].room; } - Room_StartRoomTransition(play, roomCtx, frontRoom); + // Load into a room for the first time. + // Since curRoom was initialized to `room` = -1 and `segment` = NULL in Play_InitScene, the previous room + // will also be initialized to the nulled state when this function completes. + Room_RequestNewRoom(play, roomCtx, frontRoom); - return maxRoomSize; + return roomBufferSize; } -s32 Room_StartRoomTransition(PlayState* play, RoomContext* roomCtx, s32 index) { +/** + * Tries to create an asynchronous request to transfer room data into memory. + * If successful, the requested room will be loaded into memory and becomes the new current room; the room that was + * current before becomes the previous room. + * + * Room_RequestNewRoom will be blocked from loading new rooms until Room_ProcessRoomRequest completes room + * initialization. + * + * Calling Room_RequestNewRoom outside of Room_SetupFirstRoom will allow for two rooms being initialized simultaneously. + * This allows an actor like ACTOR_EN_HOLL to seamlessly swap the two rooms as the player moves between them. Calling + * Room_FinishRoomChange afterward will finalize the room swap. + * + * @param roomNum is the id of the room to load. roomNum must NOT be the same id as curRoom.num, since this will create + * duplicate actor instances that cannot be cleaned up by calling Room_FinishRoomChange + * @returns bool false if the request could not be created. + */ +s32 Room_RequestNewRoom(PlayState* play, RoomContext* roomCtx, s32 index) { if (roomCtx->status == 0) { size_t size; @@ -556,33 +582,40 @@ s32 Room_StartRoomTransition(PlayState* play, RoomContext* roomCtx, s32 index) { roomCtx->curRoom.segment = NULL; roomCtx->status = 1; - size = play->roomList[index].vromEnd - play->roomList[index].vromStart; - roomCtx->activeRoomVram = (void*)(ALIGN16((uintptr_t)roomCtx->roomMemPages[roomCtx->activeMemPage] - - (size + 8) * roomCtx->activeMemPage - 7)); + size = play->roomList.romFiles[index].vromEnd - play->roomList.romFiles[index].vromStart; + roomCtx->roomRequestAddr = (void*)(ALIGN16((uintptr_t)roomCtx->bufPtrs[roomCtx->activeBufPage] - + (size + 8) * roomCtx->activeBufPage - 7)); osCreateMesgQueue(&roomCtx->loadQueue, roomCtx->loadMsg, ARRAY_COUNT(roomCtx->loadMsg)); - DmaMgr_RequestAsync(&roomCtx->dmaRequest, roomCtx->activeRoomVram, play->roomList[index].vromStart, size, 0, - &roomCtx->loadQueue, NULL); - roomCtx->activeMemPage ^= 1; + DmaMgr_RequestAsync(&roomCtx->dmaRequest, roomCtx->roomRequestAddr, play->roomList.romFiles[index].vromStart, + size, 0, &roomCtx->loadQueue, NULL); + roomCtx->activeBufPage ^= 1; - return 1; + return true; } - return 0; + return false; } -s32 Room_HandleLoadCallbacks(PlayState* play, RoomContext* roomCtx) { +/** + * Completes room initialization for the room requested by a call to Room_RequestNewRoom. + * This function does not block the thread if the room data is still being transferred. + * + * @returns bool false if a dma transfer is in progress. + */ +s32 Room_ProcessRoomRequest(PlayState* play, RoomContext* roomCtx) { if (roomCtx->status == 1) { if (osRecvMesg(&roomCtx->loadQueue, NULL, OS_MESG_NOBLOCK) == 0) { roomCtx->status = 0; - roomCtx->curRoom.segment = roomCtx->activeRoomVram; - gSegments[0x03] = OS_K0_TO_PHYSICAL(roomCtx->activeRoomVram); + roomCtx->curRoom.segment = roomCtx->roomRequestAddr; + gSegments[0x03] = OS_K0_TO_PHYSICAL(roomCtx->curRoom.segment); Scene_ExecuteCommands(play, roomCtx->curRoom.segment); func_80123140(play, GET_PLAYER(play)); Actor_SpawnTransitionActors(play, &play->actorCtx); - if (((play->sceneId != SCENE_IKANA) || (roomCtx->curRoom.num != 1)) && (play->sceneId != SCENE_IKNINSIDE)) { + if (!(((play->sceneId == SCENE_IKANA) && (roomCtx->curRoom.num == 1)) || + (play->sceneId == SCENE_IKNINSIDE))) { play->envCtx.lightSettingOverride = LIGHT_SETTING_OVERRIDE_NONE; play->envCtx.lightBlendOverride = LIGHT_BLEND_OVERRIDE_NONE; } @@ -591,11 +624,11 @@ s32 Room_HandleLoadCallbacks(PlayState* play, RoomContext* roomCtx) { Environment_StopStormNatureAmbience(play); } } else { - return 0; + return false; } } - return 1; + return true; } RoomDrawHandler sRoomDrawHandlers[] = { @@ -613,9 +646,17 @@ void Room_Draw(PlayState* play, Room* room, u32 flags) { return; } -void func_8012EBF8(PlayState* play, RoomContext* roomCtx) { +/** + * Finalizes a swap between two rooms. + * + * When a new room is created with Room_RequestNewRoom, the previous room and its actors remain in memory. This allows + * an actor like ACTOR_EN_HOLL to seamlessly swap the two rooms as the player moves between them. + */ +void Room_FinishRoomChange(PlayState* play, RoomContext* roomCtx) { + // Delete the previous room roomCtx->prevRoom.num = -1; roomCtx->prevRoom.segment = NULL; + func_800BA798(play, &play->actorCtx); Actor_SpawnTransitionActors(play, &play->actorCtx); if (roomCtx->curRoom.num > -1) { diff --git a/src/code/z_scene.c b/src/code/z_scene.c index 175a0abd4..e7a2c50db 100644 --- a/src/code/z_scene.c +++ b/src/code/z_scene.c @@ -220,8 +220,8 @@ void Scene_CommandCollisionHeader(PlayState* play, SceneCmd* cmd) { // SceneTableEntry Header Command 0x04: Room List void Scene_CommandRoomList(PlayState* play, SceneCmd* cmd) { - play->numRooms = cmd->roomList.num; - play->roomList = Lib_SegmentedToVirtual(cmd->roomList.segment); + play->roomList.count = cmd->roomList.num; + play->roomList.romFiles = Lib_SegmentedToVirtual(cmd->roomList.segment); } // SceneTableEntry Header Command 0x06: Entrance List |
