From c0cf83a814d13a9a07a2ca260203134fc4c5b735 Mon Sep 17 00:00:00 2001 From: Dragorn421 Date: Thu, 1 Sep 2022 01:28:51 +0200 Subject: [PATCH] Doc room drawing (#1283) * (wip) some doc on room draw2 * doc room_draw2 * do what can be done for `func_80095AA0` * wip * more cleanup around Room_DrawBackground2D * format" * commit to naming things * move forward declarations of draw handlers to draw handlers array * two z_room regs * `R_MESH2_` -> `R_ROOM_CULL_` * offset -> quakeOffset * kb -> kB * Improve cull mesh type doc * `Sphere16` MeshHeaderCullEntry.bounds * Revert "`Sphere16` MeshHeaderCullEntry.bounds" (ZAPD...) This reverts commit cbe55e8090f2fcd00be3a81e64ae133254417599. * Mesh header type: "cull" -> "cullable" * Reword some Cullable doc Co-authored-by: EllipticEllipsis * `boundsSphere*` for now for the can't-be-`Sphere16 bounds` * Improve the PrerenderMulti bgCamInfo usage situation * Comment on `overrideBgCamIndex` * "are left" -> "remain" * enum and defines for room draw debug regs * drawBg -> drawBackground * "mesh header all" -> "mesh header normal" :shrug: * array_count back to define * Name some temps a lot less specifically * "mesh header" -> "room shape" * "Room shape prerender" -> "Room shape image" * `ROOM_SHAPE_IMAGE_FORMAT_` -> `ROOM_SHAPE_IMAGE_AMOUNT_` * `RoomShapeImageMultiBackgroundEntry` -> `RoomShapeImageMultiBgEntry` * Remove references to "header" (old "mesh header" name) * Axe variable names Co-authored-by: EllipticEllipsis --- include/functions.h | 6 +- include/regs.h | 6 + include/z64.h | 2 +- include/z64bgcheck.h | 2 +- include/z64camera.h | 2 +- include/z64scene.h | 110 ++-- src/code/z_camera.c | 10 +- src/code/z_play.c | 4 +- src/code/z_room.c | 528 ++++++++++-------- src/code/z_scene.c | 6 +- .../ovl_kaleido_scope/z_kaleido_map_PAL.c | 13 +- 11 files changed, 380 insertions(+), 309 deletions(-) diff --git a/include/functions.h b/include/functions.h index fe1e99d357..e7ba5818c2 100644 --- a/include/functions.h +++ b/include/functions.h @@ -1132,9 +1132,9 @@ Gfx* Gfx_TwoTexScrollEnvColor(GraphicsContext* gfxCtx, s32 tile1, u32 x1, u32 y1 Gfx* Gfx_EnvColor(GraphicsContext* gfxCtx, s32 r, s32 g, s32 b, s32 a); void Gfx_SetupFrame(GraphicsContext* gfxCtx, u8 r, u8 g, u8 b); void func_80095974(GraphicsContext* gfxCtx); -void func_80095AA0(PlayState* play, Room* room, Input* arg2, UNK_TYPE arg3); -void func_8009638C(Gfx** displayList, void* source, void* tlut, u16 width, u16 height, u8 fmt, u8 siz, u16 mode0, - u16 tlutCount, f32 frameX, f32 frameY); +void func_80095AA0(PlayState* play, Room* room, Input* input, s32 arg3); +void Room_DrawBackground2D(Gfx** gfxP, void* tex, void* tlut, u16 width, u16 height, u8 fmt, u8 siz, u16 tlutMode, + u16 tlutCount, f32 offsetX, f32 offsetY); void func_80096FD4(PlayState* play, Room* room); u32 func_80096FE8(PlayState* play, RoomContext* roomCtx); s32 func_8009728C(PlayState* play, RoomContext* roomCtx, s32 roomNum); diff --git a/include/regs.h b/include/regs.h index e3db0ebf90..d9b0708fd9 100644 --- a/include/regs.h +++ b/include/regs.h @@ -48,6 +48,8 @@ #define R_ENV_TIME_SPEED_OLD REG(15) // Most likely used during development. Unused in the final game. #define R_RUN_SPEED_LIMIT REG(45) #define R_ENABLE_ARENA_DBG SREG(0) +#define R_ROOM_IMAGE_NODRAW_FLAGS SREG(25) +#define R_ROOM_BG2D_FORCE_SCALEBG SREG(26) #define R_UPDATE_RATE SREG(30) #define R_ENABLE_AUDIO_DBG SREG(36) #define R_FB_FILTER_TYPE SREG(80) @@ -131,6 +133,10 @@ #define R_TEXTBOX_TEXHEIGHT_TARGET XREG(77) #define R_ENV_LIGHT1_DIR(i) cREG(3 + (i)) #define R_ENV_LIGHT2_DIR(i) cREG(6 + (i)) +#define R_ROOM_CULL_DEBUG_MODE iREG(86) +#define R_ROOM_CULL_NUM_ENTRIES iREG(87) +#define R_ROOM_CULL_USED_ENTRIES iREG(88) +#define R_ROOM_CULL_DEBUG_TARGET iREG(89) #define R_B_LABEL_DD WREG(0) #define R_OW_MINIMAP_X WREG(29) #define R_OW_MINIMAP_Y WREG(30) diff --git a/include/z64.h b/include/z64.h index c9df02d0e2..6fb89528a9 100644 --- a/include/z64.h +++ b/include/z64.h @@ -872,7 +872,7 @@ typedef struct { /* 0x03 */ u8 behaviorType1; /* 0x04 */ s8 echo; /* 0x05 */ u8 lensMode; - /* 0x08 */ MeshHeader* meshHeader; // original name: "ground_shape" + /* 0x08 */ RoomShape* roomShape; // original name: "ground_shape" /* 0x0C */ void* segment; /* 0x10 */ char unk_10[0x4]; } Room; // size = 0x14 diff --git a/include/z64bgcheck.h b/include/z64bgcheck.h index aa8a6859ce..8b52364061 100644 --- a/include/z64bgcheck.h +++ b/include/z64bgcheck.h @@ -64,7 +64,7 @@ typedef struct { /* 0x06 */ Vec3s rot; /* 0x0C */ s16 fov; /* 0x0E */ union { - s16 jfifId; + s16 roomImageOverrideBgCamIndex; s16 timer; s16 flags; }; diff --git a/include/z64camera.h b/include/z64camera.h index ab87799110..5ea1d97599 100644 --- a/include/z64camera.h +++ b/include/z64camera.h @@ -813,7 +813,7 @@ typedef struct { /* 0x0 */ Vec3s rot; /* 0x6 */ s16 fov; /* 0x8 */ s16 updDirTimer; - /* 0xA */ s16 jfifId; + /* 0xA */ s16 roomImageOverrideBgCamIndex; } Fixed3ReadWriteData; // size = 0xC typedef struct { diff --git a/include/z64scene.h b/include/z64scene.h index 3c5afdf875..ede0d52492 100644 --- a/include/z64scene.h +++ b/include/z64scene.h @@ -58,44 +58,44 @@ typedef struct { /* 0x04 */ Vec3s* points; // Segment Address to the array of points } Path; // size = 0x8 -// Mesh headers +// Room shapes typedef enum { - /* 0 */ MESH_HEADER_TYPE_0, - /* 1 */ MESH_HEADER_TYPE_1, - /* 2 */ MESH_HEADER_TYPE_2, - /* 3 */ MESH_HEADER_TYPE_MAX -} MeshHeaderType; + /* 0 */ ROOM_SHAPE_TYPE_NORMAL, + /* 1 */ ROOM_SHAPE_TYPE_IMAGE, + /* 2 */ ROOM_SHAPE_TYPE_CULLABLE, + /* 3 */ ROOM_SHAPE_TYPE_MAX +} RoomShapeType; typedef struct { /* 0x00 */ u8 type; -} MeshHeaderBase; // size = 0x01 +} RoomShapeBase; // size = 0x01 typedef struct { /* 0x00 */ Gfx* opa; /* 0x04 */ Gfx* xlu; -} MeshHeader01Entry; // size = 0x08 +} RoomShapeDListsEntry; // size = 0x08 typedef struct { - /* 0x00 */ MeshHeaderBase base; + /* 0x00 */ RoomShapeBase base; /* 0x01 */ u8 numEntries; - /* 0x04 */ MeshHeader01Entry* entries; - /* 0x08 */ MeshHeader01Entry* entriesEnd; -} MeshHeader0; // size = 0x0C + /* 0x04 */ RoomShapeDListsEntry* entries; + /* 0x08 */ RoomShapeDListsEntry* entriesEnd; +} RoomShapeNormal; // size = 0x0C typedef enum { - /* 1 */ MESH_HEADER1_FORMAT_SINGLE = 1, - /* 2 */ MESH_HEADER1_FORMAT_MULTI -} MeshHeader1Format; + /* 1 */ ROOM_SHAPE_IMAGE_AMOUNT_SINGLE = 1, + /* 2 */ ROOM_SHAPE_IMAGE_AMOUNT_MULTI +} RoomShapeImageAmountType; typedef struct { - /* 0x00 */ MeshHeaderBase base; - /* 0x01 */ u8 format; // MeshHeader1Format - /* 0x04 */ MeshHeader01Entry* entry; -} MeshHeader1Base; // size = 0x08 + /* 0x00 */ RoomShapeBase base; + /* 0x01 */ u8 amountType; // RoomShapeImageAmountType + /* 0x04 */ RoomShapeDListsEntry* entry; +} RoomShapeImageBase; // size = 0x08 typedef struct { - /* 0x00 */ MeshHeader1Base base; + /* 0x00 */ RoomShapeImageBase base; /* 0x08 */ void* source; /* 0x0C */ u32 unk_0C; /* 0x10 */ void* tlut; @@ -103,13 +103,13 @@ typedef struct { /* 0x16 */ u16 height; /* 0x18 */ u8 fmt; /* 0x19 */ u8 siz; - /* 0x1A */ u16 mode0; + /* 0x1A */ u16 tlutMode; /* 0x1C */ u16 tlutCount; -} MeshHeader1Single; // size = 0x20 +} RoomShapeImageSingle; // size = 0x20 typedef struct { /* 0x00 */ u16 unk_00; - /* 0x02 */ u8 id; + /* 0x02 */ u8 bgCamIndex; // for which bg cam index is this entry for /* 0x04 */ void* source; /* 0x08 */ u32 unk_0C; /* 0x0C */ void* tlut; @@ -117,44 +117,52 @@ typedef struct { /* 0x12 */ u16 height; /* 0x14 */ u8 fmt; /* 0x15 */ u8 siz; - /* 0x16 */ u16 mode0; + /* 0x16 */ u16 tlutMode; /* 0x18 */ u16 tlutCount; -} BgImage; // size = 0x1C +} RoomShapeImageMultiBgEntry; // size = 0x1C typedef struct { - /* 0x00 */ MeshHeader1Base base; - /* 0x08 */ u8 count; - /* 0x0C */ BgImage* list; -} MeshHeader1Multi; // size = 0x10 + /* 0x00 */ RoomShapeImageBase base; + /* 0x08 */ u8 numBackgrounds; + /* 0x0C */ RoomShapeImageMultiBgEntry* backgrounds; +} RoomShapeImageMulti; // size = 0x10 typedef struct { - /* 0x00 */ Vec3s pos; - /* 0x06 */ s16 unk_06; + /* 0x00 */ Vec3s boundsSphereCenter; + /* 0x06 */ s16 boundsSphereRadius; /* 0x08 */ Gfx* opa; /* 0x0C */ Gfx* xlu; -} MeshHeader2Entry; // size = 0x10 +} RoomShapeCullableEntry; // size = 0x10 + +#define ROOM_SHAPE_CULLABLE_MAX_ENTRIES 64 typedef struct { - /* 0x00 */ MeshHeaderBase base; + /* 0x00 */ RoomShapeBase base; /* 0x01 */ u8 numEntries; - /* 0x04 */ MeshHeader2Entry* entries; - /* 0x08 */ MeshHeader2Entry* entriesEnd; -} MeshHeader2; // size = 0x0C + /* 0x04 */ RoomShapeCullableEntry* entries; + /* 0x08 */ RoomShapeCullableEntry* entriesEnd; +} RoomShapeCullable; // size = 0x0C typedef union { - MeshHeaderBase base; - MeshHeader0 meshHeader0; - MeshHeader1Base meshHeader1Base; - MeshHeader1Single meshHeader1Single; - MeshHeader1Multi meshHeader1Multi; - MeshHeader2 meshHeader2; -} MeshHeader; // "Ground Shape" + RoomShapeBase base; + RoomShapeNormal normal; + union { + RoomShapeImageBase base; + RoomShapeImageSingle single; + RoomShapeImageMulti multi; + } image; + RoomShapeCullable cullable; +} RoomShape; // "Ground Shape" // TODO update ZAPD -typedef MeshHeader01Entry PolygonDlist; -typedef MeshHeader0 PolygonType0; -typedef MeshHeader2Entry PolygonDlist2; -typedef MeshHeader2 PolygonType2; +typedef RoomShapeDListsEntry PolygonDlist; +typedef RoomShapeNormal PolygonType0; +typedef RoomShapeImageSingle MeshHeader1Single; +typedef RoomShapeImageMultiBgEntry BgImage; +typedef RoomShapeImageMulti MeshHeader1Multi; +typedef RoomShapeCullableEntry PolygonDlist2; +typedef RoomShapeCullable PolygonType2; +#define SCENE_CMD_MESH SCENE_CMD_ROOM_SHAPE #define ROOM_DRAW_OPA (1 << 0) #define ROOM_DRAW_XLU (1 << 1) @@ -228,7 +236,7 @@ typedef struct { typedef struct { /* 0x00 */ u8 code; /* 0x01 */ u8 data1; - /* 0x04 */ MeshHeaderBase* data; + /* 0x04 */ RoomShapeBase* data; } SCmdMesh; typedef struct { @@ -474,7 +482,7 @@ typedef enum { /* 0x07 */ SCENE_CMD_ID_SPECIAL_FILES, /* 0x08 */ SCENE_CMD_ID_ROOM_BEHAVIOR, /* 0x09 */ SCENE_CMD_ID_UNDEFINED_9, - /* 0x0A */ SCENE_CMD_ID_MESH_HEADER, + /* 0x0A */ SCENE_CMD_ID_ROOM_SHAPE, /* 0x0B */ SCENE_CMD_ID_OBJECT_LIST, /* 0x0C */ SCENE_CMD_ID_LIGHT_LIST, /* 0x0D */ SCENE_CMD_ID_PATH_LIST, @@ -524,8 +532,8 @@ typedef enum { #define SCENE_CMD_UNK_09() \ { SCENE_CMD_ID_UNDEFINED_9, 0, CMD_W(0) } -#define SCENE_CMD_MESH(meshHeader) \ - { SCENE_CMD_ID_MESH_HEADER, 0, CMD_PTR(meshHeader) } +#define SCENE_CMD_ROOM_SHAPE(roomShape) \ + { SCENE_CMD_ID_ROOM_SHAPE, 0, CMD_PTR(roomShape) } #define SCENE_CMD_OBJECT_LIST(numObjects, objectList) \ { SCENE_CMD_ID_OBJECT_LIST, numObjects, CMD_PTR(objectList) } diff --git a/src/code/z_camera.c b/src/code/z_camera.c index a46705140f..0607a1c5cd 100644 --- a/src/code/z_camera.c +++ b/src/code/z_camera.c @@ -4059,7 +4059,7 @@ s32 Camera_Fixed3(Camera* camera) { *eye = *eyeNext; rwData->rot = bgCamFuncData->rot; rwData->fov = bgCamFuncData->fov; - rwData->jfifId = bgCamFuncData->jfifId; + rwData->roomImageOverrideBgCamIndex = bgCamFuncData->roomImageOverrideBgCamIndex; if (rwData->fov == -1) { rwData->fov = 6000; } @@ -4078,9 +4078,9 @@ s32 Camera_Fixed3(Camera* camera) { camera->animState++; } - if (bgCamFuncData->jfifId != rwData->jfifId) { - osSyncPrintf("camera: position change %d \n", rwData->jfifId); - rwData->jfifId = bgCamFuncData->jfifId; + if (bgCamFuncData->roomImageOverrideBgCamIndex != rwData->roomImageOverrideBgCamIndex) { + osSyncPrintf("camera: position change %d \n", rwData->roomImageOverrideBgCamIndex); + rwData->roomImageOverrideBgCamIndex = bgCamFuncData->roomImageOverrideBgCamIndex; rwData->updDirTimer = 5; } @@ -6984,7 +6984,7 @@ void func_80057FC4(Camera* camera) { if (camera != &camera->play->mainCamera) { camera->prevSetting = camera->setting = CAM_SET_FREE0; camera->unk_14C &= ~0x4; - } else if (camera->play->roomCtx.curRoom.meshHeader->base.type != MESH_HEADER_TYPE_1) { + } else if (camera->play->roomCtx.curRoom.roomShape->base.type != ROOM_SHAPE_TYPE_IMAGE) { switch (camera->play->roomCtx.curRoom.behaviorType1) { case ROOM_BEHAVIOR_TYPE1_1: Camera_ChangeDoorCam(camera, NULL, -99, 0, 0, 18, 10); diff --git a/src/code/z_play.c b/src/code/z_play.c index ceeb68f75b..b191dd1cfa 100644 --- a/src/code/z_play.c +++ b/src/code/z_play.c @@ -1731,8 +1731,8 @@ void Play_TriggerRespawn(PlayState* this) { s32 Play_CamIsNotFixed(PlayState* this) { // SCENE_CAM_TYPE_FIXED_SHOP_VIEWPOINT was probably intended to be in this condition, - // but the scene mesh header handles all shop cases regardless - return (this->roomCtx.curRoom.meshHeader->base.type != MESH_HEADER_TYPE_1) && + // but the room shape type check handles all shop cases regardless + return (this->roomCtx.curRoom.roomShape->base.type != ROOM_SHAPE_TYPE_IMAGE) && (R_SCENE_CAM_TYPE != SCENE_CAM_TYPE_FIXED_TOGGLE_VIEWPOINT) && (R_SCENE_CAM_TYPE != SCENE_CAM_TYPE_FIXED) && (R_SCENE_CAM_TYPE != SCENE_CAM_TYPE_FIXED_MARKET) && (this->sceneId != SCENE_HAIRAL_NIWA); } diff --git a/src/code/z_room.c b/src/code/z_room.c index 3a6b33d4ea..add5101380 100644 --- a/src/code/z_room.c +++ b/src/code/z_room.c @@ -1,10 +1,6 @@ #include "global.h" #include "vt.h" -void Room_Draw0(PlayState* play, Room* room, u32 flags); -void Room_Draw2(PlayState* play, Room* room, u32 flags); -void Room_Draw1(PlayState* play, Room* room, u32 flags); - Vec3f D_801270A0 = { 0.0f, 0.0f, 0.0f }; // unused @@ -22,19 +18,23 @@ Gfx D_801270B0[] = { gsSPEndDisplayList(), }; -void (*sRoomDrawHandlers[MESH_HEADER_TYPE_MAX])(PlayState* play, Room* room, u32 flags) = { - Room_Draw0, - Room_Draw1, - Room_Draw2, +void Room_DrawNormal(PlayState* play, Room* room, u32 flags); +void Room_DrawImage(PlayState* play, Room* room, u32 flags); +void Room_DrawCullable(PlayState* play, Room* room, u32 flags); + +void (*sRoomDrawHandlers[ROOM_SHAPE_TYPE_MAX])(PlayState* play, Room* room, u32 flags) = { + Room_DrawNormal, // ROOM_SHAPE_TYPE_NORMAL + Room_DrawImage, // ROOM_SHAPE_TYPE_IMAGE + Room_DrawCullable, // ROOM_SHAPE_TYPE_CULLABLE }; -void func_80095AA0(PlayState* play, Room* room, Input* arg2, UNK_TYPE arg3) { +void func_80095AA0(PlayState* play, Room* room, Input* input, s32 arg3) { } -void Room_Draw0(PlayState* play, Room* room, u32 flags) { +void Room_DrawNormal(PlayState* play, Room* room, u32 flags) { s32 i; - MeshHeader0* meshHeader0; - MeshHeader01Entry* meshHeader0Entry; + RoomShapeNormal* roomShape; + RoomShapeDListsEntry* entry; OPEN_DISPS(play->state.gfxCtx, "../z_room.c", 193); @@ -52,59 +52,75 @@ void Room_Draw0(PlayState* play, Room* room, u32 flags) { gSPMatrix(POLY_XLU_DISP++, &gMtxClear, G_MTX_MODELVIEW | G_MTX_LOAD); } - meshHeader0 = &room->meshHeader->meshHeader0; - meshHeader0Entry = SEGMENTED_TO_VIRTUAL(meshHeader0->entries); - for (i = 0; i < meshHeader0->numEntries; i++) { - if ((flags & ROOM_DRAW_OPA) && (meshHeader0Entry->opa != NULL)) { - gSPDisplayList(POLY_OPA_DISP++, meshHeader0Entry->opa); + roomShape = &room->roomShape->normal; + entry = SEGMENTED_TO_VIRTUAL(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 & ROOM_DRAW_XLU) && (meshHeader0Entry->xlu != NULL)) { - gSPDisplayList(POLY_XLU_DISP++, meshHeader0Entry->xlu); + if ((flags & ROOM_DRAW_XLU) && (entry->xlu != NULL)) { + gSPDisplayList(POLY_XLU_DISP++, entry->xlu); } - meshHeader0Entry++; + entry++; } CLOSE_DISPS(play->state.gfxCtx, "../z_room.c", 239); } -#define SHAPE_SORT_MAX 64 +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 struct_80095D04 { - /* 0x00 */ MeshHeader2Entry* unk_00; - /* 0x04 */ f32 unk_04; - /* 0x08 */ struct struct_80095D04* unk_08; - /* 0x0C */ struct struct_80095D04* unk_0C; -} struct_80095D04; // size = 0x10 +typedef struct RoomShapeCullableEntryLinked { + /* 0x00 */ RoomShapeCullableEntry* entry; + /* 0x04 */ f32 boundsNearZ; + /* 0x08 */ struct RoomShapeCullableEntryLinked* prev; + /* 0x0C */ struct RoomShapeCullableEntryLinked* next; +} RoomShapeCullableEntryLinked; // size = 0x10 -void Room_Draw2(PlayState* play, Room* room, u32 flags) { - MeshHeader2* meshHeader2; - MeshHeader2Entry* meshHeader2Entry; - struct_80095D04 spB8[SHAPE_SORT_MAX]; - struct_80095D04* spB4 = NULL; - struct_80095D04* spB0 = NULL; - struct_80095D04* iter; +/** + * Handle room drawing for the "cullable" type of room shape. + * + * Each entry referenced by the room shape struct is attached to display lists, and a position and radius indicating the + * bounding sphere for the geometry drawn. + * The first step Z-sorts the entries, and excludes the entries with a bounding sphere that is entirely before or + * beyond the rendered depth range. + * The second step draws the entries that remain, from nearest to furthest. + */ +void Room_DrawCullable(PlayState* play, Room* room, u32 flags) { + RoomShapeCullable* roomShape; + RoomShapeCullableEntry* roomShapeCullableEntry; + RoomShapeCullableEntryLinked linkedEntriesBuffer[ROOM_SHAPE_CULLABLE_MAX_ENTRIES]; + RoomShapeCullableEntryLinked* head = NULL; + RoomShapeCullableEntryLinked* tail = NULL; + RoomShapeCullableEntryLinked* iter; s32 pad; - struct_80095D04* spA4; + RoomShapeCullableEntryLinked* insert; s32 j; s32 i; Vec3f pos; Vec3f projectedPos; f32 projectedW; s32 pad2; - MeshHeader2Entry* meshHeader2Entries; - MeshHeader2Entry* meshHeader2EntryIter; - f32 temp_f2; + RoomShapeCullableEntry* roomShapeCullableEntries; + RoomShapeCullableEntry* roomShapeCullableEntryIter; + f32 entryBoundsNearZ; OPEN_DISPS(play->state.gfxCtx, "../z_room.c", 287); + if (flags & ROOM_DRAW_OPA) { func_800342EC(&D_801270A0, play); gSPSegment(POLY_OPA_DISP++, 0x03, room->segment); func_80093C80(play); gSPMatrix(POLY_OPA_DISP++, &gMtxClear, G_MTX_MODELVIEW | G_MTX_LOAD); } + if (1) {} + if (flags & ROOM_DRAW_XLU) { func_8003435C(&D_801270A0, play); gSPSegment(POLY_XLU_DISP++, 0x03, room->segment); @@ -112,80 +128,103 @@ void Room_Draw2(PlayState* play, Room* room, u32 flags) { gSPMatrix(POLY_XLU_DISP++, &gMtxClear, G_MTX_MODELVIEW | G_MTX_LOAD); } - meshHeader2 = &room->meshHeader->meshHeader2; - meshHeader2Entry = SEGMENTED_TO_VIRTUAL(meshHeader2->entries); - spA4 = spB8; + roomShape = &room->roomShape->cullable; + roomShapeCullableEntry = SEGMENTED_TO_VIRTUAL(roomShape->entries); + insert = linkedEntriesBuffer; - ASSERT(meshHeader2->numEntries <= SHAPE_SORT_MAX, "polygon2->num <= SHAPE_SORT_MAX", "../z_room.c", 317); - meshHeader2Entries = meshHeader2Entry; + ASSERT(roomShape->numEntries <= ROOM_SHAPE_CULLABLE_MAX_ENTRIES, "polygon2->num <= SHAPE_SORT_MAX", "../z_room.c", + 317); - for (i = 0; i < meshHeader2->numEntries; i++, meshHeader2Entry++) { - pos.x = meshHeader2Entry->pos.x; - pos.y = meshHeader2Entry->pos.y; - pos.z = meshHeader2Entry->pos.z; + roomShapeCullableEntries = roomShapeCullableEntry; + + // 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_Vec3fMtxFMultXYZW(&play->viewProjectionMtxF, &pos, &projectedPos, &projectedW); - if (-(f32)meshHeader2Entry->unk_06 < projectedPos.z) { - temp_f2 = projectedPos.z - meshHeader2Entry->unk_06; - if (temp_f2 < play->lightCtx.fogFar) { - spA4->unk_00 = meshHeader2Entry; - spA4->unk_04 = temp_f2; - iter = spB4; + + // If the entry bounding sphere isn't fully before the rendered depth range + if (-(f32)roomShapeCullableEntry->boundsSphereRadius < projectedPos.z) { + + // Compute the depth of the nearest point in the entry's bounding sphere + entryBoundsNearZ = projectedPos.z - roomShapeCullableEntry->boundsSphereRadius; + + // If the entry bounding sphere isn't fully beyond the rendered depth range + if (entryBoundsNearZ < play->lightCtx.fogFar) { + + // This entry will be rendered + insert->entry = roomShapeCullableEntry; + 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) { - spB4 = spB0 = spA4; - spA4->unk_08 = spA4->unk_0C = NULL; + head = tail = insert; + insert->prev = insert->next = NULL; } else { do { - if (spA4->unk_04 < iter->unk_04) { + if (insert->boundsNearZ < iter->boundsNearZ) { break; } - iter = iter->unk_0C; + iter = iter->next; } while (iter != NULL); if (iter == NULL) { - spA4->unk_08 = spB0; - spA4->unk_0C = NULL; - spB0->unk_0C = spA4; - spB0 = spA4; + insert->prev = tail; + insert->next = NULL; + tail->next = insert; + tail = insert; } else { - spA4->unk_08 = iter->unk_08; - if (spA4->unk_08 == NULL) { - spB4 = spA4; + insert->prev = iter->prev; + if (insert->prev == NULL) { + head = insert; } else { - spA4->unk_08->unk_0C = spA4; + insert->prev->next = insert; } - iter->unk_08 = spA4; - spA4->unk_0C = iter; + iter->prev = insert; + insert->next = iter; } } - spA4++; + + insert++; } } } - iREG(87) = meshHeader2->numEntries & 0xFFFF & 0xFFFF & 0xFFFF; // if this is real then I might not be + // if this is real then I might not be + R_ROOM_CULL_NUM_ENTRIES = roomShape->numEntries & 0xFFFF & 0xFFFF & 0xFFFF; - for (i = 1; spB4 != NULL; spB4 = spB4->unk_0C, i++) { + // Draw entries, from nearest to furthest + for (i = 1; head != NULL; head = head->next, i++) { Gfx* displayList; - meshHeader2Entry = spB4->unk_00; - if (iREG(86) != 0) { - meshHeader2EntryIter = meshHeader2Entries; - for (j = 0; j < meshHeader2->numEntries; j++, meshHeader2EntryIter++) { - if (meshHeader2Entry == meshHeader2EntryIter) { - break; // This loop does nothing? + roomShapeCullableEntry = head->entry; + + if (R_ROOM_CULL_DEBUG_MODE != ROOM_CULL_DEBUG_MODE_OFF) { + // Debug mode drawing + + // This loop does nothing + roomShapeCullableEntryIter = roomShapeCullableEntries; + for (j = 0; j < roomShape->numEntries; j++, roomShapeCullableEntryIter++) { + if (roomShapeCullableEntry == roomShapeCullableEntryIter) { + break; } } - if (((iREG(86) == 1) && (iREG(89) >= i)) || ((iREG(86) == 2) && (iREG(89) == i))) { + 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 = meshHeader2Entry->opa; + displayList = roomShapeCullableEntry->opa; if (displayList != NULL) { gSPDisplayList(POLY_OPA_DISP++, displayList); } } if (flags & ROOM_DRAW_XLU) { - displayList = meshHeader2Entry->xlu; + displayList = roomShapeCullableEntry->xlu; if (displayList != NULL) { gSPDisplayList(POLY_XLU_DISP++, displayList); } @@ -193,14 +232,14 @@ void Room_Draw2(PlayState* play, Room* room, u32 flags) { } } else { if (flags & ROOM_DRAW_OPA) { - displayList = meshHeader2Entry->opa; + displayList = roomShapeCullableEntry->opa; if (displayList != NULL) { gSPDisplayList(POLY_OPA_DISP++, displayList); } } if (flags & ROOM_DRAW_XLU) { - displayList = meshHeader2Entry->xlu; + displayList = roomShapeCullableEntry->xlu; if (displayList != NULL) { gSPDisplayList(POLY_XLU_DISP++, displayList); } @@ -208,14 +247,18 @@ void Room_Draw2(PlayState* play, Room* room, u32 flags) { } } - iREG(88) = i - 1; + R_ROOM_CULL_USED_ENTRIES = i - 1; CLOSE_DISPS(play->state.gfxCtx, "../z_room.c", 430); } #define JPEG_MARKER 0xFFD8FFE0 -s32 func_80096238(void* data) { +/** + * If the data is JPEG, decode it and overwrite the initial data with the result. + * Uses the depth frame buffer as temporary storage. + */ +s32 Room_DecodeJpeg(void* data) { OSTime time; if (*(u32*)data == JPEG_MARKER) { @@ -232,10 +275,10 @@ s32 func_80096238(void* data) { osSyncPrintf("成功…だと思う。 time = %6.3f ms \n", OS_CYCLES_TO_USEC(time) / 1000.0f); // "Writing back to original address from work buffer." osSyncPrintf("ワークバッファから元のアドレスに書き戻します。\n"); - // "If the original buffer size isn't at least 150kb, it will be out of control." + // "If the original buffer size isn't at least 150kB, it will be out of control." osSyncPrintf("元のバッファのサイズが150キロバイト無いと暴走するでしょう。\n"); - bcopy(gZBuffer, data, sizeof(gZBuffer)); + bcopy(gZBuffer, data, sizeof(u16[SCREEN_HEIGHT][SCREEN_WIDTH])); } else { osSyncPrintf("失敗!なんで〜\n"); // "Failure! Why is it 〜" } @@ -244,72 +287,78 @@ s32 func_80096238(void* data) { return 0; } -void func_8009638C(Gfx** displayList, void* source, void* tlut, u16 width, u16 height, u8 fmt, u8 siz, u16 mode0, - u16 tlutCount, f32 frameX, f32 frameY) { - Gfx* displayListHead; +void Room_DrawBackground2D(Gfx** gfxP, void* tex, void* tlut, u16 width, u16 height, u8 fmt, u8 siz, u16 tlutMode, + u16 tlutCount, f32 offsetX, f32 offsetY) { + Gfx* gfx = *gfxP; uObjBg* bg; - displayListHead = *displayList; - func_80096238(SEGMENTED_TO_VIRTUAL(source)); + Room_DecodeJpeg(SEGMENTED_TO_VIRTUAL(tex)); + + bg = (uObjBg*)(gfx + 1); + gSPBranchList(gfx, (u32)bg + sizeof(uObjBg)); - bg = (uObjBg*)(displayListHead + 1); - gSPBranchList(displayListHead, (u8*)bg + sizeof(uObjBg)); bg->b.imageX = 0; - bg->b.imageW = width * 4; - bg->b.frameX = frameX * 4; + bg->b.imageW = width * (1 << 2); + bg->b.frameX = offsetX * (1 << 2); bg->b.imageY = 0; - bg->b.imageH = height * 4; - bg->b.frameY = frameY * 4; - bg->b.imagePtr = source; + bg->b.imageH = height * (1 << 2); + bg->b.frameY = offsetY * (1 << 2); + bg->b.imagePtr = tex; bg->b.imageLoad = G_BGLT_LOADTILE; bg->b.imageFmt = fmt; bg->b.imageSiz = siz; bg->b.imagePal = 0; bg->b.imageFlip = 0; - displayListHead = (void*)(bg + 1); + gfx = (Gfx*)((u32)bg + sizeof(uObjBg)); + if (fmt == G_IM_FMT_CI) { - gDPLoadTLUT(displayListHead++, tlutCount, 256, tlut); + gDPLoadTLUT(gfx++, tlutCount, 256, tlut); } else { - gDPPipeSync(displayListHead++); + gDPPipeSync(gfx++); } - if ((fmt == G_IM_FMT_RGBA) && (SREG(26) == 0)) { - bg->b.frameW = width * 4; - bg->b.frameH = height * 4; + if ((fmt == G_IM_FMT_RGBA) && !R_ROOM_BG2D_FORCE_SCALEBG) { + bg->b.frameW = width * (1 << 2); + bg->b.frameH = height * (1 << 2); guS2DInitBg(bg); - gDPSetOtherMode(displayListHead++, mode0 | G_TL_TILE | G_TD_CLAMP | G_TP_NONE | G_CYC_COPY | G_PM_NPRIMITIVE, + gDPSetOtherMode(gfx++, tlutMode | G_TL_TILE | G_TD_CLAMP | G_TP_NONE | G_CYC_COPY | G_PM_NPRIMITIVE, G_AC_THRESHOLD | G_ZS_PIXEL | G_RM_NOOP | G_RM_NOOP2); - gSPBgRectCopy(displayListHead++, bg); + gSPBgRectCopy(gfx++, bg); } else { - bg->s.frameW = width * 4; - bg->s.frameH = height * 4; - bg->s.scaleW = 1024; - bg->s.scaleH = 1024; + bg->s.frameW = width * (1 << 2); + bg->s.frameH = height * (1 << 2); + bg->s.scaleW = 1 << 10; + bg->s.scaleH = 1 << 10; bg->s.imageYorig = bg->b.imageY; - gDPSetOtherMode(displayListHead++, - mode0 | G_AD_DISABLE | G_CD_DISABLE | G_CK_NONE | G_TC_FILT | G_TF_POINT | G_TT_NONE | - G_TL_TILE | G_TD_CLAMP | G_TP_NONE | G_CYC_1CYCLE | G_PM_NPRIMITIVE, + gDPSetOtherMode(gfx++, + tlutMode | G_AD_DISABLE | G_CD_DISABLE | G_CK_NONE | G_TC_FILT | G_TF_POINT | G_TL_TILE | + G_TD_CLAMP | G_TP_NONE | G_CYC_1CYCLE | G_PM_NPRIMITIVE, G_AC_THRESHOLD | G_ZS_PIXEL | AA_EN | CVG_DST_CLAMP | ZMODE_OPA | CVG_X_ALPHA | ALPHA_CVG_SEL | GBL_c1(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_BL, G_BL_1MA) | GBL_c2(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_BL, G_BL_1MA)); - gDPSetCombineLERP(displayListHead++, 0, 0, 0, TEXEL0, 0, 0, 0, 1, 0, 0, 0, TEXEL0, 0, 0, 0, 1); - gSPObjRenderMode(displayListHead++, G_OBJRM_ANTIALIAS | G_OBJRM_BILERP); - gSPBgRect1Cyc(displayListHead++, bg); + gDPSetCombineLERP(gfx++, 0, 0, 0, TEXEL0, 0, 0, 0, 1, 0, 0, 0, TEXEL0, 0, 0, 0, 1); + gSPObjRenderMode(gfx++, G_OBJRM_ANTIALIAS | G_OBJRM_BILERP); + gSPBgRect1Cyc(gfx++, bg); } - gDPPipeSync(displayListHead++); - *displayList = displayListHead; + gDPPipeSync(gfx++); + + *gfxP = gfx; } -void Room_Draw1Single(PlayState* play, Room* room, u32 flags) { +#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* spA8; - MeshHeader1Single* meshHeader1Single; - MeshHeader01Entry* meshHeader1Entry; + Gfx* gfx; + RoomShapeImageSingle* roomShape; + RoomShapeDListsEntry* entry; u32 isFixedCamera; - u32 drawBg; + u32 drawBackground; u32 drawOpa; u32 drawXlu; @@ -317,123 +366,34 @@ void Room_Draw1Single(PlayState* play, Room* room, u32 flags) { activeCam = GET_ACTIVE_CAM(play); isFixedCamera = (activeCam->setting == CAM_SET_PREREND_FIXED); - meshHeader1Single = &room->meshHeader->meshHeader1Single; - meshHeader1Entry = SEGMENTED_TO_VIRTUAL(meshHeader1Single->base.entry); - drawBg = (flags & ROOM_DRAW_OPA) && isFixedCamera && meshHeader1Single->source && !(SREG(25) & 1); - drawOpa = (flags & ROOM_DRAW_OPA) && (meshHeader1Entry->opa != NULL) && !(SREG(25) & 2); - drawXlu = (flags & ROOM_DRAW_XLU) && (meshHeader1Entry->xlu != NULL) && !(SREG(25) & 4); + roomShape = &room->roomShape->image.single; + entry = SEGMENTED_TO_VIRTUAL(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 || drawBg) { + if (drawOpa || drawBackground) { gSPSegment(POLY_OPA_DISP++, 0x03, room->segment); if (drawOpa) { Gfx_SetupDL_25Opa(play->state.gfxCtx); gSPMatrix(POLY_OPA_DISP++, &gMtxClear, G_MTX_MODELVIEW | G_MTX_LOAD); - gSPDisplayList(POLY_OPA_DISP++, meshHeader1Entry->opa); + gSPDisplayList(POLY_OPA_DISP++, entry->opa); } - if (drawBg) { + if (drawBackground) { gSPLoadUcodeL(POLY_OPA_DISP++, gspS2DEX2d_fifo); { - Vec3f sp60; - spA8 = POLY_OPA_DISP; - Camera_GetSkyboxOffset(&sp60, activeCam); - func_8009638C(&spA8, meshHeader1Single->source, meshHeader1Single->tlut, meshHeader1Single->width, - meshHeader1Single->height, meshHeader1Single->fmt, meshHeader1Single->siz, - meshHeader1Single->mode0, meshHeader1Single->tlutCount, - (sp60.x + sp60.z) * 1.2f + sp60.y * 0.6f, sp60.y * 2.4f + (sp60.x + sp60.z) * 0.3f); - POLY_OPA_DISP = spA8; - } - - gSPLoadUcode(POLY_OPA_DISP++, SysUcode_GetUCode(), SysUcode_GetUCodeData()); - } - } - - if (drawXlu) { - gSPSegment(POLY_XLU_DISP++, 0x03, room->segment); - Gfx_SetupDL_25Xlu(play->state.gfxCtx); - gSPMatrix(POLY_XLU_DISP++, &gMtxClear, G_MTX_MODELVIEW | G_MTX_LOAD); - gSPDisplayList(POLY_XLU_DISP++, meshHeader1Entry->xlu); - } - - CLOSE_DISPS(play->state.gfxCtx, "../z_room.c", 691); -} - -BgImage* func_80096A74(MeshHeader1Multi* meshHeader1Multi, PlayState* play) { - Camera* activeCam = GET_ACTIVE_CAM(play); - s32 bgCamIndex = activeCam->bgCamIndex; - s16 jfifId; - Player* player; - BgImage* bgImage; - s32 i; - - jfifId = ((BgCamFuncData*)BgCheck_GetBgCamFuncDataImpl(&play->colCtx, bgCamIndex, BGCHECK_SCENE))->jfifId; - if (jfifId >= 0) { - bgCamIndex = jfifId; - } - - player = GET_PLAYER(play); - player->actor.params = (player->actor.params & 0xFF00) | bgCamIndex; - - bgImage = SEGMENTED_TO_VIRTUAL(meshHeader1Multi->list); - for (i = 0; i < meshHeader1Multi->count; i++) { - if (bgImage->id == bgCamIndex) { - return bgImage; - } - bgImage++; - } - - // "z_room.c: Data consistent with camera id does not exist camid=%d" - osSyncPrintf(VT_COL(RED, WHITE) "z_room.c:カメラIDに一致するデータが存在しません camid=%d\n" VT_RST, bgCamIndex); - LogUtils_HungupThread("../z_room.c", 726); - - return NULL; -} - -void Room_Draw1Multi(PlayState* play, Room* room, u32 flags) { - Camera* activeCam; - Gfx* gfx; - MeshHeader1Multi* meshHeader1Multi; - BgImage* bgImage; - MeshHeader01Entry* meshHeader1Entry; - u32 isFixedCamera; - u32 drawBg; - u32 drawOpa; - u32 drawXlu; - - OPEN_DISPS(play->state.gfxCtx, "../z_room.c", 752); - - activeCam = GET_ACTIVE_CAM(play); - isFixedCamera = (activeCam->setting == CAM_SET_PREREND_FIXED); - meshHeader1Multi = &room->meshHeader->meshHeader1Multi; - meshHeader1Entry = SEGMENTED_TO_VIRTUAL(meshHeader1Multi->base.entry); - bgImage = func_80096A74(meshHeader1Multi, play); - drawBg = (flags & ROOM_DRAW_OPA) && isFixedCamera && bgImage->source && !(SREG(25) & 1); - drawOpa = (flags & ROOM_DRAW_OPA) && (meshHeader1Entry->opa != NULL) && !(SREG(25) & 2); - drawXlu = (flags & ROOM_DRAW_XLU) && (meshHeader1Entry->xlu != NULL) && !(SREG(25) & 4); - - if (drawOpa || drawBg) { - gSPSegment(POLY_OPA_DISP++, 0x03, room->segment); - - if (drawOpa) { - Gfx_SetupDL_25Opa(play->state.gfxCtx); - gSPMatrix(POLY_OPA_DISP++, &gMtxClear, G_MTX_MODELVIEW | G_MTX_LOAD); - gSPDisplayList(POLY_OPA_DISP++, meshHeader1Entry->opa); - } - - if (drawBg) { - gSPLoadUcodeL(POLY_OPA_DISP++, gspS2DEX2d_fifo); - - { - Vec3f skyboxOffset; + Vec3f quakeOffset; gfx = POLY_OPA_DISP; - Camera_GetSkyboxOffset(&skyboxOffset, activeCam); - func_8009638C(&gfx, bgImage->source, bgImage->tlut, bgImage->width, bgImage->height, bgImage->fmt, - bgImage->siz, bgImage->mode0, bgImage->tlutCount, - (skyboxOffset.x + skyboxOffset.z) * 1.2f + skyboxOffset.y * 0.6f, - skyboxOffset.y * 2.4f + (skyboxOffset.x + skyboxOffset.z) * 0.3f); + Camera_GetSkyboxOffset(&quakeOffset, activeCam); + Room_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); POLY_OPA_DISP = gfx; } @@ -445,19 +405,117 @@ void Room_Draw1Multi(PlayState* play, Room* room, u32 flags) { gSPSegment(POLY_XLU_DISP++, 0x03, room->segment); Gfx_SetupDL_25Xlu(play->state.gfxCtx); gSPMatrix(POLY_XLU_DISP++, &gMtxClear, G_MTX_MODELVIEW | G_MTX_LOAD); - gSPDisplayList(POLY_XLU_DISP++, meshHeader1Entry->xlu); + gSPDisplayList(POLY_XLU_DISP++, entry->xlu); + } + + CLOSE_DISPS(play->state.gfxCtx, "../z_room.c", 691); +} + +RoomShapeImageMultiBgEntry* Room_GetImageMultiBgEntry(RoomShapeImageMulti* roomShapeImageMulti, PlayState* play) { + Camera* activeCam = GET_ACTIVE_CAM(play); + s32 bgCamIndex = activeCam->bgCamIndex; + s16 overrideBgCamIndex; + Player* player; + RoomShapeImageMultiBgEntry* bgEntry; + s32 i; + + // In mq debug vanilla scenes, overrideBgCamIndex is always -1 or the same as bgCamIndex + 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 = SEGMENTED_TO_VIRTUAL(roomShapeImageMulti->backgrounds); + for (i = 0; i < roomShapeImageMulti->numBackgrounds; i++) { + if (bgEntry->bgCamIndex == bgCamIndex) { + return bgEntry; + } + bgEntry++; + } + + // "z_room.c: Data consistent with camera id does not exist camid=%d" + osSyncPrintf(VT_COL(RED, WHITE) "z_room.c:カメラIDに一致するデータが存在しません camid=%d\n" VT_RST, bgCamIndex); + LogUtils_HungupThread("../z_room.c", 726); + + 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, "../z_room.c", 752); + + activeCam = GET_ACTIVE_CAM(play); + isFixedCamera = (activeCam->setting == CAM_SET_PREREND_FIXED); + roomShape = &room->roomShape->image.multi; + dListsEntry = SEGMENTED_TO_VIRTUAL(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) { + Gfx_SetupDL_25Opa(play->state.gfxCtx); + gSPMatrix(POLY_OPA_DISP++, &gMtxClear, G_MTX_MODELVIEW | G_MTX_LOAD); + gSPDisplayList(POLY_OPA_DISP++, dListsEntry->opa); + } + + if (drawBackground) { + gSPLoadUcodeL(POLY_OPA_DISP++, gspS2DEX2d_fifo); + + { + Vec3f quakeOffset; + + gfx = POLY_OPA_DISP; + Camera_GetSkyboxOffset(&quakeOffset, activeCam); + Room_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); + POLY_OPA_DISP = gfx; + } + + gSPLoadUcode(POLY_OPA_DISP++, SysUcode_GetUCode(), SysUcode_GetUCodeData()); + } + } + + if (drawXlu) { + gSPSegment(POLY_XLU_DISP++, 0x03, room->segment); + Gfx_SetupDL_25Xlu(play->state.gfxCtx); + gSPMatrix(POLY_XLU_DISP++, &gMtxClear, G_MTX_MODELVIEW | G_MTX_LOAD); + gSPDisplayList(POLY_XLU_DISP++, dListsEntry->xlu); } CLOSE_DISPS(play->state.gfxCtx, "../z_room.c", 819); } -void Room_Draw1(PlayState* play, Room* room, u32 flags) { - MeshHeader1Base* meshHeader1Base = &room->meshHeader->meshHeader1Base; +void Room_DrawImage(PlayState* play, Room* room, u32 flags) { + RoomShapeImageBase* roomShape = &room->roomShape->image.base; - if (meshHeader1Base->format == MESH_HEADER1_FORMAT_SINGLE) { - Room_Draw1Single(play, room, flags); - } else if (meshHeader1Base->format == MESH_HEADER1_FORMAT_MULTI) { - Room_Draw1Multi(play, room, flags); + 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 { LogUtils_HungupThread("../z_room.c", 841); } @@ -578,9 +636,9 @@ s32 func_800973FC(PlayState* play, RoomContext* roomCtx) { void Room_Draw(PlayState* play, Room* room, u32 flags) { if (room->segment != NULL) { gSegments[3] = VIRTUAL_TO_PHYSICAL(room->segment); - ASSERT(room->meshHeader->base.type < ARRAY_COUNTU(sRoomDrawHandlers), + ASSERT(room->roomShape->base.type < ARRAY_COUNTU(sRoomDrawHandlers), "this->ground_shape->polygon.type < number(Room_Draw_Proc)", "../z_room.c", 1125); - sRoomDrawHandlers[room->meshHeader->base.type](play, room, flags); + sRoomDrawHandlers[room->roomShape->base.type](play, room, flags); } } diff --git a/src/code/z_scene.c b/src/code/z_scene.c index fc2d32295a..6f21159949 100644 --- a/src/code/z_scene.c +++ b/src/code/z_scene.c @@ -243,8 +243,8 @@ void Scene_CommandRoomBehavior(PlayState* play, SceneCmd* cmd) { play->msgCtx.disableWarpSongs = (cmd->roomBehavior.gpFlag2 >> 0xA) & 1; } -void Scene_CommandMeshHeader(PlayState* play, SceneCmd* cmd) { - play->roomCtx.curRoom.meshHeader = SEGMENTED_TO_VIRTUAL(cmd->mesh.data); +void Scene_CommandRoomShape(PlayState* play, SceneCmd* cmd) { + play->roomCtx.curRoom.roomShape = SEGMENTED_TO_VIRTUAL(cmd->mesh.data); } void Scene_CommandObjectList(PlayState* play, SceneCmd* cmd) { @@ -480,7 +480,7 @@ void (*gSceneCmdHandlers[SCENE_CMD_ID_MAX])(PlayState*, SceneCmd*) = { Scene_CommandSpecialFiles, // SCENE_CMD_ID_SPECIAL_FILES Scene_CommandRoomBehavior, // SCENE_CMD_ID_ROOM_BEHAVIOR Scene_CommandUndefined9, // SCENE_CMD_ID_UNDEFINED_9 - Scene_CommandMeshHeader, // SCENE_CMD_ID_MESH_HEADER + Scene_CommandRoomShape, // SCENE_CMD_ID_ROOM_SHAPE Scene_CommandObjectList, // SCENE_CMD_ID_OBJECT_LIST Scene_CommandLightList, // SCENE_CMD_ID_LIGHT_LIST Scene_CommandPathList, // SCENE_CMD_ID_PATH_LIST diff --git a/src/overlays/misc/ovl_kaleido_scope/z_kaleido_map_PAL.c b/src/overlays/misc/ovl_kaleido_scope/z_kaleido_map_PAL.c index eda00ac513..d90400de77 100644 --- a/src/overlays/misc/ovl_kaleido_scope/z_kaleido_map_PAL.c +++ b/src/overlays/misc/ovl_kaleido_scope/z_kaleido_map_PAL.c @@ -526,17 +526,16 @@ void KaleidoScope_DrawWorldMap(PlayState* play, GraphicsContext* gfxCtx) { gSP1Quadrangle(POLY_OPA_DISP++, j, j + 2, j + 3, j + 1, 0); } else if (HREG(15) == 1) { - Gfx* sp1CC = POLY_OPA_DISP; - void* mapImage = gWorldMapImageTex; + Gfx* gfx = POLY_OPA_DISP; - gSPLoadUcodeL(sp1CC++, gspS2DEX2d_fifo); + gSPLoadUcodeL(gfx++, gspS2DEX2d_fifo); - func_8009638C(&sp1CC, mapImage, gWorldMapImageTLUT, 216, 128, G_IM_FMT_CI, G_IM_SIZ_8b, 0x8000, 256, - HREG(13) / 100.0f, HREG(14) / 100.0f); + Room_DrawBackground2D(&gfx, gWorldMapImageTex, gWorldMapImageTLUT, 216, 128, G_IM_FMT_CI, G_IM_SIZ_8b, + G_TT_RGBA16, 256, HREG(13) / 100.0f, HREG(14) / 100.0f); - gSPLoadUcode(sp1CC++, SysUcode_GetUCode(), SysUcode_GetUCodeData()); + gSPLoadUcode(gfx++, SysUcode_GetUCode(), SysUcode_GetUCodeData()); - POLY_OPA_DISP = sp1CC; + POLY_OPA_DISP = gfx; } if (HREG(15) == 2) {