mirror of https://github.com/zeldaret/mm.git
625 lines
22 KiB
C
625 lines
22 KiB
C
#include "global.h"
|
|
#include "PR/gs2dex.h"
|
|
#include "debug.h"
|
|
|
|
void Room_Noop(PlayState* play, Room* room, Input* input, s32 arg3) {
|
|
}
|
|
|
|
void Room_DrawNone(PlayState* play, Room* room, u32 flags) {
|
|
}
|
|
|
|
static Vec3f sZeroVec = { 0.0f, 0.0f, 0.0f };
|
|
|
|
void Room_DrawNormal(PlayState* play, Room* room, u32 flags) {
|
|
RoomShapeNormal* roomShape;
|
|
RoomShapeDListsEntry* entry;
|
|
s32 i;
|
|
|
|
OPEN_DISPS(play->state.gfxCtx);
|
|
|
|
if (flags & ROOM_DRAW_OPA) {
|
|
func_800BCBF4(&sZeroVec, play);
|
|
gSPSegment(POLY_OPA_DISP++, 0x03, room->segment);
|
|
func_8012C268(&play->state);
|
|
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);
|
|
Gfx_SetupDL25_Xlu(play->state.gfxCtx);
|
|
gSPMatrix(POLY_XLU_DISP++, &gIdentityMtx, G_MTX_MODELVIEW | G_MTX_LOAD);
|
|
}
|
|
|
|
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 & ROOM_DRAW_XLU) && (entry->xlu != NULL)) {
|
|
gSPDisplayList(POLY_XLU_DISP++, entry->xlu);
|
|
}
|
|
|
|
entry++;
|
|
}
|
|
|
|
CLOSE_DISPS(play->state.gfxCtx);
|
|
}
|
|
|
|
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 {
|
|
/* 0x0 */ RoomShapeCullableEntry* entry;
|
|
/* 0x4 */ f32 boundsNearZ;
|
|
/* 0x8 */ struct RoomShapeCullableEntryLinked* prev;
|
|
/* 0xC */ struct RoomShapeCullableEntryLinked* next;
|
|
} RoomShapeCullableEntryLinked; // size = 0x10
|
|
|
|
#define ROOM_SHAPE_CULLABLE_MAX_ENTRIES 128
|
|
|
|
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;
|
|
Gfx* displayList;
|
|
RoomShapeCullableEntryLinked* insert;
|
|
f32 entryBoundsNearZ;
|
|
s32 i;
|
|
Vec3f pos;
|
|
Vec3f projectedPos;
|
|
RoomShapeCullableEntry* roomShapeCullableEntries;
|
|
|
|
OPEN_DISPS(play->state.gfxCtx);
|
|
|
|
if (flags & ROOM_DRAW_OPA) {
|
|
func_800BCBF4(&sZeroVec, play);
|
|
|
|
gSPSegment(POLY_OPA_DISP++, 0x03, room->segment);
|
|
if (play->roomCtx.unk74 != NULL) {
|
|
gSPSegment(POLY_OPA_DISP++, 0x06, play->roomCtx.unk74);
|
|
}
|
|
func_8012C268(&play->state);
|
|
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);
|
|
}
|
|
Gfx_SetupDL25_Xlu(play->state.gfxCtx);
|
|
gSPMatrix(POLY_XLU_DISP++, &gIdentityMtx, G_MTX_MODELVIEW | G_MTX_LOAD);
|
|
}
|
|
|
|
if (room->enablePosLights || (MREG(93) != 0)) {
|
|
gSPSetGeometryMode(POLY_OPA_DISP++, G_LIGHTING_POSITIONAL);
|
|
gSPSetGeometryMode(POLY_XLU_DISP++, G_LIGHTING_POSITIONAL);
|
|
}
|
|
|
|
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;
|
|
f32 var_fv1;
|
|
s32 var_a1;
|
|
|
|
// 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 pad;
|
|
|
|
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 (; tail != NULL; tail = tail->prev) {
|
|
f32 temp_fv0;
|
|
f32 temp_fv1;
|
|
|
|
roomShapeCullableEntry = tail->entry;
|
|
displayList = roomShapeCullableEntry->xlu;
|
|
|
|
if (displayList != NULL) {
|
|
if (roomShapeCullableEntry->boundsSphereRadius & 1) {
|
|
|
|
temp_fv0 = tail->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);
|
|
}
|
|
|
|
#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) {
|
|
Gfx_SetupDL25_Opa(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);
|
|
Gfx_SetupDL25_Xlu(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->bgCamIndex;
|
|
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++;
|
|
}
|
|
|
|
_dbg_hungup("../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) {
|
|
Gfx_SetupDL25_Opa(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);
|
|
Gfx_SetupDL25_Xlu(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 {
|
|
_dbg_hungup("../z_room.c", 965);
|
|
}
|
|
}
|
|
|
|
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 < ARRAY_COUNT(roomCtx->unk7A); i++) {
|
|
roomCtx->unk7A[i] = 0;
|
|
}
|
|
}
|
|
|
|
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_AllocTailAlign16(&play->state.heap, maxRoomSize);
|
|
if (roomCtx->roomMemPages[0] == NULL) {
|
|
_dbg_hungup("../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->status == 0) {
|
|
size_t size;
|
|
|
|
roomCtx->prevRoom = roomCtx->curRoom;
|
|
roomCtx->curRoom.num = 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));
|
|
|
|
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;
|
|
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
s32 Room_HandleLoadCallbacks(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[3] = VIRTUAL_TO_PHYSICAL(roomCtx->activeRoomVram);
|
|
|
|
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)) {
|
|
play->envCtx.lightSettingOverride = 0xFF;
|
|
play->envCtx.unk_E0 = 0;
|
|
}
|
|
func_800FEAB0();
|
|
if (!func_800FE4B8(play)) {
|
|
func_800FD858(play);
|
|
}
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
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) {
|
|
gSegments[3] = VIRTUAL_TO_PHYSICAL(room->segment);
|
|
sRoomDrawHandlers[room->roomShape->base.type](play, room, flags);
|
|
}
|
|
return;
|
|
}
|
|
|
|
void func_8012EBF8(PlayState* play, RoomContext* roomCtx) {
|
|
roomCtx->prevRoom.num = -1;
|
|
roomCtx->prevRoom.segment = NULL;
|
|
func_800BA798(play, &play->actorCtx);
|
|
Actor_SpawnTransitionActors(play, &play->actorCtx);
|
|
if (roomCtx->curRoom.num > -1) {
|
|
Map_InitRoomData(play, roomCtx->curRoom.num);
|
|
Minimap_SavePlayerRoomInitInfo(play);
|
|
}
|
|
func_801A3CD8(play->roomCtx.curRoom.echo);
|
|
}
|