mirror of
https://github.com/zeldaret/mm.git
synced 2026-07-09 13:45:23 -04:00
Update Room Documentation (#1678)
* Implement Room Documentation * nit * Resolve Dragorn fixes (OoT) * Resolve Fig suggestions, fix comment wording (OoT) * hensldm nit
This commit is contained in:
@@ -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);
|
||||
|
||||
+4
-3
@@ -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))) {
|
||||
|
||||
+70
-29
@@ -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) {
|
||||
|
||||
+2
-2
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user