#ifdef WIN32 #include #endif #include "global.h" #include "vt.h" #include "soh/Enhancements/randomizer/randomizer_entrance.h" #include #include #include "public/bridge/gfxbridge.h" void func_80095AB4(PlayState* play, Room* room, u32 flags); void func_80095D04(PlayState* play, Room* room, u32 flags); void func_80096F6C(PlayState* play, Room* room, u32 flags); Vec3f D_801270A0 = { 0.0f, 0.0f, 0.0f }; // unused Gfx D_801270B0[] = { gsDPPipeSync(), gsSPClearGeometryMode(G_ZBUFFER | G_CULL_BOTH | G_FOG | G_LIGHTING | G_TEXTURE_GEN | G_TEXTURE_GEN_LINEAR | G_LOD), gsSPTexture(0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_OFF), gsDPSetCombineMode(G_CC_SHADE, G_CC_SHADE), gsDPSetOtherMode(G_AD_DISABLE | G_CD_MAGICSQ | G_CK_NONE | G_TC_FILT | G_TF_BILERP | G_TT_NONE | G_TL_TILE | G_TD_CLAMP | G_TP_PERSP | G_CYC_FILL | G_PM_NPRIMITIVE, G_AC_NONE | G_ZS_PIXEL | G_RM_NOOP | G_RM_NOOP2), gsSPLoadGeometryMode(G_ZBUFFER | G_SHADE | G_CULL_BACK | G_LIGHTING | G_SHADING_SMOOTH), gsDPSetScissor(G_SC_NON_INTERLACE, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT), gsSPClipRatio(FRUSTRATIO_1), gsSPEndDisplayList(), }; s32 OTRfunc_8009728C(PlayState* play, RoomContext* roomCtx, s32 roomNum); s32 OTRfunc_800973FC(PlayState* play, RoomContext* roomCtx); void (*sRoomDrawHandlers[])(PlayState* play, Room* room, u32 flags) = { func_80095AB4, func_80096F6C, func_80095D04, }; void func_80095AA0(PlayState* play, Room* room, Input* arg2, UNK_TYPE arg3) { } // Room Draw Polygon Type 0 void func_80095AB4(PlayState* play, Room* room, u32 flags) { s32 i; PolygonType0* polygon0; PolygonDlist* polygonDlist; OPEN_DISPS(play->state.gfxCtx); if (flags & 1) { 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 (flags & 2) { func_8003435C(&D_801270A0, play); gSPSegment(POLY_XLU_DISP++, 0x03, room->segment); Gfx_SetupDL_25Xlu(play->state.gfxCtx); gSPMatrix(POLY_XLU_DISP++, &gMtxClear, G_MTX_MODELVIEW | G_MTX_LOAD); } polygon0 = &room->meshHeader->polygon0; polygonDlist = SEGMENTED_TO_VIRTUAL(polygon0->start); for (i = 0; i < polygon0->num; i++) { if ((flags & 1) && (polygonDlist->opa != NULL)) { gSPDisplayList(POLY_OPA_DISP++, polygonDlist->opa); } if ((flags & 2) && (polygonDlist->xlu != NULL)) { gSPDisplayList(POLY_XLU_DISP++, polygonDlist->xlu); } polygonDlist++; } CLOSE_DISPS(play->state.gfxCtx); } #define SHAPE_SORT_MAX 64 typedef struct struct_80095D04 { /* 0x00 */ PolygonDlist2* unk_00; /* 0x04 */ f32 unk_04; /* 0x08 */ struct struct_80095D04* unk_08; /* 0x0C */ struct struct_80095D04* unk_0C; } struct_80095D04; // size = 0x10 // Room Draw Polygon Type 2 void func_80095D04(PlayState* play, Room* room, u32 flags) { PolygonType2* polygon2; PolygonDlist2* polygonDlist; struct_80095D04 spB8[SHAPE_SORT_MAX]; struct_80095D04* spB4 = NULL; struct_80095D04* spB0 = NULL; struct_80095D04* phi_v0; s32 pad; struct_80095D04* spA4; s32 phi_v1; s32 sp9C; Vec3f sp90; Vec3f sp84; f32 sp80; s32 pad2; PolygonDlist2* sp78; PolygonDlist2* temp; f32 temp_f2; OPEN_DISPS(play->state.gfxCtx); if (flags & 1) { 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 (flags & 2) { func_8003435C(&D_801270A0, play); //gSPSegment(POLY_XLU_DISP++, 0x03, room->segment); Gfx_SetupDL_25Xlu(play->state.gfxCtx); gSPMatrix(POLY_XLU_DISP++, &gMtxClear, G_MTX_MODELVIEW | G_MTX_LOAD); } polygon2 = &room->meshHeader->polygon2; polygonDlist = SEGMENTED_TO_VIRTUAL(polygon2->start); spA4 = spB8; assert(polygon2->num <= SHAPE_SORT_MAX); sp78 = polygonDlist; for (sp9C = 0; sp9C < polygon2->num; sp9C++, polygonDlist++) { sp90.x = polygonDlist->pos.x; sp90.y = polygonDlist->pos.y; sp90.z = polygonDlist->pos.z; SkinMatrix_Vec3fMtxFMultXYZW(&play->viewProjectionMtxF, &sp90, &sp84, &sp80); if (-(f32)polygonDlist->unk_06 < sp84.z) { temp_f2 = sp84.z - polygonDlist->unk_06; if (temp_f2 < play->lightCtx.fogFar) { phi_v0 = spB4; spA4->unk_00 = polygonDlist; spA4->unk_04 = temp_f2; if (phi_v0 == NULL) { spB4 = spB0 = spA4; spA4->unk_08 = spA4->unk_0C = NULL; } else { do { if (spA4->unk_04 < phi_v0->unk_04) { break; } phi_v0 = phi_v0->unk_0C; } while (phi_v0 != NULL); if (phi_v0 == NULL) { spA4->unk_08 = spB0; spA4->unk_0C = NULL; spB0->unk_0C = spA4; spB0 = spA4; } else { spA4->unk_08 = phi_v0->unk_08; if (spA4->unk_08 == NULL) { spB4 = spA4; } else { spA4->unk_08->unk_0C = spA4; } phi_v0->unk_08 = spA4; spA4->unk_0C = phi_v0; } } spA4++; } } } iREG(87) = polygon2->num & 0xFFFF & 0xFFFF & 0xFFFF; // if this is real then I might not be for (sp9C = 1; spB4 != NULL; spB4 = spB4->unk_0C, sp9C++) { Gfx* temp2; polygonDlist = spB4->unk_00; if (iREG(86) != 0) { temp = sp78; for (phi_v1 = 0; phi_v1 < polygon2->num; phi_v1++, temp++) { if (polygonDlist == temp) { break; // This loop does nothing? } } if (((iREG(86) == 1) && (iREG(89) >= sp9C)) || ((iREG(86) == 2) && (iREG(89) == sp9C))) { if (flags & 1) { temp2 = polygonDlist->opa; if (temp2 != NULL) { gSPDisplayList(POLY_OPA_DISP++, temp2); } } if (flags & 2) { temp2 = polygonDlist->xlu; if (temp2 != NULL) { gSPDisplayList(POLY_XLU_DISP++, temp2); } } } } else { if (flags & 1) { temp2 = polygonDlist->opa; if (temp2 != NULL) { gSPDisplayList(POLY_OPA_DISP++, temp2); } } if (flags & 2) { temp2 = polygonDlist->xlu; if (temp2 != NULL) { gSPDisplayList(POLY_XLU_DISP++, temp2); } } } } iREG(88) = sp9C - 1; CLOSE_DISPS(play->state.gfxCtx); } #define JPEG_MARKER 0xFFD8FFE0 s32 swapAndConvertJPEG(void* data) { OSTime time; if (BE32SWAP(*(u32*)data) == JPEG_MARKER) { size_t size = 320 * 240 * 2; char *decodedJpeg = ResourceMgr_LoadJPEG(data, size); osSyncPrintf("Expanding jpeg data\n"); osSyncPrintf("Work buffer address (Z buffer) %08x\n", gZBuffer); time = osGetTime(); memcpy(data, decodedJpeg, size); time = osGetTime() - time; osSyncPrintf("Success... I think. time = %6.3f ms", OS_CYCLES_TO_USEC(time) / 1000.0f); osSyncPrintf("Writing back to original address from work buffer."); osSyncPrintf("If the original buffer size isn't at least 150kb, it will be out of control."); return 1; } return 0; } 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; bg = (uObjBg*)(gfx + 1); gSPBranchList(gfx, (Gfx*)(bg + 1)); bg->b.imageX = 0; bg->b.imageW = width * (1 << 2); bg->b.frameX = offsetX * (1 << 2); bg->b.imageY = 0; 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 = CVarGetInteger("gMirroredWorld", 0) ? G_BG_FLAG_FLIPS : 0; // When an alt resource exists for the background, we need to unload the original asset // to clear the cache so the alt asset will be loaded instead // OTRTODO: If Alt loading over original cache is fixed, this line can most likely be removed ResourceMgr_UnloadOriginalWhenAltExists((char*)tex); if (ResourceMgr_ResourceIsBackground((char*)tex)) { char* blob = (char*)ResourceGetDataByName((char *)tex); swapAndConvertJPEG(blob); bg->b.imagePtr = (uintptr_t)blob; } gfx = (Gfx*)(bg + 1); if (fmt == G_IM_FMT_CI) { gDPLoadTLUT(gfx++, tlutCount, 256, tlut); } else { gDPPipeSync(gfx++); } if ((fmt == G_IM_FMT_RGBA) && (SREG(26) == 0)) { bg->b.frameW = width * (1 << 2); bg->b.frameH = height * (1 << 2); guS2DInitBg(bg); // #region SOH [Port][Widescreen] // When larger than 4:3 we want to render an additional black rectangle behind the 2d image // to simulate black bars on the side that cover up the world s16 newX = OTRGetRectDimensionFromLeftEdge(0); if (newX < 0) { gDPSetOtherMode(gfx++, tlutMode | G_TL_TILE | G_TD_CLAMP | G_TP_NONE | G_CYC_FILL | G_PM_NPRIMITIVE, G_AC_THRESHOLD | G_ZS_PIXEL | G_RM_NOOP | G_RM_NOOP2); gDPSetFillColor(gfx++, GPACK_RGBA5551(0, 0, 0, 1) << 16 | GPACK_RGBA5551(0, 0, 0, 1)); gDPFillWideRectangle(gfx++, newX, 0, OTRGetRectDimensionFromRightEdge(SCREEN_WIDTH), SCREEN_HEIGHT); } // #endregion 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); gDPLoadMultiTile(gfx++, bg->b.imagePtr, 0, G_TX_RENDERTILE, G_IM_FMT_RGBA, G_IM_SIZ_16b, 320, 0, 0, 0, 0 + 31, 0 + 31, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOLOD); gSPBgRectCopy(gfx++, bg); } else { 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(gfx++, tlutMode | 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, 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(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(gfx++); *gfxP = gfx; } // Room Draw Polygon Type 1 - Single Format void func_80096680(PlayState* play, Room* room, u32 flags) { Camera* camera; Gfx* spA8; PolygonType1* polygon1; PolygonDlist* polygonDlist; u32 sp9C; u32 sp98; u32 sp94; u32 sp90; OPEN_DISPS(play->state.gfxCtx); camera = GET_ACTIVE_CAM(play); sp9C = (camera->setting == CAM_SET_PREREND_FIXED); polygon1 = &room->meshHeader->polygon1; polygonDlist = SEGMENTED_TO_VIRTUAL(polygon1->dlist); sp98 = (flags & 1) && sp9C && polygon1->single.source && !(SREG(25) & 1); sp94 = (flags & 1) && polygonDlist->opa && !(SREG(25) & 2); sp90 = (flags & 2) && polygonDlist->xlu && !(SREG(25) & 4); if (sp94 || sp98) { gSPSegment(POLY_OPA_DISP++, 0x03, room->segment); if (sp94) { Gfx_SetupDL_25Opa(play->state.gfxCtx); gSPMatrix(POLY_OPA_DISP++, &gMtxClear, G_MTX_MODELVIEW | G_MTX_LOAD); gSPDisplayList(POLY_OPA_DISP++, polygonDlist->opa); } if (sp98) { gSPLoadUcodeL(POLY_OPA_DISP++, ucode_s2dex); { Vec3f sp60; spA8 = POLY_OPA_DISP; Camera_GetSkyboxOffset(&sp60, camera); Room_DrawBackground2D(&spA8, polygon1->single.source, polygon1->single.tlut, polygon1->single.width, polygon1->single.height, polygon1->single.fmt, polygon1->single.siz, polygon1->single.mode0, polygon1->single.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()); } } if (sp90) { 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++, polygonDlist->xlu); } CLOSE_DISPS(play->state.gfxCtx); } BgImage* func_80096A74(PolygonType1* polygon1, PlayState* play) { Camera* camera; s32 camId; s16 camId2; Player* player; BgImage* bgImage; s32 i; camera = GET_ACTIVE_CAM(play); camId = camera->camDataIdx; if (camId == -1 && (CVarGetInteger("gNoRestrictItems", 0) || CVarGetInteger("gCrowdControl", 0))) { // This prevents a crash when using items that change the // camera (such as din's fire), voiding out or dying on // scenes with prerendered backgrounds. return NULL; } // jfifid camId2 = func_80041C10(&play->colCtx, camId, BGCHECK_SCENE)[2].y; if (camId2 >= 0) { camId = camId2; } player = GET_PLAYER(play); player->actor.params = (player->actor.params & 0xFF00) | camId; bgImage = SEGMENTED_TO_VIRTUAL(polygon1->multi.list); for (i = 0; i < polygon1->multi.count; i++) { if (bgImage->id == camId) { 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, camId); LOG_HUNGUP_THREAD(); return NULL; } // Room Draw Polygon Type 1 - Multi Format void func_80096B6C(PlayState* play, Room* room, u32 flags) { Camera* camera; Gfx* spA8; PolygonType1* polygon1; BgImage* bgImage; PolygonDlist* polygonDlist; u32 sp98; u32 sp94; u32 sp90; u32 sp8C; OPEN_DISPS(play->state.gfxCtx); camera = GET_ACTIVE_CAM(play); sp98 = (camera->setting == CAM_SET_PREREND_FIXED); polygon1 = &room->meshHeader->polygon1; polygonDlist = SEGMENTED_TO_VIRTUAL(polygon1->dlist); bgImage = func_80096A74(polygon1, play); sp94 = (flags & 1) && sp98 && bgImage->source && !(SREG(25) & 1); sp90 = (flags & 1) && polygonDlist->opa && !(SREG(25) & 2); sp8C = (flags & 2) && polygonDlist->xlu && !(SREG(25) & 4); if (sp90 || sp94) { gSPSegment(POLY_OPA_DISP++, 0x03, room->segment); if (sp90) { Gfx_SetupDL_25Opa(play->state.gfxCtx); gSPMatrix(POLY_OPA_DISP++, &gMtxClear, G_MTX_MODELVIEW | G_MTX_LOAD); gSPDisplayList(POLY_OPA_DISP++, polygonDlist->opa); } if (sp94) { gSPLoadUcodeL(POLY_OPA_DISP++, ucode_s2dex); { Vec3f sp5C; spA8 = POLY_OPA_DISP; Camera_GetSkyboxOffset(&sp5C, camera); Room_DrawBackground2D(&spA8, bgImage->source, bgImage->tlut, bgImage->width, bgImage->height, bgImage->fmt, bgImage->siz, bgImage->mode0, bgImage->tlutCount, (sp5C.x + sp5C.z) * 1.2f + sp5C.y * 0.6f, sp5C.y * 2.4f + (sp5C.x + sp5C.z) * 0.3f); POLY_OPA_DISP = spA8; } gSPLoadUcode(POLY_OPA_DISP++, SysUcode_GetUCode()); } } if (sp8C) { 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++, polygonDlist->xlu); } CLOSE_DISPS(play->state.gfxCtx); } // Room Draw Polygon Type 1 void func_80096F6C(PlayState* play, Room* room, u32 flags) { PolygonType1* polygon1 = &room->meshHeader->polygon1; if (polygon1->format == 1) { func_80096680(play, room, flags); } else if (polygon1->format == 2) { func_80096B6C(play, room, flags); } else { LOG_HUNGUP_THREAD(); } } void func_80096FD4(PlayState* play, Room* room) { room->num = -1; room->segment = NULL; } u32 func_80096FE8(PlayState* play, RoomContext* roomCtx) { u32 maxRoomSize = 0; RomFile* roomList = play->roomList; u32 roomSize; s32 i; s32 j; s32 frontRoom; s32 backRoom; u32 frontRoomSize; u32 backRoomSize; u32 cumulRoomSize; for (i = 0; i < play->numRooms; i++) { roomSize = roomList[i].vromEnd - roomList[i].vromStart; osSyncPrintf("ROOM%d size=%d\n", i, roomSize); if (maxRoomSize < roomSize) { maxRoomSize = roomSize; } } if (play->transiActorCtx.numActors != 0) { RomFile* roomList = play->roomList; TransitionActorEntry* transitionActor = &play->transiActorCtx.list[0]; LOG_NUM("game_play->room_rom_address.num", play->numRooms); for (j = 0; j < play->transiActorCtx.numActors; 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; osSyncPrintf("DOOR%d=<%d> ROOM1=<%d, %d> ROOM2=<%d, %d>\n", j, cumulRoomSize, frontRoom, frontRoomSize, backRoom, backRoomSize); if (maxRoomSize < cumulRoomSize) { maxRoomSize = cumulRoomSize; } transitionActor++; } } osSyncPrintf(VT_FGCOL(YELLOW)); // "Room buffer size=%08x(%5.1fK)" osSyncPrintf("部屋バッファサイズ=%08x(%5.1fK)\n", maxRoomSize, maxRoomSize / 1024.0f); roomCtx->bufPtrs[0] = GAMESTATE_ALLOC_MC(&play->state, maxRoomSize); // "Room buffer initial pointer=%08x" osSyncPrintf("部屋バッファ開始ポインタ=%08x\n", roomCtx->bufPtrs[0]); roomCtx->bufPtrs[1] = (void*)((intptr_t)roomCtx->bufPtrs[0] + maxRoomSize); // "Room buffer end pointer=%08x" osSyncPrintf("部屋バッファ終了ポインタ=%08x\n", roomCtx->bufPtrs[1]); osSyncPrintf(VT_RST); roomCtx->unk_30 = 0; roomCtx->status = 0; frontRoom = gSaveContext.respawnFlag > 0 ? ((void)0, gSaveContext.respawn[gSaveContext.respawnFlag - 1].roomIndex) : play->setupEntranceList[play->curSpawn].room; // In ER, override roomNum to load based on scene and spawn during scene init if (IS_RANDO && gSaveContext.respawnFlag <= 0 && Randomizer_GetSettingValue(RSK_SHUFFLE_ENTRANCES)) { frontRoom = Entrance_OverrideSpawnSceneRoom(play->sceneNum, play->curSpawn, frontRoom); } func_8009728C(play, roomCtx, frontRoom); return maxRoomSize; } s32 func_8009728C(PlayState* play, RoomContext* roomCtx, s32 roomNum) { size_t size; return OTRfunc_8009728C(play, roomCtx, roomNum); if (roomCtx->status == 0) { roomCtx->prevRoom = roomCtx->curRoom; roomCtx->curRoom.num = roomNum; roomCtx->curRoom.segment = NULL; roomCtx->status = 1; assert(roomNum < play->numRooms); size = play->roomList[roomNum].vromEnd - play->roomList[roomNum].vromStart; roomCtx->unk_34 = (void*)ALIGN16((intptr_t)roomCtx->bufPtrs[roomCtx->unk_30] - ((size + 8) * roomCtx->unk_30 + 7)); osCreateMesgQueue(&roomCtx->loadQueue, &roomCtx->loadMsg, 1); DmaMgr_SendRequest2(&roomCtx->dmaRequest, roomCtx->unk_34, play->roomList[roomNum].vromStart, size, 0, &roomCtx->loadQueue, OS_MESG_PTR(NULL), __FILE__, __LINE__); roomCtx->unk_30 ^= 1; return 1; } return 0; } s32 func_800973FC(PlayState* play, RoomContext* roomCtx) { return OTRfunc_800973FC(play, roomCtx); if (roomCtx->status == 1) { if (!osRecvMesg(&roomCtx->loadQueue, NULL, OS_MESG_NOBLOCK)) { roomCtx->status = 0; roomCtx->curRoom.segment = roomCtx->unk_34; gSegments[3] = VIRTUAL_TO_PHYSICAL(roomCtx->unk_34); Scene_ExecuteCommands(play, roomCtx->curRoom.segment); Player_SetBootData(play, GET_PLAYER(play)); Actor_SpawnTransitionActors(play, &play->actorCtx); return 1; } return 0; } return 1; } 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)); sRoomDrawHandlers[room->meshHeader->base.type](play, room, flags); } } void func_80097534(PlayState* play, RoomContext* roomCtx) { roomCtx->prevRoom.num = -1; roomCtx->prevRoom.segment = NULL; func_80031B14(play, &play->actorCtx); //kills all actors without room num set to -1 Actor_SpawnTransitionActors(play, &play->actorCtx); Map_InitRoomData(play, roomCtx->curRoom.num); if (!((play->sceneNum >= SCENE_HYRULE_FIELD) && (play->sceneNum <= SCENE_LON_LON_RANCH))) { Map_SavePlayerInitialInfo(play); } Audio_SetEnvReverb(play->roomCtx.curRoom.echo); u8 idx = gSaveContext.sohStats.tsIdx; gSaveContext.sohStats.sceneTimestamps[idx].scene = gSaveContext.sohStats.sceneNum; gSaveContext.sohStats.sceneTimestamps[idx].room = gSaveContext.sohStats.roomNum; gSaveContext.sohStats.sceneTimestamps[idx].roomTime = gSaveContext.sohStats.roomTimer / 2; gSaveContext.sohStats.sceneTimestamps[idx].isRoom = gPlayState->sceneNum == gSaveContext.sohStats.sceneTimestamps[idx].scene && gPlayState->roomCtx.curRoom.num != gSaveContext.sohStats.sceneTimestamps[idx].room; gSaveContext.sohStats.tsIdx++; gSaveContext.sohStats.roomNum = roomCtx->curRoom.num; gSaveContext.sohStats.roomTimer = 0; }