summaryrefslogtreecommitdiff
path: root/src/code/z_room.c
diff options
context:
space:
mode:
authorengineer124 <47598039+engineer124@users.noreply.github.com>2023-03-23 09:36:09 +1100
committerGitHub <noreply@github.com>2023-03-23 09:36:09 +1100
commit2cb01b5b6a69635f7c8f554cf97442268aff28be (patch)
treea0603a4c4827fb4068d806d11638c1503c356650 /src/code/z_room.c
parent9bb978527f619abbedbc5119fa2811385b29c01e (diff)
z_room (1 non-matching) (#1143)
* begin room docs and decomp * match Room_DrawImageSingle * match Room_DrawImageMulti * Room_AllocateAndLoad non-matching * big improvements on Room_DrawCullable * match Room_AllocateAndLoad * improvement? * cleanup * comments * cleanup * small pr suggestions * PR Suggestions * cleanup sceneCmds * some PR * PR Suggestions * more PR Suggestions * col to collision
Diffstat (limited to 'src/code/z_room.c')
-rw-r--r--src/code/z_room.c591
1 files changed, 540 insertions, 51 deletions
diff --git a/src/code/z_room.c b/src/code/z_room.c
index eb615c409..3358bb300 100644
--- a/src/code/z_room.c
+++ b/src/code/z_room.c
@@ -1,62 +1,481 @@
#include "global.h"
-void Room_nop8012D510(PlayState* play, Room* room, UNK_PTR param_3, UNK_TYPE1 param_4) {
+void Room_Noop(PlayState* play, Room* room, Input* input, s32 arg3) {
}
-void Room_DrawType3Mesh(PlayState* play, Room* room, u32 flags) {
+void Room_DrawNone(PlayState* play, Room* room, u32 flags) {
}
-void Room_DrawType0Mesh(PlayState* play, Room* room, u32 flags) {
- RoomMeshType0* mesh;
+static Vec3f sZeroVec = { 0.0f, 0.0f, 0.0f };
+
+void Room_DrawNormal(PlayState* play, Room* room, u32 flags) {
+ RoomShapeNormal* roomShape;
+ RoomShapeDListsEntry* entry;
s32 i;
- RoomMeshType0Params* meshParams;
- GraphicsContext* gfxCtx;
- UNK_TYPE4 pad;
-
- gfxCtx = play->state.gfxCtx;
- if (flags & 1) {
- func_800BCBF4(&D_801C1D10, play);
- gSPSegment(gfxCtx->polyOpa.p++, 0x03, room->segment);
+
+ OPEN_DISPS(play->state.gfxCtx);
+
+ if (flags & ROOM_DRAW_OPA) {
+ func_800BCBF4(&sZeroVec, play);
+ gSPSegment(POLY_OPA_DISP++, 0x03, room->segment);
func_8012C268(play);
- gSPMatrix(gfxCtx->polyOpa.p++, &gIdentityMtx, G_MTX_MODELVIEW | G_MTX_LOAD);
+ gSPMatrix(POLY_OPA_DISP++, &gIdentityMtx, G_MTX_MODELVIEW | G_MTX_LOAD);
}
- if (flags & 2) {
- func_800BCC68(&D_801C1D10, play);
- gSPSegment(gfxCtx->polyXlu.p++, 0x03, room->segment);
+ if (flags & ROOM_DRAW_XLU) {
+ func_800BCC68(&sZeroVec, play);
+ gSPSegment(POLY_XLU_DISP++, 0x03, room->segment);
func_8012C2DC(play->state.gfxCtx);
- gSPMatrix(gfxCtx->polyXlu.p++, &gIdentityMtx, G_MTX_MODELVIEW | G_MTX_LOAD);
+ gSPMatrix(POLY_XLU_DISP++, &gIdentityMtx, G_MTX_MODELVIEW | G_MTX_LOAD);
}
- mesh = &room->mesh->type0;
- meshParams = Lib_SegmentedToVirtual(mesh->paramsStart);
- for (i = 0; i < mesh->count; i++) {
- if ((flags & 1) && (meshParams->opaqueDl != NULL)) {
- gSPDisplayList(gfxCtx->polyOpa.p++, meshParams->opaqueDl);
+ roomShape = &room->roomShape->normal;
+ entry = Lib_SegmentedToVirtual(roomShape->entries);
+ for (i = 0; i < roomShape->numEntries; i++) {
+ if ((flags & ROOM_DRAW_OPA) && (entry->opa != NULL)) {
+ gSPDisplayList(POLY_OPA_DISP++, entry->opa);
}
- if ((flags & 2) && (meshParams->translucentDl != NULL)) {
- gSPDisplayList(gfxCtx->polyXlu.p++, meshParams->translucentDl);
+ if ((flags & ROOM_DRAW_XLU) && (entry->xlu != NULL)) {
+ gSPDisplayList(POLY_XLU_DISP++, entry->xlu);
}
- meshParams++;
+ entry++;
}
+
+ CLOSE_DISPS(play->state.gfxCtx);
}
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_room/Room_DrawType2Mesh.s")
+typedef enum {
+ /* 0 */ ROOM_CULL_DEBUG_MODE_OFF,
+ /* 1 */ ROOM_CULL_DEBUG_MODE_UP_TO_TARGET,
+ /* 2 */ ROOM_CULL_DEBUG_MODE_ONLY_TARGET
+} RoomCullableDebugMode;
+
+typedef struct RoomShapeCullableEntryLinked {
+ /* 0x00 */ RoomShapeCullableEntry* entry;
+ /* 0x04 */ f32 boundsNearZ;
+ /* 0x08 */ struct RoomShapeCullableEntryLinked* prev;
+ /* 0x0C */ struct RoomShapeCullableEntryLinked* next;
+} RoomShapeCullableEntryLinked; // size = 0x10
+
+// TODO: 127 is an arbitrarily chosen number to make the stack sorta work
+#define ROOM_SHAPE_CULLABLE_MAX_ENTRIES 127
+
+#ifdef NON_MATCHING
+// Small regalloc, likely related to temp usage and scoping
+void Room_DrawCullable(PlayState* play, Room* room, u32 flags) {
+ RoomShapeCullable* roomShape;
+ RoomShapeCullableEntry* roomShapeCullableEntry;
+ RoomShapeCullableEntry* roomShapeCullableEntries;
+ RoomShapeCullableEntry* roomShapeCullableEntryIter;
+ Gfx* displayList;
+ f32 entryBoundsNearZ;
+ RoomShapeCullableEntryLinked linkedEntriesBuffer[ROOM_SHAPE_CULLABLE_MAX_ENTRIES];
+ RoomShapeCullableEntryLinked* head = NULL;
+ RoomShapeCullableEntryLinked* tail = NULL;
+ s32 var_a1;
+ RoomShapeCullableEntryLinked* iter;
+ RoomShapeCullableEntryLinked* insert;
+ f32 var_fv1;
+ s32 i;
+ Vec3f pos;
+ Vec3f projectedPos;
+ s32 pad2;
+
+ OPEN_DISPS(play->state.gfxCtx);
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_room/func_8012DEE8.s")
+ if (flags & ROOM_DRAW_OPA) {
+ func_800BCBF4(&sZeroVec, play);
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_room/func_8012E254.s")
+ //! TODO: Fake
+ if (1) {}
+ if (1) {}
+ if (1) {}
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_room/func_8012E32C.s")
+ gSPSegment(POLY_OPA_DISP++, 0x03, room->segment);
+ if (play->roomCtx.unk74 != NULL) {
+ gSPSegment(POLY_OPA_DISP++, 0x06, play->roomCtx.unk74);
+ }
+ func_8012C268(play);
+ gSPMatrix(POLY_OPA_DISP++, &gIdentityMtx, G_MTX_MODELVIEW | G_MTX_LOAD);
+ }
+
+ if (flags & ROOM_DRAW_XLU) {
+ func_800BCC68(&sZeroVec, play);
+ gSPSegment(POLY_XLU_DISP++, 0x03, room->segment);
+ if (play->roomCtx.unk74 != NULL) {
+ gSPSegment(POLY_XLU_DISP++, 0x06, play->roomCtx.unk74);
+ }
+ func_8012C2DC(play->state.gfxCtx);
+ gSPMatrix(POLY_XLU_DISP++, &gIdentityMtx, G_MTX_MODELVIEW | G_MTX_LOAD);
+ }
+
+ if ((room->enablePosLights != 0) || (MREG(93) != 0)) {
+ gSPSetGeometryMode(POLY_OPA_DISP++, G_LIGHTING_POSITIONAL);
+ gSPSetGeometryMode(POLY_XLU_DISP++, G_LIGHTING_POSITIONAL);
+ }
-void Room_DrawType1Mesh(PlayState* play, Room* room, u32 flags) {
- RoomMeshType1* mesh = &room->mesh->type1;
- if (mesh->format == 1) {
- func_8012DEE8(play, room, flags);
- } else if (mesh->format == 2) {
- func_8012E32C(play, room, flags);
+ roomShape = &room->roomShape->cullable;
+ roomShapeCullableEntry = Lib_SegmentedToVirtual(roomShape->entries);
+ insert = linkedEntriesBuffer;
+
+ roomShapeCullableEntries = roomShapeCullableEntry;
+
+ if (play->roomCtx.unk78 < 0) {
+ for (i = 0; i < roomShape->numEntries; i++, roomShapeCullableEntry++) {
+ if (R_ROOM_CULL_DEBUG_MODE != 0) {
+ if (((R_ROOM_CULL_DEBUG_MODE == ROOM_CULL_DEBUG_MODE_UP_TO_TARGET) &&
+ (i <= R_ROOM_CULL_DEBUG_TARGET)) ||
+ ((R_ROOM_CULL_DEBUG_MODE == ROOM_CULL_DEBUG_MODE_ONLY_TARGET) && (i == R_ROOM_CULL_DEBUG_TARGET))) {
+ if (flags & ROOM_DRAW_OPA) {
+ displayList = roomShapeCullableEntry->opa;
+ if (displayList != NULL) {
+ gSPDisplayList(POLY_OPA_DISP++, displayList);
+ }
+ }
+
+ if (flags & ROOM_DRAW_XLU) {
+ displayList = roomShapeCullableEntry->xlu;
+ if (displayList != NULL) {
+ gSPDisplayList(POLY_XLU_DISP++, displayList);
+ }
+ }
+ }
+ } else {
+ if (flags & ROOM_DRAW_OPA) {
+ displayList = roomShapeCullableEntry->opa;
+ if (displayList != NULL) {
+ gSPDisplayList(POLY_OPA_DISP++, displayList);
+ }
+ }
+
+ if (flags & ROOM_DRAW_XLU) {
+ displayList = roomShapeCullableEntry->xlu;
+ if (displayList != NULL) {
+ gSPDisplayList(POLY_XLU_DISP++, displayList);
+ }
+ }
+ }
+ }
+ } else {
+ f32 var_fa1 = 1.0f / play->projectionMtxFDiagonal.z; // sp54
+ s32 pad5;
+
+ // Pick and sort entries by depth
+ for (i = 0; i < roomShape->numEntries; i++, roomShapeCullableEntry++) {
+
+ // Project the entry position, to get the depth it is at.
+ pos.x = roomShapeCullableEntry->boundsSphereCenter.x;
+ pos.y = roomShapeCullableEntry->boundsSphereCenter.y;
+ pos.z = roomShapeCullableEntry->boundsSphereCenter.z;
+ SkinMatrix_Vec3fMtxFMultXYZ(&play->viewProjectionMtxF, &pos, &projectedPos);
+
+ projectedPos.z *= var_fa1;
+
+ var_fv1 = ABS_ALT(roomShapeCullableEntry->boundsSphereRadius);
+
+ // If the entry bounding sphere isn't fully before the rendered depth range
+ if (-var_fv1 < projectedPos.z) {
+
+ // Compute the depth of the nearest point in the entry's bounding sphere
+ entryBoundsNearZ = projectedPos.z - var_fv1;
+
+ // If the entry bounding sphere isn't fully beyond the rendered depth range
+ if (entryBoundsNearZ < play->lightCtx.zFar) {
+
+ // This entry will be rendered
+ insert->entry = roomShapeCullableEntry;
+
+ if (roomShapeCullableEntry->boundsSphereRadius < 0) {
+ insert->boundsNearZ = FLT_MAX;
+ } else {
+ insert->boundsNearZ = entryBoundsNearZ;
+ }
+
+ // Insert into the linked list, ordered by ascending depth of the nearest point in the bounding
+ // sphere
+ iter = head;
+ if (iter == NULL) {
+ head = tail = insert;
+ insert->prev = insert->next = NULL;
+ } else {
+ do {
+ if (insert->boundsNearZ < iter->boundsNearZ) {
+ break;
+ }
+ iter = iter->next;
+ } while (iter != NULL);
+
+ if (iter == NULL) {
+ insert->prev = tail;
+ insert->next = NULL;
+ tail->next = insert;
+ tail = insert;
+ } else {
+ insert->prev = iter->prev;
+ if (insert->prev == NULL) {
+ head = insert;
+ } else {
+ insert->prev->next = insert;
+ }
+ iter->prev = insert;
+ insert->next = iter;
+ }
+ }
+
+ insert++;
+ }
+ }
+ }
+
+ //! FAKE: Similar trick used in OoT
+ R_ROOM_CULL_NUM_ENTRIES = roomShape->numEntries & 0xFFFF & 0xFFFF & 0xFFFF;
+
+ // Draw entries, from nearest to furthest
+ i = 1;
+
+ if (flags & ROOM_DRAW_OPA) {
+ for (; head != NULL; head = head->next, i++) {
+ s32 pad3;
+ RoomShapeCullableEntry* roomShapeCullableEntry;
+
+ roomShapeCullableEntry = head->entry;
+
+ if (R_ROOM_CULL_DEBUG_MODE != ROOM_CULL_DEBUG_MODE_OFF) {
+ // Debug mode drawing
+
+ if (((R_ROOM_CULL_DEBUG_MODE == ROOM_CULL_DEBUG_MODE_UP_TO_TARGET) &&
+ (i <= R_ROOM_CULL_DEBUG_TARGET)) ||
+ ((R_ROOM_CULL_DEBUG_MODE == ROOM_CULL_DEBUG_MODE_ONLY_TARGET) &&
+ (i == R_ROOM_CULL_DEBUG_TARGET))) {
+
+ displayList = roomShapeCullableEntry->opa;
+ if (displayList != NULL) {
+ gSPDisplayList(POLY_OPA_DISP++, displayList);
+ }
+ }
+ } else {
+ displayList = roomShapeCullableEntry->opa;
+ if (displayList != NULL) {
+ gSPDisplayList(POLY_OPA_DISP++, displayList);
+ }
+ }
+ }
+ }
+
+ if (flags & ROOM_DRAW_XLU) {
+ for (; head != NULL; head = head->prev) {
+ f32 temp_fv0;
+ f32 temp_fv1;
+
+ roomShapeCullableEntry = head->entry;
+ displayList = roomShapeCullableEntry->xlu;
+
+ if (displayList != NULL) {
+ if (roomShapeCullableEntry->boundsSphereRadius & 1) {
+
+ temp_fv0 = head->boundsNearZ - (f32)(iREG(93) + 0xBB8);
+ temp_fv1 = iREG(94) + 0x7D0;
+
+ if (temp_fv0 < temp_fv1) {
+ if (temp_fv0 < 0.0f) {
+ var_a1 = 255;
+ } else {
+ var_a1 = 255 - (s32)((temp_fv0 / temp_fv1) * 255.0f);
+ }
+ gDPSetEnvColor(POLY_XLU_DISP++, 255, 255, 255, var_a1);
+ gSPDisplayList(POLY_XLU_DISP++, displayList);
+ }
+ } else {
+ gSPDisplayList(POLY_XLU_DISP++, displayList);
+ }
+ }
+ }
+ }
+
+ R_ROOM_CULL_USED_ENTRIES = i - 1;
+ }
+
+ CLOSE_DISPS(play->state.gfxCtx);
+}
+#else
+void Room_DrawCullable(PlayState* play, Room* room, u32 flags);
+#pragma GLOBAL_ASM("asm/non_matchings/code/z_room/Room_DrawCullable.s")
+#endif
+
+#define ROOM_IMAGE_NODRAW_BACKGROUND (1 << 0)
+#define ROOM_IMAGE_NODRAW_OPA (1 << 1)
+#define ROOM_IMAGE_NODRAW_XLU (1 << 2)
+
+void Room_DrawImageSingle(PlayState* play, Room* room, u32 flags) {
+ Camera* activeCam;
+ Gfx* gfx;
+ RoomShapeImageSingle* roomShape;
+ RoomShapeDListsEntry* entry;
+ u32 isFixedCamera;
+ u32 drawBackground;
+ u32 drawOpa;
+ u32 drawXlu;
+
+ OPEN_DISPS(play->state.gfxCtx);
+
+ activeCam = GET_ACTIVE_CAM(play);
+ isFixedCamera = false; // Condition is inferred from OoT
+ roomShape = &room->roomShape->image.single;
+ entry = Lib_SegmentedToVirtual(roomShape->base.entry);
+ drawBackground = (flags & ROOM_DRAW_OPA) && isFixedCamera && (roomShape->source != NULL) &&
+ !(R_ROOM_IMAGE_NODRAW_FLAGS & ROOM_IMAGE_NODRAW_BACKGROUND);
+ drawOpa = (flags & ROOM_DRAW_OPA) && (entry->opa != NULL) && !(R_ROOM_IMAGE_NODRAW_FLAGS & ROOM_IMAGE_NODRAW_OPA);
+ drawXlu = (flags & ROOM_DRAW_XLU) && (entry->xlu != NULL) && !(R_ROOM_IMAGE_NODRAW_FLAGS & ROOM_IMAGE_NODRAW_XLU);
+
+ if (drawOpa || drawBackground) {
+ gSPSegment(POLY_OPA_DISP++, 0x03, room->segment);
+
+ if (drawOpa) {
+ func_8012C28C(play->state.gfxCtx);
+ gSPMatrix(POLY_OPA_DISP++, &gIdentityMtx, G_MTX_MODELVIEW | G_MTX_LOAD);
+ gSPDisplayList(POLY_OPA_DISP++, entry->opa);
+ }
+
+ if (drawBackground) {
+ gSPLoadUcodeL(POLY_OPA_DISP++, gspS2DEX2_fifo);
+
+ gfx = POLY_OPA_DISP;
+
+ {
+ Vec3f quakeOffset;
+
+ Camera_GetQuakeOffset(&quakeOffset, activeCam);
+
+ Prerender_DrawBackground2D(
+ &gfx, roomShape->source, roomShape->tlut, roomShape->width, roomShape->height, roomShape->fmt,
+ roomShape->siz, roomShape->tlutMode, roomShape->tlutCount,
+ (quakeOffset.x + quakeOffset.z) * 1.2f + quakeOffset.y * 0.6f,
+ quakeOffset.y * 2.4f + (quakeOffset.x + quakeOffset.z) * 0.3f, 1.0f, 1.0f, 0);
+ }
+
+ POLY_OPA_DISP = gfx;
+
+ gSPLoadUcode(POLY_OPA_DISP++, SysUcode_GetUCode(), SysUcode_GetUCodeData());
+ }
+ }
+
+ if (drawXlu) {
+ gSPSegment(POLY_XLU_DISP++, 0x03, room->segment);
+ func_8012C2DC(play->state.gfxCtx);
+ gSPMatrix(POLY_XLU_DISP++, &gIdentityMtx, G_MTX_MODELVIEW | G_MTX_LOAD);
+ gSPDisplayList(POLY_XLU_DISP++, entry->xlu);
+ }
+
+ CLOSE_DISPS(play->state.gfxCtx);
+}
+
+RoomShapeImageMultiBgEntry* Room_GetImageMultiBgEntry(RoomShapeImageMulti* roomShapeImageMulti, PlayState* play) {
+ Camera* activeCam = GET_ACTIVE_CAM(play);
+ s32 bgCamIndex = activeCam->bgCamDataId;
+ s16 overrideBgCamIndex;
+ Player* player;
+ RoomShapeImageMultiBgEntry* bgEntry;
+ s32 i;
+
+ overrideBgCamIndex = ((BgCamFuncData*)BgCheck_GetBgCamFuncDataImpl(&play->colCtx, bgCamIndex, BGCHECK_SCENE))
+ ->roomImageOverrideBgCamIndex;
+ if (overrideBgCamIndex >= 0) {
+ bgCamIndex = overrideBgCamIndex;
+ }
+
+ player = GET_PLAYER(play);
+ player->actor.params = (player->actor.params & 0xFF00) | bgCamIndex;
+
+ bgEntry = Lib_SegmentedToVirtual(roomShapeImageMulti->backgrounds);
+ for (i = 0; i < roomShapeImageMulti->numBackgrounds; i++) {
+ if (bgEntry->bgCamIndex == bgCamIndex) {
+ return bgEntry;
+ }
+ bgEntry++;
+ }
+
+ __assert("../z_room.c", 849);
+
+ return NULL;
+}
+
+void Room_DrawImageMulti(PlayState* play, Room* room, u32 flags) {
+ Camera* activeCam;
+ Gfx* gfx;
+ RoomShapeImageMulti* roomShape;
+ RoomShapeImageMultiBgEntry* bgEntry;
+ RoomShapeDListsEntry* dListsEntry;
+ u32 isFixedCamera;
+ u32 drawBackground;
+ u32 drawOpa;
+ u32 drawXlu;
+
+ OPEN_DISPS(play->state.gfxCtx);
+
+ activeCam = GET_ACTIVE_CAM(play);
+ isFixedCamera = false; // Condition is inferred from OoT
+ roomShape = &room->roomShape->image.multi;
+ dListsEntry = Lib_SegmentedToVirtual(roomShape->base.entry);
+
+ bgEntry = Room_GetImageMultiBgEntry(roomShape, play);
+
+ drawBackground = (flags & ROOM_DRAW_OPA) && isFixedCamera && (bgEntry->source != NULL) &&
+ !(R_ROOM_IMAGE_NODRAW_FLAGS & ROOM_IMAGE_NODRAW_BACKGROUND);
+ drawOpa =
+ (flags & ROOM_DRAW_OPA) && (dListsEntry->opa != NULL) && !(R_ROOM_IMAGE_NODRAW_FLAGS & ROOM_IMAGE_NODRAW_OPA);
+ drawXlu =
+ (flags & ROOM_DRAW_XLU) && (dListsEntry->xlu != NULL) && !(R_ROOM_IMAGE_NODRAW_FLAGS & ROOM_IMAGE_NODRAW_XLU);
+
+ if (drawOpa || drawBackground) {
+ gSPSegment(POLY_OPA_DISP++, 0x03, room->segment);
+
+ if (drawOpa) {
+ func_8012C28C(play->state.gfxCtx);
+ gSPMatrix(POLY_OPA_DISP++, &gIdentityMtx, G_MTX_MODELVIEW | G_MTX_LOAD);
+ gSPDisplayList(POLY_OPA_DISP++, dListsEntry->opa);
+ }
+
+ if (drawBackground) {
+ gSPLoadUcodeL(POLY_OPA_DISP++, gspS2DEX2_fifo);
+
+ gfx = POLY_OPA_DISP;
+
+ {
+ Vec3f quakeOffset;
+
+ Camera_GetQuakeOffset(&quakeOffset, activeCam);
+ Prerender_DrawBackground2D(&gfx, bgEntry->source, bgEntry->tlut, bgEntry->width, bgEntry->height,
+ bgEntry->fmt, bgEntry->siz, bgEntry->tlutMode, bgEntry->tlutCount,
+ (quakeOffset.x + quakeOffset.z) * 1.2f + quakeOffset.y * 0.6f,
+ quakeOffset.y * 2.4f + (quakeOffset.x + quakeOffset.z) * 0.3f, 1.0f, 1.0f,
+ 0);
+ }
+
+ POLY_OPA_DISP = gfx;
+
+ gSPLoadUcode(POLY_OPA_DISP++, SysUcode_GetUCode(), SysUcode_GetUCodeData());
+ }
+ }
+
+ if (drawXlu) {
+ gSPSegment(POLY_XLU_DISP++, 0x03, room->segment);
+ func_8012C2DC(play->state.gfxCtx);
+ gSPMatrix(POLY_XLU_DISP++, &gIdentityMtx, G_MTX_MODELVIEW | G_MTX_LOAD);
+ gSPDisplayList(POLY_XLU_DISP++, dListsEntry->xlu);
+ }
+
+ CLOSE_DISPS(play->state.gfxCtx);
+}
+
+void Room_DrawImage(PlayState* play, Room* room, u32 flags) {
+ RoomShapeImageBase* roomShape = &room->roomShape->image.base;
+
+ if (roomShape->amountType == ROOM_SHAPE_IMAGE_AMOUNT_SINGLE) {
+ Room_DrawImageSingle(play, room, flags);
+ } else if (roomShape->amountType == ROOM_SHAPE_IMAGE_AMOUNT_MULTI) {
+ Room_DrawImageMulti(play, room, flags);
} else {
__assert("../z_room.c", 965);
}
@@ -64,31 +483,96 @@ void Room_DrawType1Mesh(PlayState* play, Room* room, u32 flags) {
void Room_Init(PlayState* play, RoomContext* roomCtx) {
s32 i;
+
roomCtx->curRoom.num = -1;
roomCtx->curRoom.segment = NULL;
roomCtx->unk78 = 1;
roomCtx->unk79 = 0;
- for (i = 0; i < 3; i++) {
+ for (i = 0; i < ARRAY_COUNT(roomCtx->unk7A); i++) {
roomCtx->unk7A[i] = 0;
}
}
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_room/Room_AllocateAndLoad.s")
+size_t Room_AllocateAndLoad(PlayState* play, RoomContext* roomCtx) {
+ size_t maxRoomSize = 0;
+ size_t roomSize;
+ s32 i;
+ s32 j;
+ s32 frontRoom;
+ s32 backRoom;
+ size_t frontRoomSize;
+ size_t backRoomSize;
+ size_t cumulRoomSize;
+ s32 pad[2];
+
+ {
+ RomFile* roomList = play->roomList;
+
+ for (i = 0; i < play->numRooms; i++) {
+ roomSize = roomList[i].vromEnd - roomList[i].vromStart;
+ maxRoomSize = MAX(roomSize, maxRoomSize);
+ }
+ }
+
+ if ((u32)play->doorCtx.numTransitionActors != 0) {
+ RomFile* roomList = play->roomList;
+ TransitionActorEntry* transitionActor = &play->doorCtx.transitionActorList[0];
+
+ for (j = 0; j < play->doorCtx.numTransitionActors; j++) {
+ frontRoom = transitionActor->sides[0].room;
+ backRoom = transitionActor->sides[1].room;
+ frontRoomSize = (frontRoom < 0) ? 0 : roomList[frontRoom].vromEnd - roomList[frontRoom].vromStart;
+ backRoomSize = (backRoom < 0) ? 0 : roomList[backRoom].vromEnd - roomList[backRoom].vromStart;
+ cumulRoomSize = (frontRoom != backRoom) ? frontRoomSize + backRoomSize : frontRoomSize;
+
+ maxRoomSize = MAX(cumulRoomSize, maxRoomSize);
+ transitionActor++;
+ }
+ }
+
+ roomCtx->roomMemPages[0] = THA_AllocEndAlign16(&play->state.heap, maxRoomSize);
+ if (roomCtx->roomMemPages[0] == NULL) {
+ __assert("../z_room.c", 1078);
+ }
+ roomCtx->roomMemPages[1] = (void*)((uintptr_t)roomCtx->roomMemPages[0] + maxRoomSize);
+ roomCtx->activeMemPage = 0;
+ roomCtx->status = 0;
+
+ if ((gSaveContext.respawnFlag != 0) && (gSaveContext.respawnFlag != -2) && (gSaveContext.respawnFlag != -7)) {
+ s32 respawnMode;
+
+ if ((gSaveContext.respawnFlag == -8) || (gSaveContext.respawnFlag == -5) || (gSaveContext.respawnFlag == -4) ||
+ ((gSaveContext.respawnFlag < 0) && (gSaveContext.respawnFlag != -1) && (gSaveContext.respawnFlag != -6))) {
+ respawnMode = RESPAWN_MODE_DOWN;
+ } else if (gSaveContext.respawnFlag < 0) {
+ respawnMode = RESPAWN_MODE_TOP;
+ } else {
+ respawnMode = gSaveContext.respawnFlag - 1;
+ }
+ frontRoom = gSaveContext.respawn[respawnMode].roomIndex;
+ } else {
+ frontRoom = play->setupEntranceList[play->curSpawn].room;
+ }
+
+ Room_StartRoomTransition(play, roomCtx, frontRoom);
+
+ return maxRoomSize;
+}
s32 Room_StartRoomTransition(PlayState* play, RoomContext* roomCtx, s32 index) {
- if (roomCtx->unk31 == 0) {
- s32 size;
+ if (roomCtx->status == 0) {
+ size_t size;
roomCtx->prevRoom = roomCtx->curRoom;
roomCtx->curRoom.num = index;
roomCtx->curRoom.segment = NULL;
- roomCtx->unk31 = 1;
+ roomCtx->status = 1;
size = play->roomList[index].vromEnd - play->roomList[index].vromStart;
- roomCtx->activeRoomVram = (void*)(ALIGN16((u32)roomCtx->roomMemPages[roomCtx->activeMemPage] -
+ roomCtx->activeRoomVram = (void*)(ALIGN16((uintptr_t)roomCtx->roomMemPages[roomCtx->activeMemPage] -
(size + 8) * roomCtx->activeMemPage - 7));
- osCreateMesgQueue(&roomCtx->loadQueue, roomCtx->loadMsg, 1);
+ osCreateMesgQueue(&roomCtx->loadQueue, roomCtx->loadMsg, ARRAY_COUNT(roomCtx->loadMsg));
DmaMgr_SendRequestImpl(&roomCtx->dmaRequest, roomCtx->activeRoomVram, play->roomList[index].vromStart, size, 0,
&roomCtx->loadQueue, NULL);
roomCtx->activeMemPage ^= 1;
@@ -100,14 +584,13 @@ s32 Room_StartRoomTransition(PlayState* play, RoomContext* roomCtx, s32 index) {
}
s32 Room_HandleLoadCallbacks(PlayState* play, RoomContext* roomCtx) {
- if (roomCtx->unk31 == 1) {
- if (!osRecvMesg(&roomCtx->loadQueue, NULL, OS_MESG_NOBLOCK)) {
- roomCtx->unk31 = 0;
+ if (roomCtx->status == 1) {
+ if (osRecvMesg(&roomCtx->loadQueue, NULL, OS_MESG_NOBLOCK) == 0) {
+ roomCtx->status = 0;
roomCtx->curRoom.segment = roomCtx->activeRoomVram;
- // TODO: Segment number enum
- gSegments[0x03] = VIRTUAL_TO_PHYSICAL(roomCtx->activeRoomVram);
+ gSegments[3] = VIRTUAL_TO_PHYSICAL(roomCtx->activeRoomVram);
- Scene_ProcessHeader(play, (SceneCmd*)roomCtx->curRoom.segment);
+ Scene_ExecuteCommands(play, roomCtx->curRoom.segment);
func_80123140(play, GET_PLAYER(play));
Actor_SpawnTransitionActors(play, &play->actorCtx);
@@ -127,11 +610,17 @@ s32 Room_HandleLoadCallbacks(PlayState* play, RoomContext* roomCtx) {
return 1;
}
+RoomDrawHandler sRoomDrawHandlers[] = {
+ Room_DrawNormal, // ROOM_SHAPE_TYPE_NORMAL
+ Room_DrawImage, // ROOM_SHAPE_TYPE_IMAGE
+ Room_DrawCullable, // ROOM_SHAPE_TYPE_CULLABLE
+ Room_DrawNone, // ROOM_SHAPE_TYPE_NONE
+};
+
void Room_Draw(PlayState* play, Room* room, u32 flags) {
if (room->segment != NULL) {
- // TODO: Segment number enum
- gSegments[0x03] = VIRTUAL_TO_PHYSICAL(room->segment);
- roomDrawFuncs[room->mesh->type0.type](play, room, flags);
+ gSegments[3] = VIRTUAL_TO_PHYSICAL(room->segment);
+ sRoomDrawHandlers[room->roomShape->base.type](play, room, flags);
}
return;
}