#include #include "constants.h" #include "game/debug.h" #include "game/dlights.h" #include "game/game_006900.h" #include "game/room.h" #include "game/chr.h" #include "game/prop.h" #include "game/ceil.h" #include "game/bondgun.h" #include "game/tex.h" #include "game/camera.h" #include "game/player.h" #include "game/sky.h" #include "game/stars.h" #include "game/dyntex.h" #include "game/game_13c510.h" #include "game/game_1531a0.h" #include "game/gfxmemory.h" #include "game/gfxreplace.h" #include "game/bg.h" #include "game/game_165360.h" #include "game/stagetable.h" #include "game/env.h" #include "game/room.h" #include "game/file.h" #include "game/lv.h" #include "game/texdecompress.h" #include "game/wallhit.h" #include "bss.h" #include "lib/rzip.h" #include "lib/vi.h" #include "lib/dma.h" #include "lib/main.h" #include "lib/memp.h" #include "lib/mema.h" #include "lib/rng.h" #include "lib/mtx.h" #include "lib/lib_2f490.h" #include "data.h" #include "types.h" #define BGCMD_END 0x00 #define BGCMD_PUSH 0x01 #define BGCMD_POP 0x02 #define BGCMD_AND 0x03 #define BGCMD_OR 0x04 #define BGCMD_NOT 0x05 #define BGCMD_XOR 0x06 #define BGCMD_PUSH_CAMINROOMRANGE 0x14 #define BGCMD_SETRESULT_TRUE 0x1e #define BGCMD_SETRESULT_IFPORTALINFOV 0x1f #define BGCMD_IFRESULT_SHOWROOM 0x20 #define BGCMD_SETRESULT_FALSE 0x21 #define BGCMD_SETRESULT_TRUEIFTHROUGHPORTAL 0x22 #define BGCMD_SETRESULT_FALSEIFNOTTHROUGHPORTAL 0x23 #define BGCMD_DISABLEROOM 0x24 #define BGCMD_DISABLEROOMRANGE 0x25 #define BGCMD_LOADROOM 0x26 #define BGCMD_LOADROOMRANGE 0x27 #define BGCMD_SETROOMTESTSDISABLED 0x28 #define BGCMD_PUSH_PORTALISOPEN 0x29 #define BGCMD_2A 0x2a #define BGCMD_BRANCH 0x50 #define BGCMD_THROW 0x51 #define BGCMD_CATCH 0x52 #define BGCMD_IF 0x5a #define BGCMD_ELSE 0x5b #define BGCMD_ENDIF 0x5c #define BGCMD_PORTALARG 0x64 #define BGCMD_ROOMARG 0x65 #define BGRESULT_TRUE 0 #define BGRESULT_FALSE 1 #define VTXBATCHTYPE_OPA 0x01 #define VTXBATCHTYPE_XLU 0x02 struct var800a4640 var800a4640; u8 *g_BgPrimaryData; u32 var800a4920; u32 g_BgSection3; struct room *g_Rooms; u8 *g_MpRoomVisibility; s16 g_ActiveRoomNums[350]; s32 g_NumActiveRooms; u16 g_BgUnloadDelay240; u16 g_BgUnloadDelay240_2; u32 var800a4bf4; s16 g_GlareRooms[100]; u32 *g_BgPrimaryData2; struct bgroom *g_BgRooms; struct bgportal *g_BgPortals; struct var800a4ccc *var800a4ccc; u8 *var800a4cd0; struct bgcmd *g_BgCommands; u8 *g_BgLightsFileData; f32 *g_BgTable5; s16 *g_RoomPortals; s16 var800a4ce4; s16 var800a4ce6; struct var800a4ce8 *var800a4ce8; struct portalthing *g_PortalThings; struct var800a4cf0 var800a4cf0; s32 g_StageIndex = 1; u32 var8007fc04 = 0x00000000; u8 *var8007fc08 = NULL; #if VERSION < VERSION_NTSC_1_0 u32 var80082474nb = 0; #endif s16 var8007fc0c = 0; s16 var8007fc10 = 0; s32 g_NumRoomsWithGlares = 0; u32 var8007fc18 = 0x01000100; u32 var8007fc1c = 0x00000000; s32 g_CamRoom = 0x00000001; struct var800a4640_00 *var8007fc24 = &var800a4640.unk2d0; s32 var8007fc28 = 0; s32 var8007fc2c = 0; s32 var8007fc30 = 0; s32 var8007fc34 = 0; u32 g_BgNumRoomLoadCandidates = 0x00000000; u16 var8007fc3c = 0xfffe; s32 g_NumPortalThings = 0; void roomUnpauseProps(u32 roomnum, bool tintedglassonly) { struct prop *prop; struct defaultobj *obj; s16 *propnumptr; s16 rooms[2]; s16 propnums[256]; rooms[0] = roomnum; rooms[1] = -1; roomGetProps(rooms, propnums, 256); propnumptr = propnums; while (*propnumptr >= 0) { prop = &g_Vars.props[*propnumptr]; if (!prop->active) { if (tintedglassonly) { /** * @bug: A missing prop->type check means this is inadvertently * casting other pointer types to obj pointers. By chance this * happens to be harmless. */ obj = prop->obj; if (obj->type == OBJTYPE_TINTEDGLASS) { propUnpause(prop); } } else { propUnpause(prop); } } propnumptr++; } } void roomSetOnscreen(s32 roomnum, s32 draworder, struct screenbox *box) { s32 index; #if VERSION < VERSION_NTSC_1_0 g_Rooms[roomnum].flags |= ROOMFLAG_ONSCREEN; #endif if ((g_Rooms[roomnum].flags & ROOMFLAG_DISABLEDBYSCRIPT) == 0) { #if VERSION >= VERSION_NTSC_1_0 g_Rooms[roomnum].flags |= ROOMFLAG_ONSCREEN; #endif if (g_Rooms[roomnum].flags & ROOMFLAG_0800) { box->xmin = var800a4640.unk2d0.box.xmin; box->ymin = var800a4640.unk2d0.box.ymin; box->xmax = var800a4640.unk2d0.box.xmax; box->ymax = var800a4640.unk2d0.box.ymax; } if (var8007fc3c == var800a4ce8[roomnum].unk00) { index = var800a4ce8[roomnum].unk02; if (draworder > var800a4640.unk000[index].draworder) { var800a4640.unk000[index].draworder = draworder; if (var800a4ce6 < var800a4640.unk000[index].draworder) { var800a4ce6 = var800a4640.unk000[index].draworder; } if (var800a4ce4 > var800a4640.unk000[index].draworder) { var800a4ce4 = var800a4640.unk000[index].draworder; } } boxExpand(&var800a4640.unk000[index].box, box); } else { index = var8007fc2c; if (index > 59) { index = 59; } var800a4640.unk000[index].roomnum = roomnum; var800a4640.unk000[index].draworder = draworder; var800a4640.unk000[index].box.xmin = box->xmin; var800a4640.unk000[index].box.ymin = box->ymin; var800a4640.unk000[index].box.xmax = box->xmax; var800a4640.unk000[index].box.ymax = box->ymax; if (var800a4ce6 < var800a4640.unk000[index].draworder) { var800a4ce6 = var800a4640.unk000[index].draworder; } if (var800a4ce4 > var800a4640.unk000[index].draworder) { var800a4ce4 = var800a4640.unk000[index].draworder; } var800a4ce8[roomnum].unk00 = var8007fc3c; var800a4ce8[roomnum].unk02 = index; var8007fc30++; if (var8007fc30 < 60) { var8007fc2c = var8007fc30; } roomUnpauseProps(roomnum, false); if (g_Rooms[roomnum].loaded240 == 0 && var8007fc10 > 0) { var8007fc10--; bgLoadRoom(roomnum); } else if (g_Rooms[roomnum].loaded240 == 0) { var8007fc10--; } } } } void func0f158108(s32 roomnum, u8 *arg1, u8 *arg2) { *arg1 = g_BgRooms[roomnum].unk10; *arg2 = g_BgRooms[roomnum].unk11; } struct var800a4640_00 *func0f158140(s32 roomnum) { s32 index = 60; if (var8007fc3c == var800a4ce8[roomnum].unk00) { index = var800a4ce8[roomnum].unk02; } return &var800a4640.unk000[index]; } Gfx *bg0f158184(Gfx *gdl, struct xraydata *xraydata) { struct gfxvtx *vertices; u32 *colours; s32 end; s32 i; s32 count; if (xraydata->numtris > 0) { vertices = gfxAllocateVertices(xraydata->numvertices); colours = gfxAllocateColours(xraydata->numvertices); for (i = 0; i < xraydata->numvertices; i++) { vertices[i].x = xraydata->vertices[i][0]; vertices[i].y = xraydata->vertices[i][1]; vertices[i].z = xraydata->vertices[i][2]; vertices[i].colour = i << 2; colours[i] = xraydata->colours[i]; } count = xraydata->numvertices; gDPSetColorArray(gdl++, colours, count); count = xraydata->numvertices; gDPSetVerticeArray(gdl++, vertices, count); end = (xraydata->numtris - 1) / 4 + 1; for (i = xraydata->numtris; i < xraydata->numtris * 4; i++) { xraydata->tris[i][0] = xraydata->tris[i][1] = xraydata->tris[i][2] = 0; } for (i = 0; i < end; i++) { gDPTri4(gdl++, xraydata->tris[i * 4 + 0][0], xraydata->tris[i * 4 + 0][1], xraydata->tris[i * 4 + 0][2], xraydata->tris[i * 4 + 1][0], xraydata->tris[i * 4 + 1][1], xraydata->tris[i * 4 + 1][2], xraydata->tris[i * 4 + 2][0], xraydata->tris[i * 4 + 2][1], xraydata->tris[i * 4 + 2][2], xraydata->tris[i * 4 + 3][0], xraydata->tris[i * 4 + 3][1], xraydata->tris[i * 4 + 3][2]); } } xraydata->numtris = 0; xraydata->numvertices = 0; return gdl; } Gfx *func0f158400(Gfx *gdl, struct xraydata *xraydata, s16 vertices1[3], s16 vertices2[3], s16 vertices3[3], u32 colour1, u32 colour2, u32 colour3) { s16 sp30[3] = {-1, -1, -1}; s32 count = 0; s16 i; if (xraydata->numtris >= 64) { gdl = bg0f158184(gdl, xraydata); } for (i = 0; i < xraydata->numvertices && sp30[0] == -1; i++) { if (vertices1[0] == xraydata->vertices[i][0] && vertices1[1] == xraydata->vertices[i][1] && vertices1[2] == xraydata->vertices[i][2]) { sp30[0] = i; count++; } } for (i = 0; i < xraydata->numvertices && sp30[1] == -1; i++) { if (vertices2[0] == xraydata->vertices[i][0] && vertices2[1] == xraydata->vertices[i][1] && vertices2[2] == xraydata->vertices[i][2]) { sp30[1] = i; count++; } } for (i = 0; i < xraydata->numvertices && sp30[2] == -1; i++) { if (vertices3[0] == xraydata->vertices[i][0] && vertices3[1] == xraydata->vertices[i][1] && vertices3[2] == xraydata->vertices[i][2]) { sp30[2] = i; count++; } } if (count < 3) { if (xraydata->numvertices - count + 3 > 16) { gdl = bg0f158184(gdl, xraydata); xraydata->vertices[0][0] = vertices1[0]; xraydata->vertices[0][1] = vertices1[1]; xraydata->vertices[0][2] = vertices1[2]; xraydata->colours[0] = colour1; xraydata->vertices[1][0] = vertices2[0]; xraydata->vertices[1][1] = vertices2[1]; xraydata->vertices[1][2] = vertices2[2]; xraydata->colours[1] = colour2; xraydata->vertices[2][0] = vertices3[0]; xraydata->vertices[2][1] = vertices3[1]; xraydata->vertices[2][2] = vertices3[2]; xraydata->colours[2] = colour3; xraydata->numvertices = 3; sp30[0] = 0; sp30[1] = 1; sp30[2] = 2; } else { if (sp30[0] == -1) { xraydata->vertices[xraydata->numvertices][0] = vertices1[0]; xraydata->vertices[xraydata->numvertices][1] = vertices1[1]; xraydata->vertices[xraydata->numvertices][2] = vertices1[2]; xraydata->colours[xraydata->numvertices] = colour1; sp30[0] = xraydata->numvertices; xraydata->numvertices++; } if (sp30[1] == -1) { xraydata->vertices[xraydata->numvertices][0] = vertices2[0]; xraydata->vertices[xraydata->numvertices][1] = vertices2[1]; xraydata->vertices[xraydata->numvertices][2] = vertices2[2]; xraydata->colours[xraydata->numvertices] = colour2; sp30[1] = xraydata->numvertices; xraydata->numvertices++; } if (sp30[2] == -1) { xraydata->vertices[xraydata->numvertices][0] = vertices3[0]; xraydata->vertices[xraydata->numvertices][1] = vertices3[1]; xraydata->vertices[xraydata->numvertices][2] = vertices3[2]; xraydata->colours[xraydata->numvertices] = colour3; sp30[2] = xraydata->numvertices; xraydata->numvertices++; } } } xraydata->tris[xraydata->numtris][0] = sp30[0]; xraydata->tris[xraydata->numtris][1] = sp30[1]; xraydata->tris[xraydata->numtris][2] = sp30[2]; xraydata->numtris++; return gdl; } void bgChooseXrayVtxColour(bool *inrange, s16 vertex[3], u32 *colour, struct xraydata *xraydata) { f32 sp2c[3]; f32 f12; f32 alphafrac; f32 anglefrac; struct player *player = g_Vars.currentplayer; f32 colfrac; *inrange = false; sp2c[0] = (f32) vertex[0] - (f32) xraydata->unk000; sp2c[0] = sp2c[0] * sp2c[0]; if (sp2c[0] < xraydata->unk010) { sp2c[2] = (f32) vertex[2] - (f32) xraydata->unk008; sp2c[2] = sp2c[2] * sp2c[2]; if (sp2c[2] < xraydata->unk010) { sp2c[1] = (f32) vertex[1] - (f32) xraydata->unk004; sp2c[1] = sp2c[1] * sp2c[1]; if (sp2c[1] < xraydata->unk010) { f32 dist = sqrtf(sp2c[0] + sp2c[1] + sp2c[2]); if (dist < xraydata->unk00c) { *inrange = true; f12 = dist / xraydata->unk00c; if (xraydata->unk014 < f12) { alphafrac = 1.0f - (f12 - xraydata->unk014) / (1.0f - xraydata->unk014); } else { alphafrac = 1.0f; } if (f12 < xraydata->unk01c) { anglefrac = xraydata->unk01c; anglefrac = f12 / anglefrac; if (1); colfrac = sinf((1.0f - anglefrac) * 1.5707964f); *colour = (u32)(colfrac * 255.0f) << player->ecol_1 | (u32)((1.0f - colfrac) * 255.0f) << player->ecol_2 | (u32)(alphafrac * 128.0f); } else { anglefrac = (f12 - xraydata->unk01c) / (1.0f - xraydata->unk01c); anglefrac = 0.65f * anglefrac + 0.35f; if (1); colfrac = sinf(anglefrac * 1.5707964f); *colour = (u32)(colfrac * 255.0f) << player->ecol_3 | 0xff << player->ecol_2 | (u32)(alphafrac * 128.0f); } } } } } if (*inrange == false) { *colour = 0x0000ff00; } } Gfx *func0f158d9c(Gfx *gdl, struct xraydata *xraydata, s16 arg2[3], s16 arg3[3], s16 arg4[3], s32 arg5, s32 arg6, s32 arg7, s32 arg8, s32 arg9, s32 arg10) { s32 spa4[3]; s16 sp9c[3] = {0, 0, 0}; s32 sum; s16 sp84[3][3]; bool inrange[3]; u32 colours[3]; s32 sp68 = -1; s32 sp64 = 0; if (xraydata->unk020 > 0) { spa4[0] = arg3[0] - arg2[0]; spa4[1] = arg3[1] - arg2[1]; spa4[2] = arg3[2] - arg2[2]; sum = spa4[0] * spa4[0] + spa4[1] * spa4[1] + spa4[2] * spa4[2]; if (sum > xraydata->unk024) { sp84[0][0] = (arg3[0] + arg2[0]) / 2; sp84[0][1] = (arg3[1] + arg2[1]) / 2; sp84[0][2] = (arg3[2] + arg2[2]) / 2; sp9c[0] = 1; sp64++; sp68 = 0; bgChooseXrayVtxColour(&inrange[0], sp84[0], &colours[0], xraydata); } spa4[0] = arg4[0] - arg3[0]; spa4[1] = arg4[1] - arg3[1]; spa4[2] = arg4[2] - arg3[2]; sum = spa4[0] * spa4[0] + spa4[1] * spa4[1] + spa4[2] * spa4[2]; if (sum > xraydata->unk024) { sp84[1][0] = (arg4[0] + arg3[0]) / 2; sp84[1][1] = (arg4[1] + arg3[1]) / 2; sp84[1][2] = (arg4[2] + arg3[2]) / 2; sp9c[1] = 1; sp64++; sp68 = 1; bgChooseXrayVtxColour(&inrange[1], sp84[1], &colours[1], xraydata); } spa4[0] = arg2[0] - arg4[0]; spa4[1] = arg2[1] - arg4[1]; spa4[2] = arg2[2] - arg4[2]; sum = spa4[0] * spa4[0] + spa4[1] * spa4[1] + spa4[2] * spa4[2]; if (sum > xraydata->unk024) { sp84[2][0] = (arg2[0] + arg4[0]) / 2; sp84[2][1] = (arg2[1] + arg4[1]) / 2; sp84[2][2] = (arg2[2] + arg4[2]) / 2; sp9c[2] = 1; sp64++; sp68 = 2; bgChooseXrayVtxColour(&inrange[2], sp84[2], &colours[2], xraydata); } } if (sp64 == 0) { if (arg8 || arg9 || arg10) { return func0f158400(gdl, xraydata, arg2, arg3, arg4, arg5, arg6, arg7); } } else { bool render; if (arg8 || arg9 || arg10) { render = true; } else { u32 mask1 = 0; u32 mask2 = 0; render = true; mask1 = (arg2[0] < xraydata->unk000) ? 1 : 0; if (arg2[1] < xraydata->unk004) { mask1 |= 2; } if (arg2[2] < xraydata->unk008) { mask1 |= 4; } mask2 = (arg3[0] < xraydata->unk000) ? 1 : 0; if (arg3[1] < xraydata->unk004) { mask2 |= 2; } if (arg3[2] < xraydata->unk008) { mask2 |= 4; } if (mask1 == mask2) { mask2 = (arg4[0] < xraydata->unk000) ? 1 : 0; if (arg4[1] < xraydata->unk004) { mask2 |= 2; } if (arg4[2] < xraydata->unk008) { mask2 |= 4; } if (mask1 == mask2) { render = false; } } } if (render) { if (sp64 == 1) { if (sp68 == 0) { gdl = func0f158d9c(gdl, xraydata, arg2, sp84[0], arg4, arg5, colours[0], arg7, arg8, inrange[0], arg10); gdl = func0f158d9c(gdl, xraydata, arg4, sp84[0], arg3, arg7, colours[0], arg6, arg10, inrange[0], arg9); } else if (sp68 == 1) { gdl = func0f158d9c(gdl, xraydata, arg3, sp84[1], arg2, arg6, colours[1], arg5, arg9, inrange[1], arg8); gdl = func0f158d9c(gdl, xraydata, arg2, sp84[1], arg4, arg5, colours[1], arg7, arg8, inrange[1], arg10); } else if (sp68 == 2) { gdl = func0f158d9c(gdl, xraydata, arg4, sp84[2], arg3, arg7, colours[2], arg6, arg10, inrange[2], arg9); gdl = func0f158d9c(gdl, xraydata, arg3, sp84[2], arg2, arg6, colours[2], arg5, arg9, inrange[2], arg8); } } else if (sp64 == 2) { s32 v0 = 0; if (sp9c[1] == 0) { v0 = 1; } if (sp9c[2] == 0) { v0 = 2; } if (v0 == 0) { gdl = func0f158d9c(gdl, xraydata, arg4, sp84[2], sp84[1], arg7, colours[2], colours[1], arg10, inrange[2], inrange[1]); gdl = func0f158d9c(gdl, xraydata, arg3, sp84[1], sp84[2], arg6, colours[1], colours[2], arg9, inrange[1], inrange[2]); gdl = func0f158d9c(gdl, xraydata, arg2, arg3, sp84[2], arg5, arg6, colours[2], arg8, arg9, inrange[2]); } else if (v0 == 1) { gdl = func0f158d9c(gdl, xraydata, arg2, sp84[0], sp84[2], arg5, colours[0], colours[2], arg8, inrange[0], inrange[2]); gdl = func0f158d9c(gdl, xraydata, arg4, sp84[2], sp84[0], arg7, colours[2], colours[0], arg10, inrange[2], inrange[0]); gdl = func0f158d9c(gdl, xraydata, arg3, arg4, sp84[0], arg6, arg7, colours[0], arg9, arg10, inrange[0]); } else { gdl = func0f158d9c(gdl, xraydata, arg3, sp84[1], sp84[0], arg6, colours[1], colours[0], arg9, inrange[1], inrange[0]); gdl = func0f158d9c(gdl, xraydata, arg2, sp84[0], sp84[1], arg5, colours[0], colours[1], arg8, inrange[0], inrange[1]); gdl = func0f158d9c(gdl, xraydata, arg4, arg2, sp84[1], arg7, arg5, colours[1], arg10, arg8, inrange[1]); } } else if (sp64 == 3) { gdl = func0f158d9c(gdl, xraydata, arg2, sp84[0], sp84[2], arg5, colours[0], colours[2], arg8, inrange[0], inrange[2]); gdl = func0f158d9c(gdl, xraydata, arg3, sp84[1], sp84[0], arg6, colours[1], colours[0], arg9, inrange[1], inrange[0]); gdl = func0f158d9c(gdl, xraydata, arg4, sp84[2], sp84[1], arg7, colours[2], colours[1], arg10, inrange[2], inrange[1]); gdl = func0f158d9c(gdl, xraydata, sp84[0], sp84[1], sp84[2], colours[0], colours[1], colours[2], inrange[0], inrange[1], inrange[2]); } } } return gdl; } u32 var8007fc54 = 0; bool g_BgCmdStack[20] = {0}; s32 g_BgCmdStackIndex = 0; u32 g_BgCmdResult = BGRESULT_TRUE; #if MATCHING GLOBAL_ASM( glabel bg0f1598b4 .late_rodata glabel var7f1b75c4 .word 0x3f333333 .text /* f1598b4: 27bdfc28 */ addiu $sp,$sp,-984 /* f1598b8: afbf005c */ sw $ra,0x5c($sp) /* f1598bc: afb60050 */ sw $s6,0x50($sp) /* f1598c0: afb00038 */ sw $s0,0x38($sp) /* f1598c4: 00e08025 */ or $s0,$a3,$zero /* f1598c8: 00a0b025 */ or $s6,$a1,$zero /* f1598cc: afbe0058 */ sw $s8,0x58($sp) /* f1598d0: afb70054 */ sw $s7,0x54($sp) /* f1598d4: afb5004c */ sw $s5,0x4c($sp) /* f1598d8: afb40048 */ sw $s4,0x48($sp) /* f1598dc: afb30044 */ sw $s3,0x44($sp) /* f1598e0: afb20040 */ sw $s2,0x40($sp) /* f1598e4: afb1003c */ sw $s1,0x3c($sp) /* f1598e8: afa403d8 */ sw $a0,0x3d8($sp) /* f1598ec: 0fc59570 */ jal stageGetCurrent /* f1598f0: afa603e0 */ sw $a2,0x3e0($sp) /* f1598f4: 3c03800a */ lui $v1,%hi(g_Vars+0x284) /* f1598f8: 8c63a244 */ lw $v1,%lo(g_Vars+0x284)($v1) /* f1598fc: 3c017f1b */ lui $at,%hi(var7f1b75c4) /* f159900: c42075c4 */ lwc1 $f0,%lo(var7f1b75c4)($at) /* f159904: c4640028 */ lwc1 $f4,0x28($v1) /* f159908: 3c013e80 */ lui $at,0x3e80 /* f15990c: 44815000 */ mtc1 $at,$f10 /* f159910: e7a40190 */ swc1 $f4,0x190($sp) /* f159914: c7a60190 */ lwc1 $f6,0x190($sp) /* f159918: 3c013e80 */ lui $at,0x3e80 /* f15991c: 46063202 */ mul.s $f8,$f6,$f6 /* f159920: 00000000 */ nop /* f159924: 460a3402 */ mul.s $f16,$f6,$f10 /* f159928: 44815000 */ mtc1 $at,$f10 /* f15992c: e7a80194 */ swc1 $f8,0x194($sp) /* f159930: e7b0019c */ swc1 $f16,0x19c($sp) /* f159934: c4720024 */ lwc1 $f18,0x24($v1) /* f159938: 46069103 */ div.s $f4,$f18,$f6 /* f15993c: e7a401a0 */ swc1 $f4,0x1a0($sp) /* f159940: c7a801a0 */ lwc1 $f8,0x1a0($sp) /* f159944: 4608003c */ c.lt.s $f0,$f8 /* f159948: 00000000 */ nop /* f15994c: 45000002 */ bc1f .L0f159958 /* f159950: 00000000 */ nop /* f159954: e7a001a0 */ swc1 $f0,0x1a0($sp) .L0f159958: /* f159958: e7aa0198 */ swc1 $f10,0x198($sp) /* f15995c: 844e002c */ lh $t6,0x2c($v0) /* f159960: 241e0006 */ addiu $s8,$zero,0x6 /* f159964: 27b70120 */ addiu $s7,$sp,0x120 /* f159968: 01ce0019 */ multu $t6,$t6 /* f15996c: afae01a4 */ sw $t6,0x1a4($sp) /* f159970: 0000c012 */ mflo $t8 /* f159974: afb801a8 */ sw $t8,0x1a8($sp) /* f159978: 86190000 */ lh $t9,0x0($s0) /* f15997c: afb90184 */ sw $t9,0x184($sp) /* f159980: 860e0002 */ lh $t6,0x2($s0) /* f159984: afae0188 */ sw $t6,0x188($sp) /* f159988: 860f0004 */ lh $t7,0x4($s0) /* f15998c: a7a003ce */ sh $zero,0x3ce($sp) /* f159990: a7a003cc */ sh $zero,0x3cc($sp) /* f159994: afaf018c */ sw $t7,0x18c($sp) .L0f159998: /* f159998: 82c20000 */ lb $v0,0x0($s6) /* f15999c: 2401ffb8 */ addiu $at,$zero,-72 /* f1599a0: 1041014f */ beq $v0,$at,.L0f159ee0 /* f1599a4: 24010001 */ addiu $at,$zero,0x1 /* f1599a8: 1041014b */ beq $v0,$at,.L0f159ed8 /* f1599ac: 24010004 */ addiu $at,$zero,0x4 /* f1599b0: 5441002a */ bnel $v0,$at,.L0f159a5c /* f1599b4: 2401ffbf */ addiu $at,$zero,-65 /* f1599b8: 92c20001 */ lbu $v0,0x1($s6) /* f1599bc: 8ec40004 */ lw $a0,0x4($s6) /* f1599c0: 3c0100ff */ lui $at,0xff /* f1599c4: 3421ffff */ ori $at,$at,0xffff /* f1599c8: 0002a902 */ srl $s5,$v0,0x4 /* f1599cc: 26b50001 */ addiu $s5,$s5,0x1 /* f1599d0: 0081c024 */ and $t8,$a0,$at /* f1599d4: 03002025 */ or $a0,$t8,$zero /* f1599d8: 00009025 */ or $s2,$zero,$zero /* f1599dc: 1aa0013e */ blez $s5,.L0f159ed8 /* f1599e0: 3043000f */ andi $v1,$v0,0xf /* f1599e4: 8fb803e0 */ lw $t8,0x3e0($sp) /* f1599e8: 0003c880 */ sll $t9,$v1,0x2 /* f1599ec: 0323c823 */ subu $t9,$t9,$v1 /* f1599f0: 0019c840 */ sll $t9,$t9,0x1 /* f1599f4: 00037080 */ sll $t6,$v1,0x2 /* f1599f8: 27af00e0 */ addiu $t7,$sp,0xe0 /* f1599fc: 01cfa021 */ addu $s4,$t6,$t7 /* f159a00: 02f98021 */ addu $s0,$s7,$t9 /* f159a04: 27b300a0 */ addiu $s3,$sp,0xa0 /* f159a08: 03048821 */ addu $s1,$t8,$a0 .L0f159a0c: /* f159a0c: 86390000 */ lh $t9,0x0($s1) /* f159a10: 02602025 */ or $a0,$s3,$zero /* f159a14: 02002825 */ or $a1,$s0,$zero /* f159a18: a6190000 */ sh $t9,0x0($s0) /* f159a1c: 862e0002 */ lh $t6,0x2($s1) /* f159a20: 02803025 */ or $a2,$s4,$zero /* f159a24: 27a70184 */ addiu $a3,$sp,0x184 /* f159a28: a60e0002 */ sh $t6,0x2($s0) /* f159a2c: 862f0004 */ lh $t7,0x4($s1) /* f159a30: 0fc56221 */ jal bgChooseXrayVtxColour /* f159a34: a60f0004 */ sh $t7,0x4($s0) /* f159a38: 26520001 */ addiu $s2,$s2,0x1 /* f159a3c: 26100006 */ addiu $s0,$s0,0x6 /* f159a40: 26730004 */ addiu $s3,$s3,0x4 /* f159a44: 26940004 */ addiu $s4,$s4,0x4 /* f159a48: 1655fff0 */ bne $s2,$s5,.L0f159a0c /* f159a4c: 2631000c */ addiu $s1,$s1,0xc /* f159a50: 1000ffd1 */ b .L0f159998 /* f159a54: 26d60008 */ addiu $s6,$s6,0x8 /* f159a58: 2401ffbf */ addiu $at,$zero,-65 .L0f159a5c: /* f159a5c: 14410056 */ bne $v0,$at,.L0f159bb8 /* f159a60: 27ad00a0 */ addiu $t5,$sp,0xa0 /* f159a64: 92d80005 */ lbu $t8,0x5($s6) /* f159a68: 241f000a */ addiu $ra,$zero,0xa /* f159a6c: 92cf0006 */ lbu $t7,0x6($s6) /* f159a70: 031f001a */ div $zero,$t8,$ra /* f159a74: 00001012 */ mflo $v0 /* f159a78: 0002cc00 */ sll $t9,$v0,0x10 /* f159a7c: 00197403 */ sra $t6,$t9,0x10 /* f159a80: 01ff001a */ div $zero,$t7,$ra /* f159a84: 01c01025 */ or $v0,$t6,$zero /* f159a88: 00001812 */ mflo $v1 /* f159a8c: 92ce0007 */ lbu $t6,0x7($s6) /* f159a90: 27ac00e0 */ addiu $t4,$sp,0xe0 /* f159a94: 17e00002 */ bnez $ra,.L0f159aa0 /* f159a98: 00000000 */ nop /* f159a9c: 0007000d */ break 0x7 .L0f159aa0: /* f159aa0: 2401ffff */ addiu $at,$zero,-1 /* f159aa4: 17e10004 */ bne $ra,$at,.L0f159ab8 /* f159aa8: 3c018000 */ lui $at,0x8000 /* f159aac: 17010002 */ bne $t8,$at,.L0f159ab8 /* f159ab0: 00000000 */ nop /* f159ab4: 0006000d */ break 0x6 .L0f159ab8: /* f159ab8: 01df001a */ div $zero,$t6,$ra /* f159abc: 00004012 */ mflo $t0 /* f159ac0: 0003c400 */ sll $t8,$v1,0x10 /* f159ac4: 0018cc03 */ sra $t9,$t8,0x10 /* f159ac8: 005e0019 */ multu $v0,$s8 /* f159acc: 03201825 */ or $v1,$t9,$zero /* f159ad0: 17e00002 */ bnez $ra,.L0f159adc /* f159ad4: 00000000 */ nop /* f159ad8: 0007000d */ break 0x7 .L0f159adc: /* f159adc: 2401ffff */ addiu $at,$zero,-1 /* f159ae0: 17e10004 */ bne $ra,$at,.L0f159af4 /* f159ae4: 3c018000 */ lui $at,0x8000 /* f159ae8: 15e10002 */ bne $t7,$at,.L0f159af4 /* f159aec: 00000000 */ nop /* f159af0: 0006000d */ break 0x6 .L0f159af4: /* f159af4: 0000c812 */ mflo $t9 /* f159af8: 00087c00 */ sll $t7,$t0,0x10 /* f159afc: 17e00002 */ bnez $ra,.L0f159b08 /* f159b00: 00000000 */ nop /* f159b04: 0007000d */ break 0x7 .L0f159b08: /* f159b08: 2401ffff */ addiu $at,$zero,-1 /* f159b0c: 17e10004 */ bne $ra,$at,.L0f159b20 /* f159b10: 3c018000 */ lui $at,0x8000 /* f159b14: 15c10002 */ bne $t6,$at,.L0f159b20 /* f159b18: 00000000 */ nop /* f159b1c: 0006000d */ break 0x6 .L0f159b20: /* f159b20: 007e0019 */ multu $v1,$s8 /* f159b24: 000fc403 */ sra $t8,$t7,0x10 /* f159b28: 03004025 */ or $t0,$t8,$zero /* f159b2c: 02f93021 */ addu $a2,$s7,$t9 /* f159b30: 00024880 */ sll $t1,$v0,0x2 /* f159b34: 0189c821 */ addu $t9,$t4,$t1 /* f159b38: 00035080 */ sll $t2,$v1,0x2 /* f159b3c: 00085880 */ sll $t3,$t0,0x2 /* f159b40: 8fa403d8 */ lw $a0,0x3d8($sp) /* f159b44: 27a50184 */ addiu $a1,$sp,0x184 /* f159b48: 00007012 */ mflo $t6 /* f159b4c: 02ee3821 */ addu $a3,$s7,$t6 /* f159b50: 00000000 */ nop /* f159b54: 031e0019 */ multu $t8,$s8 /* f159b58: 00007812 */ mflo $t7 /* f159b5c: 02efc021 */ addu $t8,$s7,$t7 /* f159b60: afb80010 */ sw $t8,0x10($sp) /* f159b64: 8f2e0000 */ lw $t6,0x0($t9) /* f159b68: 018a7821 */ addu $t7,$t4,$t2 /* f159b6c: 018bc821 */ addu $t9,$t4,$t3 /* f159b70: afae0014 */ sw $t6,0x14($sp) /* f159b74: 8df80000 */ lw $t8,0x0($t7) /* f159b78: 01a97821 */ addu $t7,$t5,$t1 /* f159b7c: afb80018 */ sw $t8,0x18($sp) /* f159b80: 8f2e0000 */ lw $t6,0x0($t9) /* f159b84: 01aac821 */ addu $t9,$t5,$t2 /* f159b88: afae001c */ sw $t6,0x1c($sp) /* f159b8c: 8df80000 */ lw $t8,0x0($t7) /* f159b90: 01ab7821 */ addu $t7,$t5,$t3 /* f159b94: afb80020 */ sw $t8,0x20($sp) /* f159b98: 8f2e0000 */ lw $t6,0x0($t9) /* f159b9c: afae0024 */ sw $t6,0x24($sp) /* f159ba0: 8df80000 */ lw $t8,0x0($t7) /* f159ba4: 0fc56367 */ jal func0f158d9c /* f159ba8: afb80028 */ sw $t8,0x28($sp) /* f159bac: afa203d8 */ sw $v0,0x3d8($sp) /* f159bb0: 1000ff79 */ b .L0f159998 /* f159bb4: 26d60008 */ addiu $s6,$s6,0x8 .L0f159bb8: /* f159bb8: 2401ffb1 */ addiu $at,$zero,-79 /* f159bbc: 144100c6 */ bne $v0,$at,.L0f159ed8 /* f159bc0: 00000000 */ nop /* f159bc4: 8ed00004 */ lw $s0,0x4($s6) /* f159bc8: 92d10007 */ lbu $s1,0x7($s6) /* f159bcc: 8ed20000 */ lw $s2,0x0($s6) /* f159bd0: 3219000f */ andi $t9,$s0,0xf /* f159bd4: 00197400 */ sll $t6,$t9,0x10 /* f159bd8: 000e8403 */ sra $s0,$t6,0x10 /* f159bdc: 021e0019 */ multu $s0,$s8 /* f159be0: 0011c102 */ srl $t8,$s1,0x4 /* f159be4: 0018cc00 */ sll $t9,$t8,0x10 /* f159be8: 00198c03 */ sra $s1,$t9,0x10 /* f159bec: 324f000f */ andi $t7,$s2,0xf /* f159bf0: 000fc400 */ sll $t8,$t7,0x10 /* f159bf4: 00189403 */ sra $s2,$t8,0x10 /* f159bf8: 27a200e0 */ addiu $v0,$sp,0xe0 /* f159bfc: 00109880 */ sll $s3,$s0,0x2 /* f159c00: 0011a080 */ sll $s4,$s1,0x2 /* f159c04: 00007012 */ mflo $t6 /* f159c08: 02ee3021 */ addu $a2,$s7,$t6 /* f159c0c: 00537021 */ addu $t6,$v0,$s3 /* f159c10: 023e0019 */ multu $s1,$s8 /* f159c14: 0012a880 */ sll $s5,$s2,0x2 /* f159c18: 27a300a0 */ addiu $v1,$sp,0xa0 /* f159c1c: 8fa403d8 */ lw $a0,0x3d8($sp) /* f159c20: 27a50184 */ addiu $a1,$sp,0x184 /* f159c24: 00007812 */ mflo $t7 /* f159c28: 02ef3821 */ addu $a3,$s7,$t7 /* f159c2c: 00000000 */ nop /* f159c30: 025e0019 */ multu $s2,$s8 /* f159c34: 0000c012 */ mflo $t8 /* f159c38: 02f8c821 */ addu $t9,$s7,$t8 /* f159c3c: afb90010 */ sw $t9,0x10($sp) /* f159c40: 8dcf0000 */ lw $t7,0x0($t6) /* f159c44: 0054c021 */ addu $t8,$v0,$s4 /* f159c48: 00557021 */ addu $t6,$v0,$s5 /* f159c4c: afaf0014 */ sw $t7,0x14($sp) /* f159c50: 8f190000 */ lw $t9,0x0($t8) /* f159c54: 0073c021 */ addu $t8,$v1,$s3 /* f159c58: afb90018 */ sw $t9,0x18($sp) /* f159c5c: 8dcf0000 */ lw $t7,0x0($t6) /* f159c60: 00747021 */ addu $t6,$v1,$s4 /* f159c64: afaf001c */ sw $t7,0x1c($sp) /* f159c68: 8f190000 */ lw $t9,0x0($t8) /* f159c6c: 0075c021 */ addu $t8,$v1,$s5 /* f159c70: afb90020 */ sw $t9,0x20($sp) /* f159c74: 8dcf0000 */ lw $t7,0x0($t6) /* f159c78: afaf0024 */ sw $t7,0x24($sp) /* f159c7c: 8f190000 */ lw $t9,0x0($t8) /* f159c80: 0fc56367 */ jal func0f158d9c /* f159c84: afb90028 */ sw $t9,0x28($sp) /* f159c88: 92d00006 */ lbu $s0,0x6($s6) /* f159c8c: 96d10006 */ lhu $s1,0x6($s6) /* f159c90: 92d20003 */ lbu $s2,0x3($s6) /* f159c94: 320e000f */ andi $t6,$s0,0xf /* f159c98: 000e7c00 */ sll $t7,$t6,0x10 /* f159c9c: 000f8403 */ sra $s0,$t7,0x10 /* f159ca0: 021e0019 */ multu $s0,$s8 /* f159ca4: 0011cb02 */ srl $t9,$s1,0xc /* f159ca8: 00197400 */ sll $t6,$t9,0x10 /* f159cac: 000e8c03 */ sra $s1,$t6,0x10 /* f159cb0: 0012c102 */ srl $t8,$s2,0x4 /* f159cb4: 0018cc00 */ sll $t9,$t8,0x10 /* f159cb8: 00199403 */ sra $s2,$t9,0x10 /* f159cbc: 27a300e0 */ addiu $v1,$sp,0xe0 /* f159cc0: 00109880 */ sll $s3,$s0,0x2 /* f159cc4: 0011a080 */ sll $s4,$s1,0x2 /* f159cc8: 00007812 */ mflo $t7 /* f159ccc: 02ef3021 */ addu $a2,$s7,$t7 /* f159cd0: 00737821 */ addu $t7,$v1,$s3 /* f159cd4: 023e0019 */ multu $s1,$s8 /* f159cd8: 0012a880 */ sll $s5,$s2,0x2 /* f159cdc: 27a800a0 */ addiu $t0,$sp,0xa0 /* f159ce0: 00402025 */ or $a0,$v0,$zero /* f159ce4: 27a50184 */ addiu $a1,$sp,0x184 /* f159ce8: 0000c012 */ mflo $t8 /* f159cec: 02f83821 */ addu $a3,$s7,$t8 /* f159cf0: 00000000 */ nop /* f159cf4: 025e0019 */ multu $s2,$s8 /* f159cf8: 0000c812 */ mflo $t9 /* f159cfc: 02f97021 */ addu $t6,$s7,$t9 /* f159d00: afae0010 */ sw $t6,0x10($sp) /* f159d04: 8df80000 */ lw $t8,0x0($t7) /* f159d08: 0074c821 */ addu $t9,$v1,$s4 /* f159d0c: 00757821 */ addu $t7,$v1,$s5 /* f159d10: afb80014 */ sw $t8,0x14($sp) /* f159d14: 8f2e0000 */ lw $t6,0x0($t9) /* f159d18: 0113c821 */ addu $t9,$t0,$s3 /* f159d1c: afae0018 */ sw $t6,0x18($sp) /* f159d20: 8df80000 */ lw $t8,0x0($t7) /* f159d24: 01147821 */ addu $t7,$t0,$s4 /* f159d28: afb8001c */ sw $t8,0x1c($sp) /* f159d2c: 8f2e0000 */ lw $t6,0x0($t9) /* f159d30: 0115c821 */ addu $t9,$t0,$s5 /* f159d34: afae0020 */ sw $t6,0x20($sp) /* f159d38: 8df80000 */ lw $t8,0x0($t7) /* f159d3c: afb80024 */ sw $t8,0x24($sp) /* f159d40: 8f2e0000 */ lw $t6,0x0($t9) /* f159d44: 0fc56367 */ jal func0f158d9c /* f159d48: afae0028 */ sw $t6,0x28($sp) /* f159d4c: 96d00004 */ lhu $s0,0x4($s6) /* f159d50: 92d10005 */ lbu $s1,0x5($s6) /* f159d54: 92d20002 */ lbu $s2,0x2($s6) /* f159d58: 320f000f */ andi $t7,$s0,0xf /* f159d5c: 000fc400 */ sll $t8,$t7,0x10 /* f159d60: 00188403 */ sra $s0,$t8,0x10 /* f159d64: 021e0019 */ multu $s0,$s8 /* f159d68: 00117102 */ srl $t6,$s1,0x4 /* f159d6c: 000e7c00 */ sll $t7,$t6,0x10 /* f159d70: 000f8c03 */ sra $s1,$t7,0x10 /* f159d74: 3259000f */ andi $t9,$s2,0xf /* f159d78: 00197400 */ sll $t6,$t9,0x10 /* f159d7c: 000e9403 */ sra $s2,$t6,0x10 /* f159d80: 27a300e0 */ addiu $v1,$sp,0xe0 /* f159d84: 00109880 */ sll $s3,$s0,0x2 /* f159d88: 0011a080 */ sll $s4,$s1,0x2 /* f159d8c: 0000c012 */ mflo $t8 /* f159d90: 02f83021 */ addu $a2,$s7,$t8 /* f159d94: 0073c021 */ addu $t8,$v1,$s3 /* f159d98: 023e0019 */ multu $s1,$s8 /* f159d9c: 0012a880 */ sll $s5,$s2,0x2 /* f159da0: 27a800a0 */ addiu $t0,$sp,0xa0 /* f159da4: 00402025 */ or $a0,$v0,$zero /* f159da8: 27a50184 */ addiu $a1,$sp,0x184 /* f159dac: 0000c812 */ mflo $t9 /* f159db0: 02f93821 */ addu $a3,$s7,$t9 /* f159db4: 00000000 */ nop /* f159db8: 025e0019 */ multu $s2,$s8 /* f159dbc: 00007012 */ mflo $t6 /* f159dc0: 02ee7821 */ addu $t7,$s7,$t6 /* f159dc4: afaf0010 */ sw $t7,0x10($sp) /* f159dc8: 8f190000 */ lw $t9,0x0($t8) /* f159dcc: 00747021 */ addu $t6,$v1,$s4 /* f159dd0: 0075c021 */ addu $t8,$v1,$s5 /* f159dd4: afb90014 */ sw $t9,0x14($sp) /* f159dd8: 8dcf0000 */ lw $t7,0x0($t6) /* f159ddc: 01137021 */ addu $t6,$t0,$s3 /* f159de0: afaf0018 */ sw $t7,0x18($sp) /* f159de4: 8f190000 */ lw $t9,0x0($t8) /* f159de8: 0114c021 */ addu $t8,$t0,$s4 /* f159dec: afb9001c */ sw $t9,0x1c($sp) /* f159df0: 8dcf0000 */ lw $t7,0x0($t6) /* f159df4: 01157021 */ addu $t6,$t0,$s5 /* f159df8: afaf0020 */ sw $t7,0x20($sp) /* f159dfc: 8f190000 */ lw $t9,0x0($t8) /* f159e00: afb90024 */ sw $t9,0x24($sp) /* f159e04: 8dcf0000 */ lw $t7,0x0($t6) /* f159e08: 0fc56367 */ jal func0f158d9c /* f159e0c: afaf0028 */ sw $t7,0x28($sp) /* f159e10: 92d00004 */ lbu $s0,0x4($s6) /* f159e14: 8ed10004 */ lw $s1,0x4($s6) /* f159e18: 96d20002 */ lhu $s2,0x2($s6) /* f159e1c: 3218000f */ andi $t8,$s0,0xf /* f159e20: 0018cc00 */ sll $t9,$t8,0x10 /* f159e24: 00198403 */ sra $s0,$t9,0x10 /* f159e28: 021e0019 */ multu $s0,$s8 /* f159e2c: 00117f02 */ srl $t7,$s1,0x1c /* f159e30: 000fc400 */ sll $t8,$t7,0x10 /* f159e34: 00188c03 */ sra $s1,$t8,0x10 /* f159e38: 00127302 */ srl $t6,$s2,0xc /* f159e3c: 000e7c00 */ sll $t7,$t6,0x10 /* f159e40: 000f9403 */ sra $s2,$t7,0x10 /* f159e44: 27a300e0 */ addiu $v1,$sp,0xe0 /* f159e48: 00109880 */ sll $s3,$s0,0x2 /* f159e4c: 0011a080 */ sll $s4,$s1,0x2 /* f159e50: 0000c812 */ mflo $t9 /* f159e54: 02f93021 */ addu $a2,$s7,$t9 /* f159e58: 0073c821 */ addu $t9,$v1,$s3 /* f159e5c: 023e0019 */ multu $s1,$s8 /* f159e60: 0012a880 */ sll $s5,$s2,0x2 /* f159e64: 27a800a0 */ addiu $t0,$sp,0xa0 /* f159e68: 00402025 */ or $a0,$v0,$zero /* f159e6c: 27a50184 */ addiu $a1,$sp,0x184 /* f159e70: 00007012 */ mflo $t6 /* f159e74: 02ee3821 */ addu $a3,$s7,$t6 /* f159e78: 00000000 */ nop /* f159e7c: 025e0019 */ multu $s2,$s8 /* f159e80: 00007812 */ mflo $t7 /* f159e84: 02efc021 */ addu $t8,$s7,$t7 /* f159e88: afb80010 */ sw $t8,0x10($sp) /* f159e8c: 8f2e0000 */ lw $t6,0x0($t9) /* f159e90: 00747821 */ addu $t7,$v1,$s4 /* f159e94: 0075c821 */ addu $t9,$v1,$s5 /* f159e98: afae0014 */ sw $t6,0x14($sp) /* f159e9c: 8df80000 */ lw $t8,0x0($t7) /* f159ea0: 01137821 */ addu $t7,$t0,$s3 /* f159ea4: afb80018 */ sw $t8,0x18($sp) /* f159ea8: 8f2e0000 */ lw $t6,0x0($t9) /* f159eac: 0114c821 */ addu $t9,$t0,$s4 /* f159eb0: afae001c */ sw $t6,0x1c($sp) /* f159eb4: 8df80000 */ lw $t8,0x0($t7) /* f159eb8: 01157821 */ addu $t7,$t0,$s5 /* f159ebc: afb80020 */ sw $t8,0x20($sp) /* f159ec0: 8f2e0000 */ lw $t6,0x0($t9) /* f159ec4: afae0024 */ sw $t6,0x24($sp) /* f159ec8: 8df80000 */ lw $t8,0x0($t7) /* f159ecc: 0fc56367 */ jal func0f158d9c /* f159ed0: afb80028 */ sw $t8,0x28($sp) /* f159ed4: afa203d8 */ sw $v0,0x3d8($sp) .L0f159ed8: /* f159ed8: 1000feaf */ b .L0f159998 /* f159edc: 26d60008 */ addiu $s6,$s6,0x8 .L0f159ee0: /* f159ee0: 8fa403d8 */ lw $a0,0x3d8($sp) /* f159ee4: 0fc56061 */ jal bg0f158184 /* f159ee8: 27a50184 */ addiu $a1,$sp,0x184 /* f159eec: 8fbf005c */ lw $ra,0x5c($sp) /* f159ef0: 8fb00038 */ lw $s0,0x38($sp) /* f159ef4: 8fb1003c */ lw $s1,0x3c($sp) /* f159ef8: 8fb20040 */ lw $s2,0x40($sp) /* f159efc: 8fb30044 */ lw $s3,0x44($sp) /* f159f00: 8fb40048 */ lw $s4,0x48($sp) /* f159f04: 8fb5004c */ lw $s5,0x4c($sp) /* f159f08: 8fb60050 */ lw $s6,0x50($sp) /* f159f0c: 8fb70054 */ lw $s7,0x54($sp) /* f159f10: 8fbe0058 */ lw $s8,0x58($sp) /* f159f14: 03e00008 */ jr $ra /* f159f18: 27bd03d8 */ addiu $sp,$sp,0x3d8 ); #else // Mismatch: Regalloc and some reordered instructions Gfx *bg0f1598b4(Gfx *gdl, Gfx *gdl2, struct gfxvtx *vertices, s16 arg3[3]) { s32 i; s32 stack; struct xraydata xraydata; struct stagetableentry *stage = stageGetCurrent(); s16 sp120[16][3]; u32 colours[16]; bool inrange[16]; xraydata.unk00c = g_Vars.currentplayer->eraserbgdist; xraydata.unk010 = xraydata.unk00c * xraydata.unk00c; xraydata.unk018 = xraydata.unk00c * 0.25f; xraydata.unk01c = g_Vars.currentplayer->eraserpropdist / xraydata.unk00c; if (xraydata.unk01c > 0.7f) { xraydata.unk01c = 0.7f; } xraydata.unk014 = 0.250f; xraydata.unk020 = stage->unk2c; xraydata.unk024 = xraydata.unk020 * xraydata.unk020; xraydata.unk000 = arg3[0]; xraydata.unk004 = arg3[1]; xraydata.unk008 = arg3[2]; xraydata.numtris = 0; xraydata.numvertices = 0; while (true) { if (gdl2->dma.cmd == G_ENDDL) { break; } if (gdl2->dma.cmd == G_MTX) { // empty } else if (gdl2->dma.cmd == G_VTX) { s32 index = gdl2->bytes[1] & 0xf; s32 numvertices = (((u32)gdl2->bytes[1] >> 4)) + 1; s32 offset = (gdl2->words.w1 & 0xffffff); struct gfxvtx *vtx = (struct gfxvtx *)((u32)vertices + offset); u32 stack[4]; for (i = 0; i < numvertices; i++) { sp120[index + i][0] = vtx->x; sp120[index + i][1] = vtx->y; sp120[index + i][2] = vtx->z; bgChooseXrayVtxColour(&inrange[i], sp120[index + i], &colours[index + i], &xraydata); vtx++; } } else if (gdl2->dma.cmd == G_TRI1) { s16 x = gdl2->tri.tri.v[0] / 10; s16 y = gdl2->tri.tri.v[1] / 10; s16 z = gdl2->tri.tri.v[2] / 10; gdl = func0f158d9c(gdl, &xraydata, sp120[x], sp120[y], sp120[z], colours[x], colours[y], colours[z], inrange[x], inrange[y], inrange[z]); } else if (gdl2->dma.cmd == G_TRI4) { s16 x; s16 y; s16 z; x = gdl2->tri4.x1; y = gdl2->tri4.y1; z = gdl2->tri4.z1; gdl = func0f158d9c(gdl, &xraydata, sp120[x], sp120[y], sp120[z], colours[x], colours[y], colours[z], inrange[x], inrange[y], inrange[z]); x = gdl2->tri4.x2; y = gdl2->tri4.y2; z = gdl2->tri4.z2; gdl = func0f158d9c(gdl, &xraydata, sp120[x], sp120[y], sp120[z], colours[x], colours[y], colours[z], inrange[x], inrange[y], inrange[z]); x = gdl2->tri4.x3; y = gdl2->tri4.y3; z = gdl2->tri4.z3; gdl = func0f158d9c(gdl, &xraydata, sp120[x], sp120[y], sp120[z], colours[x], colours[y], colours[z], inrange[x], inrange[y], inrange[z]); x = gdl2->tri4.x4; y = gdl2->tri4.y4; z = gdl2->tri4.z4; gdl = func0f158d9c(gdl, &xraydata, sp120[x], sp120[y], sp120[z], colours[x], colours[y], colours[z], inrange[x], inrange[y], inrange[z]); } gdl2++; } gdl = bg0f158184(gdl, &xraydata); return gdl; } #endif Gfx *bgRenderRoomXrayPass(Gfx *gdl, s32 roomnum, struct roomblock *block, bool recurse, s16 arg4[3]) { struct player *player = g_Vars.currentplayer; if (block == NULL) { return gdl; } switch (block->type) { case ROOMBLOCKTYPE_LEAF: gdl = bg0f1598b4(gdl, block->gdl, block->vertices, arg4); if (recurse) { gdl = bgRenderRoomXrayPass(gdl, roomnum, block->next, true, arg4); } break; case ROOMBLOCKTYPE_PARENT: if (block->child != NULL) { struct roomblock *child1 = block->child; struct roomblock *child2 = child1->next; struct coord *coords = block->unk0c; struct coord sp34; struct coord sp28; f32 sum; sp34.x = coords[1].x; sp34.y = coords[1].y; sp34.z = coords[1].z; sp28.x = coords[0].x - player->cam_pos.x; sp28.y = coords[0].y - player->cam_pos.y; sp28.z = coords[0].z - player->cam_pos.z; sum = sp34.f[0] * sp28.f[0] + sp34.f[1] * sp28.f[1] + sp34.f[2] * sp28.f[2]; if (sum < 0.0f) { gdl = bgRenderRoomXrayPass(gdl, roomnum, child1, false, arg4); gdl = bgRenderRoomXrayPass(gdl, roomnum, child2, false, arg4); } else { gdl = bgRenderRoomXrayPass(gdl, roomnum, child2, false, arg4); gdl = bgRenderRoomXrayPass(gdl, roomnum, child1, false, arg4); } if (recurse) { gdl = bgRenderRoomXrayPass(gdl, roomnum, block->next, true, arg4); } } break; } return gdl; } /** * Render the given room for the purpose of the FarSight or xray scanner. */ Gfx *bgRenderRoomInXray(Gfx *gdl, s32 roomnum) { struct coord sp54; struct coord globaldrawworldoffset; s16 sp40[3]; struct player *player = g_Vars.currentplayer; if (roomnum == 0 || roomnum >= g_Vars.roomcount) { return gdl; } if (g_Rooms[roomnum].loaded240 == 0) { if (var8007fc10 > 0) { var8007fc10--; bgLoadRoom(roomnum); } } if (g_Rooms[roomnum].loaded240 == 0) { var8007fc10--; } if (g_Rooms[roomnum].loaded240 == 0) { return gdl; } room0f166df0(roomnum, &globaldrawworldoffset); sp54.x = player->eraserpos.x - globaldrawworldoffset.x; sp54.y = player->eraserpos.y - globaldrawworldoffset.y; sp54.z = player->eraserpos.z - globaldrawworldoffset.z; sp40[0] = sp54.f[0]; sp40[1] = sp54.f[1]; sp40[2] = sp54.f[2]; gdl = roomPushMtx(gdl, roomnum); gdl = bgRenderRoomXrayPass(gdl, roomnum, g_Rooms[roomnum].gfxdata->opablocks, true, sp40); gdl = bgRenderRoomXrayPass(gdl, roomnum, g_Rooms[roomnum].gfxdata->xlublocks, true, sp40); g_Rooms[roomnum].loaded240 = 1; return gdl; } Gfx *bgRenderSceneInXray(Gfx *gdl) { s16 *roomnumptr; s16 *room; s16 i; s32 j; s16 roomnumsbyprop[200]; struct prop *prop; struct prop **ptr; s32 k; roomnumptr = roomnumsbyprop; for (ptr = g_Vars.onscreenprops; ptr < g_Vars.endonscreenprops; ptr++) { *roomnumptr = 0; prop = *ptr; if (prop) { room = prop->rooms; while (*room != -1) { if (g_Rooms[*room].flags & ROOMFLAG_ONSCREEN) { *roomnumptr = *room; break; } room++; } } roomnumptr++; } gdl = envStopFog(gdl); gSPClearGeometryMode(gdl++, G_CULL_BOTH); gSPSetGeometryMode(gdl++, G_SHADE | G_SHADING_SMOOTH); gDPSetCombineMode(gdl++, G_CC_SHADE, G_CC_SHADE); gDPSetTextureFilter(gdl++, G_TF_BILERP); gDPSetCycleType(gdl++, G_CYC_1CYCLE); gDPSetRenderMode(gdl++, G_RM_AA_XLU_SURF, G_RM_AA_XLU_SURF2); gSPMatrix(gdl++, osVirtualToPhysical(camGetOrthogonalMtxL()), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION); texSelect(&gdl, NULL, 2, 0, 2, 1, NULL); gDPSetRenderMode(gdl++, G_RM_AA_XLU_SURF, G_RM_AA_XLU_SURF2); // Render BG gdl = currentPlayerScissorToViewport(gdl); for (i = var800a4ce4; i <= var800a4ce6; i++) { for (j = 0; j < var8007fc2c; j++) { struct var800a4640_00 *thing = &var800a4640.unk000[j]; if (thing->draworder == i) { gdl = bgRenderRoomInXray(gdl, thing->roomnum); } } } // Render props gdl = currentPlayerScissorToViewport(gdl); gSPMatrix(gdl++, osVirtualToPhysical(camGetOrthogonalMtxL()), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION); if (var800a4ce4); \ if (var8007fc2c); \ for (i = var800a4ce6; i >= var800a4ce4; i--) { for (k = 0; k < var8007fc2c; k++) { struct var800a4640_00 *thing = &var800a4640.unk000[k]; if (thing->draworder == i) { gSPMatrix(gdl++, osVirtualToPhysical(camGetOrthogonalMtxL()), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION); gdl = currentPlayerScissorWithinViewportF(gdl, thing->box.xmin, thing->box.ymin, thing->box.xmax, thing->box.ymax); gSPMatrix(gdl++, osVirtualToPhysical(camGetPerspectiveMtxL()), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION); if (debugIsPropRenderingEnabled() && getVar80084040()) { if (thing->roomnum == -1) { gdl = propsRender(gdl, 0, RENDERPASS_XLU, roomnumsbyprop); } gdl = propsRender(gdl, thing->roomnum, RENDERPASS_XLU, roomnumsbyprop); } if (1); } } } gdl = skyRenderSuns(gdl, true); return gdl; } #if VERSION >= VERSION_NTSC_1_0 Gfx *bgRenderScene(Gfx *gdl) { s32 stagenum = g_Vars.stagenum; s32 firstroomnum = -1; s32 i; s32 roomnum; s16 roomnumsbyprop[200]; struct prop **ptr; struct var800a4640_00 *thing; s16 *roomnumptr; struct prop *prop; s16 tmp; s16 *room; s16 roomorder[60]; s16 roomnums[60]; g_NumRoomsWithGlares = 0; if (g_Vars.currentplayer->visionmode == VISIONMODE_XRAY) { gdl = bgRenderSceneInXray(gdl); return gdl; } // Build an array of all room numbers, and a parallel array that contains // their draw order (as defined by portal code). for (roomnum = 0; roomnum < var8007fc2c; roomnum++) { roomorder[roomnum] = var800a4640.unk000[roomnum].draworder; roomnums[roomnum] = roomnum; } // Sort them by distance ascending if (var8007fc2c >= 2) { do { i = false; for (roomnum = 0; roomnum < var8007fc2c - 1; roomnum++) { if (roomorder[roomnum + 1] < roomorder[roomnum]) { tmp = roomorder[roomnum]; roomorder[roomnum] = roomorder[roomnum + 1]; roomorder[roomnum + 1] = tmp; tmp = roomnums[roomnum]; roomnums[roomnum] = roomnums[roomnum + 1]; roomnums[roomnum + 1] = tmp; i = true; } } } while (i); } gdl = currentPlayerScissorToViewport(gdl); // Render special "always on" rooms, such as the Defection moon, // Attack Ship planet, and other sky tricks that are implemented as rooms if (!USINGDEVICE(DEVICE_NIGHTVISION) && !USINGDEVICE(DEVICE_IRSCANNER) && (stagenum == g_Stages[STAGEINDEX_INFILTRATION].id || stagenum == g_Stages[STAGEINDEX_RESCUE].id || stagenum == g_Stages[STAGEINDEX_ESCAPE].id || stagenum == g_Stages[STAGEINDEX_MAIANSOS].id || stagenum == g_Stages[STAGEINDEX_SKEDARRUINS].id || stagenum == g_Stages[STAGEINDEX_WAR].id || stagenum == g_Stages[STAGEINDEX_DEFECTION].id || stagenum == g_Stages[STAGEINDEX_EXTRACTION].id || stagenum == g_Stages[STAGEINDEX_MBR].id || stagenum == g_Stages[STAGEINDEX_TEST_OLD].id || stagenum == g_Stages[STAGEINDEX_ATTACKSHIP].id)) { gdl = envStopFog(gdl); gdl = vi0000ab78(gdl); roomnum = -1; if (stagenum == g_Stages[STAGEINDEX_INFILTRATION].id || stagenum == g_Stages[STAGEINDEX_RESCUE].id || stagenum == g_Stages[STAGEINDEX_ESCAPE].id || stagenum == g_Stages[STAGEINDEX_MAIANSOS].id) { roomnum = 0x0f; } else if (stagenum == g_Stages[STAGEINDEX_SKEDARRUINS].id || stagenum == g_Stages[STAGEINDEX_WAR].id) { roomnum = 0x02; } else if (stagenum == g_Stages[STAGEINDEX_DEFECTION].id || stagenum == g_Stages[STAGEINDEX_EXTRACTION].id || stagenum == g_Stages[STAGEINDEX_MBR].id) { roomnum = 0x01; } else if (stagenum == g_Stages[STAGEINDEX_TEST_OLD].id) { roomnum = 0x01; } else if (stagenum == g_Stages[STAGEINDEX_ATTACKSHIP].id) { roomnum = 0x71; } if (PLAYERCOUNT() == 1 && (stagenum == STAGE_DEFECTION || stagenum == STAGE_EXTRACTION || stagenum == STAGE_TEST_OLD || stagenum == STAGE_INFILTRATION || stagenum == STAGE_ESCAPE || stagenum == STAGE_ATTACKSHIP)) { gdl = text0f153628(gdl); gSPMatrix(gdl++, osVirtualToPhysical(camGetOrthogonalMtxL()), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION); gdl = playerLoadMatrix(gdl); gdl = envStopFog(gdl); gdl = starsRender(gdl); gdl = text0f153780(gdl); gdl = vi0000ab78(gdl); } if (roomnum != -1) { if (!g_Rooms[roomnum].loaded240) { bgLoadRoom(roomnum); } gdl = bgRenderRoomOpaque(gdl, roomnum); } gSPPerspNormalize(gdl++, viGetPerspScale()); } gdl = skyRenderSuns(gdl, false); // Build an array of room numbers per onscreen prop. // For each onscreen prop there is exactly one entry in the roomnumsbyprop array. roomnumptr = roomnumsbyprop; \ if (var8007fc2c); for (ptr = g_Vars.onscreenprops; ptr < g_Vars.endonscreenprops; ptr++) { *roomnumptr = 0; prop = *ptr; if (prop) { room = prop->rooms; while (*room != -1) { if (g_Rooms[*room].flags & ROOMFLAG_ONSCREEN) { *roomnumptr = *room; break; } room++; } } roomnumptr++; } // Render the opaque passes for (i = 0; i < var8007fc2c; i++) { roomnum = roomnums[i]; if (firstroomnum < 0) { firstroomnum = var800a4640.unk000[roomnum].roomnum; } thing = &var800a4640.unk000[roomnum]; // Render prop opaque components - pre BG pass gSPMatrix(gdl++, osVirtualToPhysical(camGetPerspectiveMtxL()), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION); gdl = envStopFog(gdl); if (debugIsPropRenderingEnabled() && getVar80084040()) { if (firstroomnum == thing->roomnum) { gdl = propsRender(gdl, 0, RENDERPASS_OPA_PREBG, roomnumsbyprop); } gdl = propsRender(gdl, thing->roomnum, RENDERPASS_OPA_PREBG, roomnumsbyprop); } // Render BG opaque components gSPMatrix(gdl++, osVirtualToPhysical(camGetOrthogonalMtxL()), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION); gdl = currentPlayerScissorWithinViewportF(gdl, thing->box.xmin, thing->box.ymin, thing->box.xmax, thing->box.ymax); gdl = envStartFog(gdl, false); if (debugIsBgRenderingEnabled() && getVar80084040()) { if (g_StageIndex != STAGEINDEX_TEST_OLD) { gdl = bgRenderRoomOpaque(gdl, thing->roomnum); } } // Render prop opaque components - post BG pass gSPMatrix(gdl++, osVirtualToPhysical(camGetPerspectiveMtxL()), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION); gdl = envStopFog(gdl); if (debugIsPropRenderingEnabled() && getVar80084040()) { if (firstroomnum == thing->roomnum) { gdl = propsRender(gdl, 0, RENDERPASS_OPA_POSTBG, roomnumsbyprop); } gdl = propsRender(gdl, thing->roomnum, RENDERPASS_OPA_POSTBG, roomnumsbyprop); } } gdl = envStopFog(gdl); gdl = currentPlayerScissorToViewport(gdl); // Render wall hits gSPMatrix(gdl++, osVirtualToPhysical(camGetOrthogonalMtxL()), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION); if (getVar80084040() && g_Vars.currentplayer->visionmode != VISIONMODE_XRAY) { for (i = 0; i < var8007fc2c; i++) { roomnum = roomnums[i]; gdl = wallhitRenderBgHits(var800a4640.unk000[roomnum].roomnum, gdl); } } // In NTSC 1.0 and newer this hack fixes a regalloc issue. // In NTSC beta this same regalloc issue occurs. // Applying the hack in NTSC beta fixes the regalloc issue but generates // very different code. #if VERSION >= VERSION_NTSC_1_0 if (1) #endif for (i = var8007fc2c - 1; i >= 0; i--) { roomnum = roomnums[i]; gSPMatrix(gdl++, osVirtualToPhysical(camGetOrthogonalMtxL()), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION); thing = &var800a4640.unk000[roomnum]; // Render BG translucent components gdl = currentPlayerScissorWithinViewportF(gdl, thing->box.xmin, thing->box.ymin, thing->box.xmax, thing->box.ymax); gdl = envStartFog(gdl, true); if (debugIsBgRenderingEnabled() && getVar80084040()) { gdl = bgRenderRoomXlu(gdl, thing->roomnum); } gSPMatrix(gdl++, osVirtualToPhysical(camGetPerspectiveMtxL()), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION); gdl = envStopFog(gdl); // Render prop translucent components if (debugIsPropRenderingEnabled() && getVar80084040()) { if (firstroomnum == thing->roomnum) { gdl = propsRender(gdl, 0, RENDERPASS_XLU, roomnumsbyprop); } gdl = propsRender(gdl, thing->roomnum, RENDERPASS_XLU, roomnumsbyprop); } if (!g_Vars.mplayerisrunning) { artifactsCalculateGlaresForRoom(thing->roomnum); if (g_NumRoomsWithGlares < 100) { g_GlareRooms[g_NumRoomsWithGlares++] = thing->roomnum; } } } #if VERSION < VERSION_NTSC_1_0 debug0f119a80nb(); #endif return gdl; } #else GLOBAL_ASM( glabel bgRenderScene /* f154d54: 27bdfcc8 */ addiu $sp,$sp,-824 /* f154d58: 3c0e800a */ lui $t6,0x800a /* f154d5c: 8dcee944 */ lw $t6,-0x16bc($t6) /* f154d60: 3c018008 */ lui $at,0x8008 /* f154d64: afbf003c */ sw $ra,0x3c($sp) /* f154d68: afb60038 */ sw $s6,0x38($sp) /* f154d6c: afb50034 */ sw $s5,0x34($sp) /* f154d70: afb40030 */ sw $s4,0x30($sp) /* f154d74: afb3002c */ sw $s3,0x2c($sp) /* f154d78: afb20028 */ sw $s2,0x28($sp) /* f154d7c: afb10024 */ sw $s1,0x24($sp) /* f154d80: afb00020 */ sw $s0,0x20($sp) /* f154d84: ac202478 */ sw $zero,0x2478($at) /* f154d88: 95cf0010 */ lhu $t7,0x10($t6) /* f154d8c: 3c13800a */ lui $s3,0x800a /* f154d90: 24010001 */ addiu $at,$zero,0x1 /* f154d94: 00808825 */ or $s1,$a0,$zero /* f154d98: 8e73eb74 */ lw $s3,-0x148c($s3) /* f154d9c: 15e10005 */ bne $t7,$at,.NB0f154db4 /* f154da0: 2416ffff */ addiu $s6,$zero,-1 /* f154da4: 0fc55249 */ jal bgRenderSceneInXray /* f154da8: 00000000 */ sll $zero,$zero,0x0 /* f154dac: 1000026a */ beqz $zero,.NB0f155758 /* f154db0: 8fbf003c */ lw $ra,0x3c($sp) .NB0f154db4: /* f154db4: 3c098008 */ lui $t1,0x8008 /* f154db8: 8d292490 */ lw $t1,0x2490($t1) /* f154dbc: 00009025 */ or $s2,$zero,$zero /* f154dc0: 1920000d */ blez $t1,.NB0f154df8 /* f154dc4: 3c10800b */ lui $s0,0x800b /* f154dc8: 26108dc0 */ addiu $s0,$s0,-29248 /* f154dcc: 27a40108 */ addiu $a0,$sp,0x108 /* f154dd0: 27a30090 */ addiu $v1,$sp,0x90 .NB0f154dd4: /* f154dd4: a4720000 */ sh $s2,0x0($v1) /* f154dd8: 92180003 */ lbu $t8,0x3($s0) /* f154ddc: 26520001 */ addiu $s2,$s2,0x1 /* f154de0: 0249082a */ slt $at,$s2,$t1 /* f154de4: 24840002 */ addiu $a0,$a0,0x2 /* f154de8: 2610000c */ addiu $s0,$s0,0xc /* f154dec: 24630002 */ addiu $v1,$v1,0x2 /* f154df0: 1420fff8 */ bnez $at,.NB0f154dd4 /* f154df4: a498fffe */ sh $t8,-0x2($a0) .NB0f154df8: /* f154df8: 29210002 */ slti $at,$t1,0x2 /* f154dfc: 1420001b */ bnez $at,.NB0f154e6c /* f154e00: 252affff */ addiu $t2,$t1,-1 /* f154e04: 27a90090 */ addiu $t1,$sp,0x90 .NB0f154e08: /* f154e08: 19400016 */ blez $t2,.NB0f154e64 /* f154e0c: 0000a025 */ or $s4,$zero,$zero /* f154e10: 27a40108 */ addiu $a0,$sp,0x108 /* f154e14: 000a5840 */ sll $t3,$t2,0x1 /* f154e18: 01644021 */ addu $t0,$t3,$a0 /* f154e1c: 00002825 */ or $a1,$zero,$zero .NB0f154e20: /* f154e20: 84860002 */ lh $a2,0x2($a0) /* f154e24: 84870000 */ lh $a3,0x0($a0) /* f154e28: 01251821 */ addu $v1,$t1,$a1 /* f154e2c: 00c7082a */ slt $at,$a2,$a3 /* f154e30: 50200009 */ beqzl $at,.NB0f154e58 /* f154e34: 24840002 */ addiu $a0,$a0,0x2 /* f154e38: 84620000 */ lh $v0,0x0($v1) /* f154e3c: 846d0002 */ lh $t5,0x2($v1) /* f154e40: a4860000 */ sh $a2,0x0($a0) /* f154e44: a4870002 */ sh $a3,0x2($a0) /* f154e48: 24140001 */ addiu $s4,$zero,0x1 /* f154e4c: a4620002 */ sh $v0,0x2($v1) /* f154e50: a46d0000 */ sh $t5,0x0($v1) /* f154e54: 24840002 */ addiu $a0,$a0,0x2 .NB0f154e58: /* f154e58: 0088082b */ sltu $at,$a0,$t0 /* f154e5c: 1420fff0 */ bnez $at,.NB0f154e20 /* f154e60: 24a50002 */ addiu $a1,$a1,0x2 .NB0f154e64: /* f154e64: 1680ffe8 */ bnez $s4,.NB0f154e08 /* f154e68: 00000000 */ sll $zero,$zero,0x0 .NB0f154e6c: /* f154e6c: 02202025 */ or $a0,$s1,$zero /* f154e70: 0fc55c96 */ jal currentPlayerScissorToViewport /* f154e74: 0000a025 */ or $s4,$zero,$zero /* f154e78: 3c03800a */ lui $v1,0x800a /* f154e7c: 8c63e944 */ lw $v1,-0x16bc($v1) /* f154e80: 00408825 */ or $s1,$v0,$zero /* f154e84: 8c6400d8 */ lw $a0,0xd8($v1) /* f154e88: 14800013 */ bnez $a0,.NB0f154ed8 /* f154e8c: 3c0e8007 */ lui $t6,0x8007 /* f154e90: 8dce2e24 */ lw $t6,0x2e24($t6) /* f154e94: 15c00010 */ bnez $t6,.NB0f154ed8 /* f154e98: 00000000 */ sll $zero,$zero,0x0 /* f154e9c: 8c620480 */ lw $v0,0x480($v1) /* f154ea0: 50400007 */ beqzl $v0,.NB0f154ec0 /* f154ea4: 8c6b1c54 */ lw $t3,0x1c54($v1) /* f154ea8: 1040000b */ beqz $v0,.NB0f154ed8 /* f154eac: 00000000 */ sll $zero,$zero,0x0 /* f154eb0: 804f0037 */ lb $t7,0x37($v0) /* f154eb4: 15e00008 */ bnez $t7,.NB0f154ed8 /* f154eb8: 00000000 */ sll $zero,$zero,0x0 /* f154ebc: 8c6b1c54 */ lw $t3,0x1c54($v1) .NB0f154ec0: /* f154ec0: 8c7800c4 */ lw $t8,0xc4($v1) /* f154ec4: 0160c827 */ nor $t9,$t3,$zero /* f154ec8: 03196024 */ and $t4,$t8,$t9 /* f154ecc: 318d0001 */ andi $t5,$t4,0x1 /* f154ed0: 55a000c1 */ bnezl $t5,.NB0f1551d8 /* f154ed4: 02202025 */ or $a0,$s1,$zero .NB0f154ed8: /* f154ed8: 14800012 */ bnez $a0,.NB0f154f24 /* f154edc: 3c0e8007 */ lui $t6,0x8007 /* f154ee0: 8dce2e24 */ lw $t6,0x2e24($t6) /* f154ee4: 15c0000f */ bnez $t6,.NB0f154f24 /* f154ee8: 00000000 */ sll $zero,$zero,0x0 /* f154eec: 8c620480 */ lw $v0,0x480($v1) /* f154ef0: 50400007 */ beqzl $v0,.NB0f154f10 /* f154ef4: 8c781c54 */ lw $t8,0x1c54($v1) /* f154ef8: 1040000a */ beqz $v0,.NB0f154f24 /* f154efc: 00000000 */ sll $zero,$zero,0x0 /* f154f00: 804f0037 */ lb $t7,0x37($v0) /* f154f04: 15e00007 */ bnez $t7,.NB0f154f24 /* f154f08: 00000000 */ sll $zero,$zero,0x0 /* f154f0c: 8c781c54 */ lw $t8,0x1c54($v1) .NB0f154f10: /* f154f10: 8c6b00c4 */ lw $t3,0xc4($v1) /* f154f14: 0300c827 */ nor $t9,$t8,$zero /* f154f18: 01796024 */ and $t4,$t3,$t9 /* f154f1c: 318d0008 */ andi $t5,$t4,0x8 /* f154f20: 15a000ac */ bnez $t5,.NB0f1551d4 .NB0f154f24: /* f154f24: 3c108008 */ lui $s0,0x8008 /* f154f28: 26102520 */ addiu $s0,$s0,0x2520 /* f154f2c: 860e05e8 */ lh $t6,0x5e8($s0) /* f154f30: 126e001f */ beq $s3,$t6,.NB0f154fb0 /* f154f34: 00000000 */ sll $zero,$zero,0x0 /* f154f38: 860f0738 */ lh $t7,0x738($s0) /* f154f3c: 126f001c */ beq $s3,$t7,.NB0f154fb0 /* f154f40: 00000000 */ sll $zero,$zero,0x0 /* f154f44: 86180118 */ lh $t8,0x118($s0) /* f154f48: 12780019 */ beq $s3,$t8,.NB0f154fb0 /* f154f4c: 00000000 */ sll $zero,$zero,0x0 /* f154f50: 860b0000 */ lh $t3,0x0($s0) /* f154f54: 126b0016 */ beq $s3,$t3,.NB0f154fb0 /* f154f58: 00000000 */ sll $zero,$zero,0x0 /* f154f5c: 861904d0 */ lh $t9,0x4d0($s0) /* f154f60: 12790013 */ beq $s3,$t9,.NB0f154fb0 /* f154f64: 00000000 */ sll $zero,$zero,0x0 /* f154f68: 860c0070 */ lh $t4,0x70($s0) /* f154f6c: 126c0010 */ beq $s3,$t4,.NB0f154fb0 /* f154f70: 00000000 */ sll $zero,$zero,0x0 /* f154f74: 860d0620 */ lh $t5,0x620($s0) /* f154f78: 126d000d */ beq $s3,$t5,.NB0f154fb0 /* f154f7c: 00000000 */ sll $zero,$zero,0x0 /* f154f80: 860e0310 */ lh $t6,0x310($s0) /* f154f84: 126e000a */ beq $s3,$t6,.NB0f154fb0 /* f154f88: 00000000 */ sll $zero,$zero,0x0 /* f154f8c: 860f07a8 */ lh $t7,0x7a8($s0) /* f154f90: 126f0007 */ beq $s3,$t7,.NB0f154fb0 /* f154f94: 00000000 */ sll $zero,$zero,0x0 /* f154f98: 86180850 */ lh $t8,0x850($s0) /* f154f9c: 12780004 */ beq $s3,$t8,.NB0f154fb0 /* f154fa0: 00000000 */ sll $zero,$zero,0x0 /* f154fa4: 860b0700 */ lh $t3,0x700($s0) /* f154fa8: 566b008b */ bnel $s3,$t3,.NB0f1551d8 /* f154fac: 02202025 */ or $a0,$s1,$zero .NB0f154fb0: /* f154fb0: 0fc583b2 */ jal envStopFog /* f154fb4: 02202025 */ or $a0,$s1,$zero /* f154fb8: 0c002b3e */ jal vi0000ab78 /* f154fbc: 00402025 */ or $a0,$v0,$zero /* f154fc0: 861905e8 */ lh $t9,0x5e8($s0) /* f154fc4: 00408825 */ or $s1,$v0,$zero /* f154fc8: 2412ffff */ addiu $s2,$zero,-1 /* f154fcc: 1279000a */ beq $s3,$t9,.NB0f154ff8 /* f154fd0: 24010001 */ addiu $at,$zero,0x1 /* f154fd4: 860c0738 */ lh $t4,0x738($s0) /* f154fd8: 126c0007 */ beq $s3,$t4,.NB0f154ff8 /* f154fdc: 00000000 */ sll $zero,$zero,0x0 /* f154fe0: 860d0118 */ lh $t5,0x118($s0) /* f154fe4: 126d0004 */ beq $s3,$t5,.NB0f154ff8 /* f154fe8: 00000000 */ sll $zero,$zero,0x0 /* f154fec: 860e0000 */ lh $t6,0x0($s0) /* f154ff0: 566e0004 */ bnel $s3,$t6,.NB0f155004 /* f154ff4: 860f04d0 */ lh $t7,0x4d0($s0) .NB0f154ff8: /* f154ff8: 1000001d */ beqz $zero,.NB0f155070 /* f154ffc: 2412000f */ addiu $s2,$zero,0xf /* f155000: 860f04d0 */ lh $t7,0x4d0($s0) .NB0f155004: /* f155004: 126f0004 */ beq $s3,$t7,.NB0f155018 /* f155008: 00000000 */ sll $zero,$zero,0x0 /* f15500c: 86180070 */ lh $t8,0x70($s0) /* f155010: 56780004 */ bnel $s3,$t8,.NB0f155024 /* f155014: 860b0620 */ lh $t3,0x620($s0) .NB0f155018: /* f155018: 10000015 */ beqz $zero,.NB0f155070 /* f15501c: 24120002 */ addiu $s2,$zero,0x2 /* f155020: 860b0620 */ lh $t3,0x620($s0) .NB0f155024: /* f155024: 126b0007 */ beq $s3,$t3,.NB0f155044 /* f155028: 00000000 */ sll $zero,$zero,0x0 /* f15502c: 86190310 */ lh $t9,0x310($s0) /* f155030: 12790004 */ beq $s3,$t9,.NB0f155044 /* f155034: 00000000 */ sll $zero,$zero,0x0 /* f155038: 860c07a8 */ lh $t4,0x7a8($s0) /* f15503c: 566c0004 */ bnel $s3,$t4,.NB0f155050 /* f155040: 860d0850 */ lh $t5,0x850($s0) .NB0f155044: /* f155044: 1000000a */ beqz $zero,.NB0f155070 /* f155048: 24120001 */ addiu $s2,$zero,0x1 /* f15504c: 860d0850 */ lh $t5,0x850($s0) .NB0f155050: /* f155050: 566d0004 */ bnel $s3,$t5,.NB0f155064 /* f155054: 860e0700 */ lh $t6,0x700($s0) /* f155058: 10000005 */ beqz $zero,.NB0f155070 /* f15505c: 24120001 */ addiu $s2,$zero,0x1 /* f155060: 860e0700 */ lh $t6,0x700($s0) .NB0f155064: /* f155064: 166e0002 */ bne $s3,$t6,.NB0f155070 /* f155068: 00000000 */ sll $zero,$zero,0x0 /* f15506c: 24120071 */ addiu $s2,$zero,0x71 .NB0f155070: /* f155070: 3c0f800a */ lui $t7,0x800a /* f155074: 8defe72c */ lw $t7,-0x18d4($t7) /* f155078: 3c18800a */ lui $t8,0x800a /* f15507c: 3c0b800a */ lui $t3,0x800a /* f155080: 11e00003 */ beqz $t7,.NB0f155090 /* f155084: 3c19800a */ lui $t9,0x800a /* f155088: 10000002 */ beqz $zero,.NB0f155094 /* f15508c: 24050001 */ addiu $a1,$zero,0x1 .NB0f155090: /* f155090: 00002825 */ or $a1,$zero,$zero .NB0f155094: /* f155094: 8f18e728 */ lw $t8,-0x18d8($t8) /* f155098: 00001825 */ or $v1,$zero,$zero /* f15509c: 00002025 */ or $a0,$zero,$zero /* f1550a0: 13000003 */ beqz $t8,.NB0f1550b0 /* f1550a4: 00001025 */ or $v0,$zero,$zero /* f1550a8: 10000001 */ beqz $zero,.NB0f1550b0 /* f1550ac: 24030001 */ addiu $v1,$zero,0x1 .NB0f1550b0: /* f1550b0: 8d6be724 */ lw $t3,-0x18dc($t3) /* f1550b4: 11600003 */ beqz $t3,.NB0f1550c4 /* f1550b8: 00000000 */ sll $zero,$zero,0x0 /* f1550bc: 10000001 */ beqz $zero,.NB0f1550c4 /* f1550c0: 24040001 */ addiu $a0,$zero,0x1 .NB0f1550c4: /* f1550c4: 8f39e730 */ lw $t9,-0x18d0($t9) /* f1550c8: 13200003 */ beqz $t9,.NB0f1550d8 /* f1550cc: 00000000 */ sll $zero,$zero,0x0 /* f1550d0: 10000001 */ beqz $zero,.NB0f1550d8 /* f1550d4: 24020001 */ addiu $v0,$zero,0x1 .NB0f1550d8: /* f1550d8: 00446021 */ addu $t4,$v0,$a0 /* f1550dc: 01836821 */ addu $t5,$t4,$v1 /* f1550e0: 01a57021 */ addu $t6,$t5,$a1 /* f1550e4: 15c10023 */ bne $t6,$at,.NB0f155174 /* f1550e8: 24010030 */ addiu $at,$zero,0x30 /* f1550ec: 1261000b */ beq $s3,$at,.NB0f15511c /* f1550f0: 24010022 */ addiu $at,$zero,0x22 /* f1550f4: 12610009 */ beq $s3,$at,.NB0f15511c /* f1550f8: 2401004e */ addiu $at,$zero,0x4e /* f1550fc: 12610007 */ beq $s3,$at,.NB0f15511c /* f155100: 2401002f */ addiu $at,$zero,0x2f /* f155104: 12610005 */ beq $s3,$at,.NB0f15511c /* f155108: 24010019 */ addiu $at,$zero,0x19 /* f15510c: 12610003 */ beq $s3,$at,.NB0f15511c /* f155110: 24010034 */ addiu $at,$zero,0x34 /* f155114: 56610018 */ bnel $s3,$at,.NB0f155178 /* f155118: 2406ffff */ addiu $a2,$zero,-1 .NB0f15511c: /* f15511c: 0fc5374a */ jal text0f153628 /* f155120: 02202025 */ or $a0,$s1,$zero /* f155124: 3c0f0103 */ lui $t7,0x103 /* f155128: 35ef0040 */ ori $t7,$t7,0x40 /* f15512c: ac4f0000 */ sw $t7,0x0($v0) /* f155130: 00408025 */ or $s0,$v0,$zero /* f155134: 0fc2cb5a */ jal camGetOrthogonalMtxL /* f155138: 24510008 */ addiu $s1,$v0,0x8 /* f15513c: 0c013100 */ jal osVirtualToPhysical /* f155140: 00402025 */ or $a0,$v0,$zero /* f155144: ae020004 */ sw $v0,0x4($s0) /* f155148: 0fc303b1 */ jal playerLoadMatrix /* f15514c: 02202025 */ or $a0,$s1,$zero /* f155150: 0fc583b2 */ jal envStopFog /* f155154: 00402025 */ or $a0,$v0,$zero /* f155158: 0fc4c503 */ jal starsRender /* f15515c: 00402025 */ or $a0,$v0,$zero /* f155160: 0fc537a0 */ jal text0f153780 /* f155164: 00402025 */ or $a0,$v0,$zero /* f155168: 0c002b3e */ jal vi0000ab78 /* f15516c: 00402025 */ or $a0,$v0,$zero /* f155170: 00408825 */ or $s1,$v0,$zero .NB0f155174: /* f155174: 2406ffff */ addiu $a2,$zero,-1 .NB0f155178: /* f155178: 1246000f */ beq $s2,$a2,.NB0f1551b8 /* f15517c: 2407008c */ addiu $a3,$zero,0x8c /* f155180: 02470019 */ multu $s2,$a3 /* f155184: 3c18800b */ lui $t8,0x800b /* f155188: 8f1890a8 */ lw $t8,-0x6f58($t8) /* f15518c: 00005812 */ mflo $t3 /* f155190: 030bc821 */ addu $t9,$t8,$t3 /* f155194: 872c0002 */ lh $t4,0x2($t9) /* f155198: 55800004 */ bnezl $t4,.NB0f1551ac /* f15519c: 02202025 */ or $a0,$s1,$zero /* f1551a0: 0fc560fc */ jal bgLoadRoom /* f1551a4: 02402025 */ or $a0,$s2,$zero /* f1551a8: 02202025 */ or $a0,$s1,$zero .NB0f1551ac: /* f1551ac: 0fc564ca */ jal bgRenderRoomOpaque /* f1551b0: 02402825 */ or $a1,$s2,$zero /* f1551b4: 00408825 */ or $s1,$v0,$zero .NB0f1551b8: /* f1551b8: 3c0dbc00 */ lui $t5,0xbc00 /* f1551bc: 35ad000e */ ori $t5,$t5,0xe /* f1551c0: 02208025 */ or $s0,$s1,$zero /* f1551c4: ae0d0000 */ sw $t5,0x0($s0) /* f1551c8: 0c002b3b */ jal viGetPerspScale /* f1551cc: 26310008 */ addiu $s1,$s1,0x8 /* f1551d0: ae020004 */ sw $v0,0x4($s0) .NB0f1551d4: /* f1551d4: 02202025 */ or $a0,$s1,$zero .NB0f1551d8: /* f1551d8: 0fc481ab */ jal skyRenderSuns /* f1551dc: 00002825 */ or $a1,$zero,$zero /* f1551e0: 3c05800a */ lui $a1,0x800a /* f1551e4: 3c0e800a */ lui $t6,0x800a /* f1551e8: 8dceea0c */ lw $t6,-0x15f4($t6) /* f1551ec: 8ca5ea08 */ lw $a1,-0x15f8($a1) /* f1551f0: 27b50198 */ addiu $s5,$sp,0x198 /* f1551f4: 3c098008 */ lui $t1,0x8008 /* f1551f8: 00ae082b */ sltu $at,$a1,$t6 /* f1551fc: 2406ffff */ addiu $a2,$zero,-1 /* f155200: 2407008c */ addiu $a3,$zero,0x8c /* f155204: 00408825 */ or $s1,$v0,$zero /* f155208: 8d292490 */ lw $t1,0x2490($t1) /* f15520c: 10200022 */ beqz $at,.NB0f155298 /* f155210: 02a04025 */ or $t0,$s5,$zero /* f155214: a5000000 */ sh $zero,0x0($t0) .NB0f155218: /* f155218: 8ca30000 */ lw $v1,0x0($a1) /* f15521c: 3c0d800a */ lui $t5,0x800a /* f155220: 10600015 */ beqz $v1,.NB0f155278 /* f155224: 00000000 */ sll $zero,$zero,0x0 /* f155228: 846f0028 */ lh $t7,0x28($v1) /* f15522c: 24620028 */ addiu $v0,$v1,0x28 /* f155230: 3c04800b */ lui $a0,0x800b /* f155234: 10cf0010 */ beq $a2,$t7,.NB0f155278 /* f155238: 00000000 */ sll $zero,$zero,0x0 /* f15523c: 8c8490a8 */ lw $a0,-0x6f58($a0) /* f155240: 84430000 */ lh $v1,0x0($v0) .NB0f155244: /* f155244: 00670019 */ multu $v1,$a3 /* f155248: 0000c012 */ mflo $t8 /* f15524c: 00985821 */ addu $t3,$a0,$t8 /* f155250: 95790000 */ lhu $t9,0x0($t3) /* f155254: 332c0004 */ andi $t4,$t9,0x4 /* f155258: 51800004 */ beqzl $t4,.NB0f15526c /* f15525c: 84430002 */ lh $v1,0x2($v0) /* f155260: 10000005 */ beqz $zero,.NB0f155278 /* f155264: a5030000 */ sh $v1,0x0($t0) /* f155268: 84430002 */ lh $v1,0x2($v0) .NB0f15526c: /* f15526c: 24420002 */ addiu $v0,$v0,0x2 /* f155270: 14c3fff4 */ bne $a2,$v1,.NB0f155244 /* f155274: 00000000 */ sll $zero,$zero,0x0 .NB0f155278: /* f155278: 8dadea0c */ lw $t5,-0x15f4($t5) /* f15527c: 24a50004 */ addiu $a1,$a1,0x4 /* f155280: 25080002 */ addiu $t0,$t0,0x2 /* f155284: 00ad082b */ sltu $at,$a1,$t5 /* f155288: 5420ffe3 */ bnezl $at,.NB0f155218 /* f15528c: a5000000 */ sh $zero,0x0($t0) /* f155290: 3c098008 */ lui $t1,0x8008 /* f155294: 8d292490 */ lw $t1,0x2490($t1) .NB0f155298: /* f155298: 1920008c */ blez $t1,.NB0f1554cc /* f15529c: 27b30090 */ addiu $s3,$sp,0x90 .NB0f1552a0: /* f1552a0: 06c10007 */ bgez $s6,.NB0f1552c0 /* f1552a4: 86720000 */ lh $s2,0x0($s3) /* f1552a8: 00127080 */ sll $t6,$s2,0x2 /* f1552ac: 01d27023 */ subu $t6,$t6,$s2 /* f1552b0: 000e7080 */ sll $t6,$t6,0x2 /* f1552b4: 3c16800b */ lui $s6,0x800b /* f1552b8: 02ceb021 */ addu $s6,$s6,$t6 /* f1552bc: 86d68dc0 */ lh $s6,-0x7240($s6) .NB0f1552c0: /* f1552c0: 3c0f0103 */ lui $t7,0x103 /* f1552c4: 0012c080 */ sll $t8,$s2,0x2 /* f1552c8: 0312c023 */ subu $t8,$t8,$s2 /* f1552cc: 35ef0040 */ ori $t7,$t7,0x40 /* f1552d0: 02201025 */ or $v0,$s1,$zero /* f1552d4: 3c0b800b */ lui $t3,0x800b /* f1552d8: 256b8dc0 */ addiu $t3,$t3,-29248 /* f1552dc: ac4f0000 */ sw $t7,0x0($v0) /* f1552e0: 0018c080 */ sll $t8,$t8,0x2 /* f1552e4: 030b8021 */ addu $s0,$t8,$t3 /* f1552e8: afa20084 */ sw $v0,0x84($sp) /* f1552ec: 0fc2cb52 */ jal camGetPerspectiveMtxL /* f1552f0: 26310008 */ addiu $s1,$s1,0x8 /* f1552f4: 0c013100 */ jal osVirtualToPhysical /* f1552f8: 00402025 */ or $a0,$v0,$zero /* f1552fc: 8fb90084 */ lw $t9,0x84($sp) /* f155300: 02202025 */ or $a0,$s1,$zero /* f155304: 0fc583b2 */ jal envStopFog /* f155308: af220004 */ sw $v0,0x4($t9) /* f15530c: 0fc46640 */ jal debugIsPropRenderingEnabled /* f155310: 00408825 */ or $s1,$v0,$zero /* f155314: 50400014 */ beqzl $v0,.NB0f155368 /* f155318: 3c0c0103 */ lui $t4,0x103 /* f15531c: 0fc58908 */ jal getVar80084040 /* f155320: 00000000 */ sll $zero,$zero,0x0 /* f155324: 50400010 */ beqzl $v0,.NB0f155368 /* f155328: 3c0c0103 */ lui $t4,0x103 /* f15532c: 86050000 */ lh $a1,0x0($s0) /* f155330: 02202025 */ or $a0,$s1,$zero /* f155334: 00003025 */ or $a2,$zero,$zero /* f155338: 16c50005 */ bne $s6,$a1,.NB0f155350 /* f15533c: 02a03825 */ or $a3,$s5,$zero /* f155340: 0fc17ea2 */ jal propsRender /* f155344: 00002825 */ or $a1,$zero,$zero /* f155348: 00408825 */ or $s1,$v0,$zero /* f15534c: 86050000 */ lh $a1,0x0($s0) .NB0f155350: /* f155350: 02202025 */ or $a0,$s1,$zero /* f155354: 00003025 */ or $a2,$zero,$zero /* f155358: 0fc17ea2 */ jal propsRender /* f15535c: 02a03825 */ or $a3,$s5,$zero /* f155360: 00408825 */ or $s1,$v0,$zero /* f155364: 3c0c0103 */ lui $t4,0x103 .NB0f155368: /* f155368: 358c0040 */ ori $t4,$t4,0x40 /* f15536c: 02201025 */ or $v0,$s1,$zero /* f155370: ac4c0000 */ sw $t4,0x0($v0) /* f155374: afa20080 */ sw $v0,0x80($sp) /* f155378: 0fc2cb5a */ jal camGetOrthogonalMtxL /* f15537c: 26310008 */ addiu $s1,$s1,0x8 /* f155380: 0c013100 */ jal osVirtualToPhysical /* f155384: 00402025 */ or $a0,$v0,$zero /* f155388: 8fad0080 */ lw $t5,0x80($sp) /* f15538c: 02202025 */ or $a0,$s1,$zero /* f155390: ada20004 */ sw $v0,0x4($t5) /* f155394: 86180008 */ lh $t8,0x8($s0) /* f155398: 860f0006 */ lh $t7,0x6($s0) /* f15539c: 860e0004 */ lh $t6,0x4($s0) /* f1553a0: 860b000a */ lh $t3,0xa($s0) /* f1553a4: 44984000 */ mtc1 $t8,$f8 /* f1553a8: 448f3000 */ mtc1 $t7,$f6 /* f1553ac: 448e2000 */ mtc1 $t6,$f4 /* f1553b0: 448b5000 */ mtc1 $t3,$f10 /* f1553b4: 46804220 */ cvt.s.w $f8,$f8 /* f1553b8: 468031a0 */ cvt.s.w $f6,$f6 /* f1553bc: 44074000 */ mfc1 $a3,$f8 /* f1553c0: 46802120 */ cvt.s.w $f4,$f4 /* f1553c4: 44063000 */ mfc1 $a2,$f6 /* f1553c8: 46805420 */ cvt.s.w $f16,$f10 /* f1553cc: 44052000 */ mfc1 $a1,$f4 /* f1553d0: 0fc55ca6 */ jal currentPlayerScissorWithinViewportF /* f1553d4: e7b00010 */ swc1 $f16,0x10($sp) /* f1553d8: 00402025 */ or $a0,$v0,$zero /* f1553dc: 0fc58328 */ jal envStartFog /* f1553e0: 00002825 */ or $a1,$zero,$zero /* f1553e4: 0fc4663d */ jal debugIsBgRenderingEnabled /* f1553e8: 00408825 */ or $s1,$v0,$zero /* f1553ec: 5040000e */ beqzl $v0,.NB0f155428 /* f1553f0: 3c0c0103 */ lui $t4,0x103 /* f1553f4: 0fc58908 */ jal getVar80084040 /* f1553f8: 00000000 */ sll $zero,$zero,0x0 /* f1553fc: 10400009 */ beqz $v0,.NB0f155424 /* f155400: 3c198008 */ lui $t9,0x8008 /* f155404: 8f392460 */ lw $t9,0x2460($t9) /* f155408: 24010026 */ addiu $at,$zero,0x26 /* f15540c: 02202025 */ or $a0,$s1,$zero /* f155410: 53210005 */ beql $t9,$at,.NB0f155428 /* f155414: 3c0c0103 */ lui $t4,0x103 /* f155418: 0fc564ca */ jal bgRenderRoomOpaque /* f15541c: 86050000 */ lh $a1,0x0($s0) /* f155420: 00408825 */ or $s1,$v0,$zero .NB0f155424: /* f155424: 3c0c0103 */ lui $t4,0x103 .NB0f155428: /* f155428: 358c0040 */ ori $t4,$t4,0x40 /* f15542c: 02201025 */ or $v0,$s1,$zero /* f155430: ac4c0000 */ sw $t4,0x0($v0) /* f155434: afa2007c */ sw $v0,0x7c($sp) /* f155438: 0fc2cb52 */ jal camGetPerspectiveMtxL /* f15543c: 26310008 */ addiu $s1,$s1,0x8 /* f155440: 0c013100 */ jal osVirtualToPhysical /* f155444: 00402025 */ or $a0,$v0,$zero /* f155448: 8fad007c */ lw $t5,0x7c($sp) /* f15544c: 02202025 */ or $a0,$s1,$zero /* f155450: 0fc583b2 */ jal envStopFog /* f155454: ada20004 */ sw $v0,0x4($t5) /* f155458: 0fc46640 */ jal debugIsPropRenderingEnabled /* f15545c: 00408825 */ or $s1,$v0,$zero /* f155460: 10400013 */ beqz $v0,.NB0f1554b0 /* f155464: 00000000 */ sll $zero,$zero,0x0 /* f155468: 0fc58908 */ jal getVar80084040 /* f15546c: 00000000 */ sll $zero,$zero,0x0 /* f155470: 1040000f */ beqz $v0,.NB0f1554b0 /* f155474: 00000000 */ sll $zero,$zero,0x0 /* f155478: 86050000 */ lh $a1,0x0($s0) /* f15547c: 02202025 */ or $a0,$s1,$zero /* f155480: 24060002 */ addiu $a2,$zero,0x2 /* f155484: 16c50005 */ bne $s6,$a1,.NB0f15549c /* f155488: 02a03825 */ or $a3,$s5,$zero /* f15548c: 0fc17ea2 */ jal propsRender /* f155490: 00002825 */ or $a1,$zero,$zero /* f155494: 00408825 */ or $s1,$v0,$zero /* f155498: 86050000 */ lh $a1,0x0($s0) .NB0f15549c: /* f15549c: 02202025 */ or $a0,$s1,$zero /* f1554a0: 24060002 */ addiu $a2,$zero,0x2 /* f1554a4: 0fc17ea2 */ jal propsRender /* f1554a8: 02a03825 */ or $a3,$s5,$zero /* f1554ac: 00408825 */ or $s1,$v0,$zero .NB0f1554b0: /* f1554b0: 3c0e8008 */ lui $t6,0x8008 /* f1554b4: 8dce2490 */ lw $t6,0x2490($t6) /* f1554b8: 26940001 */ addiu $s4,$s4,0x1 /* f1554bc: 26730002 */ addiu $s3,$s3,0x2 /* f1554c0: 028e082a */ slt $at,$s4,$t6 /* f1554c4: 1420ff76 */ bnez $at,.NB0f1552a0 /* f1554c8: 00000000 */ sll $zero,$zero,0x0 .NB0f1554cc: /* f1554cc: 0fc583b2 */ jal envStopFog /* f1554d0: 02202025 */ or $a0,$s1,$zero /* f1554d4: 0fc55c96 */ jal currentPlayerScissorToViewport /* f1554d8: 00402025 */ or $a0,$v0,$zero /* f1554dc: 3c0f0103 */ lui $t7,0x103 /* f1554e0: 35ef0040 */ ori $t7,$t7,0x40 /* f1554e4: ac4f0000 */ sw $t7,0x0($v0) /* f1554e8: 00408025 */ or $s0,$v0,$zero /* f1554ec: 0fc2cb5a */ jal camGetOrthogonalMtxL /* f1554f0: 24510008 */ addiu $s1,$v0,0x8 /* f1554f4: 0c013100 */ jal osVirtualToPhysical /* f1554f8: 00402025 */ or $a0,$v0,$zero /* f1554fc: 0fc58908 */ jal getVar80084040 /* f155500: ae020004 */ sw $v0,0x4($s0) /* f155504: 1040001c */ beqz $v0,.NB0f155578 /* f155508: 3c18800a */ lui $t8,0x800a /* f15550c: 8f18e944 */ lw $t8,-0x16bc($t8) /* f155510: 24010001 */ addiu $at,$zero,0x1 /* f155514: 3c198008 */ lui $t9,0x8008 /* f155518: 970b0010 */ lhu $t3,0x10($t8) /* f15551c: 11610016 */ beq $t3,$at,.NB0f155578 /* f155520: 00000000 */ sll $zero,$zero,0x0 /* f155524: 8f392490 */ lw $t9,0x2490($t9) /* f155528: 0000a025 */ or $s4,$zero,$zero /* f15552c: 27b30090 */ addiu $s3,$sp,0x90 /* f155530: 1b200011 */ blez $t9,.NB0f155578 /* f155534: 00000000 */ sll $zero,$zero,0x0 .NB0f155538: /* f155538: 86720000 */ lh $s2,0x0($s3) /* f15553c: 3c04800b */ lui $a0,0x800b /* f155540: 02202825 */ or $a1,$s1,$zero /* f155544: 00126080 */ sll $t4,$s2,0x2 /* f155548: 01926023 */ subu $t4,$t4,$s2 /* f15554c: 000c6080 */ sll $t4,$t4,0x2 /* f155550: 008c2021 */ addu $a0,$a0,$t4 /* f155554: 0fc4ef16 */ jal wallhitRenderBgHits /* f155558: 84848dc0 */ lh $a0,-0x7240($a0) /* f15555c: 3c0d8008 */ lui $t5,0x8008 /* f155560: 8dad2490 */ lw $t5,0x2490($t5) /* f155564: 26940001 */ addiu $s4,$s4,0x1 /* f155568: 26730002 */ addiu $s3,$s3,0x2 /* f15556c: 028d082a */ slt $at,$s4,$t5 /* f155570: 1420fff1 */ bnez $at,.NB0f155538 /* f155574: 00408825 */ or $s1,$v0,$zero .NB0f155578: /* f155578: 3c098008 */ lui $t1,0x8008 /* f15557c: 8d292490 */ lw $t1,0x2490($t1) /* f155580: 27af0090 */ addiu $t7,$sp,0x90 /* f155584: 2534ffff */ addiu $s4,$t1,-1 /* f155588: 0680006f */ bltz $s4,.NB0f155748 /* f15558c: 00147040 */ sll $t6,$s4,0x1 /* f155590: 3c14800b */ lui $s4,0x800b /* f155594: 26949378 */ addiu $s4,$s4,-27784 /* f155598: 01cf9821 */ addu $s3,$t6,$t7 /* f15559c: 3c180103 */ lui $t8,0x103 .NB0f1555a0: /* f1555a0: 86720000 */ lh $s2,0x0($s3) /* f1555a4: 37180040 */ ori $t8,$t8,0x40 /* f1555a8: 02201025 */ or $v0,$s1,$zero /* f1555ac: ac580000 */ sw $t8,0x0($v0) /* f1555b0: afa20074 */ sw $v0,0x74($sp) /* f1555b4: 0fc2cb5a */ jal camGetOrthogonalMtxL /* f1555b8: 26310008 */ addiu $s1,$s1,0x8 /* f1555bc: 0c013100 */ jal osVirtualToPhysical /* f1555c0: 00402025 */ or $a0,$v0,$zero /* f1555c4: 8fab0074 */ lw $t3,0x74($sp) /* f1555c8: 0012c880 */ sll $t9,$s2,0x2 /* f1555cc: 0332c823 */ subu $t9,$t9,$s2 /* f1555d0: 3c0c800b */ lui $t4,0x800b /* f1555d4: 258c8dc0 */ addiu $t4,$t4,-29248 /* f1555d8: 0019c880 */ sll $t9,$t9,0x2 /* f1555dc: 032c8021 */ addu $s0,$t9,$t4 /* f1555e0: ad620004 */ sw $v0,0x4($t3) /* f1555e4: 860f0008 */ lh $t7,0x8($s0) /* f1555e8: 860e0006 */ lh $t6,0x6($s0) /* f1555ec: 860d0004 */ lh $t5,0x4($s0) /* f1555f0: 8618000a */ lh $t8,0xa($s0) /* f1555f4: 448f3000 */ mtc1 $t7,$f6 /* f1555f8: 448e2000 */ mtc1 $t6,$f4 /* f1555fc: 448d9000 */ mtc1 $t5,$f18 /* f155600: 44984000 */ mtc1 $t8,$f8 /* f155604: 468031a0 */ cvt.s.w $f6,$f6 /* f155608: 02202025 */ or $a0,$s1,$zero /* f15560c: 46802120 */ cvt.s.w $f4,$f4 /* f155610: 44073000 */ mfc1 $a3,$f6 /* f155614: 468094a0 */ cvt.s.w $f18,$f18 /* f155618: 44062000 */ mfc1 $a2,$f4 /* f15561c: 468042a0 */ cvt.s.w $f10,$f8 /* f155620: 44059000 */ mfc1 $a1,$f18 /* f155624: 0fc55ca6 */ jal currentPlayerScissorWithinViewportF /* f155628: e7aa0010 */ swc1 $f10,0x10($sp) /* f15562c: 00402025 */ or $a0,$v0,$zero /* f155630: 0fc58328 */ jal envStartFog /* f155634: 24050001 */ addiu $a1,$zero,0x1 /* f155638: 0fc4663d */ jal debugIsBgRenderingEnabled /* f15563c: 00408825 */ or $s1,$v0,$zero /* f155640: 50400009 */ beqzl $v0,.NB0f155668 /* f155644: 3c0b0103 */ lui $t3,0x103 /* f155648: 0fc58908 */ jal getVar80084040 /* f15564c: 00000000 */ sll $zero,$zero,0x0 /* f155650: 10400004 */ beqz $v0,.NB0f155664 /* f155654: 02202025 */ or $a0,$s1,$zero /* f155658: 0fc564f5 */ jal bgRenderRoomXlu /* f15565c: 86050000 */ lh $a1,0x0($s0) /* f155660: 00408825 */ or $s1,$v0,$zero .NB0f155664: /* f155664: 3c0b0103 */ lui $t3,0x103 .NB0f155668: /* f155668: 356b0040 */ ori $t3,$t3,0x40 /* f15566c: 02201025 */ or $v0,$s1,$zero /* f155670: ac4b0000 */ sw $t3,0x0($v0) /* f155674: afa20070 */ sw $v0,0x70($sp) /* f155678: 0fc2cb52 */ jal camGetPerspectiveMtxL /* f15567c: 26310008 */ addiu $s1,$s1,0x8 /* f155680: 0c013100 */ jal osVirtualToPhysical /* f155684: 00402025 */ or $a0,$v0,$zero /* f155688: 8fb90070 */ lw $t9,0x70($sp) /* f15568c: 02202025 */ or $a0,$s1,$zero /* f155690: 0fc583b2 */ jal envStopFog /* f155694: af220004 */ sw $v0,0x4($t9) /* f155698: 0fc46640 */ jal debugIsPropRenderingEnabled /* f15569c: 00408825 */ or $s1,$v0,$zero /* f1556a0: 10400013 */ beqz $v0,.NB0f1556f0 /* f1556a4: 00000000 */ sll $zero,$zero,0x0 /* f1556a8: 0fc58908 */ jal getVar80084040 /* f1556ac: 00000000 */ sll $zero,$zero,0x0 /* f1556b0: 1040000f */ beqz $v0,.NB0f1556f0 /* f1556b4: 00000000 */ sll $zero,$zero,0x0 /* f1556b8: 86050000 */ lh $a1,0x0($s0) /* f1556bc: 02202025 */ or $a0,$s1,$zero /* f1556c0: 24060001 */ addiu $a2,$zero,0x1 /* f1556c4: 16c50005 */ bne $s6,$a1,.NB0f1556dc /* f1556c8: 02a03825 */ or $a3,$s5,$zero /* f1556cc: 0fc17ea2 */ jal propsRender /* f1556d0: 00002825 */ or $a1,$zero,$zero /* f1556d4: 00408825 */ or $s1,$v0,$zero /* f1556d8: 86050000 */ lh $a1,0x0($s0) .NB0f1556dc: /* f1556dc: 02202025 */ or $a0,$s1,$zero /* f1556e0: 24060001 */ addiu $a2,$zero,0x1 /* f1556e4: 0fc17ea2 */ jal propsRender /* f1556e8: 02a03825 */ or $a3,$s5,$zero /* f1556ec: 00408825 */ or $s1,$v0,$zero .NB0f1556f0: /* f1556f0: 3c0c800a */ lui $t4,0x800a /* f1556f4: 8d8ce9d4 */ lw $t4,-0x162c($t4) /* f1556f8: 5580000f */ bnezl $t4,.NB0f155738 /* f1556fc: 2673fffe */ addiu $s3,$s3,-2 /* f155700: 0fc4dca0 */ jal artifactsCalculateGlaresForRoom /* f155704: 86040000 */ lh $a0,0x0($s0) /* f155708: 3c028008 */ lui $v0,0x8008 /* f15570c: 8c422478 */ lw $v0,0x2478($v0) /* f155710: 28410064 */ slti $at,$v0,0x64 /* f155714: 10200007 */ beqz $at,.NB0f155734 /* f155718: 00027040 */ sll $t6,$v0,0x1 /* f15571c: 860d0000 */ lh $t5,0x0($s0) /* f155720: 028e7821 */ addu $t7,$s4,$t6 /* f155724: 24580001 */ addiu $t8,$v0,0x1 /* f155728: 3c018008 */ lui $at,0x8008 /* f15572c: a5ed0000 */ sh $t5,0x0($t7) /* f155730: ac382478 */ sw $t8,0x2478($at) .NB0f155734: /* f155734: 2673fffe */ addiu $s3,$s3,-2 .NB0f155738: /* f155738: 27ab0090 */ addiu $t3,$sp,0x90 /* f15573c: 026b082b */ sltu $at,$s3,$t3 /* f155740: 5020ff97 */ beqzl $at,.NB0f1555a0 /* f155744: 3c180103 */ lui $t8,0x103 .NB0f155748: /* f155748: 0fc466a0 */ jal debug0f119a80nb /* f15574c: 00000000 */ sll $zero,$zero,0x0 /* f155750: 02201025 */ or $v0,$s1,$zero /* f155754: 8fbf003c */ lw $ra,0x3c($sp) .NB0f155758: /* f155758: 8fb00020 */ lw $s0,0x20($sp) /* f15575c: 8fb10024 */ lw $s1,0x24($sp) /* f155760: 8fb20028 */ lw $s2,0x28($sp) /* f155764: 8fb3002c */ lw $s3,0x2c($sp) /* f155768: 8fb40030 */ lw $s4,0x30($sp) /* f15576c: 8fb50034 */ lw $s5,0x34($sp) /* f155770: 8fb60038 */ lw $s6,0x38($sp) /* f155774: 03e00008 */ jr $ra /* f155778: 27bd0338 */ addiu $sp,$sp,0x338 ); #endif Gfx *bgRenderArtifacts(Gfx *gdl) { s32 i; if (g_Vars.mplayerisrunning == false && g_NumRoomsWithGlares > 0) { gdl = artifactsConfigureForGlares(gdl); for (i = 0; i < g_NumRoomsWithGlares; i++) { gdl = artifactsRenderGlaresForRoom(gdl, g_GlareRooms[i]); } gdl = artifactsUnconfigureForGlares(gdl); } gdl = skyRenderArtifacts(gdl); return gdl; } void bgLoadFile(void *memaddr, u32 offset, u32 len) { if (var8007fc04) { bcopy(var8007fc08 + offset, memaddr, len); } else { fileLoadPartToAddr(g_Stages[g_StageIndex].bgfileid, memaddr, offset, len); } } s32 stageGetIndex2(s32 stagenum) { s32 index = -1; s32 i; for (i = 0; i != ARRAYCOUNT(g_Stages); i++) { if (g_Stages[i].id == stagenum) { index = i; } } return index; } f32 portal0f15b274(s32 portalnum) { struct portalvertices *pvertices = (struct portalvertices *)((u32)g_BgPortals + g_BgPortals[portalnum].verticesoffset); s32 count = pvertices->count; s32 i; s32 j; f32 sum = 0.0f; f32 sp90[3]; f32 sp84[3]; f32 sp78[3]; for (i = 2; i < count; i++) { for (j = 0; j < 3; j++) { sp84[j] = pvertices->vertices[i - 1].f[j] - pvertices->vertices[0].f[j]; sp78[j] = pvertices->vertices[i].f[j] - pvertices->vertices[i - 1].f[j]; } sp90[0] = sp84[1] * sp78[2] - sp84[2] * sp78[1]; sp90[1] = -sp84[0] * sp78[2] + sp84[2] * sp78[0]; sp90[2] = sp84[0] * sp78[1] - sp84[1] * sp78[0]; sum += sqrtf(sp90[0] * sp90[0] + sp90[1] * sp90[1] + sp90[2] * sp90[2]) * 0.5f; } return sum; } void func0f15b3e4(s32 portalnum, struct coord *a, struct coord *b, struct coord *c, struct coord *d) { struct portalvertices *pvertices; pvertices = (struct portalvertices *)((u32)g_BgPortals + g_BgPortals[portalnum].verticesoffset); a->x = pvertices->vertices[0].x; a->y = pvertices->vertices[0].y; a->z = pvertices->vertices[0].z; b->x = pvertices->vertices[1].x - pvertices->vertices[0].x; b->y = pvertices->vertices[1].y - pvertices->vertices[0].y; b->z = pvertices->vertices[1].z - pvertices->vertices[0].z; c->x = pvertices->vertices[1].x - pvertices->vertices[0].x; c->y = pvertices->vertices[1].y - pvertices->vertices[0].y; c->z = pvertices->vertices[1].z - pvertices->vertices[0].z; d->x = (var800a4ccc + portalnum)->coord.x; d->y = (var800a4ccc + portalnum)->coord.y; d->z = (var800a4ccc + portalnum)->coord.z; } u8 func0f15b4c0(s32 portal) { s32 uVar2 = portal0f15b274(portal) / 10000.0f; if (uVar2 > 0xff) { uVar2 = 0xff; } return uVar2; } u8 func0f15b508(s32 index) { return var800a4cd0[index]; } #if PIRACYCHECKS u32 not(u32 arg) { return ~arg; } u32 xorBabebabe(u32 value) { return value ^ 0xbabebabe; } #endif #if VERSION < VERSION_NTSC_1_0 /** * The following two functions were surely debug code that was accidentally left * in the NTSC beta build, whose purpose is to debug a light data corruption * issue. * * The first function is run on stage start and builds the known good checksums. * The second function runs on every tick, re-sums them and induces a crash if * they've changed. */ void bgBuildReferenceLightSums(void) { s32 i; g_BgNumLightsChecksum = 0; for (i = 0; i < g_Vars.roomcount; i++) { g_BgNumLightsChecksum += g_Rooms[i].numlights; } g_BgLightsOffsetChecksum = 0; for (i = 0; i < g_Vars.roomcount; i++) { g_BgLightsOffsetChecksum += g_Rooms[i].lightindex; } } void bgVerifyLightSums(char *file, s32 line) { s32 i; s32 sum; char message[128]; u32 stack; sum = 0; for (i = 0; i < g_Vars.roomcount; i++) { sum += g_Rooms[i].numlights; } if (sum != g_BgNumLightsChecksum) { sprintf(message, "NumLightsChecksum failed %s %d", file, line); crashSetMessage(message); CRASH(); } sum = 0; for (i = 0; i < g_Vars.roomcount; i++) { sum += g_Rooms[i].lightindex; } if (sum != g_BgLightsOffsetChecksum) { sprintf(message, "LightsOffsetChecksum failed %s %d", file, line); crashSetMessage(message); CRASH(); } } #endif #if VERSION >= VERSION_NTSC_1_0 /** * Extracts and inflates primary data (room/portal/light tables) from the * BG file to memory, ensures required textures are loaded, and sets some * global pointers to each table within the primary data. * * -- Overview ----------------------------------------------------------------- * * The structure of a BG File is: * * - Section 1: * - Primary data (compressed): * - Room table, with pointers to their room gfx data * - Portal table * - Portal command list * - Light table * - For each room, a compressed binary containing gfx data * - Section 2 (compressed) - list of texture IDs to load * - Section 3 (compressed) - unknown and not read by this function * * Each section has a header (uncompressed) containing size information: * * Section 1 header is 0x0c bytes long: * - 4 bytes decompressed size of primary data * - 4 bytes compressed size of section 1 in its entirety * - 4 bytes compressed size of primary data * * Section 2 and 3 headers are 0x04 bytes long: * - 2 bytes decompressed size of data (mask with 0x7fff) * - 2 bytes compressed size of data * * -- Primary Data (compressed) ------------------------------------------------ * * Header is 0x18 bytes long: * - 4 bytes null * - 4 bytes pointer to room table * - 4 bytes pointer to portal table * - 4 bytes pointer to portal commands list * - 4 bytes pointer to light table * - 4 bytes null */ void bgReset(s32 stagenum) { u8 *header; u8 headerbuffer[0x50]; u32 numtextures; u16 *section2; s32 j; s32 i; u32 primcompsize; u32 inflatedsize; // used for both primary and section 2 u32 section2compsize; u32 section2start; u32 section1compsize; u32 scratch; var8007fc0c = 8; if (IS4MB()) { g_BgUnloadDelay240 = 6; g_BgUnloadDelay240_2 = 6; } else { g_BgUnloadDelay240 = 120; g_BgUnloadDelay240_2 = 120; } g_StageIndex = stageGetIndex2(stagenum); if (g_StageIndex < 0) { g_StageIndex = 0; } // Copy section 1 header to stack and parse into variables header = (u8 *)ALIGN16((u32)headerbuffer); bgLoadFile(header, 0, 0x40); inflatedsize = *(u32 *)&header[0]; section1compsize = *(u32 *)&header[4]; primcompsize = *(u32 *)&header[8]; var8007fc54 = inflatedsize - primcompsize; var8007fc54 -= 0xc; inflatedsize = ALIGN16(inflatedsize); // Allocate space for the primary bg data // An extra 0x8000 or so is given as temporary scratch space g_BgPrimaryData = mempAlloc(ALIGN16(inflatedsize + 0x8010), MEMPOOL_STAGE); // Set up pointer to scratch space scratch = ((u32)g_BgPrimaryData + inflatedsize) - primcompsize; scratch = ALIGN16(scratch + 0x8000); g_LoadType = LOADTYPE_BG; // Copy section 1 header + compressed primary to scratch space bgLoadFile((u8 *)scratch, 0, ALIGN16(primcompsize + 15)); // Inflate primary data to the start of the buffer scratch += 0xc; bgInflate((u8 *)scratch, g_BgPrimaryData, primcompsize); // Shrink the allocation (ie. free the scratch space) mempRealloc(g_BgPrimaryData, inflatedsize, MEMPOOL_STAGE); // Load the section 2 header section2start = section1compsize + 0xc; bgLoadFile(header, section2start, 0x40); inflatedsize = (*(u16 *)&header[0] & 0x7fff) - 1; section2compsize = *(u16 *)&header[2]; inflatedsize = (inflatedsize | 0xf) + 1; // Allocate space for the section 2 data (texture ID list). // This is the cause and fix for the Challenge 7 memory corruption bug in // NTSC 1.0. A full writeup about the bug and how the fix works can be found // in the docs folder of this project. #if VERSION >= VERSION_NTSC_FINAL section2 = mempAlloc(inflatedsize + 0x8000, MEMPOOL_STAGE); scratch = (u32)section2 + 0x8000; #else section2 = mempAlloc(inflatedsize + 0x800, MEMPOOL_STAGE); scratch = (u32)section2 + 0x800; #endif // Load compressed data from ROM to scratch bgLoadFile((u8 *)scratch, section2start + 4, ((section2compsize - 1) | 0xf) + 1); // Inflate section 2 to the start of the buffer bgInflate((u8 *)scratch, (u8 *)section2, section2compsize); // Iterate texture IDs and ensure they're loaded inflatedsize = (*(u16 *)&header[0] & 0x7fff) >> 1; for (i = 0; i != inflatedsize; i++) { texLoadFromTextureNum(section2[i], NULL); } if (i); // Free section 2 mempRealloc(section2, 0, MEMPOOL_STAGE); g_BgSection3 = section2start + section2compsize + 4; #if PIRACYCHECKS { u32 addr = not(PAL ? ~0xb0000340 : ~0xb0000454); u32 actualvalue; u32 expectedvalue = xorBabebabe((PAL ? 0x0330c820 : 0x0109082b) ^ 0xbabebabe); osPiReadIo(addr, &actualvalue); if (actualvalue != expectedvalue) { // Copy 0x40 bytes from a random location in ROM to a random // location in RAM. The write address can be anywhere in the // boot segment or in the lib segment up to modelRenderNodeDl. dmaExec((void *)(PHYS_TO_K0(0x1000) + (random() & 0x1fff8)), random() & 0x1fffe, 0x40); } } #endif var800a4920 = *(u32 *)g_BgPrimaryData; if (var800a4920 == 0) { g_BgPrimaryData2 = (u32 *)g_BgPrimaryData; g_BgRooms = (struct bgroom *)(g_BgPrimaryData2[1] + g_BgPrimaryData + 0xf1000000); if (g_BgPrimaryData); g_Vars.roomcount = 0; for (j = 1; g_BgRooms[j].unk00 != 0; j++) { g_Vars.roomcount++; } g_BgPortals = (struct bgportal *)(g_BgPrimaryData2[2] + g_BgPrimaryData + 0xf1000000); if (g_BgPrimaryData2[3] == 0) { g_BgCommands = NULL; } else { g_BgCommands = (struct bgcmd *)(g_BgPrimaryData2[3] + g_BgPrimaryData + 0xf1000000); } if (g_BgPrimaryData2[4] == 0) { g_BgLightsFileData = NULL; } else { g_BgLightsFileData = (u8 *)(g_BgPrimaryData2[4] + g_BgPrimaryData + 0xf1000000); } if (g_BgPrimaryData2[5] == 0) { g_BgTable5 = NULL; } else { g_BgTable5 = (f32 *)(g_BgPrimaryData2[5] + g_BgPrimaryData + 0xf1000000); } } } #else GLOBAL_ASM( glabel bgReset /* f155d14: 3c0f8009 */ lui $t7,0x8009 /* f155d18: 91ef30e0 */ lbu $t7,0x30e0($t7) /* f155d1c: 27bdff48 */ addiu $sp,$sp,-184 /* f155d20: 240e0008 */ addiu $t6,$zero,0x8 /* f155d24: 3c018008 */ lui $at,0x8008 /* f155d28: a42e2470 */ sh $t6,0x2470($at) /* f155d2c: 24010001 */ addiu $at,$zero,0x1 /* f155d30: afbf0024 */ sw $ra,0x24($sp) /* f155d34: afb20020 */ sw $s2,0x20($sp) /* f155d38: afb1001c */ sw $s1,0x1c($sp) /* f155d3c: 15e10007 */ bne $t7,$at,.NB0f155d5c /* f155d40: afb00018 */ sw $s0,0x18($sp) /* f155d44: 24020078 */ addiu $v0,$zero,0x78 /* f155d48: 3c01800b */ lui $at,0x800b /* f155d4c: a4229370 */ sh $v0,-0x6c90($at) /* f155d50: 3c01800b */ lui $at,0x800b /* f155d54: 10000006 */ beqz $zero,.NB0f155d70 /* f155d58: a4229372 */ sh $v0,-0x6c8e($at) .NB0f155d5c: /* f155d5c: 24020e10 */ addiu $v0,$zero,0xe10 /* f155d60: 3c01800b */ lui $at,0x800b /* f155d64: a4229370 */ sh $v0,-0x6c90($at) /* f155d68: 3c01800b */ lui $at,0x800b /* f155d6c: a4229372 */ sh $v0,-0x6c8e($at) .NB0f155d70: /* f155d70: 3c01800b */ lui $at,0x800b /* f155d74: 0fc55629 */ jal stageGetIndex2 /* f155d78: ac209374 */ sw $zero,-0x6c8c($at) /* f155d7c: 3c038008 */ lui $v1,0x8008 /* f155d80: 24632460 */ addiu $v1,$v1,0x2460 /* f155d84: 04410002 */ bgez $v0,.NB0f155d90 /* f155d88: ac620000 */ sw $v0,0x0($v1) /* f155d8c: ac600000 */ sw $zero,0x0($v1) .NB0f155d90: /* f155d90: 03a02025 */ or $a0,$sp,$zero /* f155d94: 24840073 */ addiu $a0,$a0,0x73 /* f155d98: 3499000f */ ori $t9,$a0,0xf /* f155d9c: 3b24000f */ xori $a0,$t9,0xf /* f155da0: afa40038 */ sw $a0,0x38($sp) /* f155da4: 00002825 */ or $a1,$zero,$zero /* f155da8: 0fc5560b */ jal bgLoadFile /* f155dac: 24060040 */ addiu $a2,$zero,0x40 /* f155db0: 8fa30038 */ lw $v1,0x38($sp) /* f155db4: 3c028008 */ lui $v0,0x8008 /* f155db8: 3401801f */ dli $at,0x801f /* f155dbc: 8c6a0004 */ lw $t2,0x4($v1) /* f155dc0: 8c720000 */ lw $s2,0x0($v1) /* f155dc4: 244224b8 */ addiu $v0,$v0,0x24b8 /* f155dc8: afaa0040 */ sw $t2,0x40($sp) /* f155dcc: 8c710008 */ lw $s1,0x8($v1) /* f155dd0: 24050004 */ addiu $a1,$zero,0x4 /* f155dd4: 02515823 */ subu $t3,$s2,$s1 /* f155dd8: 2652000f */ addiu $s2,$s2,0xf /* f155ddc: 364e000f */ ori $t6,$s2,0xf /* f155de0: 39d2000f */ xori $s2,$t6,0xf /* f155de4: 02412021 */ addu $a0,$s2,$at /* f155de8: ac4b0000 */ sw $t3,0x0($v0) /* f155dec: 256dfff4 */ addiu $t5,$t3,-12 /* f155df0: 3498000f */ ori $t8,$a0,0xf /* f155df4: ac4d0000 */ sw $t5,0x0($v0) /* f155df8: 0c004a0e */ jal mempAlloc /* f155dfc: 3b04000f */ xori $a0,$t8,0xf /* f155e00: 00525021 */ addu $t2,$v0,$s2 /* f155e04: 01518023 */ subu $s0,$t2,$s1 /* f155e08: 3401800f */ dli $at,0x800f /* f155e0c: 3c03800b */ lui $v1,0x800b /* f155e10: 02018021 */ addu $s0,$s0,$at /* f155e14: 2463909c */ addiu $v1,$v1,-28516 /* f155e18: 360b000f */ ori $t3,$s0,0xf /* f155e1c: 2626001e */ addiu $a2,$s1,0x1e /* f155e20: ac620000 */ sw $v0,0x0($v1) /* f155e24: 3964000f */ xori $a0,$t3,0xf /* f155e28: 3c018006 */ lui $at,0x8006 /* f155e2c: 240d0001 */ addiu $t5,$zero,0x1 /* f155e30: 34ce000f */ ori $t6,$a2,0xf /* f155e34: 00808025 */ or $s0,$a0,$zero /* f155e38: a02df2c0 */ sb $t5,-0xd40($at) /* f155e3c: 39c6000f */ xori $a2,$t6,0xf /* f155e40: 0fc5560b */ jal bgLoadFile /* f155e44: 00002825 */ or $a1,$zero,$zero /* f155e48: 3c05800b */ lui $a1,0x800b /* f155e4c: 2604000c */ addiu $a0,$s0,0xc /* f155e50: 8ca5909c */ lw $a1,-0x6f64($a1) /* f155e54: 0fc56023 */ jal bgInflate /* f155e58: 02203025 */ or $a2,$s1,$zero /* f155e5c: 3c04800b */ lui $a0,0x800b /* f155e60: 8c84909c */ lw $a0,-0x6f64($a0) /* f155e64: 02402825 */ or $a1,$s2,$zero /* f155e68: 0c004a53 */ jal mempRealloc /* f155e6c: 24060004 */ addiu $a2,$zero,0x4 /* f155e70: 8fa50040 */ lw $a1,0x40($sp) /* f155e74: 8fa40038 */ lw $a0,0x38($sp) /* f155e78: 24060040 */ addiu $a2,$zero,0x40 /* f155e7c: 24a5000c */ addiu $a1,$a1,0xc /* f155e80: 0fc5560b */ jal bgLoadFile /* f155e84: afa50034 */ sw $a1,0x34($sp) /* f155e88: 8fa20038 */ lw $v0,0x38($sp) /* f155e8c: 24050004 */ addiu $a1,$zero,0x4 /* f155e90: 94520000 */ lhu $s2,0x0($v0) /* f155e94: 94590002 */ lhu $t9,0x2($v0) /* f155e98: 32587fff */ andi $t8,$s2,0x7fff /* f155e9c: 2712ffff */ addiu $s2,$t8,-1 /* f155ea0: 3649000f */ ori $t1,$s2,0xf /* f155ea4: 25240801 */ addiu $a0,$t1,0x801 /* f155ea8: 0c004a0e */ jal mempAlloc /* f155eac: afb90048 */ sw $t9,0x48($sp) /* f155eb0: 8fa60048 */ lw $a2,0x48($sp) /* f155eb4: 8fa50034 */ lw $a1,0x34($sp) /* f155eb8: 24440800 */ addiu $a0,$v0,0x800 /* f155ebc: 24c6ffff */ addiu $a2,$a2,-1 /* f155ec0: 34ca000f */ ori $t2,$a2,0xf /* f155ec4: afa2005c */ sw $v0,0x5c($sp) /* f155ec8: 00808025 */ or $s0,$a0,$zero /* f155ecc: 25460001 */ addiu $a2,$t2,0x1 /* f155ed0: 0fc5560b */ jal bgLoadFile /* f155ed4: 24a50004 */ addiu $a1,$a1,0x4 /* f155ed8: 02002025 */ or $a0,$s0,$zero /* f155edc: 8fa5005c */ lw $a1,0x5c($sp) /* f155ee0: 0fc56023 */ jal bgInflate /* f155ee4: 8fa60048 */ lw $a2,0x48($sp) /* f155ee8: 8fab0038 */ lw $t3,0x38($sp) /* f155eec: 00008025 */ or $s0,$zero,$zero /* f155ef0: 8fb1005c */ lw $s1,0x5c($sp) /* f155ef4: 95720000 */ lhu $s2,0x0($t3) /* f155ef8: 324c7fff */ andi $t4,$s2,0x7fff /* f155efc: 000c9043 */ sra $s2,$t4,0x1 /* f155f00: 52400008 */ beqzl $s2,.NB0f155f24 /* f155f04: 8fa4005c */ lw $a0,0x5c($sp) .NB0f155f08: /* f155f08: 96240000 */ lhu $a0,0x0($s1) /* f155f0c: 0fc5b860 */ jal texLoadFromTextureNum /* f155f10: 00002825 */ or $a1,$zero,$zero /* f155f14: 26100001 */ addiu $s0,$s0,0x1 /* f155f18: 1612fffb */ bne $s0,$s2,.NB0f155f08 /* f155f1c: 26310002 */ addiu $s1,$s1,0x2 /* f155f20: 8fa4005c */ lw $a0,0x5c($sp) .NB0f155f24: /* f155f24: 00002825 */ or $a1,$zero,$zero /* f155f28: 0c004a53 */ jal mempRealloc /* f155f2c: 24060004 */ addiu $a2,$zero,0x4 /* f155f30: 8fae0034 */ lw $t6,0x34($sp) /* f155f34: 8faf0048 */ lw $t7,0x48($sp) /* f155f38: 3c04800b */ lui $a0,0x800b /* f155f3c: 8c84909c */ lw $a0,-0x6f64($a0) /* f155f40: 01cfc021 */ addu $t8,$t6,$t7 /* f155f44: 27190004 */ addiu $t9,$t8,0x4 /* f155f48: 3c01800b */ lui $at,0x800b /* f155f4c: ac3990a4 */ sw $t9,-0x6f5c($at) /* f155f50: 8c890000 */ lw $t1,0x0($a0) /* f155f54: 3c03800b */ lui $v1,0x800b /* f155f58: 246390a0 */ addiu $v1,$v1,-28512 /* f155f5c: 1520003a */ bnez $t1,.NB0f156048 /* f155f60: ac690000 */ sw $t1,0x0($v1) /* f155f64: 3c02800b */ lui $v0,0x800b /* f155f68: 24429440 */ addiu $v0,$v0,-27584 /* f155f6c: ac440000 */ sw $a0,0x0($v0) /* f155f70: 8c8b0004 */ lw $t3,0x4($a0) /* f155f74: 3c07f100 */ lui $a3,0xf100 /* f155f78: 3c08800b */ lui $t0,0x800b /* f155f7c: 3c03800a */ lui $v1,0x800a /* f155f80: 01646021 */ addu $t4,$t3,$a0 /* f155f84: 25089444 */ addiu $t0,$t0,-27580 /* f155f88: 01876821 */ addu $t5,$t4,$a3 /* f155f8c: 2463e6c0 */ addiu $v1,$v1,-6464 /* f155f90: ad0d0000 */ sw $t5,0x0($t0) /* f155f94: ac6002bc */ sw $zero,0x2bc($v1) /* f155f98: 8dae0014 */ lw $t6,0x14($t5) /* f155f9c: 00802825 */ or $a1,$a0,$zero /* f155fa0: 25a20014 */ addiu $v0,$t5,0x14 /* f155fa4: 51c00009 */ beqzl $t6,.NB0f155fcc /* f155fa8: 8ca90008 */ lw $t1,0x8($a1) /* f155fac: 8c6f02bc */ lw $t7,0x2bc($v1) .NB0f155fb0: /* f155fb0: 24420014 */ addiu $v0,$v0,0x14 /* f155fb4: 25f80001 */ addiu $t8,$t7,0x1 /* f155fb8: ac7802bc */ sw $t8,0x2bc($v1) /* f155fbc: 8c590000 */ lw $t9,0x0($v0) /* f155fc0: 5720fffb */ bnezl $t9,.NB0f155fb0 /* f155fc4: 8c6f02bc */ lw $t7,0x2bc($v1) /* f155fc8: 8ca90008 */ lw $t1,0x8($a1) .NB0f155fcc: /* f155fcc: 3c01800b */ lui $at,0x800b /* f155fd0: 01245021 */ addu $t2,$t1,$a0 /* f155fd4: 01475821 */ addu $t3,$t2,$a3 /* f155fd8: ac2b9448 */ sw $t3,-0x6bb8($at) /* f155fdc: 8ca2000c */ lw $v0,0xc($a1) /* f155fe0: 3c01800b */ lui $at,0x800b /* f155fe4: 14400004 */ bnez $v0,.NB0f155ff8 /* f155fe8: 00446021 */ addu $t4,$v0,$a0 /* f155fec: 3c01800b */ lui $at,0x800b /* f155ff0: 10000003 */ beqz $zero,.NB0f156000 /* f155ff4: ac209454 */ sw $zero,-0x6bac($at) .NB0f155ff8: /* f155ff8: 01876821 */ addu $t5,$t4,$a3 /* f155ffc: ac2d9454 */ sw $t5,-0x6bac($at) .NB0f156000: /* f156000: 8ca20010 */ lw $v0,0x10($a1) /* f156004: 3c01800b */ lui $at,0x800b /* f156008: 14400004 */ bnez $v0,.NB0f15601c /* f15600c: 00447021 */ addu $t6,$v0,$a0 /* f156010: 3c01800b */ lui $at,0x800b /* f156014: 10000003 */ beqz $zero,.NB0f156024 /* f156018: ac209458 */ sw $zero,-0x6ba8($at) .NB0f15601c: /* f15601c: 01c77821 */ addu $t7,$t6,$a3 /* f156020: ac2f9458 */ sw $t7,-0x6ba8($at) .NB0f156024: /* f156024: 8ca20014 */ lw $v0,0x14($a1) /* f156028: 3c01800b */ lui $at,0x800b /* f15602c: 14400004 */ bnez $v0,.NB0f156040 /* f156030: 0044c021 */ addu $t8,$v0,$a0 /* f156034: 3c01800b */ lui $at,0x800b /* f156038: 10000003 */ beqz $zero,.NB0f156048 /* f15603c: ac20945c */ sw $zero,-0x6ba4($at) .NB0f156040: /* f156040: 0307c821 */ addu $t9,$t8,$a3 /* f156044: ac39945c */ sw $t9,-0x6ba4($at) .NB0f156048: /* f156048: 8fbf0024 */ lw $ra,0x24($sp) /* f15604c: 8fb00018 */ lw $s0,0x18($sp) /* f156050: 8fb1001c */ lw $s1,0x1c($sp) /* f156054: 8fb20020 */ lw $s2,0x20($sp) /* f156058: 03e00008 */ jr $ra /* f15605c: 27bd00b8 */ addiu $sp,$sp,0xb8 ); #endif void bgBuildTables(s32 stagenum) { s32 i; s32 j; s32 k; u32 r; u8 *header; s32 numportals; s32 index; f32 divisor; s16 lightindex; s32 candportalnum; s32 numportalsthisroom; bool swap; struct portalvertices *pvertices; struct var800a4ccc *tmp; s32 numvertices; struct var800a4ccc tmp2; u8 *scratch; u8 headerbuffer[0x50]; s32 thisneighbournum; s32 offset; u32 inflatedsize; u32 section3compsize; s16 *bboxptr; u8 *section3; u16 *datalenptr; u8 *numlightsptr; g_Rooms = mempAlloc(ALIGN16(g_Vars.roomcount * sizeof(struct room)), MEMPOOL_STAGE); var800a4ce8 = mempAlloc(ALIGN16(g_Vars.roomcount * sizeof(struct var800a4ce8)), MEMPOOL_STAGE); for (i = 0; i < g_Vars.roomcount; i++) { var800a4ce8[i].unk00 = 0xffff; var800a4ce8[i].unk02 = 0; } if (g_Vars.mplayerisrunning) { g_MpRoomVisibility = mempAlloc(ALIGN16(g_Vars.roomcount), MEMPOOL_STAGE); for (i = 0; i < g_Vars.roomcount; i++) { g_MpRoomVisibility[i] = 0; } } for (i = 0; i < g_Vars.roomcount; i++) { g_Rooms[i].vtxbatches = NULL; g_Rooms[i].numlights = 0; g_Rooms[i].lightindex = 0; g_Rooms[i].flags = 0; g_Rooms[i].unk4d = 0; g_Rooms[i].lightop = 0; g_Rooms[i].unk4e_04 = 0; } func0f15c880(g_Stages[g_StageIndex].unk14); chr0f028490(g_Stages[g_StageIndex].unk14); for (i = 0; i < 4; i++) { g_Vars.playerstats[i].scale_bg2gfx = g_Stages[g_StageIndex].unk18; } mtx00016748(1); if (var800a4920 == 0) { numportals = 0; for (i = 0; g_BgPortals[i].verticesoffset != 0; i++) { numportals++; } g_NumPortalThings = numportals; g_PortalThings = mempAlloc(ALIGN16(g_NumPortalThings * sizeof(struct portalthing)), MEMPOOL_STAGE); // Iterate the portals and update their verticesoffset value. In // storage, the g_BgPortals array is followed by vertice data, and each // portal's verticesoffset value is an index into the vertice data. // Here, the unk00 value is being converted to an offset relative to the // start of the g_BgPortals array. Start by initialising offset past the // end of the portal array, which is the start of the vertice data. offset = numportals * sizeof(struct bgportal); offset += sizeof(struct bgportal); // Because each group of vertices is variable length, the portals can't // be iterated in order and have their offset calculated. The vertice // data has to be iterated in storage order, then iterate all portals to // see if any refer to this index. for (i = 1; true; i++) { for (j = 0; j < numportals; j++) { if (g_BgPortals[j].verticesoffset == i) { g_BgPortals[j].verticesoffset = offset; } } pvertices = (struct portalvertices *)((u32)g_BgPortals + offset); if (pvertices->count <= 0) { break; } offset += pvertices->count * 12; offset += 4; } // Calculate g_RoomPortals: An array of portal numbers, ordered by room // number ascending. Each room struct contains an index into this array // where its portal numbers start. index = 0; g_RoomPortals = mempAlloc(ALIGN16((numportals == 0 ? 1 : numportals) * sizeof(s16 *)), MEMPOOL_STAGE); g_Vars.roomportalrecursionlimit = 0; for (i = 0; i < g_Vars.roomcount; i++) { numportalsthisroom = 0; g_Rooms[i].roomportallistoffset = index; for (j = 0; j < numportals; j++) { if (i == g_BgPortals[j].roomnum1) { g_RoomPortals[index] = j; numportalsthisroom++; index++; } if (i == g_BgPortals[j].roomnum2) { g_RoomPortals[index] = j; numportalsthisroom++; index++; } } g_Rooms[i].numportals = numportalsthisroom; if (numportalsthisroom > g_Vars.roomportalrecursionlimit) { g_Vars.roomportalrecursionlimit = numportalsthisroom; } } // Sort the portal numbers in g_RoomPortals within their room groups. // Sorting is done by neighbouring room number ascending. // // @bug: The k loop doesn't reset to j after doing a swap, which means // some items may not be sorted correctly. This isn't a problem if the // data on ROM is already sorted, or if they actually don't need to be // sorted. for (i = 0; i < g_Vars.roomcount; i++) { for (j = 0; j < g_Rooms[i].numportals; j++) { if (g_BgPortals[g_RoomPortals[g_Rooms[i].roomportallistoffset + j]].roomnum1 == i) { thisneighbournum = g_BgPortals[g_RoomPortals[g_Rooms[i].roomportallistoffset + j]].roomnum2; } else { thisneighbournum = g_BgPortals[g_RoomPortals[g_Rooms[i].roomportallistoffset + j]].roomnum1; } for (k = j; k < g_Rooms[i].numportals; k++) { swap = false; if (i == g_BgPortals[g_RoomPortals[g_Rooms[i].roomportallistoffset + k]].roomnum1) { if (g_BgPortals[g_RoomPortals[g_Rooms[i].roomportallistoffset + k]].roomnum2 < thisneighbournum) { swap = true; } } else { if (g_BgPortals[g_RoomPortals[g_Rooms[i].roomportallistoffset + k]].roomnum1 < thisneighbournum) { swap = true; } } if (swap) { candportalnum = g_RoomPortals[g_Rooms[i].roomportallistoffset + k]; g_RoomPortals[g_Rooms[i].roomportallistoffset + k] = g_RoomPortals[g_Rooms[i].roomportallistoffset + j]; g_RoomPortals[g_Rooms[i].roomportallistoffset + j] = candportalnum; if (g_BgPortals[g_RoomPortals[g_Rooms[i].roomportallistoffset + j]].roomnum1 == i) { thisneighbournum = g_BgPortals[g_RoomPortals[g_Rooms[i].roomportallistoffset + j]].roomnum2; } else { thisneighbournum = g_BgPortals[g_RoomPortals[g_Rooms[i].roomportallistoffset + j]].roomnum1; } } } } } var800a4cd0 = mempAlloc(ALIGN16(numportals == 0 ? 1 : numportals), MEMPOOL_STAGE); for (i = 0; i < numportals; i++) { var800a4cd0[i] = func0f15b4c0(i); } var800a4ccc = mempAlloc(ALIGN16(numportals * sizeof(struct var800a4ccc)), MEMPOOL_STAGE); for (i = 0; i < numportals; i++) { tmp2.coord.x = 0.0f; tmp2.coord.y = 0.0f; tmp2.coord.z = 0.0f; pvertices = (struct portalvertices *)((u32)g_BgPortals + g_BgPortals[i].verticesoffset); for (j = 0; j < pvertices->count; j++) { struct coord *next = &pvertices->vertices[(j + 1) % pvertices->count]; tmp2.coord.x += (pvertices->vertices[j].y - next->y) * (pvertices->vertices[j].z + next->z); tmp2.coord.y += (pvertices->vertices[j].z - next->z) * (pvertices->vertices[j].x + next->x); tmp2.coord.z += (pvertices->vertices[j].x - next->x) * (pvertices->vertices[j].y + next->y); } divisor = -sqrtf(tmp2.coord.f[0] * tmp2.coord.f[0] + tmp2.coord.f[1] * tmp2.coord.f[1] + tmp2.coord.f[2] * tmp2.coord.f[2]); tmp2.coord.x = tmp2.coord.x / divisor; tmp2.coord.y = tmp2.coord.y / divisor; tmp2.coord.z = tmp2.coord.z / divisor; tmp2.min = MAXFLOAT; tmp2.max = MINFLOAT; for (j = 0; j < pvertices->count; j++) { f32 value = pvertices->vertices[j].f[0] * tmp2.coord.f[0] + pvertices->vertices[j].f[1] * tmp2.coord.f[1] + pvertices->vertices[j].f[2] * tmp2.coord.f[2]; if (value < tmp2.min) { tmp2.min = value; } if (value > tmp2.max) { tmp2.max = value; } } tmp = &var800a4ccc[i]; tmp->coord.x = tmp2.coord.x; tmp->coord.y = tmp2.coord.y; tmp->coord.z = tmp2.coord.z; tmp->min = tmp2.min; tmp->max = tmp2.max; } portal0f0b65a8(numportals); if (g_BgCommands != NULL) { for (i = 0; g_BgCommands[i].type != BGCMD_END; i++) { if (g_BgCommands[i].type == BGCMD_PORTALARG) { g_BgCommands[i].param = portalFindNumByVertices((void *)(g_BgCommands[i].param + (u32)g_BgPrimaryData + 0xf1000000)); } } } for (i = 0; i < g_Vars.roomcount; i++) { g_Rooms[i].flags = 0; g_Rooms[i].unk06 = 0; g_Rooms[i].unk07 = 1; g_Rooms[i].loaded240 = 0; g_Rooms[i].gfxdata = NULL; g_Rooms[i].gfxdatalen = -1; g_Rooms[i].opawallhits = NULL; g_Rooms[i].xluwallhits = NULL; } roomsReset(); g_Rooms[0].bbmin[0] = 0.0f; g_Rooms[0].bbmin[1] = 0.0f; g_Rooms[0].bbmin[2] = 0.0f; g_Rooms[0].bbmax[0] = 0.0f; g_Rooms[0].bbmax[1] = 0.0f; g_Rooms[0].bbmax[2] = 0.0f; dyntexReset(); // Load section 3 of the BG file. To do this, the header of the BG file // must be loaded first as it contains the offset to section 3. Then // section 3 is loaded and inflated. Data is read out of section 3, then // the section 3 allocation is resized to 0, effectively freeing it. // Load and read the header header = (u8 *)ALIGN16((u32)headerbuffer); bgLoadFile(header, g_BgSection3, 0x40); inflatedsize = (*(u16 *)&header[0] & 0x7fff) - 1; section3compsize = *(u16 *)&header[2]; inflatedsize = (inflatedsize | 0xf) + 1; // Load and inflate section 3 #if VERSION >= VERSION_NTSC_FINAL section3 = mempAlloc(inflatedsize + 0x8000, MEMPOOL_STAGE); scratch = section3 + 0x8000; #else section3 = mempAlloc(inflatedsize + 0x1000, MEMPOOL_STAGE); scratch = section3 + 0x1000; #endif bgLoadFile(scratch, g_BgSection3 + 4, ((section3compsize - 1) | 0xf) + 1); bgInflate(scratch, section3, section3compsize); // Section 3 starts with a table of room bounding boxes bboxptr = (s16 *) section3; for (r = 1; r < g_Vars.roomcount; r++) { // Calculate bounding box g_Rooms[r].bbmin[0] = *bboxptr + g_BgRooms[r].pos.x; bboxptr++; g_Rooms[r].bbmin[1] = *bboxptr + g_BgRooms[r].pos.y; bboxptr++; g_Rooms[r].bbmin[2] = *bboxptr + g_BgRooms[r].pos.z; bboxptr++; g_Rooms[r].bbmax[0] = *bboxptr + g_BgRooms[r].pos.x; bboxptr++; g_Rooms[r].bbmax[1] = *bboxptr + g_BgRooms[r].pos.y; bboxptr++; g_Rooms[r].bbmax[2] = *bboxptr + g_BgRooms[r].pos.z; bboxptr++; if (1); // Calculate centre g_Rooms[r].centre.x = (g_Rooms[r].bbmin[0] + g_Rooms[r].bbmax[0]) / 2.0f; g_Rooms[r].centre.y = (g_Rooms[r].bbmin[1] + g_Rooms[r].bbmax[1]) / 2.0f; g_Rooms[r].centre.z = (g_Rooms[r].bbmin[2] + g_Rooms[r].bbmax[2]) / 2.0f; if (1); // Calculate radius g_Rooms[r].radius = sqrtf((g_Rooms[r].bbmin[0] - g_Rooms[r].bbmax[0]) * (g_Rooms[r].bbmin[0] - g_Rooms[r].bbmax[0]) + (g_Rooms[r].bbmin[1] - g_Rooms[r].bbmax[1]) * (g_Rooms[r].bbmin[1] - g_Rooms[r].bbmax[1]) + (g_Rooms[r].bbmin[2] - g_Rooms[r].bbmax[2]) * (g_Rooms[r].bbmin[2] - g_Rooms[r].bbmax[2])) / 2.0f; } // The next part of section 3 is a list of roomgfxdata sizes. // There is one per room and the value needs to be multiplied by 0x10. datalenptr = (u16 *) bboxptr; for (r = 1; r < g_Vars.roomcount; r++) { g_Rooms[r].gfxdatalen = ALIGN16(*datalenptr * 0x10 + 0x100); datalenptr++; } // The last part of section 3 is the number of lights per room. // This is calculating the index into the lights file where each room's // lights start. The light data is already ordered by room, so it can do // this easily by adding to the offset of the previous one. lightindex = 0; numlightsptr = (u8 *) datalenptr; for (r = 1; r < g_Vars.roomcount; r++) { g_Rooms[r].numlights = *numlightsptr; if (g_Rooms[r].numlights > 0) { g_Rooms[r].lightindex = lightindex; lightindex += g_Rooms[r].numlights; } else { g_Rooms[r].lightindex = -1; } numlightsptr++; } // Free the section 3 allocation mempRealloc(section3, 0, MEMPOOL_STAGE); for (i = 1; i < g_Vars.roomcount; i++) { roomInitLights(i); } // Initialise a table related to lights. // j is being reused here as a total light count. j = 0; for (i = 1; i < g_Vars.roomcount; i++) { j += g_Rooms[i].numlights; } if (j) { var800a41a0 = mempAlloc(ALIGN16(j * 3), MEMPOOL_STAGE); for (i = 0; i < j; i++) { var800a41a0[i * 3 + 0] = 0; var800a41a0[i * 3 + 1] = 0; var800a41a0[i * 3 + 2] = 0; } } else { var800a41a0 = NULL; } for (i = 0; g_BgPortals[i].verticesoffset != 0; i++) { func0f164ab8(i); } for (i = 1; i < g_Vars.roomcount; i++) { room0f164c64(i); } for (i = 1; i < g_Vars.roomcount; i++) { bgExpandRoomToPortals(i); } for (i = 0; g_BgPortals[i].verticesoffset != 0; i++) { g_BgPortals[i].flags &= (~PORTALFLAG_CLOSED) & 0xff; } } envSetStageNum(stagenum); var8007fc10 = 200; wallhitReset(); func0f002a98(); func0f001c0c(); #if VERSION < VERSION_NTSC_1_0 bgBuildReferenceLightSums(); #endif } void bgStop(void) { bgUnloadAllRooms(); mtx00016748(1); } void func0f15c880(f32 arg0) { // empty } f32 func0f15c888(void) { return g_Stages[g_StageIndex].unk1c / g_Stages[g_StageIndex].unk14; } f32 currentPlayerGetScaleBg2Gfx(void) { return g_Vars.currentplayerstats->scale_bg2gfx; } void currentPlayerSetScaleBg2Gfx(f32 scale) { g_Vars.currentplayerstats->scale_bg2gfx = g_Stages[g_StageIndex].unk18 * scale; mtx00016748(g_Vars.currentplayerstats->scale_bg2gfx); } void func0f15c920(void) { var8007fc3c++; if (var8007fc3c == 0xffff) { var8007fc3c = 1; func0f15cd28(); } #if PIRACYCHECKS if ((var8007fc3c & 0xff) == 0xff) { u32 checksum = 0; s32 *ptr = (s32 *)&menuTickTimers; s32 *end = (s32 *)&menuGetSinOscFrac; while (ptr < end) { checksum ^= ~*ptr; checksum ^= *ptr << 5; checksum ^= *ptr >> 15; ptr++; } if (checksum != CHECKSUM_PLACEHOLDER) { ptr = (s32 *)&bgBuildTables + 20; if (1) { end = &ptr[4]; } while (ptr < end) { *ptr -= 0x24e21; ptr++; } } } #endif } void bgTick(void) { s32 tickmode; g_NumActiveRooms = 0; #if VERSION < VERSION_NTSC_1_0 bgVerifyLightSums("bg.c", 5761); #endif func0f15c920(); if (g_Vars.currentplayerindex == 0) { bgTickRooms(); } tickmode = g_Vars.tickmode; if (tickmode == TICKMODE_NORMAL) { var8007fc10 = 4; #if VERSION >= VERSION_NTSC_1_0 if (IS8MB() && var8007fc0c) #else if (var8007fc0c) #endif { var8007fc0c--; var8007fc10 = 200; } } else { var8007fc0c = 8; var8007fc10 = 200; } if (g_Vars.currentplayer->visionmode == VISIONMODE_XRAY) { var8007fc10 = 100; } g_CamRoom = g_Vars.currentplayer->cam_room; #if VERSION >= VERSION_NTSC_1_0 bgTickPortals(); #else bgVerifyLightSums("bg.c", 5834); bgTickPortals(); bgVerifyLightSums("bg.c", 5846); #endif } Gfx *bgRender(Gfx *gdl) { gdl = lightsSetDefault(gdl); gSPSegment(gdl++, SPSEGMENT_BG_DL, g_BgPrimaryData); gdl = envStartFog(gdl, false); gdl = func0f164150(gdl); gdl = currentPlayerScissorToViewport(gdl); gdl = envStopFog(gdl); gSPMatrix(gdl++, var80092870, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION); gdl = playerLoadMatrix(gdl); return gdl; } f32 func0f15cb5c(s32 arg0) { return g_BgTable5[arg0 + 1]; } Gfx *currentPlayerScissorToViewport(Gfx *gdl) { return currentPlayerScissorWithinViewport(gdl, g_Vars.currentplayer->viewleft, g_Vars.currentplayer->viewtop, g_Vars.currentplayer->viewleft + g_Vars.currentplayer->viewwidth, g_Vars.currentplayer->viewtop + g_Vars.currentplayer->viewheight); } Gfx *currentPlayerScissorWithinViewportF(Gfx *gdl, f32 viewleft, f32 viewtop, f32 viewright, f32 viewbottom) { gdl = currentPlayerScissorWithinViewport(gdl, viewleft, viewtop, ceil(viewright), ceil(viewbottom)); return gdl; } Gfx *currentPlayerScissorWithinViewport(Gfx *gdl, s32 viewleft, s32 viewtop, s32 viewright, s32 viewbottom) { if (viewleft < g_Vars.currentplayer->viewleft) { viewleft = g_Vars.currentplayer->viewleft; } if (viewtop < g_Vars.currentplayer->viewtop) { viewtop = g_Vars.currentplayer->viewtop; } if (viewright > g_Vars.currentplayer->viewleft + g_Vars.currentplayer->viewwidth) { viewright = g_Vars.currentplayer->viewleft + g_Vars.currentplayer->viewwidth; } if (viewbottom > g_Vars.currentplayer->viewtop + g_Vars.currentplayer->viewheight) { viewbottom = g_Vars.currentplayer->viewtop + g_Vars.currentplayer->viewheight; } gDPSetScissor(gdl++, G_SC_NON_INTERLACE, viewleft, viewtop, viewright, viewbottom); return gdl; } void func0f15cd28(void) { s32 i; for (i = 0; i < g_NumPortalThings; i++) { g_PortalThings[i].unk06 = -1; g_PortalThings[i].unk04 = 0; g_PortalThings[i].unk00 = 0; } } bool func0f15cd90(u32 room, struct screenbox *screen) { s32 i; struct coord roomscreenpos; struct coord corner; s32 numa = 0; s32 numb = 0; s32 numc = 0; s32 numd = 0; s32 nume = 0; s32 numf = 0; for (i = 0; i != 8; i++) { if (i & 1) { corner.x = g_Rooms[room].bbmin[0]; } else { corner.x = g_Rooms[room].bbmax[0]; } if (i & 2) { corner.y = g_Rooms[room].bbmin[1]; } else { corner.y = g_Rooms[room].bbmax[1]; } if (i & 4) { corner.z = g_Rooms[room].bbmin[2]; } else { corner.z = g_Rooms[room].bbmax[2]; } if (func0f15d08c(&corner, &roomscreenpos) == 0) { if (var800a4cf0.zrange.far <= -roomscreenpos.z) { numb++; } if (roomscreenpos.x > screen->xmin) { numc++; } if (roomscreenpos.x < screen->xmax) { numd++; } if (roomscreenpos.y > screen->ymin) { nume++; } if (roomscreenpos.y < screen->ymax) { numf++; } numa++; } else { if (var800a4cf0.zrange.far <= -roomscreenpos.z) { numb++; } if (roomscreenpos.x < screen->xmin) { numc++; } else if (screen->xmax < roomscreenpos.x) { numd++; } if (roomscreenpos.y < screen->ymin) { nume++; } else if (screen->ymax < roomscreenpos.y) { numf++; } } } if (numa == 8 || numb == 8 || numc == 8 || numd == 8 || nume == 8 || numf == 8) { return false; } return true; } bool func0f15d08c(struct coord *a, struct coord *b) { Mtxf *matrix = camGetWorldToScreenMtxf(); b->x = a->x; b->y = a->y; b->z = a->z; mtx4TransformVecInPlace(matrix, b); cam0f0b4d68(b, b->f); if (b->z > 0) { return false; } return true; } bool g_PortalGetScreenBbox(s32 portalnum, struct screenbox *box) { s32 i; s32 j; s32 len; s32 start; s32 sp2ec; f32 sp2e4[2]; f32 sp2d4[2][2]; struct portalthing2 *thing; struct portalthing2 things[40]; if (var8007fc3c == g_PortalThings[portalnum].unk04) { box->xmin = g_PortalThings[portalnum].xmin; box->ymin = g_PortalThings[portalnum].ymin; box->xmax = g_PortalThings[portalnum].xmax; box->ymax = g_PortalThings[portalnum].ymax; return g_PortalThings[portalnum].unk06; } len = func0f165360(portalnum, &start, things); sp2ec = 0; thing = &things[start]; for (j = 0; j < len; j++) { if (thing->coord.z <= 0.0f) { cam0f0b4d68(&thing->coord, sp2e4); if (sp2ec == 0) { sp2d4[0][0] = sp2d4[1][0] = sp2e4[0]; sp2d4[0][1] = sp2d4[1][1] = sp2e4[1]; } else { if (sp2e4[0] < sp2d4[0][0]) { sp2d4[0][0] = sp2e4[0]; } if (sp2d4[1][0] < sp2e4[0]) { sp2d4[1][0] = sp2e4[0]; } if (sp2e4[1] < sp2d4[0][1]) { sp2d4[0][1] = sp2e4[1]; } if (sp2d4[1][1] < sp2e4[1]) { sp2d4[1][1] = sp2e4[1]; } } sp2ec++; } thing++; } if (sp2ec == 0) { box->xmin = 0; box->xmax = 0; box->ymin = 0; box->ymax = 0; } else if (sp2d4[1][0] < sp2d4[0][0] || sp2d4[1][1] < sp2d4[0][1]) { struct player *player = g_Vars.currentplayer; box->xmin = player->screenxminf; box->ymin = player->screenyminf; box->xmax = player->screenxmaxf; box->ymax = player->screenymaxf; } else { sp2d4[0][0] -= 0.5f; sp2d4[0][1] -= 0.5f; sp2d4[1][0] += 0.5f; sp2d4[1][1] += 0.5f; for (i = 0; i < 2; i++) { for (j = 0; j < 2; j++) { f32 value = sp2d4[i][j]; if (value >= 0.0f) { if (value > 32000.0f) { box->array[i][j] = 32000; } else { box->array[i][j] = value; } } else if (value < -32000.0f) { box->array[i][j] = -32000; } else { box->array[i][j] = value; } } } } g_PortalThings[portalnum].xmin = box->xmin; g_PortalThings[portalnum].ymin = box->ymin; g_PortalThings[portalnum].xmax = box->xmax; g_PortalThings[portalnum].ymax = box->ymax; g_PortalThings[portalnum].unk06 = sp2ec; g_PortalThings[portalnum].unk04 = var8007fc3c; return sp2ec; } Gfx *boxRenderBorder(Gfx *gdl, s32 x1, s32 y1, s32 x2, s32 y2) { gDPFillRectangle(gdl++, x1, y1, x2 + 1, y2 + 1); return gdl; } Gfx *boxRender(Gfx *gdl, s32 x1, s32 y1, s32 x2, s32 y2) { gdl = boxRenderBorder(gdl, x1, y1, x2, y1); // top gdl = boxRenderBorder(gdl, x2, y1, x2, y2); // right gdl = boxRenderBorder(gdl, x1, y2, x2, y2); // bottom gdl = boxRenderBorder(gdl, x1, y1, x1, y2); // left return gdl; } bool boxGetIntersection(struct screenbox *a, struct screenbox *b) { a->xmin = a->xmin > b->xmin ? a->xmin : b->xmin; a->ymin = a->ymin > b->ymin ? a->ymin : b->ymin; a->xmax = b->xmax > a->xmax ? a->xmax : b->xmax; a->ymax = b->ymax > a->ymax ? a->ymax : b->ymax; if (a->xmin >= a->xmax) { a->xmin = a->xmax; return false; } if (a->ymax <= a->ymin) { a->ymin = a->ymax; return false; } return true; } void boxExpand(struct screenbox *a, struct screenbox *b) { a->xmin = a->xmin < b->xmin ? a->xmin : b->xmin; a->ymin = a->ymin < b->ymin ? a->ymin : b->ymin; a->xmax = a->xmax > b->xmax ? a->xmax : b->xmax; a->ymax = a->ymax > b->ymax ? a->ymax : b->ymax; } void boxCopy(struct screenbox *dst, struct screenbox *src) { dst->xmin = src->xmin; dst->ymin = src->ymin; dst->xmax = src->xmax; dst->ymax = src->ymax; } bool roomIsOnscreen(s32 room) { if (g_Vars.mplayerisrunning) { return (g_MpRoomVisibility[room] & 0xf) != 0; } return g_Rooms[room].flags & ROOMFLAG_ONSCREEN; } bool roomIsStandby(s32 room) { if (g_Vars.mplayerisrunning) { return (g_MpRoomVisibility[room] & 0xf0) != 0; } return g_Rooms[room].flags & ROOMFLAG_STANDBY; } bool roomIsOnPlayerScreen(s32 room, u32 playernum) { if (g_Vars.mplayerisrunning) { return (g_MpRoomVisibility[room] & (1 << playernum)) != 0; } return g_Rooms[room].flags & ROOMFLAG_ONSCREEN; } bool roomIsOnPlayerStandby(s32 room, u32 playernum) { if (g_Vars.mplayerisrunning) { return (g_MpRoomVisibility[room] & (0x10 << playernum)) != 0; } return g_Rooms[room].flags & ROOMFLAG_STANDBY; } s32 portalFindNumByVertices(struct portalvertices *arg0) { s32 i; struct bgportal *portal = g_BgPortals; for (i = 0; portal[i].verticesoffset != 0; i++) { struct portalvertices *pvertices = (struct portalvertices *)((u32)portal + portal[i].verticesoffset); if (pvertices == arg0) { return i; } } return 0; } /** * Build a string showing the state of all rooms in the stage. * * The string contains "L" if a room is loaded, "." if not, and has line breaks * every 40 characters. * * Nothing is done with the string though. It's likely that debug versions of * the game would send the string to the host computer or display it on the HUD. */ void roomsHandleStateDebugging(void) { if (debugIsRoomStateDebugEnabled()) { u8 string[704]; s32 len = 0; s32 i; for (i = 1; i < g_Vars.roomcount; i++) { if ((i - 1) % 40 == 0) { if (i != 1) { string[len] = '\n'; len++; } } if (g_Rooms[i].loaded240) { string[len] = 'L'; } else { string[len] = '.'; } len++; } string[len] = '\0'; } } u32 bgInflate(u8 *src, u8 *dst, u32 len) { u32 result; u8 scratch[5120]; #if VERSION < VERSION_NTSC_1_0 char message[128]; #endif if (rzipIs1173(src)) { result = rzipInflate(src, dst, &scratch); #if VERSION < VERSION_NTSC_1_0 if (!result) { sprintf(message, "DMA-Crash %s %d Ram: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", "bg.c", 6914, src[0], src[1], src[2], src[3], src[4], src[5], src[6], src[7], src[8], src[9], src[10], src[11], src[12], src[13], src[14], src[15]); crashSetMessage(&message); CRASH(); } #endif } else { result = len; bcopy(src, dst, len); } return result; } Gfx *roomGetNextGdlInBlock(struct roomblock *block, Gfx *start, Gfx *end) { \ Gfx *tmp; \ while (true) { if (block == NULL) { return end; } if (start); if (start); if (start); if (start); switch (block->type) { case ROOMBLOCKTYPE_LEAF: if (block->gdl > start && (block->gdl < end || end == NULL)) { end = block->gdl; } block = block->next; break; case ROOMBLOCKTYPE_PARENT: tmp = roomGetNextGdlInBlock(block->child, start, end); block = block->next; end = tmp; break; default: return end; } } return end; } Gfx *roomGetNextGdlInLayer(s32 roomnum, Gfx *start, u32 types) { struct roomblock *opablocks = g_Rooms[roomnum].gfxdata->opablocks; struct roomblock *xlublocks = g_Rooms[roomnum].gfxdata->xlublocks; Gfx *opagdl = NULL; Gfx *xlugdl = NULL; if ((types & VTXBATCHTYPE_OPA) && opablocks) { opagdl = roomGetNextGdlInBlock(opablocks, start, NULL); if (types == VTXBATCHTYPE_OPA) { return opagdl; } } if ((types & VTXBATCHTYPE_XLU) && xlublocks) { xlugdl = roomGetNextGdlInBlock(xlublocks, start, NULL); if (types == VTXBATCHTYPE_XLU) { return xlugdl; } } if (opagdl) { if (xlugdl && xlugdl < opagdl) { return xlugdl; } return opagdl; } return xlugdl; } struct gfxvtx *roomFindVerticesForGdl(s32 roomnum, Gfx *gdl) { struct roomblock *block = g_Rooms[roomnum].gfxdata->blocks; u32 end = (u32)g_Rooms[roomnum].gfxdata->vertices; while ((u32)(block + 1) <= end) { switch (block->type) { case ROOMBLOCKTYPE_LEAF: if (gdl == block->gdl) { return block->vertices; } break; case ROOMBLOCKTYPE_PARENT: if ((u32)block->unk0c < end) { end = (u32)block->unk0c; } break; } block++; } return NULL; } #if MATCHING #if VERSION >= VERSION_NTSC_1_0 GLOBAL_ASM( glabel bgLoadRoom /* f15dc58: 27bdfd08 */ addiu $sp,$sp,-760 /* f15dc5c: afbf0034 */ sw $ra,0x34($sp) /* f15dc60: afb40030 */ sw $s4,0x30($sp) /* f15dc64: afb3002c */ sw $s3,0x2c($sp) /* f15dc68: afb20028 */ sw $s2,0x28($sp) /* f15dc6c: afb10024 */ sw $s1,0x24($sp) /* f15dc70: 108001f8 */ beqz $a0,.L0f15e454 /* f15dc74: afb00020 */ sw $s0,0x20($sp) /* f15dc78: 3c0e800a */ lui $t6,%hi(g_Vars+0x2bc) /* f15dc7c: 8dcea27c */ lw $t6,%lo(g_Vars+0x2bc)($t6) /* f15dc80: 000478c0 */ sll $t7,$a0,0x3 /* f15dc84: 01e47821 */ addu $t7,$t7,$a0 /* f15dc88: 008e082a */ slt $at,$a0,$t6 /* f15dc8c: 102001f1 */ beqz $at,.L0f15e454 /* f15dc90: 000f7880 */ sll $t7,$t7,0x2 /* f15dc94: 3c18800a */ lui $t8,%hi(g_Rooms) /* f15dc98: 8f184928 */ lw $t8,%lo(g_Rooms)($t8) /* f15dc9c: 01e47823 */ subu $t7,$t7,$a0 /* f15dca0: 000f7880 */ sll $t7,$t7,0x2 /* f15dca4: afaf0054 */ sw $t7,0x54($sp) /* f15dca8: 030f1821 */ addu $v1,$t8,$t7 /* f15dcac: 846b0002 */ lh $t3,0x2($v1) /* f15dcb0: 556001e9 */ bnezl $t3,.L0f15e458 /* f15dcb4: 8fbf0034 */ lw $ra,0x34($sp) /* f15dcb8: 8c620080 */ lw $v0,0x80($v1) /* f15dcbc: 18400009 */ blez $v0,.L0f15dce4 /* f15dcc0: 00000000 */ nop /* f15dcc4: afa202f4 */ sw $v0,0x2f4($sp) /* f15dcc8: 0fc47b6c */ jal debug0f11edb0 /* f15dccc: afa402f8 */ sw $a0,0x2f8($sp) /* f15dcd0: 10400007 */ beqz $v0,.L0f15dcf0 /* f15dcd4: 8fac02f4 */ lw $t4,0x2f4($sp) /* f15dcd8: 258d0400 */ addiu $t5,$t4,0x400 /* f15dcdc: 10000004 */ b .L0f15dcf0 /* f15dce0: afad02f4 */ sw $t5,0x2f4($sp) .L0f15dce4: /* f15dce4: 0c004b37 */ jal memaGetLongestFree /* f15dce8: afa402f8 */ sw $a0,0x2f8($sp) /* f15dcec: afa202f4 */ sw $v0,0x2f4($sp) .L0f15dcf0: /* f15dcf0: 8fa402f4 */ lw $a0,0x2f4($sp) /* f15dcf4: 0fc5796e */ jal bgGarbageCollectRooms /* f15dcf8: 00002825 */ or $a1,$zero,$zero /* f15dcfc: 0c004aac */ jal memaAlloc /* f15dd00: 8fa402f4 */ lw $a0,0x2f4($sp) /* f15dd04: 104001d3 */ beqz $v0,.L0f15e454 /* f15dd08: 0040a025 */ or $s4,$v0,$zero /* f15dd0c: 0fc4f0dc */ jal dyntexSetCurrentRoom /* f15dd10: 87a402fa */ lh $a0,0x2fa($sp) /* f15dd14: 8fb002f8 */ lw $s0,0x2f8($sp) /* f15dd18: 3c11800a */ lui $s1,%hi(g_BgRooms) /* f15dd1c: 26314cc4 */ addiu $s1,$s1,%lo(g_BgRooms) /* f15dd20: 8e2f0000 */ lw $t7,0x0($s1) /* f15dd24: 00107080 */ sll $t6,$s0,0x2 /* f15dd28: 01d07021 */ addu $t6,$t6,$s0 /* f15dd2c: 000e8080 */ sll $s0,$t6,0x2 /* f15dd30: 01f01021 */ addu $v0,$t7,$s0 /* f15dd34: 8c430000 */ lw $v1,0x0($v0) /* f15dd38: 8c580014 */ lw $t8,0x14($v0) /* f15dd3c: 3c04800a */ lui $a0,%hi(g_BgPrimaryData) /* f15dd40: 8c84491c */ lw $a0,%lo(g_BgPrimaryData)($a0) /* f15dd44: 03039023 */ subu $s2,$t8,$v1 /* f15dd48: 2652000f */ addiu $s2,$s2,0xf /* f15dd4c: 2401fff0 */ addiu $at,$zero,-16 /* f15dd50: 8fa702f4 */ lw $a3,0x2f4($sp) /* f15dd54: 0241c824 */ and $t9,$s2,$at /* f15dd58: 00645821 */ addu $t3,$v1,$a0 /* f15dd5c: 3c01f100 */ lui $at,0xf100 /* f15dd60: 3c0c8008 */ lui $t4,%hi(var8007fc54) /* f15dd64: 01642823 */ subu $a1,$t3,$a0 /* f15dd68: 8d8cfc54 */ lw $t4,%lo(var8007fc54)($t4) /* f15dd6c: 00a12821 */ addu $a1,$a1,$at /* f15dd70: 00f9082a */ slt $at,$a3,$t9 /* f15dd74: 03209025 */ or $s2,$t9,$zero /* f15dd78: 10200005 */ beqz $at,.L0f15dd90 /* f15dd7c: 00ac2823 */ subu $a1,$a1,$t4 /* f15dd80: 0fc4f0dc */ jal dyntexSetCurrentRoom /* f15dd84: 2404ffff */ addiu $a0,$zero,-1 /* f15dd88: 100001b3 */ b .L0f15e458 /* f15dd8c: 8fbf0034 */ lw $ra,0x34($sp) .L0f15dd90: /* f15dd90: 00f26823 */ subu $t5,$a3,$s2 /* f15dd94: 01b49821 */ addu $s3,$t5,$s4 /* f15dd98: 02602025 */ or $a0,$s3,$zero /* f15dd9c: 0fc56c71 */ jal bgLoadFile /* f15dda0: 02403025 */ or $a2,$s2,$zero /* f15dda4: 0c002277 */ jal rzipIs1173 /* f15dda8: 02602025 */ or $a0,$s3,$zero /* f15ddac: 10400009 */ beqz $v0,.L0f15ddd4 /* f15ddb0: 8fae02f4 */ lw $t6,0x2f4($sp) /* f15ddb4: 264f0020 */ addiu $t7,$s2,0x20 /* f15ddb8: 01cf082a */ slt $at,$t6,$t7 /* f15ddbc: 50200006 */ beqzl $at,.L0f15ddd8 /* f15ddc0: 8e380000 */ lw $t8,0x0($s1) /* f15ddc4: 0fc4f0dc */ jal dyntexSetCurrentRoom /* f15ddc8: 2404ffff */ addiu $a0,$zero,-1 /* f15ddcc: 100001a2 */ b .L0f15e458 /* f15ddd0: 8fbf0034 */ lw $ra,0x34($sp) .L0f15ddd4: /* f15ddd4: 8e380000 */ lw $t8,0x0($s1) .L0f15ddd8: /* f15ddd8: 02602025 */ or $a0,$s3,$zero /* f15dddc: 02802825 */ or $a1,$s4,$zero /* f15dde0: 03101021 */ addu $v0,$t8,$s0 /* f15dde4: 8c590014 */ lw $t9,0x14($v0) /* f15dde8: 8c4b0000 */ lw $t3,0x0($v0) /* f15ddec: 0fc5766a */ jal bgInflate /* f15ddf0: 032b3023 */ subu $a2,$t9,$t3 /* f15ddf4: 3c09800a */ lui $t1,%hi(g_Rooms) /* f15ddf8: 25294928 */ addiu $t1,$t1,%lo(g_Rooms) /* f15ddfc: 8fa80054 */ lw $t0,0x54($sp) /* f15de00: 8d2c0000 */ lw $t4,0x0($t1) /* f15de04: afa202f0 */ sw $v0,0x2f0($sp) /* f15de08: 24060003 */ addiu $a2,$zero,0x3 /* f15de0c: 01886821 */ addu $t5,$t4,$t0 /* f15de10: adb40014 */ sw $s4,0x14($t5) /* f15de14: 8d2e0000 */ lw $t6,0x0($t1) /* f15de18: 01c87821 */ addu $t7,$t6,$t0 /* f15de1c: 8df30014 */ lw $s3,0x14($t7) /* f15de20: 8e630000 */ lw $v1,0x0($s3) /* f15de24: 5060000b */ beqzl $v1,.L0f15de54 /* f15de28: 8e620004 */ lw $v0,0x4($s3) /* f15de2c: 8e380000 */ lw $t8,0x0($s1) /* f15de30: 0310c821 */ addu $t9,$t8,$s0 /* f15de34: 8f2b0000 */ lw $t3,0x0($t9) /* f15de38: 006b6023 */ subu $t4,$v1,$t3 /* f15de3c: 01946821 */ addu $t5,$t4,$s4 /* f15de40: ae6d0000 */ sw $t5,0x0($s3) /* f15de44: 8d2e0000 */ lw $t6,0x0($t1) /* f15de48: 01c87821 */ addu $t7,$t6,$t0 /* f15de4c: 8df30014 */ lw $s3,0x14($t7) /* f15de50: 8e620004 */ lw $v0,0x4($s3) .L0f15de54: /* f15de54: 5040000b */ beqzl $v0,.L0f15de84 /* f15de58: 8e620008 */ lw $v0,0x8($s3) /* f15de5c: 8e380000 */ lw $t8,0x0($s1) /* f15de60: 0310c821 */ addu $t9,$t8,$s0 /* f15de64: 8f2b0000 */ lw $t3,0x0($t9) /* f15de68: 004b6023 */ subu $t4,$v0,$t3 /* f15de6c: 01946821 */ addu $t5,$t4,$s4 /* f15de70: ae6d0004 */ sw $t5,0x4($s3) /* f15de74: 8d2e0000 */ lw $t6,0x0($t1) /* f15de78: 01c87821 */ addu $t7,$t6,$t0 /* f15de7c: 8df30014 */ lw $s3,0x14($t7) /* f15de80: 8e620008 */ lw $v0,0x8($s3) .L0f15de84: /* f15de84: 5040000b */ beqzl $v0,.L0f15deb4 /* f15de88: 8e62000c */ lw $v0,0xc($s3) /* f15de8c: 8e380000 */ lw $t8,0x0($s1) /* f15de90: 0310c821 */ addu $t9,$t8,$s0 /* f15de94: 8f2b0000 */ lw $t3,0x0($t9) /* f15de98: 004b6023 */ subu $t4,$v0,$t3 /* f15de9c: 01946821 */ addu $t5,$t4,$s4 /* f15dea0: ae6d0008 */ sw $t5,0x8($s3) /* f15dea4: 8d2e0000 */ lw $t6,0x0($t1) /* f15dea8: 01c87821 */ addu $t7,$t6,$t0 /* f15deac: 8df30014 */ lw $s3,0x14($t7) /* f15deb0: 8e62000c */ lw $v0,0xc($s3) .L0f15deb4: /* f15deb4: 5040000b */ beqzl $v0,.L0f15dee4 /* f15deb8: 8e620000 */ lw $v0,0x0($s3) /* f15debc: 8e380000 */ lw $t8,0x0($s1) /* f15dec0: 0310c821 */ addu $t9,$t8,$s0 /* f15dec4: 8f2b0000 */ lw $t3,0x0($t9) /* f15dec8: 004b6023 */ subu $t4,$v0,$t3 /* f15decc: 01946821 */ addu $t5,$t4,$s4 /* f15ded0: ae6d000c */ sw $t5,0xc($s3) /* f15ded4: 8d2e0000 */ lw $t6,0x0($t1) /* f15ded8: 01c87821 */ addu $t7,$t6,$t0 /* f15dedc: 8df30014 */ lw $s3,0x14($t7) /* f15dee0: 8e620000 */ lw $v0,0x0($s3) .L0f15dee4: /* f15dee4: 26630018 */ addiu $v1,$s3,0x18 /* f15dee8: 24650014 */ addiu $a1,$v1,0x14 /* f15deec: 0045082b */ sltu $at,$v0,$a1 /* f15def0: 14200060 */ bnez $at,.L0f15e074 /* f15def4: 00402025 */ or $a0,$v0,$zero /* f15def8: 24070001 */ addiu $a3,$zero,0x1 /* f15defc: 90620000 */ lbu $v0,0x0($v1) .L0f15df00: /* f15df00: 50400006 */ beqzl $v0,.L0f15df1c /* f15df04: 8c620004 */ lw $v0,0x4($v1) /* f15df08: 50470029 */ beql $v0,$a3,.L0f15dfb0 /* f15df0c: 8c620004 */ lw $v0,0x4($v1) /* f15df10: 10000050 */ b .L0f15e054 /* f15df14: 00a01825 */ or $v1,$a1,$zero /* f15df18: 8c620004 */ lw $v0,0x4($v1) .L0f15df1c: /* f15df1c: 50400008 */ beqzl $v0,.L0f15df40 /* f15df20: 8c620008 */ lw $v0,0x8($v1) /* f15df24: 8e380000 */ lw $t8,0x0($s1) /* f15df28: 0310c821 */ addu $t9,$t8,$s0 /* f15df2c: 8f2b0000 */ lw $t3,0x0($t9) /* f15df30: 004b6023 */ subu $t4,$v0,$t3 /* f15df34: 01946821 */ addu $t5,$t4,$s4 /* f15df38: ac6d0004 */ sw $t5,0x4($v1) /* f15df3c: 8c620008 */ lw $v0,0x8($v1) .L0f15df40: /* f15df40: 50400008 */ beqzl $v0,.L0f15df64 /* f15df44: 8c62000c */ lw $v0,0xc($v1) /* f15df48: 8e2e0000 */ lw $t6,0x0($s1) /* f15df4c: 01d07821 */ addu $t7,$t6,$s0 /* f15df50: 8df80000 */ lw $t8,0x0($t7) /* f15df54: 0058c823 */ subu $t9,$v0,$t8 /* f15df58: 03345821 */ addu $t3,$t9,$s4 /* f15df5c: ac6b0008 */ sw $t3,0x8($v1) /* f15df60: 8c62000c */ lw $v0,0xc($v1) .L0f15df64: /* f15df64: 50400008 */ beqzl $v0,.L0f15df88 /* f15df68: 8c620010 */ lw $v0,0x10($v1) /* f15df6c: 8e2c0000 */ lw $t4,0x0($s1) /* f15df70: 01906821 */ addu $t5,$t4,$s0 /* f15df74: 8dae0000 */ lw $t6,0x0($t5) /* f15df78: 004e7823 */ subu $t7,$v0,$t6 /* f15df7c: 01f4c021 */ addu $t8,$t7,$s4 /* f15df80: ac78000c */ sw $t8,0xc($v1) /* f15df84: 8c620010 */ lw $v0,0x10($v1) .L0f15df88: /* f15df88: 50400032 */ beqzl $v0,.L0f15e054 /* f15df8c: 00a01825 */ or $v1,$a1,$zero /* f15df90: 8e390000 */ lw $t9,0x0($s1) /* f15df94: 03305821 */ addu $t3,$t9,$s0 /* f15df98: 8d6c0000 */ lw $t4,0x0($t3) /* f15df9c: 004c6823 */ subu $t5,$v0,$t4 /* f15dfa0: 01b47021 */ addu $t6,$t5,$s4 /* f15dfa4: 1000002a */ b .L0f15e050 /* f15dfa8: ac6e0010 */ sw $t6,0x10($v1) /* f15dfac: 8c620004 */ lw $v0,0x4($v1) .L0f15dfb0: /* f15dfb0: 50400008 */ beqzl $v0,.L0f15dfd4 /* f15dfb4: 8c620008 */ lw $v0,0x8($v1) /* f15dfb8: 8e2f0000 */ lw $t7,0x0($s1) /* f15dfbc: 01f0c021 */ addu $t8,$t7,$s0 /* f15dfc0: 8f190000 */ lw $t9,0x0($t8) /* f15dfc4: 00595823 */ subu $t3,$v0,$t9 /* f15dfc8: 01746021 */ addu $t4,$t3,$s4 /* f15dfcc: ac6c0004 */ sw $t4,0x4($v1) /* f15dfd0: 8c620008 */ lw $v0,0x8($v1) .L0f15dfd4: /* f15dfd4: 50400008 */ beqzl $v0,.L0f15dff8 /* f15dfd8: 8c62000c */ lw $v0,0xc($v1) /* f15dfdc: 8e2d0000 */ lw $t5,0x0($s1) /* f15dfe0: 01b07021 */ addu $t6,$t5,$s0 /* f15dfe4: 8dcf0000 */ lw $t7,0x0($t6) /* f15dfe8: 004fc023 */ subu $t8,$v0,$t7 /* f15dfec: 0314c821 */ addu $t9,$t8,$s4 /* f15dff0: ac790008 */ sw $t9,0x8($v1) /* f15dff4: 8c62000c */ lw $v0,0xc($v1) .L0f15dff8: /* f15dff8: 50400008 */ beqzl $v0,.L0f15e01c /* f15dffc: 8c620010 */ lw $v0,0x10($v1) /* f15e000: 8e2b0000 */ lw $t3,0x0($s1) /* f15e004: 01706021 */ addu $t4,$t3,$s0 /* f15e008: 8d8d0000 */ lw $t5,0x0($t4) /* f15e00c: 004d7023 */ subu $t6,$v0,$t5 /* f15e010: 01d47821 */ addu $t7,$t6,$s4 /* f15e014: ac6f000c */ sw $t7,0xc($v1) /* f15e018: 8c620010 */ lw $v0,0x10($v1) .L0f15e01c: /* f15e01c: 50400008 */ beqzl $v0,.L0f15e040 /* f15e020: 8c62000c */ lw $v0,0xc($v1) /* f15e024: 8e380000 */ lw $t8,0x0($s1) /* f15e028: 0310c821 */ addu $t9,$t8,$s0 /* f15e02c: 8f2b0000 */ lw $t3,0x0($t9) /* f15e030: 004b6023 */ subu $t4,$v0,$t3 /* f15e034: 01946821 */ addu $t5,$t4,$s4 /* f15e038: ac6d0010 */ sw $t5,0x10($v1) /* f15e03c: 8c62000c */ lw $v0,0xc($v1) .L0f15e040: /* f15e040: 0044082b */ sltu $at,$v0,$a0 /* f15e044: 50200003 */ beqzl $at,.L0f15e054 /* f15e048: 00a01825 */ or $v1,$a1,$zero /* f15e04c: 00402025 */ or $a0,$v0,$zero .L0f15e050: /* f15e050: 00a01825 */ or $v1,$a1,$zero .L0f15e054: /* f15e054: 24a50014 */ addiu $a1,$a1,0x14 /* f15e058: 0085082b */ sltu $at,$a0,$a1 /* f15e05c: 5020ffa8 */ beqzl $at,.L0f15df00 /* f15e060: 90620000 */ lbu $v0,0x0($v1) /* f15e064: 8d2e0000 */ lw $t6,0x0($t1) /* f15e068: 01c87821 */ addu $t7,$t6,$t0 /* f15e06c: 8df30014 */ lw $s3,0x14($t7) /* f15e070: 8e620000 */ lw $v0,0x0($s3) .L0f15e074: /* f15e074: 8e780004 */ lw $t8,0x4($s3) /* f15e078: 2401000c */ addiu $at,$zero,0xc /* f15e07c: 00002825 */ or $a1,$zero,$zero /* f15e080: 0302c823 */ subu $t9,$t8,$v0 /* f15e084: 0321001b */ divu $zero,$t9,$at /* f15e088: 00005812 */ mflo $t3 /* f15e08c: a66b0014 */ sh $t3,0x14($s3) /* f15e090: 0fc576ad */ jal roomGetNextGdlInLayer /* f15e094: 8fa402f8 */ lw $a0,0x2f8($sp) /* f15e098: 3c0c800a */ lui $t4,%hi(g_Rooms) /* f15e09c: 8d8c4928 */ lw $t4,%lo(g_Rooms)($t4) /* f15e0a0: 8fad0054 */ lw $t5,0x54($sp) /* f15e0a4: 00009025 */ or $s2,$zero,$zero /* f15e0a8: 00002825 */ or $a1,$zero,$zero /* f15e0ac: 018d7021 */ addu $t6,$t4,$t5 /* f15e0b0: 8dd30014 */ lw $s3,0x14($t6) /* f15e0b4: 24060003 */ addiu $a2,$zero,0x3 /* f15e0b8: 8e6f0004 */ lw $t7,0x4($s3) /* f15e0bc: 004fc023 */ subu $t8,$v0,$t7 /* f15e0c0: 0018c882 */ srl $t9,$t8,0x2 /* f15e0c4: a6790016 */ sh $t9,0x16($s3) /* f15e0c8: 0fc576ad */ jal roomGetNextGdlInLayer /* f15e0cc: 8fa402f8 */ lw $a0,0x2f8($sp) /* f15e0d0: 10400014 */ beqz $v0,.L0f15e124 /* f15e0d4: 00408025 */ or $s0,$v0,$zero /* f15e0d8: 00121080 */ sll $v0,$s2,0x2 /* f15e0dc: 27ab0208 */ addiu $t3,$sp,0x208 /* f15e0e0: 27ac0140 */ addiu $t4,$sp,0x140 /* f15e0e4: 004c8821 */ addu $s1,$v0,$t4 /* f15e0e8: 004b9821 */ addu $s3,$v0,$t3 .L0f15e0ec: /* f15e0ec: ae700000 */ sw $s0,0x0($s3) /* f15e0f0: 8fa402f8 */ lw $a0,0x2f8($sp) /* f15e0f4: 0fc576ed */ jal roomFindVerticesForGdl /* f15e0f8: 02002825 */ or $a1,$s0,$zero /* f15e0fc: ae220000 */ sw $v0,0x0($s1) /* f15e100: 26520001 */ addiu $s2,$s2,0x1 /* f15e104: 26730004 */ addiu $s3,$s3,0x4 /* f15e108: 26310004 */ addiu $s1,$s1,0x4 /* f15e10c: 8fa402f8 */ lw $a0,0x2f8($sp) /* f15e110: 02002825 */ or $a1,$s0,$zero /* f15e114: 0fc576ad */ jal roomGetNextGdlInLayer /* f15e118: 24060003 */ addiu $a2,$zero,0x3 /* f15e11c: 1440fff3 */ bnez $v0,.L0f15e0ec /* f15e120: 00408025 */ or $s0,$v0,$zero .L0f15e124: /* f15e124: 8fae02f0 */ lw $t6,0x2f0($sp) /* f15e128: 00123880 */ sll $a3,$s2,0x2 /* f15e12c: 27ad0208 */ addiu $t5,$sp,0x208 /* f15e130: 00ed9821 */ addu $s3,$a3,$t5 /* f15e134: 028e1021 */ addu $v0,$s4,$t6 /* f15e138: ae620000 */ sw $v0,0x0($s3) /* f15e13c: 8fb802f4 */ lw $t8,0x2f4($sp) /* f15e140: 8fa40208 */ lw $a0,0x208($sp) /* f15e144: afa7004c */ sw $a3,0x4c($sp) /* f15e148: 02988021 */ addu $s0,$s4,$t8 /* f15e14c: 00441823 */ subu $v1,$v0,$a0 /* f15e150: 02032823 */ subu $a1,$s0,$v1 /* f15e154: 0fc5d7bd */ jal texCopyGdls /* f15e158: 00603025 */ or $a2,$v1,$zero /* f15e15c: 26420001 */ addiu $v0,$s2,0x1 /* f15e160: 1840000d */ blez $v0,.L0f15e198 /* f15e164: 00004025 */ or $t0,$zero,$zero /* f15e168: 8e790000 */ lw $t9,0x0($s3) /* f15e16c: 27a90078 */ addiu $t1,$sp,0x78 /* f15e170: 27a30208 */ addiu $v1,$sp,0x208 /* f15e174: 02192023 */ subu $a0,$s0,$t9 .L0f15e178: /* f15e178: 8c6b0000 */ lw $t3,0x0($v1) /* f15e17c: 25080001 */ addiu $t0,$t0,0x1 /* f15e180: 25290004 */ addiu $t1,$t1,0x4 /* f15e184: 008b6021 */ addu $t4,$a0,$t3 /* f15e188: 24630004 */ addiu $v1,$v1,0x4 /* f15e18c: 1502fffa */ bne $t0,$v0,.L0f15e178 /* f15e190: ad2cfffc */ sw $t4,-0x4($t1) /* f15e194: 00004025 */ or $t0,$zero,$zero .L0f15e198: /* f15e198: 1a40001e */ blez $s2,.L0f15e214 /* f15e19c: 8fa60208 */ lw $a2,0x208($sp) /* f15e1a0: 27a90078 */ addiu $t1,$sp,0x78 /* f15e1a4: 27a30208 */ addiu $v1,$sp,0x208 /* f15e1a8: 27b00140 */ addiu $s0,$sp,0x140 .L0f15e1ac: /* f15e1ac: 8c6d0004 */ lw $t5,0x4($v1) /* f15e1b0: 8c6e0000 */ lw $t6,0x0($v1) /* f15e1b4: 8e180000 */ lw $t8,0x0($s0) /* f15e1b8: 8d240000 */ lw $a0,0x0($t1) /* f15e1bc: afa90040 */ sw $t1,0x40($sp) /* f15e1c0: afa8006c */ sw $t0,0x6c($sp) /* f15e1c4: afa602dc */ sw $a2,0x2dc($sp) /* f15e1c8: afa30038 */ sw $v1,0x38($sp) /* f15e1cc: 00003825 */ or $a3,$zero,$zero /* f15e1d0: 01ae2823 */ subu $a1,$t5,$t6 /* f15e1d4: 0fc5d5b0 */ jal texLoadFromGdl /* f15e1d8: afb80010 */ sw $t8,0x10($sp) /* f15e1dc: 8fa602dc */ lw $a2,0x2dc($sp) /* f15e1e0: 8fa90040 */ lw $t1,0x40($sp) /* f15e1e4: 8fa30038 */ lw $v1,0x38($sp) /* f15e1e8: 8fa8006c */ lw $t0,0x6c($sp) /* f15e1ec: ad260000 */ sw $a2,0x0($t1) /* f15e1f0: 00c23021 */ addu $a2,$a2,$v0 /* f15e1f4: 24c60007 */ addiu $a2,$a2,0x7 /* f15e1f8: 34cf0007 */ ori $t7,$a2,0x7 /* f15e1fc: 25080001 */ addiu $t0,$t0,0x1 /* f15e200: 26100004 */ addiu $s0,$s0,0x4 /* f15e204: 39e60007 */ xori $a2,$t7,0x7 /* f15e208: 25290004 */ addiu $t1,$t1,0x4 /* f15e20c: 1512ffe7 */ bne $t0,$s2,.L0f15e1ac /* f15e210: 24630004 */ addiu $v1,$v1,0x4 .L0f15e214: /* f15e214: 8fab004c */ lw $t3,0x4c($sp) /* f15e218: 27b00078 */ addiu $s0,$sp,0x78 /* f15e21c: 3c0d800a */ lui $t5,%hi(g_Rooms) /* f15e220: 020b6021 */ addu $t4,$s0,$t3 /* f15e224: ad860000 */ sw $a2,0x0($t4) /* f15e228: 8fae0054 */ lw $t6,0x54($sp) /* f15e22c: 8dad4928 */ lw $t5,%lo(g_Rooms)($t5) /* f15e230: 00d4c023 */ subu $t8,$a2,$s4 /* f15e234: 270f002f */ addiu $t7,$t8,0x2f /* f15e238: 35f9000f */ ori $t9,$t7,0xf /* f15e23c: 3b2b000f */ xori $t3,$t9,0xf /* f15e240: 01ae1821 */ addu $v1,$t5,$t6 /* f15e244: ac6b0080 */ sw $t3,0x80($v1) /* f15e248: 3c0c800a */ lui $t4,%hi(g_Rooms) /* f15e24c: 8d8c4928 */ lw $t4,%lo(g_Rooms)($t4) /* f15e250: 8fad0054 */ lw $t5,0x54($sp) /* f15e254: 240a0001 */ addiu $t2,$zero,0x1 /* f15e258: 3c0e800a */ lui $t6,%hi(g_Rooms) /* f15e25c: 018d1821 */ addu $v1,$t4,$t5 /* f15e260: a46a0002 */ sh $t2,0x2($v1) /* f15e264: 8fb80054 */ lw $t8,0x54($sp) /* f15e268: 8dce4928 */ lw $t6,%lo(g_Rooms)($t6) /* f15e26c: 8faf02f4 */ lw $t7,0x2f4($sp) /* f15e270: 02802025 */ or $a0,$s4,$zero /* f15e274: 01d81821 */ addu $v1,$t6,$t8 /* f15e278: 8c620080 */ lw $v0,0x80($v1) /* f15e27c: 01e02825 */ or $a1,$t7,$zero /* f15e280: 51e20009 */ beql $t7,$v0,.L0f15e2a8 /* f15e284: 8c730014 */ lw $s3,0x14($v1) /* f15e288: 0c004b52 */ jal memaRealloc /* f15e28c: 00403025 */ or $a2,$v0,$zero /* f15e290: 3c19800a */ lui $t9,%hi(g_Rooms) /* f15e294: 8f394928 */ lw $t9,%lo(g_Rooms)($t9) /* f15e298: 8fab0054 */ lw $t3,0x54($sp) /* f15e29c: 240a0001 */ addiu $t2,$zero,0x1 /* f15e2a0: 032b1821 */ addu $v1,$t9,$t3 /* f15e2a4: 8c730014 */ lw $s3,0x14($v1) .L0f15e2a8: /* f15e2a8: 3c18800a */ lui $t8,%hi(g_FogEnabled) /* f15e2ac: 3c0f800a */ lui $t7,%hi(g_Rooms) /* f15e2b0: 8e670000 */ lw $a3,0x0($s3) /* f15e2b4: 26650018 */ addiu $a1,$s3,0x18 /* f15e2b8: 24a90014 */ addiu $t1,$a1,0x14 /* f15e2bc: 00e9082b */ sltu $at,$a3,$t1 /* f15e2c0: 14200026 */ bnez $at,.L0f15e35c /* f15e2c4: 3c19800a */ lui $t9,%hi(var800a65e4) /* f15e2c8: 90a20000 */ lbu $v0,0x0($a1) .L0f15e2cc: /* f15e2cc: 50400006 */ beqzl $v0,.L0f15e2e8 /* f15e2d0: 8ca60008 */ lw $a2,0x8($a1) /* f15e2d4: 504a0018 */ beql $v0,$t2,.L0f15e338 /* f15e2d8: 8ca2000c */ lw $v0,0xc($a1) /* f15e2dc: 1000001b */ b .L0f15e34c /* f15e2e0: 01202825 */ or $a1,$t1,$zero /* f15e2e4: 8ca60008 */ lw $a2,0x8($a1) .L0f15e2e8: /* f15e2e8: 50c00018 */ beqzl $a2,.L0f15e34c /* f15e2ec: 01202825 */ or $a1,$t1,$zero /* f15e2f0: 1a400015 */ blez $s2,.L0f15e348 /* f15e2f4: 00004025 */ or $t0,$zero,$zero /* f15e2f8: 00001025 */ or $v0,$zero,$zero /* f15e2fc: 27a30208 */ addiu $v1,$sp,0x208 /* f15e300: 00c02025 */ or $a0,$a2,$zero .L0f15e304: /* f15e304: 8c6c0000 */ lw $t4,0x0($v1) /* f15e308: 25080001 */ addiu $t0,$t0,0x1 /* f15e30c: 24630004 */ addiu $v1,$v1,0x4 /* f15e310: 148c0004 */ bne $a0,$t4,.L0f15e324 /* f15e314: 02026821 */ addu $t5,$s0,$v0 /* f15e318: 8dae0000 */ lw $t6,0x0($t5) /* f15e31c: 1000000a */ b .L0f15e348 /* f15e320: acae0008 */ sw $t6,0x8($a1) .L0f15e324: /* f15e324: 1512fff7 */ bne $t0,$s2,.L0f15e304 /* f15e328: 24420004 */ addiu $v0,$v0,0x4 /* f15e32c: 10000007 */ b .L0f15e34c /* f15e330: 01202825 */ or $a1,$t1,$zero /* f15e334: 8ca2000c */ lw $v0,0xc($a1) .L0f15e338: /* f15e338: 0047082b */ sltu $at,$v0,$a3 /* f15e33c: 50200003 */ beqzl $at,.L0f15e34c /* f15e340: 01202825 */ or $a1,$t1,$zero /* f15e344: 00403825 */ or $a3,$v0,$zero .L0f15e348: /* f15e348: 01202825 */ or $a1,$t1,$zero .L0f15e34c: /* f15e34c: 25290014 */ addiu $t1,$t1,0x14 /* f15e350: 00e9082b */ sltu $at,$a3,$t1 /* f15e354: 5020ffdd */ beqzl $at,.L0f15e2cc /* f15e358: 90a20000 */ lbu $v0,0x0($a1) .L0f15e35c: /* f15e35c: 8f1865e0 */ lw $t8,%lo(g_FogEnabled)($t8) /* f15e360: 13000012 */ beqz $t8,.L0f15e3ac /* f15e364: 00000000 */ nop /* f15e368: 8def4928 */ lw $t7,%lo(g_Rooms)($t7) /* f15e36c: 8fb90054 */ lw $t9,0x54($sp) /* f15e370: 24050001 */ addiu $a1,$zero,0x1 /* f15e374: 01f95821 */ addu $t3,$t7,$t9 /* f15e378: 8d6c0014 */ lw $t4,0x14($t3) /* f15e37c: 0fc595ca */ jal gfxReplaceGbiCommandsRecursively /* f15e380: 8d840008 */ lw $a0,0x8($t4) /* f15e384: 3c0d800a */ lui $t5,%hi(g_Rooms) /* f15e388: 8dad4928 */ lw $t5,%lo(g_Rooms)($t5) /* f15e38c: 8fae0054 */ lw $t6,0x54($sp) /* f15e390: 24050005 */ addiu $a1,$zero,0x5 /* f15e394: 01aec021 */ addu $t8,$t5,$t6 /* f15e398: 8f0f0014 */ lw $t7,0x14($t8) /* f15e39c: 0fc595ca */ jal gfxReplaceGbiCommandsRecursively /* f15e3a0: 8de4000c */ lw $a0,0xc($t7) /* f15e3a4: 10000014 */ b .L0f15e3f8 /* f15e3a8: 00000000 */ nop .L0f15e3ac: /* f15e3ac: 8f3965e4 */ lw $t9,%lo(var800a65e4)($t9) /* f15e3b0: 3c0b800a */ lui $t3,%hi(g_Rooms) /* f15e3b4: 8fac0054 */ lw $t4,0x54($sp) /* f15e3b8: 1720000f */ bnez $t9,.L0f15e3f8 /* f15e3bc: 00000000 */ nop /* f15e3c0: 8d6b4928 */ lw $t3,%lo(g_Rooms)($t3) /* f15e3c4: 24050006 */ addiu $a1,$zero,0x6 /* f15e3c8: 016c6821 */ addu $t5,$t3,$t4 /* f15e3cc: 8dae0014 */ lw $t6,0x14($t5) /* f15e3d0: 0fc595ca */ jal gfxReplaceGbiCommandsRecursively /* f15e3d4: 8dc40008 */ lw $a0,0x8($t6) /* f15e3d8: 3c18800a */ lui $t8,%hi(g_Rooms) /* f15e3dc: 8f184928 */ lw $t8,%lo(g_Rooms)($t8) /* f15e3e0: 8faf0054 */ lw $t7,0x54($sp) /* f15e3e4: 24050007 */ addiu $a1,$zero,0x7 /* f15e3e8: 030fc821 */ addu $t9,$t8,$t7 /* f15e3ec: 8f2b0014 */ lw $t3,0x14($t9) /* f15e3f0: 0fc595ca */ jal gfxReplaceGbiCommandsRecursively /* f15e3f4: 8d64000c */ lw $a0,0xc($t3) .L0f15e3f8: /* f15e3f8: 0fc57be7 */ jal bgFindRoomVtxBatches /* f15e3fc: 8fa402f8 */ lw $a0,0x2f8($sp) /* f15e400: 3c0c800a */ lui $t4,%hi(g_Rooms) /* f15e404: 8d8c4928 */ lw $t4,%lo(g_Rooms)($t4) /* f15e408: 8fad0054 */ lw $t5,0x54($sp) /* f15e40c: 3c0f800a */ lui $t7,%hi(g_Rooms) /* f15e410: 2404ffff */ addiu $a0,$zero,-1 /* f15e414: 018d1821 */ addu $v1,$t4,$t5 /* f15e418: 946e0000 */ lhu $t6,0x0($v1) /* f15e41c: 3c0d800a */ lui $t5,%hi(g_Rooms) /* f15e420: 35d80100 */ ori $t8,$t6,0x100 /* f15e424: a4780000 */ sh $t8,0x0($v1) /* f15e428: 8fb90054 */ lw $t9,0x54($sp) /* f15e42c: 8def4928 */ lw $t7,%lo(g_Rooms)($t7) /* f15e430: 01f91821 */ addu $v1,$t7,$t9 /* f15e434: 946b0000 */ lhu $t3,0x0($v1) /* f15e438: 356c0200 */ ori $t4,$t3,0x200 /* f15e43c: a46c0000 */ sh $t4,0x0($v1) /* f15e440: 8fae0054 */ lw $t6,0x54($sp) /* f15e444: 8dad4928 */ lw $t5,%lo(g_Rooms)($t5) /* f15e448: 01aec021 */ addu $t8,$t5,$t6 /* f15e44c: 0fc4f0dc */ jal dyntexSetCurrentRoom /* f15e450: af000058 */ sw $zero,0x58($t8) .L0f15e454: /* f15e454: 8fbf0034 */ lw $ra,0x34($sp) .L0f15e458: /* f15e458: 8fb00020 */ lw $s0,0x20($sp) /* f15e45c: 8fb10024 */ lw $s1,0x24($sp) /* f15e460: 8fb20028 */ lw $s2,0x28($sp) /* f15e464: 8fb3002c */ lw $s3,0x2c($sp) /* f15e468: 8fb40030 */ lw $s4,0x30($sp) /* f15e46c: 03e00008 */ jr $ra /* f15e470: 27bd02f8 */ addiu $sp,$sp,0x2f8 ); #else GLOBAL_ASM( glabel bgLoadRoom /* f1583f0: 27bdfd08 */ addiu $sp,$sp,-760 /* f1583f4: afa402f8 */ sw $a0,0x2f8($sp) /* f1583f8: afbf002c */ sw $ra,0x2c($sp) /* f1583fc: 3c047f1b */ lui $a0,0x7f1b /* f158400: afb30028 */ sw $s3,0x28($sp) /* f158404: afb20024 */ sw $s2,0x24($sp) /* f158408: afb10020 */ sw $s1,0x20($sp) /* f15840c: afb0001c */ sw $s0,0x1c($sp) /* f158410: 24841a2c */ addiu $a0,$a0,0x1a2c /* f158414: 0fc55704 */ jal bgVerifyLightSums /* f158418: 24051ba4 */ addiu $a1,$zero,0x1ba4 /* f15841c: 8fa402f8 */ lw $a0,0x2f8($sp) /* f158420: 3c0e800a */ lui $t6,0x800a /* f158424: 5080020e */ beqzl $a0,.NB0f158c60 /* f158428: 8fbf002c */ lw $ra,0x2c($sp) /* f15842c: 8dcee97c */ lw $t6,-0x1684($t6) /* f158430: 000478c0 */ sll $t7,$a0,0x3 /* f158434: 01e47821 */ addu $t7,$t7,$a0 /* f158438: 008e082a */ slt $at,$a0,$t6 /* f15843c: 10200207 */ beqz $at,.NB0f158c5c /* f158440: 000f7880 */ sll $t7,$t7,0x2 /* f158444: 3c18800b */ lui $t8,0x800b /* f158448: 8f1890a8 */ lw $t8,-0x6f58($t8) /* f15844c: 01e47823 */ subu $t7,$t7,$a0 /* f158450: 000f7880 */ sll $t7,$t7,0x2 /* f158454: afaf0050 */ sw $t7,0x50($sp) /* f158458: 030f1821 */ addu $v1,$t8,$t7 /* f15845c: 846b0002 */ lh $t3,0x2($v1) /* f158460: 556001ff */ bnezl $t3,.NB0f158c60 /* f158464: 8fbf002c */ lw $ra,0x2c($sp) /* f158468: 8c620080 */ lw $v0,0x80($v1) /* f15846c: 18400008 */ blez $v0,.NB0f158490 /* f158470: 00000000 */ sll $zero,$zero,0x0 /* f158474: 0fc46652 */ jal debug0f11edb0 /* f158478: afa202f4 */ sw $v0,0x2f4($sp) /* f15847c: 10400007 */ beqz $v0,.NB0f15849c /* f158480: 8fac02f4 */ lw $t4,0x2f4($sp) /* f158484: 258d0400 */ addiu $t5,$t4,0x400 /* f158488: 10000004 */ beqz $zero,.NB0f15849c /* f15848c: afad02f4 */ sw $t5,0x2f4($sp) .NB0f158490: /* f158490: 0c004d4e */ jal memaGetLongestFree /* f158494: 00000000 */ sll $zero,$zero,0x0 /* f158498: afa202f4 */ sw $v0,0x2f4($sp) .NB0f15849c: /* f15849c: 8fa402f4 */ lw $a0,0x2f4($sp) /* f1584a0: 0fc5636f */ jal bgGarbageCollectRooms /* f1584a4: 00002825 */ or $a1,$zero,$zero /* f1584a8: 0c004cc9 */ jal memaAlloc /* f1584ac: 8fa402f4 */ lw $a0,0x2f4($sp) /* f1584b0: 104001ea */ beqz $v0,.NB0f158c5c /* f1584b4: 00409825 */ or $s3,$v0,$zero /* f1584b8: 0fc4db9c */ jal dyntexSetCurrentRoom /* f1584bc: 87a402fa */ lh $a0,0x2fa($sp) /* f1584c0: 8fb002f8 */ lw $s0,0x2f8($sp) /* f1584c4: 3c11800b */ lui $s1,0x800b /* f1584c8: 26319444 */ addiu $s1,$s1,-27580 /* f1584cc: 8e2f0000 */ lw $t7,0x0($s1) /* f1584d0: 00107080 */ sll $t6,$s0,0x2 /* f1584d4: 01d07021 */ addu $t6,$t6,$s0 /* f1584d8: 000e8080 */ sll $s0,$t6,0x2 /* f1584dc: 01f01021 */ addu $v0,$t7,$s0 /* f1584e0: 8c430000 */ lw $v1,0x0($v0) /* f1584e4: 8c580014 */ lw $t8,0x14($v0) /* f1584e8: 3c04800b */ lui $a0,0x800b /* f1584ec: 8c84909c */ lw $a0,-0x6f64($a0) /* f1584f0: 03039023 */ subu $s2,$t8,$v1 /* f1584f4: 2652000f */ addiu $s2,$s2,0xf /* f1584f8: 2401fff0 */ addiu $at,$zero,-16 /* f1584fc: 8fa702f4 */ lw $a3,0x2f4($sp) /* f158500: 0241c824 */ and $t9,$s2,$at /* f158504: 00645821 */ addu $t3,$v1,$a0 /* f158508: 3c01f100 */ lui $at,0xf100 /* f15850c: 3c0c8008 */ lui $t4,0x8008 /* f158510: 01642823 */ subu $a1,$t3,$a0 /* f158514: 8d8c24b8 */ lw $t4,0x24b8($t4) /* f158518: 00a12821 */ addu $a1,$a1,$at /* f15851c: 00f9082a */ slt $at,$a3,$t9 /* f158520: 03209025 */ or $s2,$t9,$zero /* f158524: 10200005 */ beqz $at,.NB0f15853c /* f158528: 00ac2823 */ subu $a1,$a1,$t4 /* f15852c: 0fc4db9c */ jal dyntexSetCurrentRoom /* f158530: 2404ffff */ addiu $a0,$zero,-1 /* f158534: 100001ca */ beqz $zero,.NB0f158c60 /* f158538: 8fbf002c */ lw $ra,0x2c($sp) .NB0f15853c: /* f15853c: 00f26823 */ subu $t5,$a3,$s2 /* f158540: 01b32021 */ addu $a0,$t5,$s3 /* f158544: afa40048 */ sw $a0,0x48($sp) /* f158548: 0fc5560b */ jal bgLoadFile /* f15854c: 02403025 */ or $a2,$s2,$zero /* f158550: 0c0022df */ jal rzipIs1173 /* f158554: 8fa40048 */ lw $a0,0x48($sp) /* f158558: 10400009 */ beqz $v0,.NB0f158580 /* f15855c: 8fae02f4 */ lw $t6,0x2f4($sp) /* f158560: 264f0020 */ addiu $t7,$s2,0x20 /* f158564: 01cf082a */ slt $at,$t6,$t7 /* f158568: 50200006 */ beqzl $at,.NB0f158584 /* f15856c: 8e380000 */ lw $t8,0x0($s1) /* f158570: 0fc4db9c */ jal dyntexSetCurrentRoom /* f158574: 2404ffff */ addiu $a0,$zero,-1 /* f158578: 100001b9 */ beqz $zero,.NB0f158c60 /* f15857c: 8fbf002c */ lw $ra,0x2c($sp) .NB0f158580: /* f158580: 8e380000 */ lw $t8,0x0($s1) .NB0f158584: /* f158584: 8fa40048 */ lw $a0,0x48($sp) /* f158588: 02602825 */ or $a1,$s3,$zero /* f15858c: 03101021 */ addu $v0,$t8,$s0 /* f158590: 8c590014 */ lw $t9,0x14($v0) /* f158594: 8c4b0000 */ lw $t3,0x0($v0) /* f158598: 0fc56023 */ jal bgInflate /* f15859c: 032b3023 */ subu $a2,$t9,$t3 /* f1585a0: 3c09800b */ lui $t1,0x800b /* f1585a4: 252990a8 */ addiu $t1,$t1,-28504 /* f1585a8: 8fa80050 */ lw $t0,0x50($sp) /* f1585ac: 8d2c0000 */ lw $t4,0x0($t1) /* f1585b0: afa202f0 */ sw $v0,0x2f0($sp) /* f1585b4: 24060003 */ addiu $a2,$zero,0x3 /* f1585b8: 01886821 */ addu $t5,$t4,$t0 /* f1585bc: adb30014 */ sw $s3,0x14($t5) /* f1585c0: 8d2e0000 */ lw $t6,0x0($t1) /* f1585c4: 01c87821 */ addu $t7,$t6,$t0 /* f1585c8: 8df20014 */ lw $s2,0x14($t7) /* f1585cc: 8e430000 */ lw $v1,0x0($s2) /* f1585d0: 5060000b */ beqzl $v1,.NB0f158600 /* f1585d4: 8e420004 */ lw $v0,0x4($s2) /* f1585d8: 8e380000 */ lw $t8,0x0($s1) /* f1585dc: 0310c821 */ addu $t9,$t8,$s0 /* f1585e0: 8f2b0000 */ lw $t3,0x0($t9) /* f1585e4: 006b6023 */ subu $t4,$v1,$t3 /* f1585e8: 01936821 */ addu $t5,$t4,$s3 /* f1585ec: ae4d0000 */ sw $t5,0x0($s2) /* f1585f0: 8d2e0000 */ lw $t6,0x0($t1) /* f1585f4: 01c87821 */ addu $t7,$t6,$t0 /* f1585f8: 8df20014 */ lw $s2,0x14($t7) /* f1585fc: 8e420004 */ lw $v0,0x4($s2) .NB0f158600: /* f158600: 5040000b */ beqzl $v0,.NB0f158630 /* f158604: 8e420008 */ lw $v0,0x8($s2) /* f158608: 8e380000 */ lw $t8,0x0($s1) /* f15860c: 0310c821 */ addu $t9,$t8,$s0 /* f158610: 8f2b0000 */ lw $t3,0x0($t9) /* f158614: 004b6023 */ subu $t4,$v0,$t3 /* f158618: 01936821 */ addu $t5,$t4,$s3 /* f15861c: ae4d0004 */ sw $t5,0x4($s2) /* f158620: 8d2e0000 */ lw $t6,0x0($t1) /* f158624: 01c87821 */ addu $t7,$t6,$t0 /* f158628: 8df20014 */ lw $s2,0x14($t7) /* f15862c: 8e420008 */ lw $v0,0x8($s2) .NB0f158630: /* f158630: 5040000b */ beqzl $v0,.NB0f158660 /* f158634: 8e42000c */ lw $v0,0xc($s2) /* f158638: 8e380000 */ lw $t8,0x0($s1) /* f15863c: 0310c821 */ addu $t9,$t8,$s0 /* f158640: 8f2b0000 */ lw $t3,0x0($t9) /* f158644: 004b6023 */ subu $t4,$v0,$t3 /* f158648: 01936821 */ addu $t5,$t4,$s3 /* f15864c: ae4d0008 */ sw $t5,0x8($s2) /* f158650: 8d2e0000 */ lw $t6,0x0($t1) /* f158654: 01c87821 */ addu $t7,$t6,$t0 /* f158658: 8df20014 */ lw $s2,0x14($t7) /* f15865c: 8e42000c */ lw $v0,0xc($s2) .NB0f158660: /* f158660: 5040000b */ beqzl $v0,.NB0f158690 /* f158664: 8e420000 */ lw $v0,0x0($s2) /* f158668: 8e380000 */ lw $t8,0x0($s1) /* f15866c: 0310c821 */ addu $t9,$t8,$s0 /* f158670: 8f2b0000 */ lw $t3,0x0($t9) /* f158674: 004b6023 */ subu $t4,$v0,$t3 /* f158678: 01936821 */ addu $t5,$t4,$s3 /* f15867c: ae4d000c */ sw $t5,0xc($s2) /* f158680: 8d2e0000 */ lw $t6,0x0($t1) /* f158684: 01c87821 */ addu $t7,$t6,$t0 /* f158688: 8df20014 */ lw $s2,0x14($t7) /* f15868c: 8e420000 */ lw $v0,0x0($s2) .NB0f158690: /* f158690: 26430018 */ addiu $v1,$s2,0x18 /* f158694: 24650014 */ addiu $a1,$v1,0x14 /* f158698: 0045082b */ sltu $at,$v0,$a1 /* f15869c: 14200060 */ bnez $at,.NB0f158820 /* f1586a0: 00402025 */ or $a0,$v0,$zero /* f1586a4: 24070001 */ addiu $a3,$zero,0x1 /* f1586a8: 90620000 */ lbu $v0,0x0($v1) .NB0f1586ac: /* f1586ac: 50400006 */ beqzl $v0,.NB0f1586c8 /* f1586b0: 8c620004 */ lw $v0,0x4($v1) /* f1586b4: 50470029 */ beql $v0,$a3,.NB0f15875c /* f1586b8: 8c620004 */ lw $v0,0x4($v1) /* f1586bc: 10000050 */ beqz $zero,.NB0f158800 /* f1586c0: 00a01825 */ or $v1,$a1,$zero /* f1586c4: 8c620004 */ lw $v0,0x4($v1) .NB0f1586c8: /* f1586c8: 50400008 */ beqzl $v0,.NB0f1586ec /* f1586cc: 8c620008 */ lw $v0,0x8($v1) /* f1586d0: 8e380000 */ lw $t8,0x0($s1) /* f1586d4: 0310c821 */ addu $t9,$t8,$s0 /* f1586d8: 8f2b0000 */ lw $t3,0x0($t9) /* f1586dc: 004b6023 */ subu $t4,$v0,$t3 /* f1586e0: 01936821 */ addu $t5,$t4,$s3 /* f1586e4: ac6d0004 */ sw $t5,0x4($v1) /* f1586e8: 8c620008 */ lw $v0,0x8($v1) .NB0f1586ec: /* f1586ec: 50400008 */ beqzl $v0,.NB0f158710 /* f1586f0: 8c62000c */ lw $v0,0xc($v1) /* f1586f4: 8e2e0000 */ lw $t6,0x0($s1) /* f1586f8: 01d07821 */ addu $t7,$t6,$s0 /* f1586fc: 8df80000 */ lw $t8,0x0($t7) /* f158700: 0058c823 */ subu $t9,$v0,$t8 /* f158704: 03335821 */ addu $t3,$t9,$s3 /* f158708: ac6b0008 */ sw $t3,0x8($v1) /* f15870c: 8c62000c */ lw $v0,0xc($v1) .NB0f158710: /* f158710: 50400008 */ beqzl $v0,.NB0f158734 /* f158714: 8c620010 */ lw $v0,0x10($v1) /* f158718: 8e2c0000 */ lw $t4,0x0($s1) /* f15871c: 01906821 */ addu $t5,$t4,$s0 /* f158720: 8dae0000 */ lw $t6,0x0($t5) /* f158724: 004e7823 */ subu $t7,$v0,$t6 /* f158728: 01f3c021 */ addu $t8,$t7,$s3 /* f15872c: ac78000c */ sw $t8,0xc($v1) /* f158730: 8c620010 */ lw $v0,0x10($v1) .NB0f158734: /* f158734: 50400032 */ beqzl $v0,.NB0f158800 /* f158738: 00a01825 */ or $v1,$a1,$zero /* f15873c: 8e390000 */ lw $t9,0x0($s1) /* f158740: 03305821 */ addu $t3,$t9,$s0 /* f158744: 8d6c0000 */ lw $t4,0x0($t3) /* f158748: 004c6823 */ subu $t5,$v0,$t4 /* f15874c: 01b37021 */ addu $t6,$t5,$s3 /* f158750: 1000002a */ beqz $zero,.NB0f1587fc /* f158754: ac6e0010 */ sw $t6,0x10($v1) /* f158758: 8c620004 */ lw $v0,0x4($v1) .NB0f15875c: /* f15875c: 50400008 */ beqzl $v0,.NB0f158780 /* f158760: 8c620008 */ lw $v0,0x8($v1) /* f158764: 8e2f0000 */ lw $t7,0x0($s1) /* f158768: 01f0c021 */ addu $t8,$t7,$s0 /* f15876c: 8f190000 */ lw $t9,0x0($t8) /* f158770: 00595823 */ subu $t3,$v0,$t9 /* f158774: 01736021 */ addu $t4,$t3,$s3 /* f158778: ac6c0004 */ sw $t4,0x4($v1) /* f15877c: 8c620008 */ lw $v0,0x8($v1) .NB0f158780: /* f158780: 50400008 */ beqzl $v0,.NB0f1587a4 /* f158784: 8c62000c */ lw $v0,0xc($v1) /* f158788: 8e2d0000 */ lw $t5,0x0($s1) /* f15878c: 01b07021 */ addu $t6,$t5,$s0 /* f158790: 8dcf0000 */ lw $t7,0x0($t6) /* f158794: 004fc023 */ subu $t8,$v0,$t7 /* f158798: 0313c821 */ addu $t9,$t8,$s3 /* f15879c: ac790008 */ sw $t9,0x8($v1) /* f1587a0: 8c62000c */ lw $v0,0xc($v1) .NB0f1587a4: /* f1587a4: 50400008 */ beqzl $v0,.NB0f1587c8 /* f1587a8: 8c620010 */ lw $v0,0x10($v1) /* f1587ac: 8e2b0000 */ lw $t3,0x0($s1) /* f1587b0: 01706021 */ addu $t4,$t3,$s0 /* f1587b4: 8d8d0000 */ lw $t5,0x0($t4) /* f1587b8: 004d7023 */ subu $t6,$v0,$t5 /* f1587bc: 01d37821 */ addu $t7,$t6,$s3 /* f1587c0: ac6f000c */ sw $t7,0xc($v1) /* f1587c4: 8c620010 */ lw $v0,0x10($v1) .NB0f1587c8: /* f1587c8: 50400008 */ beqzl $v0,.NB0f1587ec /* f1587cc: 8c62000c */ lw $v0,0xc($v1) /* f1587d0: 8e380000 */ lw $t8,0x0($s1) /* f1587d4: 0310c821 */ addu $t9,$t8,$s0 /* f1587d8: 8f2b0000 */ lw $t3,0x0($t9) /* f1587dc: 004b6023 */ subu $t4,$v0,$t3 /* f1587e0: 01936821 */ addu $t5,$t4,$s3 /* f1587e4: ac6d0010 */ sw $t5,0x10($v1) /* f1587e8: 8c62000c */ lw $v0,0xc($v1) .NB0f1587ec: /* f1587ec: 0044082b */ sltu $at,$v0,$a0 /* f1587f0: 50200003 */ beqzl $at,.NB0f158800 /* f1587f4: 00a01825 */ or $v1,$a1,$zero /* f1587f8: 00402025 */ or $a0,$v0,$zero .NB0f1587fc: /* f1587fc: 00a01825 */ or $v1,$a1,$zero .NB0f158800: /* f158800: 24a50014 */ addiu $a1,$a1,0x14 /* f158804: 0085082b */ sltu $at,$a0,$a1 /* f158808: 5020ffa8 */ beqzl $at,.NB0f1586ac /* f15880c: 90620000 */ lbu $v0,0x0($v1) /* f158810: 8d2e0000 */ lw $t6,0x0($t1) /* f158814: 01c87821 */ addu $t7,$t6,$t0 /* f158818: 8df20014 */ lw $s2,0x14($t7) /* f15881c: 8e420000 */ lw $v0,0x0($s2) .NB0f158820: /* f158820: 8e580004 */ lw $t8,0x4($s2) /* f158824: 2401000c */ addiu $at,$zero,0xc /* f158828: 00002825 */ or $a1,$zero,$zero /* f15882c: 0302c823 */ subu $t9,$t8,$v0 /* f158830: 0321001b */ divu $zero,$t9,$at /* f158834: 00005812 */ mflo $t3 /* f158838: a64b0014 */ sh $t3,0x14($s2) /* f15883c: 0fc56093 */ jal roomGetNextGdlInLayer /* f158840: 8fa402f8 */ lw $a0,0x2f8($sp) /* f158844: 3c0c800b */ lui $t4,0x800b /* f158848: 8d8c90a8 */ lw $t4,-0x6f58($t4) /* f15884c: 8fad0050 */ lw $t5,0x50($sp) /* f158850: 00008825 */ or $s1,$zero,$zero /* f158854: 00002825 */ or $a1,$zero,$zero /* f158858: 018d7021 */ addu $t6,$t4,$t5 /* f15885c: 8dd20014 */ lw $s2,0x14($t6) /* f158860: 24060003 */ addiu $a2,$zero,0x3 /* f158864: 8e4f0004 */ lw $t7,0x4($s2) /* f158868: 004fc023 */ subu $t8,$v0,$t7 /* f15886c: 0018c882 */ srl $t9,$t8,0x2 /* f158870: a6590016 */ sh $t9,0x16($s2) /* f158874: 0fc56093 */ jal roomGetNextGdlInLayer /* f158878: 8fa402f8 */ lw $a0,0x2f8($sp) /* f15887c: 10400018 */ beqz $v0,.NB0f1588e0 /* f158880: 00408025 */ or $s0,$v0,$zero /* f158884: 00111080 */ sll $v0,$s1,0x2 /* f158888: 27ab0208 */ addiu $t3,$sp,0x208 /* f15888c: 27ac0140 */ addiu $t4,$sp,0x140 /* f158890: 004c1821 */ addu $v1,$v0,$t4 /* f158894: 004b9021 */ addu $s2,$v0,$t3 .NB0f158898: /* f158898: ae500000 */ sw $s0,0x0($s2) /* f15889c: afa30044 */ sw $v1,0x44($sp) /* f1588a0: 8fa402f8 */ lw $a0,0x2f8($sp) /* f1588a4: 0fc560d3 */ jal roomFindVerticesForGdl /* f1588a8: 02002825 */ or $a1,$s0,$zero /* f1588ac: 8fa30044 */ lw $v1,0x44($sp) /* f1588b0: 26310001 */ addiu $s1,$s1,0x1 /* f1588b4: 26520004 */ addiu $s2,$s2,0x4 /* f1588b8: ac620000 */ sw $v0,0x0($v1) /* f1588bc: 24630004 */ addiu $v1,$v1,0x4 /* f1588c0: afa30044 */ sw $v1,0x44($sp) /* f1588c4: 8fa402f8 */ lw $a0,0x2f8($sp) /* f1588c8: 02002825 */ or $a1,$s0,$zero /* f1588cc: 0fc56093 */ jal roomGetNextGdlInLayer /* f1588d0: 24060003 */ addiu $a2,$zero,0x3 /* f1588d4: 8fa30044 */ lw $v1,0x44($sp) /* f1588d8: 1440ffef */ bnez $v0,.NB0f158898 /* f1588dc: 00408025 */ or $s0,$v0,$zero .NB0f1588e0: /* f1588e0: 8fae02f0 */ lw $t6,0x2f0($sp) /* f1588e4: 00113880 */ sll $a3,$s1,0x2 /* f1588e8: 27ad0208 */ addiu $t5,$sp,0x208 /* f1588ec: 00ed9021 */ addu $s2,$a3,$t5 /* f1588f0: 026e1021 */ addu $v0,$s3,$t6 /* f1588f4: ae420000 */ sw $v0,0x0($s2) /* f1588f8: 8fb802f4 */ lw $t8,0x2f4($sp) /* f1588fc: 8fa40208 */ lw $a0,0x208($sp) /* f158900: afa70048 */ sw $a3,0x48($sp) /* f158904: 02788021 */ addu $s0,$s3,$t8 /* f158908: 00441823 */ subu $v1,$v0,$a0 /* f15890c: 02032823 */ subu $a1,$s0,$v1 /* f158910: 0fc5c2e5 */ jal texCopyGdls /* f158914: 00603025 */ or $a2,$v1,$zero /* f158918: 26220001 */ addiu $v0,$s1,0x1 /* f15891c: 1840000d */ blez $v0,.NB0f158954 /* f158920: 00004025 */ or $t0,$zero,$zero /* f158924: 8e590000 */ lw $t9,0x0($s2) /* f158928: 27a90078 */ addiu $t1,$sp,0x78 /* f15892c: 27a30208 */ addiu $v1,$sp,0x208 /* f158930: 02192023 */ subu $a0,$s0,$t9 .NB0f158934: /* f158934: 8c6b0000 */ lw $t3,0x0($v1) /* f158938: 25080001 */ addiu $t0,$t0,0x1 /* f15893c: 25290004 */ addiu $t1,$t1,0x4 /* f158940: 008b6021 */ addu $t4,$a0,$t3 /* f158944: 24630004 */ addiu $v1,$v1,0x4 /* f158948: 1502fffa */ bne $t0,$v0,.NB0f158934 /* f15894c: ad2cfffc */ sw $t4,-0x4($t1) /* f158950: 00004025 */ or $t0,$zero,$zero .NB0f158954: /* f158954: 1a20001f */ blez $s1,.NB0f1589d4 /* f158958: 8fa60208 */ lw $a2,0x208($sp) /* f15895c: 27a90078 */ addiu $t1,$sp,0x78 /* f158960: 27a30208 */ addiu $v1,$sp,0x208 /* f158964: 27b00140 */ addiu $s0,$sp,0x140 .NB0f158968: /* f158968: 8c6d0004 */ lw $t5,0x4($v1) /* f15896c: 8c6e0000 */ lw $t6,0x0($v1) /* f158970: 8e180000 */ lw $t8,0x0($s0) /* f158974: 8d240000 */ lw $a0,0x0($t1) /* f158978: 01ae2823 */ subu $a1,$t5,$t6 /* f15897c: afa50068 */ sw $a1,0x68($sp) /* f158980: afa9003c */ sw $t1,0x3c($sp) /* f158984: afa8006c */ sw $t0,0x6c($sp) /* f158988: afa602dc */ sw $a2,0x2dc($sp) /* f15898c: afa30034 */ sw $v1,0x34($sp) /* f158990: 00003825 */ or $a3,$zero,$zero /* f158994: 0fc5c0d8 */ jal texLoadFromGdl /* f158998: afb80010 */ sw $t8,0x10($sp) /* f15899c: 8fa602dc */ lw $a2,0x2dc($sp) /* f1589a0: 8fa9003c */ lw $t1,0x3c($sp) /* f1589a4: 8fa30034 */ lw $v1,0x34($sp) /* f1589a8: 8fa8006c */ lw $t0,0x6c($sp) /* f1589ac: ad260000 */ sw $a2,0x0($t1) /* f1589b0: 00c23021 */ addu $a2,$a2,$v0 /* f1589b4: 24c60007 */ addiu $a2,$a2,0x7 /* f1589b8: 34cf0007 */ ori $t7,$a2,0x7 /* f1589bc: 25080001 */ addiu $t0,$t0,0x1 /* f1589c0: 26100004 */ addiu $s0,$s0,0x4 /* f1589c4: 39e60007 */ xori $a2,$t7,0x7 /* f1589c8: 25290004 */ addiu $t1,$t1,0x4 /* f1589cc: 1511ffe6 */ bne $t0,$s1,.NB0f158968 /* f1589d0: 24630004 */ addiu $v1,$v1,0x4 .NB0f1589d4: /* f1589d4: 8fab0048 */ lw $t3,0x48($sp) /* f1589d8: 27b00078 */ addiu $s0,$sp,0x78 /* f1589dc: 3c0d800b */ lui $t5,0x800b /* f1589e0: 020b6021 */ addu $t4,$s0,$t3 /* f1589e4: ad860000 */ sw $a2,0x0($t4) /* f1589e8: 8fae0050 */ lw $t6,0x50($sp) /* f1589ec: 8dad90a8 */ lw $t5,-0x6f58($t5) /* f1589f0: 00d3c023 */ subu $t8,$a2,$s3 /* f1589f4: 270f002f */ addiu $t7,$t8,0x2f /* f1589f8: 35f9000f */ ori $t9,$t7,0xf /* f1589fc: 01ae1821 */ addu $v1,$t5,$t6 /* f158a00: 8c620080 */ lw $v0,0x80($v1) /* f158a04: 3b2b000f */ xori $t3,$t9,0xf /* f158a08: ac6b0080 */ sw $t3,0x80($v1) /* f158a0c: 3c0c800b */ lui $t4,0x800b /* f158a10: 8d8c90a8 */ lw $t4,-0x6f58($t4) /* f158a14: 8fad0050 */ lw $t5,0x50($sp) /* f158a18: 3c047f1b */ lui $a0,0x7f1b /* f158a1c: 018d1821 */ addu $v1,$t4,$t5 /* f158a20: 8c6e0080 */ lw $t6,0x80($v1) /* f158a24: 004e082a */ slt $at,$v0,$t6 /* f158a28: 5020000a */ beqzl $at,.NB0f158a54 /* f158a2c: 240a0001 */ addiu $t2,$zero,0x1 /* f158a30: 0c003074 */ jal crashSetMessage /* f158a34: 24841a34 */ addiu $a0,$a0,0x1a34 /* f158a38: 24180045 */ addiu $t8,$zero,0x45 /* f158a3c: a0180000 */ sb $t8,0x0($zero) /* f158a40: 3c0f800b */ lui $t7,0x800b /* f158a44: 8def90a8 */ lw $t7,-0x6f58($t7) /* f158a48: 8fb90050 */ lw $t9,0x50($sp) /* f158a4c: 01f91821 */ addu $v1,$t7,$t9 /* f158a50: 240a0001 */ addiu $t2,$zero,0x1 .NB0f158a54: /* f158a54: a46a0002 */ sh $t2,0x2($v1) /* f158a58: 3c0b800b */ lui $t3,0x800b /* f158a5c: 8d6b90a8 */ lw $t3,-0x6f58($t3) /* f158a60: 8fac0050 */ lw $t4,0x50($sp) /* f158a64: 8fad02f4 */ lw $t5,0x2f4($sp) /* f158a68: 02602025 */ or $a0,$s3,$zero /* f158a6c: 016c1821 */ addu $v1,$t3,$t4 /* f158a70: 8c620080 */ lw $v0,0x80($v1) /* f158a74: 01a02825 */ or $a1,$t5,$zero /* f158a78: 51a20009 */ beql $t5,$v0,.NB0f158aa0 /* f158a7c: 8c720014 */ lw $s2,0x14($v1) /* f158a80: 0c004d69 */ jal memaRealloc /* f158a84: 00403025 */ or $a2,$v0,$zero /* f158a88: 3c0e800b */ lui $t6,0x800b /* f158a8c: 8dce90a8 */ lw $t6,-0x6f58($t6) /* f158a90: 8fb80050 */ lw $t8,0x50($sp) /* f158a94: 240a0001 */ addiu $t2,$zero,0x1 /* f158a98: 01d81821 */ addu $v1,$t6,$t8 /* f158a9c: 8c720014 */ lw $s2,0x14($v1) .NB0f158aa0: /* f158aa0: 3c0c800b */ lui $t4,0x800b /* f158aa4: 3c0d800b */ lui $t5,0x800b /* f158aa8: 8e470000 */ lw $a3,0x0($s2) /* f158aac: 26450018 */ addiu $a1,$s2,0x18 /* f158ab0: 24a90014 */ addiu $t1,$a1,0x14 /* f158ab4: 00e9082b */ sltu $at,$a3,$t1 /* f158ab8: 14200026 */ bnez $at,.NB0f158b54 /* f158abc: 3c0e800b */ lui $t6,0x800b /* f158ac0: 90a20000 */ lbu $v0,0x0($a1) .NB0f158ac4: /* f158ac4: 50400006 */ beqzl $v0,.NB0f158ae0 /* f158ac8: 8ca60008 */ lw $a2,0x8($a1) /* f158acc: 504a0018 */ beql $v0,$t2,.NB0f158b30 /* f158ad0: 8ca2000c */ lw $v0,0xc($a1) /* f158ad4: 1000001b */ beqz $zero,.NB0f158b44 /* f158ad8: 01202825 */ or $a1,$t1,$zero /* f158adc: 8ca60008 */ lw $a2,0x8($a1) .NB0f158ae0: /* f158ae0: 50c00018 */ beqzl $a2,.NB0f158b44 /* f158ae4: 01202825 */ or $a1,$t1,$zero /* f158ae8: 1a200015 */ blez $s1,.NB0f158b40 /* f158aec: 00004025 */ or $t0,$zero,$zero /* f158af0: 00001025 */ or $v0,$zero,$zero /* f158af4: 27a30208 */ addiu $v1,$sp,0x208 /* f158af8: 00c02025 */ or $a0,$a2,$zero .NB0f158afc: /* f158afc: 8c6f0000 */ lw $t7,0x0($v1) /* f158b00: 25080001 */ addiu $t0,$t0,0x1 /* f158b04: 24630004 */ addiu $v1,$v1,0x4 /* f158b08: 148f0004 */ bne $a0,$t7,.NB0f158b1c /* f158b0c: 0202c821 */ addu $t9,$s0,$v0 /* f158b10: 8f2b0000 */ lw $t3,0x0($t9) /* f158b14: 1000000a */ beqz $zero,.NB0f158b40 /* f158b18: acab0008 */ sw $t3,0x8($a1) .NB0f158b1c: /* f158b1c: 1511fff7 */ bne $t0,$s1,.NB0f158afc /* f158b20: 24420004 */ addiu $v0,$v0,0x4 /* f158b24: 10000007 */ beqz $zero,.NB0f158b44 /* f158b28: 01202825 */ or $a1,$t1,$zero /* f158b2c: 8ca2000c */ lw $v0,0xc($a1) .NB0f158b30: /* f158b30: 0047082b */ sltu $at,$v0,$a3 /* f158b34: 50200003 */ beqzl $at,.NB0f158b44 /* f158b38: 01202825 */ or $a1,$t1,$zero /* f158b3c: 00403825 */ or $a3,$v0,$zero .NB0f158b40: /* f158b40: 01202825 */ or $a1,$t1,$zero .NB0f158b44: /* f158b44: 25290014 */ addiu $t1,$t1,0x14 /* f158b48: 00e9082b */ sltu $at,$a3,$t1 /* f158b4c: 5020ffdd */ beqzl $at,.NB0f158ac4 /* f158b50: 90a20000 */ lbu $v0,0x0($a1) .NB0f158b54: /* f158b54: 8d8caea0 */ lw $t4,-0x5160($t4) /* f158b58: 11800012 */ beqz $t4,.NB0f158ba4 /* f158b5c: 00000000 */ sll $zero,$zero,0x0 /* f158b60: 8dad90a8 */ lw $t5,-0x6f58($t5) /* f158b64: 8fae0050 */ lw $t6,0x50($sp) /* f158b68: 24050001 */ addiu $a1,$zero,0x1 /* f158b6c: 01aec021 */ addu $t8,$t5,$t6 /* f158b70: 8f0f0014 */ lw $t7,0x14($t8) /* f158b74: 0fc57fca */ jal gfxReplaceGbiCommandsRecursively /* f158b78: 8de40008 */ lw $a0,0x8($t7) /* f158b7c: 3c19800b */ lui $t9,0x800b /* f158b80: 8f3990a8 */ lw $t9,-0x6f58($t9) /* f158b84: 8fab0050 */ lw $t3,0x50($sp) /* f158b88: 24050005 */ addiu $a1,$zero,0x5 /* f158b8c: 032b6021 */ addu $t4,$t9,$t3 /* f158b90: 8d8d0014 */ lw $t5,0x14($t4) /* f158b94: 0fc57fca */ jal gfxReplaceGbiCommandsRecursively /* f158b98: 8da4000c */ lw $a0,0xc($t5) /* f158b9c: 10000014 */ beqz $zero,.NB0f158bf0 /* f158ba0: 00000000 */ sll $zero,$zero,0x0 .NB0f158ba4: /* f158ba4: 8dceaea4 */ lw $t6,-0x515c($t6) /* f158ba8: 3c18800b */ lui $t8,0x800b /* f158bac: 8faf0050 */ lw $t7,0x50($sp) /* f158bb0: 15c0000f */ bnez $t6,.NB0f158bf0 /* f158bb4: 00000000 */ sll $zero,$zero,0x0 /* f158bb8: 8f1890a8 */ lw $t8,-0x6f58($t8) /* f158bbc: 24050006 */ addiu $a1,$zero,0x6 /* f158bc0: 030fc821 */ addu $t9,$t8,$t7 /* f158bc4: 8f2b0014 */ lw $t3,0x14($t9) /* f158bc8: 0fc57fca */ jal gfxReplaceGbiCommandsRecursively /* f158bcc: 8d640008 */ lw $a0,0x8($t3) /* f158bd0: 3c0c800b */ lui $t4,0x800b /* f158bd4: 8d8c90a8 */ lw $t4,-0x6f58($t4) /* f158bd8: 8fad0050 */ lw $t5,0x50($sp) /* f158bdc: 24050007 */ addiu $a1,$zero,0x7 /* f158be0: 018d7021 */ addu $t6,$t4,$t5 /* f158be4: 8dd80014 */ lw $t8,0x14($t6) /* f158be8: 0fc57fca */ jal gfxReplaceGbiCommandsRecursively /* f158bec: 8f04000c */ lw $a0,0xc($t8) .NB0f158bf0: /* f158bf0: 0fc565e7 */ jal bgFindRoomVtxBatches /* f158bf4: 8fa402f8 */ lw $a0,0x2f8($sp) /* f158bf8: 3c0f800b */ lui $t7,0x800b /* f158bfc: 8def90a8 */ lw $t7,-0x6f58($t7) /* f158c00: 8fb90050 */ lw $t9,0x50($sp) /* f158c04: 3c0d800b */ lui $t5,0x800b /* f158c08: 2404ffff */ addiu $a0,$zero,-1 /* f158c0c: 01f91821 */ addu $v1,$t7,$t9 /* f158c10: 946b0000 */ lhu $t3,0x0($v1) /* f158c14: 3c19800b */ lui $t9,0x800b /* f158c18: 356c0100 */ ori $t4,$t3,0x100 /* f158c1c: a46c0000 */ sh $t4,0x0($v1) /* f158c20: 8fae0050 */ lw $t6,0x50($sp) /* f158c24: 8dad90a8 */ lw $t5,-0x6f58($t5) /* f158c28: 01ae1821 */ addu $v1,$t5,$t6 /* f158c2c: 94780000 */ lhu $t8,0x0($v1) /* f158c30: 370f0200 */ ori $t7,$t8,0x200 /* f158c34: a46f0000 */ sh $t7,0x0($v1) /* f158c38: 8fab0050 */ lw $t3,0x50($sp) /* f158c3c: 8f3990a8 */ lw $t9,-0x6f58($t9) /* f158c40: 032b6021 */ addu $t4,$t9,$t3 /* f158c44: 0fc4db9c */ jal dyntexSetCurrentRoom /* f158c48: ad800058 */ sw $zero,0x58($t4) /* f158c4c: 3c047f1b */ lui $a0,0x7f1b /* f158c50: 24841a60 */ addiu $a0,$a0,0x1a60 /* f158c54: 0fc55704 */ jal bgVerifyLightSums /* f158c58: 24051d32 */ addiu $a1,$zero,0x1d32 .NB0f158c5c: /* f158c5c: 8fbf002c */ lw $ra,0x2c($sp) .NB0f158c60: /* f158c60: 8fb0001c */ lw $s0,0x1c($sp) /* f158c64: 8fb10020 */ lw $s1,0x20($sp) /* f158c68: 8fb20024 */ lw $s2,0x24($sp) /* f158c6c: 8fb30028 */ lw $s3,0x28($sp) /* f158c70: 03e00008 */ jr $ra /* f158c74: 27bd02f8 */ addiu $sp,$sp,0x2f8 ); #endif #if VERSION < VERSION_NTSC_1_0 const char var7f1b1a2cnb[] = "bg.c"; const char var7f1b1a34nb[] = "bg.c: roominf[room].allocsize > calculated!"; const char var7f1b1a60nb[] = "bg.c"; #endif #else // Mismatch: With hacks removed, the below stores len * 4 into s1 void bgLoadRoom(s32 roomnum) { s32 size; // 2f4 s32 inflatedlen; // 2f0 u8 *allocation; s32 readlen; s32 fileoffset; u8 *memaddr; u8 *a2; // 2dc struct roomblock *block1; struct roomblock *block2; u8 *v0; u8 *gfxblocks[50]; // 208 u8 *vtxblocks[50]; // 140 u8 *sp78[50]; s32 len; u32 end1; s32 i; // 6c u32 end2; s32 prev; s32 v1; #if VERSION < VERSION_NTSC_1_0 bgVerifyLightSums("bg.c", 7076); #endif if (roomnum == 0 || roomnum >= g_Vars.roomcount) { return; } if (g_Rooms[roomnum].loaded240) { return; } // Determine how much memory to allocate. // It must be big enough to fit both the inflated and compressed room data. if (g_Rooms[roomnum].gfxdatalen > 0) { size = g_Rooms[roomnum].gfxdatalen; if (debug0f11edb0()) { size += 1024; } } else { size = memaGetLongestFree(); } // Try to free enough bytes bgGarbageCollectRooms(size, false); // Make the allocation allocation = memaAlloc(size); if (allocation != NULL) { dyntexSetCurrentRoom(roomnum); // Calculate the file offset and read length // of the compressed room data in the BG file readlen = ((g_BgRooms[roomnum + 1].unk00 - g_BgRooms[roomnum].unk00) + 0xf) & ~0xf; fileoffset = (g_BgPrimaryData + g_BgRooms[roomnum].unk00 - g_BgPrimaryData) + 0xf1000000; fileoffset -= var8007fc54; if (size < readlen) { dyntexSetCurrentRoom(-1); return; } // Load the compressed data to the right side of the allocation memaddr = size - readlen + allocation; bgLoadFile(memaddr, fileoffset, readlen); if (rzipIs1173(memaddr) && readlen + 0x20 > size) { dyntexSetCurrentRoom(-1); return; } // Uncompress the data to the left size of the allocation inflatedlen = bgInflate(memaddr, allocation, g_BgRooms[roomnum + 1].unk00 - g_BgRooms[roomnum].unk00); g_Rooms[roomnum].gfxdata = (struct roomgfxdata *)allocation; // Promote offsets to pointers in the gfxdata header if (g_Rooms[roomnum].gfxdata->vertices) { g_Rooms[roomnum].gfxdata->vertices = (struct gfxvtx *)((u32)g_Rooms[roomnum].gfxdata->vertices - g_BgRooms[roomnum].unk00 + (u32)allocation); } if (g_Rooms[roomnum].gfxdata->colours) { g_Rooms[roomnum].gfxdata->colours = (u32 *)((u32)g_Rooms[roomnum].gfxdata->colours - g_BgRooms[roomnum].unk00 + (u32)allocation); } if (g_Rooms[roomnum].gfxdata->opablocks) { g_Rooms[roomnum].gfxdata->opablocks = (struct roomblock *)((u32)g_Rooms[roomnum].gfxdata->opablocks - g_BgRooms[roomnum].unk00 + (u32)allocation); } if (g_Rooms[roomnum].gfxdata->xlublocks) { g_Rooms[roomnum].gfxdata->xlublocks = (struct roomblock *)((u32)g_Rooms[roomnum].gfxdata->xlublocks - g_BgRooms[roomnum].unk00 + (u32)allocation); } // Promote offsets to pointers in each gfxdata block block1 = g_Rooms[roomnum].gfxdata->blocks; end1 = (u32)g_Rooms[roomnum].gfxdata->vertices; while ((s32) (block1 + 1) <= end1) { switch (block1->type) { case ROOMBLOCKTYPE_LEAF: if (block1->next != NULL) { block1->next = (struct roomblock *)((u32)block1->next - g_BgRooms[roomnum].unk00 + (u32)allocation); } if (block1->gdl != 0) { block1->gdl = (Gfx *)((u32)block1->gdl - g_BgRooms[roomnum].unk00 + (u32)allocation); } if (block1->vertices != 0) { block1->vertices = (struct gfxvtx *)((u32)block1->vertices - g_BgRooms[roomnum].unk00 + (u32)allocation); } if (block1->colours != 0) { block1->colours = (u32 *)((u32)block1->colours - g_BgRooms[roomnum].unk00 + (u32)allocation); } break; case ROOMBLOCKTYPE_PARENT: if (block1->next != NULL) { block1->next = (struct roomblock *)((u32)block1->next - g_BgRooms[roomnum].unk00 + (u32)allocation); } if (block1->gdl != 0) { block1->gdl = (Gfx *)((u32)block1->gdl - g_BgRooms[roomnum].unk00 + (u32)allocation); } if (block1->vertices != 0) { block1->vertices = (struct gfxvtx *)((u32)block1->vertices - g_BgRooms[roomnum].unk00 + (u32)allocation); } if (block1->colours != 0) { block1->colours = (u32 *)((u32)block1->colours - g_BgRooms[roomnum].unk00 + (u32)allocation); } if ((u32)block1->vertices < end1) { end1 = (u32)block1->vertices; } break; } block1++; } // Calculate the number of vertices and colours g_Rooms[roomnum].gfxdata->numvertices = ((u32)g_Rooms[roomnum].gfxdata->colours - (u32)g_Rooms[roomnum].gfxdata->vertices) / sizeof(struct gfxvtx); g_Rooms[roomnum].gfxdata->numcolours = ((u32)roomGetNextGdlInLayer(roomnum, 0, VTXBATCHTYPE_OPA | VTXBATCHTYPE_XLU) - (u32)g_Rooms[roomnum].gfxdata->colours) / sizeof(u32); // Build arrays of pointers to gfx blocks and vtx blocks len = 0; v0 = (u8 *) roomGetNextGdlInLayer(roomnum, NULL, VTXBATCHTYPE_OPA | VTXBATCHTYPE_XLU); while (v0) { gfxblocks[len] = v0; vtxblocks[len] = (u8 *) roomFindVerticesForGdl(roomnum, (void *) v0); len++; v0 = (u8 *) roomGetNextGdlInLayer(roomnum, (void *) v0, VTXBATCHTYPE_OPA | VTXBATCHTYPE_XLU); } gfxblocks[len] = allocation + inflatedlen; // Copy gdls to the end of the allocation // and build a pointer array to them v1 = (gfxblocks[len] - gfxblocks[0]); \ texCopyGdls((void *) gfxblocks[0], (void *) (allocation + size - v1), v1); if (allocation + size - v1); for (i = 0; i < len + 1; i++) { sp78[i] = gfxblocks[i] + (allocation + size - gfxblocks[len]); } // Load textures by scanning the gdls. // texLoadFromGdl is reading from sp78 and writing new GBI commands // to a2, overwriting the GBI commands that were loaded from the // BG file. As these are being processed the sp78 pointers are // changed to point to the written GBI, because they need to be kept // track of temporarily so the room blocks can be pointed to them. a2 = gfxblocks[0]; for (i = 0; i < len; i++) { s32 byteswritten = texLoadFromGdl((void *) sp78[i], gfxblocks[i + 1] - gfxblocks[i], (void *) a2, NULL, vtxblocks[i]); sp78[i] = a2; a2 += byteswritten; a2 = (u8 *) ALIGN8((s32) a2); } sp78[len] = a2; // Free the right side of the allocation prev = g_Rooms[roomnum].gfxdatalen; g_Rooms[roomnum].gfxdatalen = ALIGN16(a2 - allocation + 0x20); if (g_Rooms[roomnum].gfxdatalen > prev) { #if VERSION < VERSION_NTSC_1_0 crashSetMessage("bg.c: roominf[room].allocsize > calculated!"); CRASH(); #endif } g_Rooms[roomnum].loaded240 = 1; if (g_Rooms[roomnum].gfxdatalen != size) { memaRealloc((s32) allocation, size, g_Rooms[roomnum].gfxdatalen); } // Update gdl pointers in the gfxdata so they point to the ones // that have been processed by the texture decompressor. block2 = g_Rooms[roomnum].gfxdata->blocks; // a1 = end2 = (u32) g_Rooms[roomnum].gfxdata->vertices; // a3 = while ((s32) (block2 + 1) <= end2) { switch (block2->type) { case ROOMBLOCKTYPE_LEAF: if (block2->gdl) { for (i = 0; i < len; i++) { Gfx *tmp = block2->gdl; if (tmp == (Gfx *) gfxblocks[i]) { block2->gdl = (Gfx *) sp78[i]; break; } } } break; case ROOMBLOCKTYPE_PARENT: if ((u32) block2->unk0c < end2) { end2 = (u32) block2->unk0c; } break; } block2++; } // Do some find/replaces in the gdls based on some configuration if (g_FogEnabled) { gfxReplaceGbiCommandsRecursively(g_Rooms[roomnum].gfxdata->opablocks, 1); gfxReplaceGbiCommandsRecursively(g_Rooms[roomnum].gfxdata->xlublocks, 5); } else if (var800a65e4 == 0) { gfxReplaceGbiCommandsRecursively(g_Rooms[roomnum].gfxdata->opablocks, 6); gfxReplaceGbiCommandsRecursively(g_Rooms[roomnum].gfxdata->xlublocks, 7); } // Create vertex batches - these are used for hit detection bgFindRoomVtxBatches(roomnum); g_Rooms[roomnum].flags |= ROOMFLAG_DIRTY; g_Rooms[roomnum].flags |= ROOMFLAG_0200; g_Rooms[roomnum].colours = NULL; dyntexSetCurrentRoom(-1); } #if VERSION < VERSION_NTSC_1_0 bgVerifyLightSums("bg.c", 7474); #endif } #endif const char var7f1b7420[] = "Checking Convex Room %d"; const char var7f1b7438[] = " Portal %d %s%s%.1f < %.1f"; const char var7f1b7454[] = ""; const char var7f1b7458[] = ""; const char var7f1b745c[] = " Convex Room Failed (1)"; const char var7f1b7474[] = " Portal %d %s%s%.1f > %.1f"; const char var7f1b7490[] = ""; const char var7f1b7494[] = ""; const char var7f1b7498[] = " Convex Room Failed (0)"; const char var7f1b74b0[] = "Checking Concave Room %d"; const char var7f1b74cc[] = " Checking Portal %d"; const char var7f1b74e0[] = "Reject P:%d (%s%s%.1f %.1f n3=%.1f)"; const char var7f1b7504[] = ""; const char var7f1b7508[] = ""; const char var7f1b750c[] = "Reject P:%d (%s%s%.1f %.1f n4=%.1f)"; const char var7f1b7530[] = ""; const char var7f1b7534[] = ""; const char var7f1b7538[] = " Full %d%s%s %.1f %.1f (%.1f %.1f)"; const char var7f1b755c[] = ""; const char var7f1b7560[] = ""; const char var7f1b7564[] = " Failed 2 - Crossed portal %d"; const char var7f1b7584[] = " Failed 1 - Crossed portal %d"; const char var7f1b75a4[] = " Passed"; void bgUnloadRoom(s32 roomnum) { u32 size; if (g_Rooms[roomnum].vtxbatches) { size = ((g_Rooms[roomnum].numvtxbatches) * sizeof(struct vtxbatch) + 0xf) & ~0xf; memaFree(g_Rooms[roomnum].vtxbatches, size); g_Rooms[roomnum].vtxbatches = NULL; } if (g_Rooms[roomnum].gfxdatalen > 0) { size = g_Rooms[roomnum].gfxdatalen; memaFree(g_Rooms[roomnum].gfxdata, size); g_Rooms[roomnum].gfxdata = NULL; } g_Rooms[roomnum].loaded240 = 0; } void bgUnloadAllRooms(void) { s32 i; for (i = 1; i < g_Vars.roomcount; i++) { if (g_Rooms[i].loaded240) { bgUnloadRoom(i); } } } /** * Find rooms which were recently visible and not yet unloaded, and unload them * until the given bytesneeded amount is available in mema. * * Rooms are unloaded in order of least recently visible. * * If there's still not enough space after 30 unloads and the desparate argument * is true, do a final iteration through all the rooms and free everything * that's not visible. */ void bgGarbageCollectRooms(s32 bytesneeded, bool desparate) { s32 bytesfree = memaGetLongestFree(); s32 oldestroom; s32 oldesttimer; s32 count = 0; s32 i; while (bytesfree < bytesneeded) { oldestroom = 0; oldesttimer = 0; for (i = 1; i < g_Vars.roomcount; i++) { if (g_Rooms[i].loaded240 > oldesttimer) { oldestroom = i; oldesttimer = g_Rooms[i].loaded240; } } if (oldestroom != 0) { bgUnloadRoom(oldestroom); memaDefrag(); } bytesfree = memaGetLongestFree(); count++; if (count == 30) { if (desparate == true) { for (i = 1; i < g_Vars.roomcount; i++) { #if VERSION >= VERSION_NTSC_1_0 if (g_Rooms[i].loaded240 > 8) #else if (g_Rooms[i].loaded240) #endif { bgUnloadRoom(i); memaDefrag(); if (memaGetLongestFree() >= bytesneeded) { return; } } } } break; } } } /** * Increase the loaded240 timers for rooms which are no longer visible. * If any rooms have reached the timer limit then unload them, but don't unload * more than 2 rooms per frame. */ void bgTickRooms(void) { s32 numunloaded = 0; s32 i; for (i = 1; i < g_Vars.roomcount; i++) { if (g_Rooms[i].loaded240) { #if VERSION >= VERSION_NTSC_1_0 g_Rooms[i].loaded240++; #else g_Rooms[i].loaded240 += g_Vars.lvupdate240; #endif if (g_Rooms[i].loaded240 >= g_BgUnloadDelay240) { g_Rooms[i].loaded240 = g_BgUnloadDelay240; } if (g_Rooms[i].flags & ROOMFLAG_ONSCREEN) { g_Rooms[i].loaded240 = 1; } if (numunloaded < 2 && g_Rooms[i].loaded240 == g_BgUnloadDelay240_2) { bgUnloadRoom(i); #if VERSION >= VERSION_NTSC_1_0 memaDefrag(); #endif numunloaded++; } } } } Gfx *bgRenderRoomPass(Gfx *gdl, s32 roomnum, struct roomblock *block, bool arg3) { u32 v0; if (block == NULL) { return gdl; } switch (block->type) { case ROOMBLOCKTYPE_LEAF: if (g_Rooms[roomnum].flags & ROOMFLAG_HASDYNTEX) { dyntexTickRoom(roomnum, block->vertices); } gSPSegment(gdl++, SPSEGMENT_BG_VTX, OS_PHYSICAL_TO_K0(block->vertices)); roomHighlight(roomnum); v0 = (u32)g_Rooms[roomnum].colours; if (v0 != NULL) { s32 addr = ALIGN8((u32)&g_Rooms[roomnum].gfxdata->vertices[g_Rooms[roomnum].gfxdata->numvertices]); v0 += (((s32)block->colours - addr) >> 2) * 4; } else { v0 = (u32)block->colours; } gSPSegment(gdl++, SPSEGMENT_BG_COL, OS_PHYSICAL_TO_K0(v0)); gSPDisplayList(gdl++, OS_PHYSICAL_TO_K0(block->gdl)); if (arg3) { gdl = bgRenderRoomPass(gdl, roomnum, block->next, true); } break; case ROOMBLOCKTYPE_PARENT: if (block->child != NULL) { struct roomblock *sp58; struct roomblock *sp54; struct coord *coord; f32 sum; f32 sp40[3]; f32 sp34[3]; u32 stack; sp58 = block->child; sp54 = sp58->next; coord = block->unk0c; sp40[0] = coord[1].f[0]; sp40[1] = coord[1].f[1]; sp40[2] = coord[1].f[2]; sp34[0] = coord[0].f[0] - g_Vars.currentplayer->cam_pos.f[0]; sp34[1] = coord[0].f[1] - g_Vars.currentplayer->cam_pos.f[1]; sp34[2] = coord[0].f[2] - g_Vars.currentplayer->cam_pos.f[2]; sum = sp40[0] * sp34[0] + sp40[1] * sp34[1] + sp40[2] * sp34[2]; if (sum < 0.0f) { gdl = bgRenderRoomPass(gdl, roomnum, sp58, false); gdl = bgRenderRoomPass(gdl, roomnum, sp54, false); } else { gdl = bgRenderRoomPass(gdl, roomnum, sp54, false); gdl = bgRenderRoomPass(gdl, roomnum, sp58, false); } if (arg3) { gdl = bgRenderRoomPass(gdl, roomnum, block->next, true); } } break; } return gdl; } /** * Render the opaque layer of the room. */ Gfx *bgRenderRoomOpaque(Gfx *gdl, s32 roomnum) { if (g_Rooms[roomnum].loaded240 == 0) { return gdl; } gdl = roomPushMtx(gdl, roomnum); gdl = lightsSetForRoom(gdl, roomnum); gdl = bgRenderRoomPass(gdl, roomnum, g_Rooms[roomnum].gfxdata->opablocks, true); gdl = lightsSetDefault(gdl); g_Rooms[roomnum].loaded240 = 1; return gdl; } /** * Render the transparency layer of the room. */ Gfx *bgRenderRoomXlu(Gfx *gdl, s32 roomnum) { u32 stack; if (roomnum == 0 || roomnum >= g_Vars.roomcount) { return gdl; } if (g_Rooms[roomnum].loaded240) { if (g_Rooms[roomnum].gfxdata->xlublocks == NULL) { return gdl; } roomHighlight(roomnum); if (g_Rooms[roomnum].gfxdata); if (g_Rooms[roomnum].gfxdata); gdl = roomPushMtx(gdl, roomnum); gdl = bgRenderRoomPass(gdl, roomnum, g_Rooms[roomnum].gfxdata->xlublocks, true); g_Rooms[roomnum].loaded240 = 1; } else { bgLoadRoom(roomnum); } return gdl; } s32 bgPopulateVtxBatchType(s32 roomnum, struct vtxbatch *batches, Gfx *gdl, s32 batchindex, struct gfxvtx *vertices, s32 type) { s32 i; s32 j; s32 numvertices; struct gfxvtx *batchvertices; for (i = 0; gdl[i].dma.cmd != G_ENDDL; i++) { if (gdl[i].dma.cmd == G_VTX) { batches[batchindex].gdl = gdl; batches[batchindex].gbicmdindex = i; batches[batchindex].type = type; for (j = 0; j < 3; j++) { batches[batchindex].bbmin.f[j] = 32767.0f; batches[batchindex].bbmax.f[j] = -32768.0f; } numvertices = (((u32)gdl[i].bytes[1] >> 4) & 0xf) + 1; batchvertices = (struct gfxvtx *)((u32)vertices + (gdl[i].words.w1 & 0xffffff)); for (j = 0; j < numvertices; j++) { f32 x = batchvertices[j].x; f32 y = batchvertices[j].y; f32 z = batchvertices[j].z; if (x < batches[batchindex].bbmin.x) { batches[batchindex].bbmin.x = x; } if (y < batches[batchindex].bbmin.y) { batches[batchindex].bbmin.y = y; } if (z < batches[batchindex].bbmin.z) { batches[batchindex].bbmin.z = z; } if (x > batches[batchindex].bbmax.x) { batches[batchindex].bbmax.x = x; } if (y > batches[batchindex].bbmax.y) { batches[batchindex].bbmax.y = y; } if (z > batches[batchindex].bbmax.z) { batches[batchindex].bbmax.z = z; } } if (batches[batchindex].bbmin.x == batches[batchindex].bbmax.x) { batches[batchindex].bbmax.x++; } if (batches[batchindex].bbmin.y == batches[batchindex].bbmax.y) { batches[batchindex].bbmax.y++; } if (batches[batchindex].bbmin.z == batches[batchindex].bbmax.z) { batches[batchindex].bbmax.z++; } batches[batchindex].bbmin.x += g_BgRooms[roomnum].pos.x; batches[batchindex].bbmin.y += g_BgRooms[roomnum].pos.y; batches[batchindex].bbmin.z += g_BgRooms[roomnum].pos.z; batches[batchindex].bbmax.x += g_BgRooms[roomnum].pos.x; batches[batchindex].bbmax.y += g_BgRooms[roomnum].pos.y; batches[batchindex].bbmax.z += g_BgRooms[roomnum].pos.z; batchindex++; } } return batchindex; } void bgFindRoomVtxBatches(s32 roomnum) { s32 i; s32 batchindex = 0; s32 xlucount; Gfx *gdl; struct vtxbatch *batches; if (g_Rooms[roomnum].vtxbatches == NULL) { gdl = roomGetNextGdlInLayer(roomnum, NULL, VTXBATCHTYPE_OPA); if (gdl != NULL) { while (gdl) { for (i = 0; gdl[i].dma.cmd != G_ENDDL; i++) { // if gDPSetVerticeArray if (gdl[i].dma.cmd == G_VTX) { batchindex++; } } gdl = roomGetNextGdlInLayer(roomnum, gdl, VTXBATCHTYPE_OPA); } xlucount = 0; gdl = roomGetNextGdlInLayer(roomnum, NULL, VTXBATCHTYPE_XLU); while (gdl) { for (i = 0; gdl[i].dma.cmd != G_ENDDL; i++) { // if gDPSetVerticeArray if (gdl[i].dma.cmd == G_VTX) { xlucount++; } } gdl = roomGetNextGdlInLayer(roomnum, gdl, VTXBATCHTYPE_XLU); } batchindex += xlucount; batches = memaAlloc((batchindex * sizeof(struct vtxbatch) + 0xf) & ~0xf); if (batches != NULL) { gdl = roomGetNextGdlInLayer(roomnum, NULL, VTXBATCHTYPE_OPA); batchindex = 0; g_Rooms[roomnum].vtxbatches = batches; while (gdl) { struct gfxvtx *vertices = roomFindVerticesForGdl(roomnum, gdl); batchindex = bgPopulateVtxBatchType(roomnum, batches, gdl, batchindex, vertices, VTXBATCHTYPE_OPA); gdl = roomGetNextGdlInLayer(roomnum, gdl, VTXBATCHTYPE_OPA); } if (xlucount) { gdl = roomGetNextGdlInLayer(roomnum, NULL, VTXBATCHTYPE_XLU); while (gdl) { struct gfxvtx *vertices = roomFindVerticesForGdl(roomnum, gdl); batchindex = bgPopulateVtxBatchType(roomnum, batches, gdl, batchindex, vertices, VTXBATCHTYPE_XLU); gdl = roomGetNextGdlInLayer(roomnum, gdl, VTXBATCHTYPE_XLU); } } g_Rooms[roomnum].numvtxbatches = (s16)batchindex; } } } } bool func0f15f20c(struct coord *arg0, struct coord *arg1, s32 *arg2, s32 *arg3) { struct coord sp24; struct coord sp18; sp24.x = arg2[0]; sp24.y = arg2[1]; sp24.z = arg2[2]; sp18.x = arg3[0]; sp18.y = arg3[1]; sp18.z = arg3[2]; return bgTestLineIntersectsBbox(arg0, arg1, &sp24, &sp18); } bool bgTestLineIntersectsBbox(struct coord *arg0, struct coord *arg1, struct coord *arg2, struct coord *arg3) { u32 stack[4]; f32 f0; f32 f0_2; f32 f2; f32 f2_2; f32 f6; f32 f10; f32 sp34; f32 sp30; f32 f16; f32 f18; f32 f18_2; f32 sp20; f32 f12; f32 f12_2; f32 f14; f32 f14_2; // x f18 = arg1->x; f16 = arg3->x - arg0->x; f14 = arg2->x - arg0->x; if (f18 < 0.0f) { f18 = -f18; f14 = -f14; f16 = -f16; } if (f14 < 0.0f && f16 < 0.0f) { return false; } if (f16 < f14) { f32 tmp = f14; f14 = f16; f16 = tmp; } // y f12 = arg1->y; f2 = arg3->y - arg0->y; f0 = arg2->y - arg0->y; if (f12 < 0.0f) { f12 = -f12; f0 = -f0; f2 = -f2; } if (f0 < 0.0f && f2 < 0.0f) { return false; } if (f2 < f0) { sp20 = f0; f0 = f2; f2 = sp20; } f6 = f14 * f12; f10 = f0 * f18; if (f10 < f6) { if (f2 * f18 < f6) { return false; } sp34 = f14; sp30 = f18; } else { if (f16 * f12 < f10) { return false; } sp34 = f0; sp30 = f12; } if (f16 * f12 < f2 * f18) { f0_2 = f16; f14_2 = f18; } else { f0_2 = f2; f14_2 = f12; } // z f2_2 = arg1->z; f12_2 = arg3->z - arg0->z; f18_2 = arg2->z - arg0->z; if (f2_2 < 0.0f) { f2_2 = -f2_2; f18_2 = -f18_2; f12_2 = -f12_2; } if (f18_2 < 0.0f && f12_2 < 0.0f) { return false; } if (f12_2 < f18_2) { f32 tmp = f18_2; f18_2 = f12_2; f12_2 = tmp; } if (sp34 * f2_2 < f18_2 * sp30) { if (f0_2 * f2_2 < f18_2 * f14_2) { return false; } } else { if (f12_2 * sp30 < sp34 * f2_2) { return false; } } return true; } bool bgTestHitOnObj(struct coord *arg0, struct coord *arg1, struct coord *arg2, Gfx *gdl, Gfx *gdl2, struct gfxvtx *vertices, struct hitthing *hitthing) { s16 stack; s16 triref; s32 trisremaining; bool intersectsbbox; f32 *ptr; f32 tmp; f32 sqdist; bool hit = false; struct coord *point1; struct coord *point2; struct coord *point3; struct gfxvtx *vtx; Gfx *imggdl = NULL; s32 texturenum; f32 lowestsqdist = MAXFLOAT; s32 offset; s32 numvertices; Gfx *tri4gdl; s32 count; struct coord min; struct coord max; struct coord sp8c; struct coord sp80; s32 points[3]; while (true) { if (gdl->dma.cmd == G_ENDDL) { imggdl = NULL; if (gdl2 != NULL) { gdl = gdl2; gdl2 = NULL; continue; } break; } else if (gdl->dma.cmd == G_VTX) { ptr = var800a6470; count = gdl->bytes[1] & 0xf; offset = (gdl->words.w1 & 0xffffff); numvertices = (((u32)gdl->bytes[1] >> 4) & 0xf) + 1; vtx = (struct gfxvtx *)((u32)vertices + offset); vtx -= count; ptr[0] = vtx->x; ptr[1] = vtx->y; ptr[2] = vtx->z; min.x = ptr[0]; max.x = ptr[0]; min.y = ptr[1]; max.y = ptr[1]; min.z = ptr[2]; max.z = ptr[2]; ptr += 3; vtx++; numvertices--; while (numvertices > 0) { ptr[0] = vtx->x; ptr[1] = vtx->y; ptr[2] = vtx->z; if (ptr[0] < min.x) { min.x = ptr[0]; } if (ptr[1] < min.y) { min.y = ptr[1]; } if (ptr[2] < min.z) { min.z = ptr[2]; } if (ptr[0] > max.x) { max.x = ptr[0]; } if (ptr[1] > max.y) { max.y = ptr[1]; } if (ptr[2] > max.z) { max.z = ptr[2]; } vtx++; numvertices--; ptr += 3; } intersectsbbox = true; if (arg0->x < min.x) { if (arg1->x < min.x) { intersectsbbox = false; } } else if (arg0->x > max.x) { if (arg1->x > max.x) { intersectsbbox = false; } } if (arg0->y < min.y) { if (arg1->y < min.y) { intersectsbbox = false; } } else if (arg0->y > max.y) { if (arg1->y > max.y) { intersectsbbox = false; } } if (arg0->z < min.z) { if (arg1->z < min.z) { intersectsbbox = false; } } else if (arg0->z > max.z) { if (arg1->z > max.z) { intersectsbbox = false; } } if (intersectsbbox) { intersectsbbox = bgTestLineIntersectsBbox(arg0, arg2, &min, &max); } } else if (gdl->dma.cmd == (s8)G_SETTIMG) { imggdl = gdl; } else { if (!intersectsbbox) { gdl++; continue; } if (gdl->dma.cmd != G_TRI1 && gdl->dma.cmd != G_TRI4) { gdl++; continue; } if (gdl->dma.cmd == G_TRI1) { trisremaining = 0; triref = 0; points[0] = gdl->tri.tri.v[0] / 10; points[1] = gdl->tri.tri.v[1] / 10; points[2] = gdl->tri.tri.v[2] / 10; } else if (gdl->dma.cmd == G_TRI4) { tri4gdl = gdl; trisremaining = 3; triref = 1; points[0] = gdl->tri4.x1; points[1] = gdl->tri4.y1; points[2] = gdl->tri4.z1; } do { if (points[0] == 0 && points[1] == 0 && points[2] == 0) { break; } point1 = (struct coord *) (var800a6470 + points[0] * 3); point2 = (struct coord *) (var800a6470 + points[1] * 3); point3 = (struct coord *) (var800a6470 + points[2] * 3); min.x = point1->x; max.x = point1->x; if (point2->x < min.x) { min.x = point2->x; } if (point2->x > max.x) { max.x = point2->x; } if (point3->x < min.x) { min.x = point3->x; } if (point3->x > max.x) { max.x = point3->x; } if (!(arg0->x < min.x && arg1->x < min.x) && !(arg0->x > max.x && arg1->x > max.x)) { min.z = point1->z; max.z = point1->z; if (point2->z < min.z) { min.z = point2->z; } if (point2->z > max.z) { max.z = point2->z; } if (point3->z < min.z) { min.z = point3->z; } if (point3->z > max.z) { max.z = point3->z; } if (!(arg0->z < min.z && arg1->z < min.z) && !(arg0->z > max.z && arg1->z > max.z)) { min.y = point1->y; max.y = point1->y; if (point2->y < min.y) { min.y = point2->y; } if (point2->y > max.y) { max.y = point2->y; } if (point3->y < min.y) { min.y = point3->y; } if (point3->y > max.y) { max.y = point3->y; } if (!(arg0->y < min.y && arg1->y < min.y) && !(arg0->y > max.y && arg1->y > max.y)) { if (bgTestLineIntersectsBbox(arg0, arg2, &min, &max) && func0002f560(point1, point2, point3, 0, arg0, arg1, arg2, &sp8c, &sp80)) { tmp = sp8c.x - arg0->x; sqdist = tmp * tmp; tmp = sp8c.y - arg0->y; sqdist += tmp * tmp; tmp = sp8c.z - arg0->z; sqdist += tmp * tmp; if (sqdist < lowestsqdist) { hit = true; if (imggdl == NULL || (imggdl->words.w1 & 0x0f000000) == 0x0f000000 || (imggdl->words.w1 & 0x05000000) == 0x05000000) { texturenum = -1; } else { s32 tmp = PHYS_TO_K0(imggdl->words.w1 - 8); texturenum = *(s16 *) tmp; } lowestsqdist = sqdist; hitthing->unk00.x = sp8c.x; hitthing->unk00.y = sp8c.y; hitthing->unk00.z = sp8c.z; hitthing->unk0c.x = sp80.x; hitthing->unk0c.y = sp80.y; hitthing->unk0c.z = sp80.z; hitthing->unk18 = &vtx[points[0]]; hitthing->unk1c = &vtx[points[1]]; hitthing->unk20 = &vtx[points[2]]; hitthing->texturenum = texturenum; hitthing->tricmd = gdl; hitthing->unk28 = triref; } } } } } trisremaining--; if (trisremaining == 2) { points[0] = tri4gdl->tri4.x2; points[1] = tri4gdl->tri4.y2; points[2] = tri4gdl->tri4.z2; triref = 2; } else if (trisremaining == 1) { points[0] = tri4gdl->tri4.x3; points[1] = tri4gdl->tri4.y3; points[2] = tri4gdl->tri4.z3; triref = 3; } else if (trisremaining == 0) { points[0] = tri4gdl->tri4.x4; points[1] = tri4gdl->tri4.y4; points[2] = tri4gdl->tri4.z4; triref = 1; } } while (trisremaining >= 0); } gdl++; } return hit; } #if MATCHING GLOBAL_ASM( glabel bgTestHitOnChr /* f15ffdc: 27bdff10 */ addiu $sp,$sp,-240 /* f15ffe0: afb7004c */ sw $s7,0x4c($sp) /* f15ffe4: afb50044 */ sw $s5,0x44($sp) /* f15ffe8: 00a0a825 */ or $s5,$a1,$zero /* f15ffec: 00c0b825 */ or $s7,$a2,$zero /* f15fff0: afb60048 */ sw $s6,0x48($sp) /* f15fff4: afb40040 */ sw $s4,0x40($sp) /* f15fff8: afb3003c */ sw $s3,0x3c($sp) /* f15fffc: afb20038 */ sw $s2,0x38($sp) /* f160000: 240e0010 */ addiu $t6,$zero,0x10 /* f160004: afbf0054 */ sw $ra,0x54($sp) /* f160008: afbe0050 */ sw $s8,0x50($sp) /* f16000c: afb10034 */ sw $s1,0x34($sp) /* f160010: afb00030 */ sw $s0,0x30($sp) /* f160014: afa400f0 */ sw $a0,0xf0($sp) /* f160018: afa700fc */ sw $a3,0xfc($sp) /* f16001c: afae00dc */ sw $t6,0xdc($sp) /* f160020: afa000d8 */ sw $zero,0xd8($sp) /* f160024: afa000cc */ sw $zero,0xcc($sp) /* f160028: 8fb20110 */ lw $s2,0x110($sp) /* f16002c: 8fb300e8 */ lw $s3,0xe8($sp) /* f160030: 8fb400ac */ lw $s4,0xac($sp) /* f160034: 8fb600c0 */ lw $s6,0xc0($sp) /* f160038: 2406ffb1 */ addiu $a2,$zero,-79 /* f16003c: 2405ffbf */ addiu $a1,$zero,-65 /* f160040: 87a800ee */ lh $t0,0xee($sp) /* f160044: 2403000a */ addiu $v1,$zero,0xa .L0f160048: /* f160048: 8faf0100 */ lw $t7,0x100($sp) /* f16004c: 2401ffb8 */ addiu $at,$zero,-72 /* f160050: 8fb80104 */ lw $t8,0x104($sp) /* f160054: 81e20000 */ lb $v0,0x0($t7) /* f160058: 54410007 */ bnel $v0,$at,.L0f160078 /* f16005c: 24010001 */ addiu $at,$zero,0x1 /* f160060: 53000269 */ beqzl $t8,.L0f160a08 /* f160064: 8fbf0054 */ lw $ra,0x54($sp) /* f160068: afb80100 */ sw $t8,0x100($sp) /* f16006c: 1000fff6 */ b .L0f160048 /* f160070: afa00104 */ sw $zero,0x104($sp) /* f160074: 24010001 */ addiu $at,$zero,0x1 .L0f160078: /* f160078: 1441000d */ bne $v0,$at,.L0f1600b0 /* f16007c: 8fb90100 */ lw $t9,0x100($sp) /* f160080: 8f240004 */ lw $a0,0x4($t9) /* f160084: 8faa00f0 */ lw $t2,0xf0($sp) /* f160088: 3c0100ff */ lui $at,0xff /* f16008c: 3421ffff */ ori $at,$at,0xffff /* f160090: 8d4b000c */ lw $t3,0xc($t2) /* f160094: 00814824 */ and $t1,$a0,$at /* f160098: 00099982 */ srl $s3,$t1,0x6 /* f16009c: 00136180 */ sll $t4,$s3,0x6 /* f1600a0: 016c6821 */ addu $t5,$t3,$t4 /* f1600a4: 01202025 */ or $a0,$t1,$zero /* f1600a8: 10000252 */ b .L0f1609f4 /* f1600ac: afad00a8 */ sw $t5,0xa8($sp) .L0f1600b0: /* f1600b0: 24010004 */ addiu $at,$zero,0x4 /* f1600b4: 144100c7 */ bne $v0,$at,.L0f1603d4 /* f1600b8: 8fb900e4 */ lw $t9,0xe4($sp) /* f1600bc: 8fa50100 */ lw $a1,0x100($sp) /* f1600c0: 8fb800dc */ lw $t8,0xdc($sp) /* f1600c4: 3c0100ff */ lui $at,0xff /* f1600c8: 90a20001 */ lbu $v0,0x1($a1) /* f1600cc: 8ca40004 */ lw $a0,0x4($a1) /* f1600d0: 3421ffff */ ori $at,$at,0xffff /* f1600d4: 8faf0108 */ lw $t7,0x108($sp) /* f1600d8: 3043000f */ andi $v1,$v0,0xf /* f1600dc: 00817024 */ and $t6,$a0,$at /* f1600e0: 0078082a */ slt $at,$v1,$t8 /* f1600e4: 00028902 */ srl $s1,$v0,0x4 /* f1600e8: 01c02025 */ or $a0,$t6,$zero /* f1600ec: 26310001 */ addiu $s1,$s1,0x1 /* f1600f0: 10200002 */ beqz $at,.L0f1600fc /* f1600f4: 01eeb021 */ addu $s6,$t7,$t6 /* f1600f8: afa300dc */ sw $v1,0xdc($sp) .L0f1600fc: /* f1600fc: 8fb300dc */ lw $s3,0xdc($sp) /* f160100: 8fac00d8 */ lw $t4,0xd8($sp) /* f160104: 3c0a800a */ lui $t2,%hi(var800a6470) /* f160108: 254a6470 */ addiu $t2,$t2,%lo(var800a6470) /* f16010c: 00134880 */ sll $t1,$s3,0x2 /* f160110: 012af021 */ addu $s8,$t1,$t2 /* f160114: 02231021 */ addu $v0,$s1,$v1 /* f160118: 27cb000c */ addiu $t3,$s8,0xc /* f16011c: 0182082a */ slt $at,$t4,$v0 /* f160120: 10200002 */ beqz $at,.L0f16012c /* f160124: afab0060 */ sw $t3,0x60($sp) /* f160128: afa200d8 */ sw $v0,0xd8($sp) .L0f16012c: /* f16012c: 00036880 */ sll $t5,$v1,0x2 /* f160130: 01a36823 */ subu $t5,$t5,$v1 /* f160134: 3c0f800a */ lui $t7,%hi(var800a6470) /* f160138: 25ef6470 */ addiu $t7,$t7,%lo(var800a6470) /* f16013c: 000d7080 */ sll $t6,$t5,0x2 /* f160140: 1a200019 */ blez $s1,.L0f1601a8 /* f160144: 01cf8021 */ addu $s0,$t6,$t7 .L0f160148: /* f160148: 86d80000 */ lh $t8,0x0($s6) /* f16014c: 02002825 */ or $a1,$s0,$zero /* f160150: 44982000 */ mtc1 $t8,$f4 /* f160154: 00000000 */ nop /* f160158: 468021a0 */ cvt.s.w $f6,$f4 /* f16015c: e6060000 */ swc1 $f6,0x0($s0) /* f160160: 86c90002 */ lh $t1,0x2($s6) /* f160164: 44894000 */ mtc1 $t1,$f8 /* f160168: 00000000 */ nop /* f16016c: 468042a0 */ cvt.s.w $f10,$f8 /* f160170: e60a0004 */ swc1 $f10,0x4($s0) /* f160174: 86ca0004 */ lh $t2,0x4($s6) /* f160178: 448a8000 */ mtc1 $t2,$f16 /* f16017c: 00000000 */ nop /* f160180: 468084a0 */ cvt.s.w $f18,$f16 /* f160184: e6120008 */ swc1 $f18,0x8($s0) /* f160188: a7a800ee */ sh $t0,0xee($sp) /* f16018c: 0c0056d9 */ jal mtx4TransformVecInPlace /* f160190: 8fa400a8 */ lw $a0,0xa8($sp) /* f160194: 2631ffff */ addiu $s1,$s1,-1 /* f160198: 87a800ee */ lh $t0,0xee($sp) /* f16019c: 2610000c */ addiu $s0,$s0,0xc /* f1601a0: 1e20ffe9 */ bgtz $s1,.L0f160148 /* f1601a4: 26d6000c */ addiu $s6,$s6,0xc .L0f1601a8: /* f1601a8: 8fa200d8 */ lw $v0,0xd8($sp) /* f1601ac: 8fab00dc */ lw $t3,0xdc($sp) /* f1601b0: c7c00000 */ lwc1 $f0,0x0($s8) /* f1601b4: c7c20004 */ lwc1 $f2,0x4($s8) /* f1601b8: c7cc0008 */ lwc1 $f12,0x8($s8) /* f1601bc: 0162082a */ slt $at,$t3,$v0 /* f1601c0: 8fb00060 */ lw $s0,0x60($sp) /* f1601c4: e7a0009c */ swc1 $f0,0x9c($sp) /* f1601c8: e7a00090 */ swc1 $f0,0x90($sp) /* f1601cc: e7a200a0 */ swc1 $f2,0xa0($sp) /* f1601d0: e7a20094 */ swc1 $f2,0x94($sp) /* f1601d4: e7ac00a4 */ swc1 $f12,0xa4($sp) /* f1601d8: 1020002e */ beqz $at,.L0f160294 /* f1601dc: e7ac0098 */ swc1 $f12,0x98($sp) .L0f1601e0: /* f1601e0: c6000000 */ lwc1 $f0,0x0($s0) /* f1601e4: c7a4009c */ lwc1 $f4,0x9c($sp) /* f1601e8: 26730001 */ addiu $s3,$s3,0x1 /* f1601ec: 4604003c */ c.lt.s $f0,$f4 /* f1601f0: 00000000 */ nop /* f1601f4: 45020003 */ bc1fl .L0f160204 /* f1601f8: c6000004 */ lwc1 $f0,0x4($s0) /* f1601fc: e7a0009c */ swc1 $f0,0x9c($sp) /* f160200: c6000004 */ lwc1 $f0,0x4($s0) .L0f160204: /* f160204: c7a600a0 */ lwc1 $f6,0xa0($sp) /* f160208: 4606003c */ c.lt.s $f0,$f6 /* f16020c: 00000000 */ nop /* f160210: 45020003 */ bc1fl .L0f160220 /* f160214: c6000008 */ lwc1 $f0,0x8($s0) /* f160218: e7a000a0 */ swc1 $f0,0xa0($sp) /* f16021c: c6000008 */ lwc1 $f0,0x8($s0) .L0f160220: /* f160220: c7a800a4 */ lwc1 $f8,0xa4($sp) /* f160224: 4608003c */ c.lt.s $f0,$f8 /* f160228: 00000000 */ nop /* f16022c: 45020003 */ bc1fl .L0f16023c /* f160230: c6000000 */ lwc1 $f0,0x0($s0) /* f160234: e7a000a4 */ swc1 $f0,0xa4($sp) /* f160238: c6000000 */ lwc1 $f0,0x0($s0) .L0f16023c: /* f16023c: c7aa0090 */ lwc1 $f10,0x90($sp) /* f160240: 4600503c */ c.lt.s $f10,$f0 /* f160244: 00000000 */ nop /* f160248: 45020003 */ bc1fl .L0f160258 /* f16024c: c6000004 */ lwc1 $f0,0x4($s0) /* f160250: e7a00090 */ swc1 $f0,0x90($sp) /* f160254: c6000004 */ lwc1 $f0,0x4($s0) .L0f160258: /* f160258: c7b00094 */ lwc1 $f16,0x94($sp) /* f16025c: 4600803c */ c.lt.s $f16,$f0 /* f160260: 00000000 */ nop /* f160264: 45020003 */ bc1fl .L0f160274 /* f160268: c6000008 */ lwc1 $f0,0x8($s0) /* f16026c: e7a00094 */ swc1 $f0,0x94($sp) /* f160270: c6000008 */ lwc1 $f0,0x8($s0) .L0f160274: /* f160274: c7b20098 */ lwc1 $f18,0x98($sp) /* f160278: 4600903c */ c.lt.s $f18,$f0 /* f16027c: 00000000 */ nop /* f160280: 45000002 */ bc1f .L0f16028c /* f160284: 00000000 */ nop /* f160288: e7a00098 */ swc1 $f0,0x98($sp) .L0f16028c: /* f16028c: 1662ffd4 */ bne $s3,$v0,.L0f1601e0 /* f160290: 2610000c */ addiu $s0,$s0,0xc .L0f160294: /* f160294: c6a00000 */ lwc1 $f0,0x0($s5) /* f160298: c7a4009c */ lwc1 $f4,0x9c($sp) /* f16029c: 4604003c */ c.lt.s $f0,$f4 /* f1602a0: 00000000 */ nop /* f1602a4: 45020007 */ bc1fl .L0f1602c4 /* f1602a8: c7a80090 */ lwc1 $f8,0x90($sp) /* f1602ac: c6e60000 */ lwc1 $f6,0x0($s7) /* f1602b0: 4604303c */ c.lt.s $f6,$f4 /* f1602b4: 00000000 */ nop /* f1602b8: 45030038 */ bc1tl .L0f16039c /* f1602bc: afa000e4 */ sw $zero,0xe4($sp) /* f1602c0: c7a80090 */ lwc1 $f8,0x90($sp) .L0f1602c4: /* f1602c4: 4600403c */ c.lt.s $f8,$f0 /* f1602c8: 00000000 */ nop /* f1602cc: 45020007 */ bc1fl .L0f1602ec /* f1602d0: c6a00004 */ lwc1 $f0,0x4($s5) /* f1602d4: c6ea0000 */ lwc1 $f10,0x0($s7) /* f1602d8: 460a403c */ c.lt.s $f8,$f10 /* f1602dc: 00000000 */ nop /* f1602e0: 4503002e */ bc1tl .L0f16039c /* f1602e4: afa000e4 */ sw $zero,0xe4($sp) /* f1602e8: c6a00004 */ lwc1 $f0,0x4($s5) .L0f1602ec: /* f1602ec: c7b000a0 */ lwc1 $f16,0xa0($sp) /* f1602f0: 4610003c */ c.lt.s $f0,$f16 /* f1602f4: 00000000 */ nop /* f1602f8: 45020007 */ bc1fl .L0f160318 /* f1602fc: c7a60094 */ lwc1 $f6,0x94($sp) /* f160300: c6f20004 */ lwc1 $f18,0x4($s7) /* f160304: 4610903c */ c.lt.s $f18,$f16 /* f160308: 00000000 */ nop /* f16030c: 45030023 */ bc1tl .L0f16039c /* f160310: afa000e4 */ sw $zero,0xe4($sp) /* f160314: c7a60094 */ lwc1 $f6,0x94($sp) .L0f160318: /* f160318: 4600303c */ c.lt.s $f6,$f0 /* f16031c: 00000000 */ nop /* f160320: 45020007 */ bc1fl .L0f160340 /* f160324: c6a00008 */ lwc1 $f0,0x8($s5) /* f160328: c6e40004 */ lwc1 $f4,0x4($s7) /* f16032c: 4604303c */ c.lt.s $f6,$f4 /* f160330: 00000000 */ nop /* f160334: 45030019 */ bc1tl .L0f16039c /* f160338: afa000e4 */ sw $zero,0xe4($sp) /* f16033c: c6a00008 */ lwc1 $f0,0x8($s5) .L0f160340: /* f160340: c7a800a4 */ lwc1 $f8,0xa4($sp) /* f160344: 4608003c */ c.lt.s $f0,$f8 /* f160348: 00000000 */ nop /* f16034c: 45020007 */ bc1fl .L0f16036c /* f160350: c7b20098 */ lwc1 $f18,0x98($sp) /* f160354: c6ea0008 */ lwc1 $f10,0x8($s7) /* f160358: 4608503c */ c.lt.s $f10,$f8 /* f16035c: 00000000 */ nop /* f160360: 4503000e */ bc1tl .L0f16039c /* f160364: afa000e4 */ sw $zero,0xe4($sp) /* f160368: c7b20098 */ lwc1 $f18,0x98($sp) .L0f16036c: /* f16036c: 8fa500fc */ lw $a1,0xfc($sp) /* f160370: 27a6009c */ addiu $a2,$sp,0x9c /* f160374: 4600903c */ c.lt.s $f18,$f0 /* f160378: 00000000 */ nop /* f16037c: 4502000c */ bc1fl .L0f1603b0 /* f160380: 02a02025 */ or $a0,$s5,$zero /* f160384: c6f00008 */ lwc1 $f16,0x8($s7) /* f160388: 4610903c */ c.lt.s $f18,$f16 /* f16038c: 00000000 */ nop /* f160390: 45020007 */ bc1fl .L0f1603b0 /* f160394: 02a02025 */ or $a0,$s5,$zero /* f160398: afa000e4 */ sw $zero,0xe4($sp) .L0f16039c: /* f16039c: 2406ffb1 */ addiu $a2,$zero,-79 /* f1603a0: 2405ffbf */ addiu $a1,$zero,-65 /* f1603a4: 10000193 */ b .L0f1609f4 /* f1603a8: 2403000a */ addiu $v1,$zero,0xa /* f1603ac: 02a02025 */ or $a0,$s5,$zero .L0f1603b0: /* f1603b0: 27a70090 */ addiu $a3,$sp,0x90 /* f1603b4: 0fc57cac */ jal bgTestLineIntersectsBbox /* f1603b8: a7a800ee */ sh $t0,0xee($sp) /* f1603bc: 87a800ee */ lh $t0,0xee($sp) /* f1603c0: afa200e4 */ sw $v0,0xe4($sp) /* f1603c4: 2406ffb1 */ addiu $a2,$zero,-79 /* f1603c8: 2405ffbf */ addiu $a1,$zero,-65 /* f1603cc: 10000189 */ b .L0f1609f4 /* f1603d0: 2403000a */ addiu $v1,$zero,0xa .L0f1603d4: /* f1603d4: 17200005 */ bnez $t9,.L0f1603ec /* f1603d8: 00000000 */ nop /* f1603dc: 8fac0100 */ lw $t4,0x100($sp) /* f1603e0: 258d0008 */ addiu $t5,$t4,0x8 /* f1603e4: 1000ff18 */ b .L0f160048 /* f1603e8: afad0100 */ sw $t5,0x100($sp) .L0f1603ec: /* f1603ec: 10a20007 */ beq $a1,$v0,.L0f16040c /* f1603f0: 00000000 */ nop /* f1603f4: 10c20005 */ beq $a2,$v0,.L0f16040c /* f1603f8: 00000000 */ nop /* f1603fc: 8fae0100 */ lw $t6,0x100($sp) /* f160400: 25cf0008 */ addiu $t7,$t6,0x8 /* f160404: 1000ff10 */ b .L0f160048 /* f160408: afaf0100 */ sw $t7,0x100($sp) .L0f16040c: /* f16040c: 14a2002d */ bne $a1,$v0,.L0f1604c4 /* f160410: 00000000 */ nop /* f160414: 8fa20100 */ lw $v0,0x100($sp) /* f160418: 00009825 */ or $s3,$zero,$zero /* f16041c: 00004025 */ or $t0,$zero,$zero /* f160420: 90580005 */ lbu $t8,0x5($v0) /* f160424: 0303001a */ div $zero,$t8,$v1 /* f160428: 00004812 */ mflo $t1 /* f16042c: afa9006c */ sw $t1,0x6c($sp) /* f160430: 904a0006 */ lbu $t2,0x6($v0) /* f160434: 14600002 */ bnez $v1,.L0f160440 /* f160438: 00000000 */ nop /* f16043c: 0007000d */ break 0x7 .L0f160440: /* f160440: 2401ffff */ addiu $at,$zero,-1 /* f160444: 14610004 */ bne $v1,$at,.L0f160458 /* f160448: 3c018000 */ lui $at,0x8000 /* f16044c: 17010002 */ bne $t8,$at,.L0f160458 /* f160450: 00000000 */ nop /* f160454: 0006000d */ break 0x6 .L0f160458: /* f160458: 0143001a */ div $zero,$t2,$v1 /* f16045c: 00005812 */ mflo $t3 /* f160460: afab0070 */ sw $t3,0x70($sp) /* f160464: 90590007 */ lbu $t9,0x7($v0) /* f160468: 14600002 */ bnez $v1,.L0f160474 /* f16046c: 00000000 */ nop /* f160470: 0007000d */ break 0x7 .L0f160474: /* f160474: 2401ffff */ addiu $at,$zero,-1 /* f160478: 14610004 */ bne $v1,$at,.L0f16048c /* f16047c: 3c018000 */ lui $at,0x8000 /* f160480: 15410002 */ bne $t2,$at,.L0f16048c /* f160484: 00000000 */ nop /* f160488: 0006000d */ break 0x6 .L0f16048c: /* f16048c: 0323001a */ div $zero,$t9,$v1 /* f160490: 00006012 */ mflo $t4 /* f160494: afac0074 */ sw $t4,0x74($sp) /* f160498: 14600002 */ bnez $v1,.L0f1604a4 /* f16049c: 00000000 */ nop /* f1604a0: 0007000d */ break 0x7 .L0f1604a4: /* f1604a4: 2401ffff */ addiu $at,$zero,-1 /* f1604a8: 14610004 */ bne $v1,$at,.L0f1604bc /* f1604ac: 3c018000 */ lui $at,0x8000 /* f1604b0: 17210002 */ bne $t9,$at,.L0f1604bc /* f1604b4: 00000000 */ nop /* f1604b8: 0006000d */ break 0x6 .L0f1604bc: /* f1604bc: 10000010 */ b .L0f160500 /* f1604c0: 00000000 */ nop .L0f1604c4: /* f1604c4: 14c2000e */ bne $a2,$v0,.L0f160500 /* f1604c8: 00000000 */ nop /* f1604cc: 8fad0100 */ lw $t5,0x100($sp) /* f1604d0: 24130003 */ addiu $s3,$zero,0x3 /* f1604d4: 24080001 */ addiu $t0,$zero,0x1 /* f1604d8: 8dae0004 */ lw $t6,0x4($t5) /* f1604dc: 01a0a025 */ or $s4,$t5,$zero /* f1604e0: 31cf000f */ andi $t7,$t6,0xf /* f1604e4: afaf006c */ sw $t7,0x6c($sp) /* f1604e8: 91b80007 */ lbu $t8,0x7($t5) /* f1604ec: 00184902 */ srl $t1,$t8,0x4 /* f1604f0: afa90070 */ sw $t1,0x70($sp) /* f1604f4: 8daa0000 */ lw $t2,0x0($t5) /* f1604f8: 314b000f */ andi $t3,$t2,0xf /* f1604fc: afab0074 */ sw $t3,0x74($sp) .L0f160500: /* f160500: 8fb9006c */ lw $t9,0x6c($sp) .L0f160504: /* f160504: 2403000a */ addiu $v1,$zero,0xa /* f160508: 2405ffbf */ addiu $a1,$zero,-65 /* f16050c: 17200009 */ bnez $t9,.L0f160534 /* f160510: 2406ffb1 */ addiu $a2,$zero,-79 /* f160514: 8fac0070 */ lw $t4,0x70($sp) /* f160518: 8fae0074 */ lw $t6,0x74($sp) /* f16051c: 55800006 */ bnezl $t4,.L0f160538 /* f160520: 8faf006c */ lw $t7,0x6c($sp) /* f160524: 55c00004 */ bnezl $t6,.L0f160538 /* f160528: 8faf006c */ lw $t7,0x6c($sp) /* f16052c: 10000132 */ b .L0f1609f8 /* f160530: 8fac0100 */ lw $t4,0x100($sp) .L0f160534: /* f160534: 8faf006c */ lw $t7,0x6c($sp) .L0f160538: /* f160538: 24060003 */ addiu $a2,$zero,0x3 /* f16053c: 8fad0070 */ lw $t5,0x70($sp) /* f160540: 01e60019 */ multu $t7,$a2 /* f160544: 3c05800a */ lui $a1,%hi(var800a6470) /* f160548: 24a56470 */ addiu $a1,$a1,%lo(var800a6470) /* f16054c: 8fb90074 */ lw $t9,0x74($sp) /* f160550: 0000c012 */ mflo $t8 /* f160554: 00184880 */ sll $t1,$t8,0x2 /* f160558: 01252021 */ addu $a0,$t1,$a1 /* f16055c: 01a60019 */ multu $t5,$a2 /* f160560: c4860000 */ lwc1 $f6,0x0($a0) /* f160564: 00808025 */ or $s0,$a0,$zero /* f160568: e7a6009c */ swc1 $f6,0x9c($sp) /* f16056c: c4840000 */ lwc1 $f4,0x0($a0) /* f160570: c7a8009c */ lwc1 $f8,0x9c($sp) /* f160574: e7a40090 */ swc1 $f4,0x90($sp) /* f160578: 00005012 */ mflo $t2 /* f16057c: 000a5880 */ sll $t3,$t2,0x2 /* f160580: 01651021 */ addu $v0,$t3,$a1 /* f160584: 03260019 */ multu $t9,$a2 /* f160588: c44a0000 */ lwc1 $f10,0x0($v0) /* f16058c: 00408825 */ or $s1,$v0,$zero /* f160590: 4608503c */ c.lt.s $f10,$f8 /* f160594: 00006012 */ mflo $t4 /* f160598: 000c7080 */ sll $t6,$t4,0x2 /* f16059c: 01c51821 */ addu $v1,$t6,$a1 /* f1605a0: 45000003 */ bc1f .L0f1605b0 /* f1605a4: 0060f025 */ or $s8,$v1,$zero /* f1605a8: c4520000 */ lwc1 $f18,0x0($v0) /* f1605ac: e7b2009c */ swc1 $f18,0x9c($sp) .L0f1605b0: /* f1605b0: c4400000 */ lwc1 $f0,0x0($v0) /* f1605b4: c7b00090 */ lwc1 $f16,0x90($sp) /* f1605b8: 4600803c */ c.lt.s $f16,$f0 /* f1605bc: 00000000 */ nop /* f1605c0: 45020003 */ bc1fl .L0f1605d0 /* f1605c4: c4600000 */ lwc1 $f0,0x0($v1) /* f1605c8: e7a00090 */ swc1 $f0,0x90($sp) /* f1605cc: c4600000 */ lwc1 $f0,0x0($v1) .L0f1605d0: /* f1605d0: c7a6009c */ lwc1 $f6,0x9c($sp) /* f1605d4: 4606003c */ c.lt.s $f0,$f6 /* f1605d8: 00000000 */ nop /* f1605dc: 45020004 */ bc1fl .L0f1605f0 /* f1605e0: c7a40090 */ lwc1 $f4,0x90($sp) /* f1605e4: e7a0009c */ swc1 $f0,0x9c($sp) /* f1605e8: c4600000 */ lwc1 $f0,0x0($v1) /* f1605ec: c7a40090 */ lwc1 $f4,0x90($sp) .L0f1605f0: /* f1605f0: 4600203c */ c.lt.s $f4,$f0 /* f1605f4: 00000000 */ nop /* f1605f8: 45020003 */ bc1fl .L0f160608 /* f1605fc: c6a00000 */ lwc1 $f0,0x0($s5) /* f160600: e7a00090 */ swc1 $f0,0x90($sp) /* f160604: c6a00000 */ lwc1 $f0,0x0($s5) .L0f160608: /* f160608: c7aa009c */ lwc1 $f10,0x9c($sp) /* f16060c: 460a003c */ c.lt.s $f0,$f10 /* f160610: 00000000 */ nop /* f160614: 45020007 */ bc1fl .L0f160634 /* f160618: c7b20090 */ lwc1 $f18,0x90($sp) /* f16061c: c6e80000 */ lwc1 $f8,0x0($s7) /* f160620: 460a403c */ c.lt.s $f8,$f10 /* f160624: 00000000 */ nop /* f160628: 450300c5 */ bc1tl .L0f160940 /* f16062c: 2673ffff */ addiu $s3,$s3,-1 /* f160630: c7b20090 */ lwc1 $f18,0x90($sp) .L0f160634: /* f160634: 4600903c */ c.lt.s $f18,$f0 /* f160638: 00000000 */ nop /* f16063c: 45020007 */ bc1fl .L0f16065c /* f160640: c4860008 */ lwc1 $f6,0x8($a0) /* f160644: c6f00000 */ lwc1 $f16,0x0($s7) /* f160648: 4610903c */ c.lt.s $f18,$f16 /* f16064c: 00000000 */ nop /* f160650: 450300bb */ bc1tl .L0f160940 /* f160654: 2673ffff */ addiu $s3,$s3,-1 /* f160658: c4860008 */ lwc1 $f6,0x8($a0) .L0f16065c: /* f16065c: e7a600a4 */ swc1 $f6,0xa4($sp) /* f160660: c4840008 */ lwc1 $f4,0x8($a0) /* f160664: c7a800a4 */ lwc1 $f8,0xa4($sp) /* f160668: e7a40098 */ swc1 $f4,0x98($sp) /* f16066c: c4400008 */ lwc1 $f0,0x8($v0) /* f160670: 4608003c */ c.lt.s $f0,$f8 /* f160674: 00000000 */ nop /* f160678: 45020004 */ bc1fl .L0f16068c /* f16067c: c7aa0098 */ lwc1 $f10,0x98($sp) /* f160680: e7a000a4 */ swc1 $f0,0xa4($sp) /* f160684: c4400008 */ lwc1 $f0,0x8($v0) /* f160688: c7aa0098 */ lwc1 $f10,0x98($sp) .L0f16068c: /* f16068c: 4600503c */ c.lt.s $f10,$f0 /* f160690: 00000000 */ nop /* f160694: 45020003 */ bc1fl .L0f1606a4 /* f160698: c4600008 */ lwc1 $f0,0x8($v1) /* f16069c: e7a00098 */ swc1 $f0,0x98($sp) /* f1606a0: c4600008 */ lwc1 $f0,0x8($v1) .L0f1606a4: /* f1606a4: c7b200a4 */ lwc1 $f18,0xa4($sp) /* f1606a8: 4612003c */ c.lt.s $f0,$f18 /* f1606ac: 00000000 */ nop /* f1606b0: 45020004 */ bc1fl .L0f1606c4 /* f1606b4: c7b00098 */ lwc1 $f16,0x98($sp) /* f1606b8: e7a000a4 */ swc1 $f0,0xa4($sp) /* f1606bc: c4600008 */ lwc1 $f0,0x8($v1) /* f1606c0: c7b00098 */ lwc1 $f16,0x98($sp) .L0f1606c4: /* f1606c4: 4600803c */ c.lt.s $f16,$f0 /* f1606c8: 00000000 */ nop /* f1606cc: 45020003 */ bc1fl .L0f1606dc /* f1606d0: c6a00008 */ lwc1 $f0,0x8($s5) /* f1606d4: e7a00098 */ swc1 $f0,0x98($sp) /* f1606d8: c6a00008 */ lwc1 $f0,0x8($s5) .L0f1606dc: /* f1606dc: c7a600a4 */ lwc1 $f6,0xa4($sp) /* f1606e0: 4606003c */ c.lt.s $f0,$f6 /* f1606e4: 00000000 */ nop /* f1606e8: 45020007 */ bc1fl .L0f160708 /* f1606ec: c7a80098 */ lwc1 $f8,0x98($sp) /* f1606f0: c6e40008 */ lwc1 $f4,0x8($s7) /* f1606f4: 4606203c */ c.lt.s $f4,$f6 /* f1606f8: 00000000 */ nop /* f1606fc: 45030090 */ bc1tl .L0f160940 /* f160700: 2673ffff */ addiu $s3,$s3,-1 /* f160704: c7a80098 */ lwc1 $f8,0x98($sp) .L0f160708: /* f160708: 4600403c */ c.lt.s $f8,$f0 /* f16070c: 00000000 */ nop /* f160710: 45020007 */ bc1fl .L0f160730 /* f160714: c4920004 */ lwc1 $f18,0x4($a0) /* f160718: c6ea0008 */ lwc1 $f10,0x8($s7) /* f16071c: 460a403c */ c.lt.s $f8,$f10 /* f160720: 00000000 */ nop /* f160724: 45030086 */ bc1tl .L0f160940 /* f160728: 2673ffff */ addiu $s3,$s3,-1 /* f16072c: c4920004 */ lwc1 $f18,0x4($a0) .L0f160730: /* f160730: e7b200a0 */ swc1 $f18,0xa0($sp) /* f160734: c4900004 */ lwc1 $f16,0x4($a0) /* f160738: c7a400a0 */ lwc1 $f4,0xa0($sp) /* f16073c: e7b00094 */ swc1 $f16,0x94($sp) /* f160740: c4400004 */ lwc1 $f0,0x4($v0) /* f160744: 4604003c */ c.lt.s $f0,$f4 /* f160748: 00000000 */ nop /* f16074c: 45020004 */ bc1fl .L0f160760 /* f160750: c7a60094 */ lwc1 $f6,0x94($sp) /* f160754: e7a000a0 */ swc1 $f0,0xa0($sp) /* f160758: c4400004 */ lwc1 $f0,0x4($v0) /* f16075c: c7a60094 */ lwc1 $f6,0x94($sp) .L0f160760: /* f160760: 4600303c */ c.lt.s $f6,$f0 /* f160764: 00000000 */ nop /* f160768: 45020003 */ bc1fl .L0f160778 /* f16076c: c4600004 */ lwc1 $f0,0x4($v1) /* f160770: e7a00094 */ swc1 $f0,0x94($sp) /* f160774: c4600004 */ lwc1 $f0,0x4($v1) .L0f160778: /* f160778: c7a800a0 */ lwc1 $f8,0xa0($sp) /* f16077c: 4608003c */ c.lt.s $f0,$f8 /* f160780: 00000000 */ nop /* f160784: 45020004 */ bc1fl .L0f160798 /* f160788: c7aa0094 */ lwc1 $f10,0x94($sp) /* f16078c: e7a000a0 */ swc1 $f0,0xa0($sp) /* f160790: c4600004 */ lwc1 $f0,0x4($v1) /* f160794: c7aa0094 */ lwc1 $f10,0x94($sp) .L0f160798: /* f160798: 4600503c */ c.lt.s $f10,$f0 /* f16079c: 00000000 */ nop /* f1607a0: 45020003 */ bc1fl .L0f1607b0 /* f1607a4: c6a00004 */ lwc1 $f0,0x4($s5) /* f1607a8: e7a00094 */ swc1 $f0,0x94($sp) /* f1607ac: c6a00004 */ lwc1 $f0,0x4($s5) .L0f1607b0: /* f1607b0: c7b200a0 */ lwc1 $f18,0xa0($sp) /* f1607b4: 4612003c */ c.lt.s $f0,$f18 /* f1607b8: 00000000 */ nop /* f1607bc: 45020007 */ bc1fl .L0f1607dc /* f1607c0: c7a40094 */ lwc1 $f4,0x94($sp) /* f1607c4: c6f00004 */ lwc1 $f16,0x4($s7) /* f1607c8: 4612803c */ c.lt.s $f16,$f18 /* f1607cc: 00000000 */ nop /* f1607d0: 4503005b */ bc1tl .L0f160940 /* f1607d4: 2673ffff */ addiu $s3,$s3,-1 /* f1607d8: c7a40094 */ lwc1 $f4,0x94($sp) .L0f1607dc: /* f1607dc: 8fa500fc */ lw $a1,0xfc($sp) /* f1607e0: 27a6009c */ addiu $a2,$sp,0x9c /* f1607e4: 4600203c */ c.lt.s $f4,$f0 /* f1607e8: 00000000 */ nop /* f1607ec: 45020007 */ bc1fl .L0f16080c /* f1607f0: 02a02025 */ or $a0,$s5,$zero /* f1607f4: c6e60004 */ lwc1 $f6,0x4($s7) /* f1607f8: 4606203c */ c.lt.s $f4,$f6 /* f1607fc: 00000000 */ nop /* f160800: 4503004f */ bc1tl .L0f160940 /* f160804: 2673ffff */ addiu $s3,$s3,-1 /* f160808: 02a02025 */ or $a0,$s5,$zero .L0f16080c: /* f16080c: 27a70090 */ addiu $a3,$sp,0x90 /* f160810: 0fc57cac */ jal bgTestLineIntersectsBbox /* f160814: a7a800ee */ sh $t0,0xee($sp) /* f160818: 10400048 */ beqz $v0,.L0f16093c /* f16081c: 87a800ee */ lh $t0,0xee($sp) /* f160820: 8faf00fc */ lw $t7,0xfc($sp) /* f160824: 27b80084 */ addiu $t8,$sp,0x84 /* f160828: 27a90078 */ addiu $t1,$sp,0x78 /* f16082c: afa90020 */ sw $t1,0x20($sp) /* f160830: afb8001c */ sw $t8,0x1c($sp) /* f160834: 02002025 */ or $a0,$s0,$zero /* f160838: 02202825 */ or $a1,$s1,$zero /* f16083c: 03c03025 */ or $a2,$s8,$zero /* f160840: 00003825 */ or $a3,$zero,$zero /* f160844: afb50010 */ sw $s5,0x10($sp) /* f160848: afb70014 */ sw $s7,0x14($sp) /* f16084c: a7a800ee */ sh $t0,0xee($sp) /* f160850: 0c00bd58 */ jal func0002f560 /* f160854: afaf0018 */ sw $t7,0x18($sp) /* f160858: 10400038 */ beqz $v0,.L0f16093c /* f16085c: 87a800ee */ lh $t0,0xee($sp) /* f160860: c7a80084 */ lwc1 $f8,0x84($sp) /* f160864: c6aa0000 */ lwc1 $f10,0x0($s5) /* f160868: c7b00088 */ lwc1 $f16,0x88($sp) /* f16086c: c6b20004 */ lwc1 $f18,0x4($s5) /* f160870: 460a4001 */ sub.s $f0,$f8,$f10 /* f160874: c6aa0008 */ lwc1 $f10,0x8($s5) /* f160878: c7a6008c */ lwc1 $f6,0x8c($sp) /* f16087c: 8fad010c */ lw $t5,0x10c($sp) /* f160880: 46000082 */ mul.s $f2,$f0,$f0 /* f160884: 46128001 */ sub.s $f0,$f16,$f18 /* f160888: c5b20000 */ lwc1 $f18,0x0($t5) /* f16088c: 46000102 */ mul.s $f4,$f0,$f0 /* f160890: 460a3001 */ sub.s $f0,$f6,$f10 /* f160894: 46000402 */ mul.s $f16,$f0,$f0 /* f160898: 46041080 */ add.s $f2,$f2,$f4 /* f16089c: 46101080 */ add.s $f2,$f2,$f16 /* f1608a0: 4612103c */ c.lt.s $f2,$f18 /* f1608a4: 00000000 */ nop /* f1608a8: 45020025 */ bc1fl .L0f160940 /* f1608ac: 2673ffff */ addiu $s3,$s3,-1 /* f1608b0: 240a0001 */ addiu $t2,$zero,0x1 /* f1608b4: afaa00cc */ sw $t2,0xcc($sp) /* f1608b8: e5a20000 */ swc1 $f2,0x0($t5) /* f1608bc: e6480000 */ swc1 $f8,0x0($s2) /* f1608c0: c7a40088 */ lwc1 $f4,0x88($sp) /* f1608c4: 2402000c */ addiu $v0,$zero,0xc /* f1608c8: e6440004 */ swc1 $f4,0x4($s2) /* f1608cc: c7a6008c */ lwc1 $f6,0x8c($sp) /* f1608d0: e6460008 */ swc1 $f6,0x8($s2) /* f1608d4: c7aa0078 */ lwc1 $f10,0x78($sp) /* f1608d8: e64a000c */ swc1 $f10,0xc($s2) /* f1608dc: c7b0007c */ lwc1 $f16,0x7c($sp) /* f1608e0: e6500010 */ swc1 $f16,0x10($s2) /* f1608e4: c7b20080 */ lwc1 $f18,0x80($sp) /* f1608e8: e6520014 */ swc1 $f18,0x14($s2) /* f1608ec: 8fab006c */ lw $t3,0x6c($sp) /* f1608f0: 01620019 */ multu $t3,$v0 /* f1608f4: 240bffff */ addiu $t3,$zero,-1 /* f1608f8: 0000c812 */ mflo $t9 /* f1608fc: 03366021 */ addu $t4,$t9,$s6 /* f160900: ae4c0018 */ sw $t4,0x18($s2) /* f160904: 8fae0070 */ lw $t6,0x70($sp) /* f160908: 01c20019 */ multu $t6,$v0 /* f16090c: 00007812 */ mflo $t7 /* f160910: 01f6c021 */ addu $t8,$t7,$s6 /* f160914: ae58001c */ sw $t8,0x1c($s2) /* f160918: 8fa90074 */ lw $t1,0x74($sp) /* f16091c: a64b002a */ sh $t3,0x2a($s2) /* f160920: 01220019 */ multu $t1,$v0 /* f160924: 00005012 */ mflo $t2 /* f160928: 01566821 */ addu $t5,$t2,$s6 /* f16092c: ae4d0020 */ sw $t5,0x20($s2) /* f160930: 8fb90100 */ lw $t9,0x100($sp) /* f160934: a6480028 */ sh $t0,0x28($s2) /* f160938: ae590024 */ sw $t9,0x24($s2) .L0f16093c: /* f16093c: 2673ffff */ addiu $s3,$s3,-1 .L0f160940: /* f160940: 24010002 */ addiu $at,$zero,0x2 /* f160944: 5661000d */ bnel $s3,$at,.L0f16097c /* f160948: 24010001 */ addiu $at,$zero,0x1 /* f16094c: 928c0006 */ lbu $t4,0x6($s4) /* f160950: 24080002 */ addiu $t0,$zero,0x2 /* f160954: 318e000f */ andi $t6,$t4,0xf /* f160958: afae006c */ sw $t6,0x6c($sp) /* f16095c: 968f0006 */ lhu $t7,0x6($s4) /* f160960: 000fc302 */ srl $t8,$t7,0xc /* f160964: afb80070 */ sw $t8,0x70($sp) /* f160968: 92890003 */ lbu $t1,0x3($s4) /* f16096c: 00095102 */ srl $t2,$t1,0x4 /* f160970: 1000001b */ b .L0f1609e0 /* f160974: afaa0074 */ sw $t2,0x74($sp) /* f160978: 24010001 */ addiu $at,$zero,0x1 .L0f16097c: /* f16097c: 1661000c */ bne $s3,$at,.L0f1609b0 /* f160980: 00000000 */ nop /* f160984: 968d0004 */ lhu $t5,0x4($s4) /* f160988: 24080003 */ addiu $t0,$zero,0x3 /* f16098c: 31ab000f */ andi $t3,$t5,0xf /* f160990: afab006c */ sw $t3,0x6c($sp) /* f160994: 92990005 */ lbu $t9,0x5($s4) /* f160998: 00196102 */ srl $t4,$t9,0x4 /* f16099c: afac0070 */ sw $t4,0x70($sp) /* f1609a0: 928e0002 */ lbu $t6,0x2($s4) /* f1609a4: 31cf000f */ andi $t7,$t6,0xf /* f1609a8: 1000000d */ b .L0f1609e0 /* f1609ac: afaf0074 */ sw $t7,0x74($sp) .L0f1609b0: /* f1609b0: 1660000b */ bnez $s3,.L0f1609e0 /* f1609b4: 00000000 */ nop /* f1609b8: 92980004 */ lbu $t8,0x4($s4) /* f1609bc: 24080001 */ addiu $t0,$zero,0x1 /* f1609c0: 3309000f */ andi $t1,$t8,0xf /* f1609c4: afa9006c */ sw $t1,0x6c($sp) /* f1609c8: 8e8a0004 */ lw $t2,0x4($s4) /* f1609cc: 000a6f02 */ srl $t5,$t2,0x1c /* f1609d0: afad0070 */ sw $t5,0x70($sp) /* f1609d4: 968b0002 */ lhu $t3,0x2($s4) /* f1609d8: 000bcb02 */ srl $t9,$t3,0xc /* f1609dc: afb90074 */ sw $t9,0x74($sp) .L0f1609e0: /* f1609e0: 0663fec8 */ bgezl $s3,.L0f160504 /* f1609e4: 8fb9006c */ lw $t9,0x6c($sp) /* f1609e8: 2406ffb1 */ addiu $a2,$zero,-79 /* f1609ec: 2405ffbf */ addiu $a1,$zero,-65 /* f1609f0: 2403000a */ addiu $v1,$zero,0xa .L0f1609f4: /* f1609f4: 8fac0100 */ lw $t4,0x100($sp) .L0f1609f8: /* f1609f8: 258e0008 */ addiu $t6,$t4,0x8 /* f1609fc: 1000fd92 */ b .L0f160048 /* f160a00: afae0100 */ sw $t6,0x100($sp) /* f160a04: 8fbf0054 */ lw $ra,0x54($sp) .L0f160a08: /* f160a08: 8fa200cc */ lw $v0,0xcc($sp) /* f160a0c: 8fb00030 */ lw $s0,0x30($sp) /* f160a10: 8fb10034 */ lw $s1,0x34($sp) /* f160a14: 8fb20038 */ lw $s2,0x38($sp) /* f160a18: 8fb3003c */ lw $s3,0x3c($sp) /* f160a1c: 8fb40040 */ lw $s4,0x40($sp) /* f160a20: 8fb50044 */ lw $s5,0x44($sp) /* f160a24: 8fb60048 */ lw $s6,0x48($sp) /* f160a28: 8fb7004c */ lw $s7,0x4c($sp) /* f160a2c: 8fbe0050 */ lw $s8,0x50($sp) /* f160a30: 03e00008 */ jr $ra /* f160a34: 27bd00f0 */ addiu $sp,$sp,0xf0 ); #else // Mismatch: Some moderate reordering, likely related to variable reuse. // Note that the branch instruction at 16052c can appear and disappear due to // changing other things in the function. bool bgTestHitOnChr(struct model *model, struct coord *arg1, struct coord *arg2, struct coord *arg3, Gfx *gdl, Gfx *gdl2, struct gfxvtx *vertices, f32 *sqdistptr, struct hitthing *hitthing) { s16 triref; // ee s32 trisremaining; // e8 bool intersectsbbox; // e4 s32 spdc; s32 spd8; bool hit; // cc struct gfxvtx *vtx; // c0 Mtxf *mtx; // a8 struct coord min; // 9c struct coord max; // 90 struct coord sp84; struct coord sp78; s32 points[3]; // 6c s32 v1; s32 numvertices; f32 *ptr; s32 i; struct coord *point1; struct coord *point2; struct coord *point3; Gfx *tri4gdl; spdc = 16; spd8 = 0; hit = false; while (true) { if (gdl->dma.cmd == G_ENDDL) { if (gdl2 != NULL) { gdl = gdl2; gdl2 = NULL; continue; } break; } else if (gdl->dma.cmd == G_MTX) { // 080 s32 mtxindex = (gdl->words.w1 & 0xffffff) / sizeof(Mtxf); mtx = &model->matrices[mtxindex]; } else if (gdl->dma.cmd == G_VTX) { // 0bc v1 = gdl->bytes[1] & 0xf; numvertices = ((u32)gdl->bytes[1] >> 4) + 1; vtx = (struct gfxvtx *)((u32)vertices + (gdl->words.w1 & 0xffffff)); if (v1 < spdc) { spdc = v1; } if (numvertices + v1 > spd8) { spd8 = numvertices + v1; } ptr = &var800a6470[v1 * 3]; while (numvertices > 0) { ptr[0] = vtx->x; ptr[1] = vtx->y; ptr[2] = vtx->z; mtx4TransformVecInPlace(mtx, (struct coord *) ptr); ptr += 3; vtx++; numvertices--; } ptr = &var800a6470[spdc]; min.x = ptr[0]; max.x = ptr[0]; min.y = ptr[1]; max.y = ptr[1]; min.z = ptr[2]; max.z = ptr[2]; ptr += 3; for (i = spdc; i < spd8; i++) { if (ptr[0] < min.x) { min.x = ptr[0]; } if (ptr[1] < min.y) { min.y = ptr[1]; } if (ptr[2] < min.z) { min.z = ptr[2]; } if (ptr[0] > max.x) { max.x = ptr[0]; } if (ptr[1] > max.y) { max.y = ptr[1]; } if (ptr[2] > max.z) { max.z = ptr[2]; } ptr += 3; } if ((arg1->x < min.x && arg2->x < min.x) || (arg1->x > max.x && arg2->x > max.x) || (arg1->y < min.y && arg2->y < min.y) || (arg1->y > max.y && arg2->y > max.y) || (arg1->z < min.z && arg2->z < min.z) || (arg1->z > max.z && arg2->z > max.z)) { intersectsbbox = false; } else { intersectsbbox = bgTestLineIntersectsBbox(arg1, arg3, &min, &max); } } else { // 3d4 if (!intersectsbbox) { gdl++; continue; } if ((gdl->dma.cmd != G_TRI1 && gdl->dma.cmd != G_TRI4)) { gdl++; continue; } if (gdl->dma.cmd == G_TRI1) { trisremaining = 0; triref = 0; points[0] = gdl->tri.tri.v[0] / 10; points[1] = gdl->tri.tri.v[1] / 10; points[2] = gdl->tri.tri.v[2] / 10; } else if (gdl->dma.cmd == G_TRI4) { tri4gdl = gdl; trisremaining = 3; triref = 1; points[0] = tri4gdl->tri4.x1; points[1] = tri4gdl->tri4.y1; points[2] = tri4gdl->tri4.z1; } do { if (points[0] == 0 && points[1] == 0 && points[2] == 0) { break; } point1 = (struct coord *) &var800a6470[points[0] * 3]; point2 = (struct coord *) &var800a6470[points[1] * 3]; point3 = (struct coord *) &var800a6470[points[2] * 3]; min.x = point1->x; max.x = point1->x; if (point2->x < min.x) { min.x = point2->x; } if (point2->x > max.x) { max.x = point2->x; } if (point3->x < min.x) { min.x = point3->x; } if (point3->x > max.x) { max.x = point3->x; } if (!(arg1->x < min.x && arg2->x < min.x) && !(arg1->x > max.x && arg2->x > max.x)) { min.z = point1->z; max.z = point1->z; if (point2->z < min.z) { min.z = point2->z; } if (point2->z > max.z) { max.z = point2->z; } if (point3->z < min.z) { min.z = point3->z; } if (point3->z > max.z) { max.z = point3->z; } if (!(arg1->z < min.z && arg2->z < min.z) && !(arg1->z > max.z && arg2->z > max.z)) { min.y = point1->y; max.y = point1->y; if (point2->y < min.y) { min.y = point2->y; } if (point2->y > max.y) { max.y = point2->y; } if (point3->y < min.y) { min.y = point3->y; } if (point3->y > max.y) { max.y = point3->y; } if (!(arg1->y < min.y && arg2->y < min.y) && !(arg1->y > max.y && arg2->y > max.y)) { if (bgTestLineIntersectsBbox(arg1, arg3, &min, &max) && func0002f560(point1, point2, point3, 0, arg1, arg2, arg3, &sp84, &sp78)) { f32 tmp; f32 sqdist; tmp = sp84.x - arg1->x; sqdist = tmp * tmp; tmp = sp84.y - arg1->y; sqdist += tmp * tmp; tmp = sp84.z - arg1->z; sqdist += tmp * tmp; if (sqdist < *sqdistptr) { hit = true; *sqdistptr = sqdist; hitthing->unk00.x = sp84.x; hitthing->unk00.y = sp84.y; hitthing->unk00.z = sp84.z; hitthing->unk0c.x = sp78.x; hitthing->unk0c.y = sp78.y; hitthing->unk0c.z = sp78.z; hitthing->unk18 = &vtx[points[0]]; hitthing->unk1c = &vtx[points[1]]; hitthing->unk20 = &vtx[points[2]]; hitthing->texturenum = -1; hitthing->unk28 = triref; hitthing->tricmd = gdl; } } } } } trisremaining--; if (1); if (1); if (1); if (trisremaining == 2) { points[0] = tri4gdl->tri4.x2; points[1] = tri4gdl->tri4.y2; points[2] = tri4gdl->tri4.z2; triref = 2; } else if (trisremaining == 1) { points[0] = tri4gdl->tri4.x3; points[1] = tri4gdl->tri4.y3; points[2] = tri4gdl->tri4.z3; triref = 3; } else if (trisremaining == 0) { points[0] = tri4gdl->tri4.x4; points[1] = tri4gdl->tri4.y4; points[2] = tri4gdl->tri4.z4; triref = 1; } } while (trisremaining >= 0); } gdl++; } return hit; } #endif bool bgTestHitInVtxBatch(struct coord *arg0, struct coord *arg1, struct coord *arg2, struct vtxbatch *batch, s32 roomnum, struct hitthing *hitthing) { s16 stack; s16 triref; s32 trisremaining; Gfx *gdl = batch->gdl; bool hit; s32 points[3]; s32 numvertices; f32 sqdist; f32 lowestsqdist; s32 texturenum; s32 index; struct coord *point1; struct coord *point2; struct coord *point3; struct coord spb0; struct coord spa4; struct coord min; struct coord max; struct gfxvtx *vtx; f32 *ptr; Gfx *iter; Gfx *tmpgdl; Gfx *tri4gdl; vtx = roomFindVerticesForGdl(roomnum, gdl); iter = &gdl[batch->gbicmdindex]; vtx = (struct gfxvtx *)((iter->words.w1 & 0xffffff) + (s32)vtx); numvertices = (((u32)iter->bytes[1] >> 4) & 0xf) + 1; ptr = var800a6470; while (numvertices > 0) { ptr[0] = g_BgRooms[roomnum].pos.x + vtx->x; ptr[1] = g_BgRooms[roomnum].pos.y + vtx->y; ptr[2] = g_BgRooms[roomnum].pos.z + vtx->z; ptr += 3; vtx++; numvertices--; } lowestsqdist = MAXFLOAT; hit = false; iter++; while (iter->dma.cmd != G_VTX && iter->dma.cmd != G_ENDDL) { if (iter->dma.cmd != G_TRI1 && iter->dma.cmd != G_TRI4) { iter++; continue; } if (iter->dma.cmd == G_TRI1) { trisremaining = 0; triref = 0; points[0] = iter->tri.tri.v[0] / 10; points[1] = iter->tri.tri.v[1] / 10; points[2] = iter->tri.tri.v[2] / 10; } else if (iter->dma.cmd == G_TRI4) { tri4gdl = iter; trisremaining = 3; triref = 1; points[0] = tri4gdl->tri4.x1; points[1] = tri4gdl->tri4.y1; points[2] = tri4gdl->tri4.z1; } do { if (points[0] == 0 && points[1] == 0 && points[2] == 0) { break; } point1 = (struct coord *) (var800a6470 + points[0] * 3); point2 = (struct coord *) (var800a6470 + points[1] * 3); point3 = (struct coord *) (var800a6470 + points[2] * 3); min.x = point1->x; if (point2->x < min.x) { min.x = point2->x; } if (point3->x < min.x) { min.x = point3->x; } if (!(arg0->x < min.x && arg1->x < min.x)) { max.x = point1->x; if (point2->x > max.x) { max.x = point2->x; } if (point3->x > max.x) { max.x = point3->x; } if (!(arg0->x > max.x && arg1->x > max.x)) { min.z = point1->z; if (point2->z < min.z) { min.z = point2->z; } if (point3->z < min.z) { min.z = point3->z; } if (!(arg0->z < min.z && arg1->z < min.z)) { max.z = point1->z; if (point2->z > max.z) { max.z = point2->z; } if (point3->z > max.z) { max.z = point3->z; } if (!(arg0->z > max.z && arg1->z > max.z)) { min.y = point1->y; if (point2->y < min.y) { min.y = point2->y; } if (point3->y < min.y) { min.y = point3->y; } if (!(arg0->y < min.y && arg1->y < min.y)) { max.y = point1->y; if (point2->y > max.y) { max.y = point2->y; } if (point3->y > max.y) { max.y = point3->y; } if (!(arg0->y > max.y && arg1->y > max.y)) { if (bgTestLineIntersectsBbox(arg0, arg2, &min, &max) && func0002f560(point1, point2, point3, 0, arg0, arg1, arg2, &spb0, &spa4)) { f32 tmp; tmp = spb0.x - arg0->x; sqdist = tmp * tmp; tmp = spb0.y - arg0->y; sqdist += tmp * tmp; tmp = spb0.z - arg0->z; sqdist += tmp * tmp; if (sqdist < lowestsqdist) { hit = true; tmpgdl = iter; while (tmpgdl->bytes[0] != G_SETTIMG && tmpgdl > gdl) { tmpgdl--; } if (tmpgdl == gdl || (tmpgdl->words.w1 & 0x0f000000) == 0x0f000000 || (tmpgdl->words.w1 & 0x05000000) == 0x05000000) { texturenum = -1; } else { s32 tmp = tmpgdl->words.w1 - 8; texturenum = *(s16 *) PHYS_TO_K0(tmp); } if (batch->type == VTXBATCHTYPE_XLU && g_Textures[texturenum].surfacetype == SURFACETYPE_DEFAULT) { hit = false; } if (hit) { lowestsqdist = sqdist; hitthing->unk00.x = spb0.x; hitthing->unk00.y = spb0.y; hitthing->unk00.z = spb0.z; hitthing->unk0c.x = spa4.x; hitthing->unk0c.y = spa4.y; hitthing->unk0c.z = spa4.z; hitthing->unk18 = &vtx[points[0]]; hitthing->unk1c = &vtx[points[1]]; hitthing->unk20 = &vtx[points[2]]; hitthing->texturenum = texturenum; hitthing->tricmd = iter; hitthing->unk28 = triref; hitthing->unk2c = batch->type; } } } } } } } } } trisremaining--; if (1); if (1); if (1); if (trisremaining == 2) { points[0] = tri4gdl->tri4.x2; points[1] = tri4gdl->tri4.y2; points[2] = tri4gdl->tri4.z2; triref = 2; } else if (trisremaining == 1) { points[0] = tri4gdl->tri4.x3; points[1] = tri4gdl->tri4.y3; points[2] = tri4gdl->tri4.z3; triref = 3; } else if (trisremaining == 0) { points[0] = tri4gdl->tri4.x4; points[1] = tri4gdl->tri4.y4; points[2] = tri4gdl->tri4.z4; triref = 1; } } while (trisremaining >= 0); iter++; } return hit; } s32 bg0f1612e4(struct coord *bbmin, struct coord *bbmax, struct coord *arg2, struct coord *arg3, struct coord *arg4, struct coord *arg5) { s32 i; u8 bail = true; s8 sp48[3]; s32 bestindex; f32 sp38[3]; f32 sp2c[3]; for (i = 0; i < 3; i++) { if (arg2->f[i] < bbmin->f[i]) { sp48[i] = 1; sp38[i] = bbmin->f[i]; bail = false; } else if (bbmax->f[i] < arg2->f[i]) { sp48[i] = 0; sp38[i] = bbmax->f[i]; bail = false; } else { sp48[i] = 2; sp38[i] = 0.0f; } } if (bail) { return -1; } for (i = 0; i < 3; i++) { if (sp48[i] != 2 && arg3->f[i] != 0.0f) { sp2c[i] = (sp38[i] - arg2->f[i]) * arg4->f[i]; } else { sp2c[i] = -1.0f; } } bestindex = 0; for (i = 1; i < 3; i++) { if (sp2c[i] > sp2c[bestindex]) { bestindex = i; } } if (sp2c[bestindex] < 0.0f) { return 0; } for (i = 0; i < 3; i++) { if (bestindex != i) { arg5->f[i] = arg2->f[i] + sp2c[bestindex] * arg3->f[i]; if (arg5->f[i] < bbmin->f[i] || arg5->f[i] > bbmax->f[i]) { return 0; } } else { arg5->f[i] = sp38[i]; } } return 1; } /** * Figure out which piece of BG geometry is hit in the given room based on a * line intersection from frompos to topos. Populate the hitthing struct with * the details. Props are not considered. Return true if a hit occurred. * * This is used not only for shots, but blood splatters and explosion scorch * marks too. * * Room vertices are already grouped into batches, where each batch has a * precomputed bounding box. */ bool bgTestHitInRoom(struct coord *frompos, struct coord *topos, s32 roomnum, struct hitthing *hitthing) { s32 i; s32 count; f32 f20; s32 a0; s32 numbatches; s32 j; f32 f0; f32 spc8; f32 f2; struct coord spb8; struct coord spac; struct coord spa0; struct coord sp94; struct vtxbatch *batch; struct hitthing sp60; s32 tmpindex; count = 0; spb8.x = frompos->x; spb8.y = frompos->y; spb8.z = frompos->z; spac.x = topos->x; spac.y = topos->y; spac.z = topos->z; spa0.x = spac.x - spb8.x; spa0.y = spac.y - spb8.y; spa0.z = spac.z - spb8.z; sp94.x = 1.0f / spa0.x; sp94.y = 1.0f / spa0.y; sp94.z = 1.0f / spa0.z; if (roomnum < 0 || roomnum >= g_Vars.roomcount) { return false; } batch = g_Rooms[roomnum].vtxbatches; if (batch == NULL) { return false; } numbatches = g_Rooms[roomnum].numvtxbatches; for (i = 0; i < numbatches; batch++, i++) { j = bg0f1612e4(&batch->bbmin, &batch->bbmax, &spb8, &spa0, &sp94, &hitthing->unk00); if (j == 0) { continue; } if (j == 1) { f0 = spb8.x - hitthing->unk00.x; f20 = f0 * f0; f0 = spb8.y - hitthing->unk00.y; f20 += f0 * f0; f0 = spb8.z - hitthing->unk00.z; f20 += f0 * f0; } else { f20 = -1.0f; } if (count < ARRAYCOUNT(var800a6538)) { a0 = i; for (j = 0; j < count; j++) { f2 = var800a6538[j].unk04; if (f2 > f20) { tmpindex = var800a6538[j].vtxbatchindex; var800a6538[j].vtxbatchindex = a0; a0 = tmpindex; var800a6538[j].unk04 = f20; f20 = f2; } } var800a6538[j].vtxbatchindex = a0; var800a6538[j].unk04 = f20; count++; } else { count = 0; for (j = 0; j < ARRAYCOUNT(var800a6538); j++) { if (bgTestHitInVtxBatch(&spb8, &spac, &spa0, &g_Rooms[roomnum].vtxbatches[var800a6538[j].vtxbatchindex], roomnum, hitthing)) { f0 = spb8.x - hitthing->unk00.x; f2 = f0 * f0; f0 = spb8.y - hitthing->unk00.y; f2 += f0 * f0; f0 = spb8.z - hitthing->unk00.z; f2 += f0 * f0; if (count == 0) { var800a6538[0].vtxbatchindex = var800a6538[j].vtxbatchindex; var800a6538[0].unk04 = f2; count = 1; } else if (f2 < var800a6538[0].unk04) { var800a6538[0].vtxbatchindex = var800a6538[j].vtxbatchindex; var800a6538[0].unk04 = f2; count = 1; } } } if (count != 0) { if (f20 < var800a6538[0].unk04) { var800a6538[1].unk04 = var800a6538[0].unk04; var800a6538[0].unk04 = f20; var800a6538[1].vtxbatchindex = var800a6538[0].vtxbatchindex; var800a6538[0].vtxbatchindex = i; } else { var800a6538[1].vtxbatchindex = i; var800a6538[1].unk04 = f20; } count = 2; } else { var800a6538[0].vtxbatchindex = i; var800a6538[0].unk04 = f20; count = 1; } } } if (count == 0) { return false; } batch = g_Rooms[roomnum].vtxbatches; for (i = 0; i < count; i++) { if (bgTestHitInVtxBatch(&spb8, &spac, &spa0, &batch[var800a6538[i].vtxbatchindex], roomnum, hitthing)) { i++; if (i < count) { f0 = spb8.x - hitthing->unk00.x; spc8 = f0 * f0; f0 = spb8.y - hitthing->unk00.y; spc8 += f0 * f0; f0 = spb8.z - hitthing->unk00.z; spc8 += f0 * f0; for (; i < count; i++) { if (var800a6538[i].unk04 <= spc8) { if (bgTestHitInVtxBatch(&spb8, &spac, &spa0, &batch[var800a6538[i].vtxbatchindex], roomnum, &sp60)) { f0 = spb8.f[0] - sp60.unk00.f[0]; f20 = f0 * f0; f0 = spb8.f[1] - sp60.unk00.f[1]; f20 += f0 * f0; f0 = spb8.f[2] - sp60.unk00.f[2]; f20 += f0 * f0; if (f20 < spc8) { hitthing->unk00.x = sp60.unk00.x; hitthing->unk00.y = sp60.unk00.y; hitthing->unk00.z = sp60.unk00.z; hitthing->unk0c.x = sp60.unk0c.x; hitthing->unk0c.y = sp60.unk0c.y; hitthing->unk0c.z = sp60.unk0c.z; hitthing->unk18 = sp60.unk18; hitthing->unk1c = sp60.unk1c; hitthing->unk20 = sp60.unk20; hitthing->texturenum = sp60.texturenum; hitthing->tricmd = sp60.tricmd; hitthing->unk28 = sp60.unk28; hitthing->unk2c = sp60.unk2c; spc8 = f20; } } } } } return true; } } return false; } bool roomIsLoaded(s32 room) { return g_Rooms[room].loaded240; } bool roomContainsCoord(struct coord *pos, s16 roomnum) { struct coord copy; copy.x = pos->x; copy.y = pos->y; copy.z = pos->z; return copy.f[0] >= g_Rooms[roomnum].bbmin[0] && copy.f[0] <= g_Rooms[roomnum].bbmax[0] && copy.f[2] >= g_Rooms[roomnum].bbmin[2] && copy.f[2] <= g_Rooms[roomnum].bbmax[2] && copy.f[1] >= g_Rooms[roomnum].bbmin[1] && copy.f[1] <= g_Rooms[roomnum].bbmax[1]; } bool func0f161c08(struct coord *arg0, s16 roomnum) { s32 i; for (i = 0; i < g_Rooms[roomnum].numportals; i++) { s32 portalnum = g_RoomPortals[g_Rooms[roomnum].roomportallistoffset + i]; struct var800a4ccc *thing = &var800a4ccc[portalnum]; f32 value = thing->coord.f[0] * arg0->f[0] + thing->coord.f[1] * arg0->f[1] + thing->coord.f[2] * arg0->f[2]; if (value < thing->min) { if (roomnum != g_BgPortals[portalnum].roomnum1) { return false; } } else if (value > thing->max) { if (roomnum != g_BgPortals[portalnum].roomnum2) { return false; } } } return true; } bool func0f161d30(struct coord *arg0, s16 roomnum) { s32 t5; struct coord *next; s32 t4; s32 portalnum; struct var800a4ccc *s2; s32 j; f32 f0; struct portalvertices *pvertices; struct coord sp74; struct coord sp68; struct coord sp5c; f32 sp58[1]; struct coord sp4c; struct coord *cur; f32 f18; s32 i; f32 sum; sp74.f[0] = g_Rooms[roomnum].centre.f[0]; sp74.f[1] = g_Rooms[roomnum].centre.f[1]; sp74.f[2] = g_Rooms[roomnum].centre.f[2]; for (i = 0; i < g_Rooms[roomnum].numportals; i++) { portalnum = g_RoomPortals[g_Rooms[roomnum].roomportallistoffset + i]; pvertices = (struct portalvertices *)((u8 *) g_BgPortals + g_BgPortals[portalnum].verticesoffset); s2 = &var800a4ccc[portalnum]; f0 = arg0->f[0] * s2->coord.f[0] + arg0->f[1] * s2->coord.f[1] + arg0->f[2] * s2->coord.f[2]; f18 = sp74.f[0] * s2->coord.f[0] + sp74.f[1] * s2->coord.f[1] + sp74.f[2] * s2->coord.f[2]; if (f0 < s2->min) { if (f18 < s2->min) { continue; } } else { if (f0 > s2->max && f18 > s2->max) { continue; } } sp68.f[0] = sp74.f[0] - arg0->f[0]; sp68.f[1] = sp74.f[1] - arg0->f[1]; sp68.f[2] = sp74.f[2] - arg0->f[2]; t4 = 0; t5 = true; cur = &pvertices->vertices[0]; next = &pvertices->vertices[1]; for (j = 0; j < pvertices->count; j++) { if (j + 1 == pvertices->count) { next = &pvertices->vertices[0]; } sp5c.f[0] = next->f[0] - cur->f[0]; sp5c.f[1] = next->f[1] - cur->f[1]; sp5c.f[2] = next->f[2] - cur->f[2]; sp4c.f[0] = sp5c.f[1] * sp68.f[2] - sp5c.f[2] * sp68.f[1]; sp4c.f[1] = sp5c.f[2] * sp68.f[0] - sp5c.f[0] * sp68.f[2]; sp4c.f[2] = sp5c.f[0] * sp68.f[1] - sp5c.f[1] * sp68.f[0]; sum = sp4c.f[0] * sp4c.f[0] + sp4c.f[1] * sp4c.f[1] + sp4c.f[2] * sp4c.f[2]; if (sum == 0.0f) { t5 = false; break; } sp58[0] = sp4c.f[0] * cur->f[0] + sp4c.f[1] * cur->f[1] + sp4c.f[2] * cur->f[2]; sum = sp4c.f[0] * arg0->f[0] + sp4c.f[1] * arg0->f[1] + sp4c.f[2] * arg0->f[2]; if (sum < sp58[0]) { if (t4 == 2) { t5 = false; break; } t4 = 1; } else if (t4 == 1) { t5 = false; break; } else { t4 = 2; } cur++; next++; } if (t5) { if (f0 < s2->min) { if (roomnum == g_BgPortals[portalnum].roomnum2) { return false; } } else if (f0 > s2->max) { if (roomnum == g_BgPortals[portalnum].roomnum1) { return false; } } } } return true; } bool func0f162128(struct coord *arg0, s16 roomnum) { if (g_Rooms[roomnum].flags & ROOMFLAG_0010) { return func0f161d30(arg0, roomnum); } return func0f161c08(arg0, roomnum); } /** * Find rooms near the given pos so the caller can decide which room pos is * actually in. * * inrooms should point to an empty array of room numbers whose length is max + 1. * The function will populate this array with room numbers where the pos is * inside the room's bounding box. * * aboverooms works the same way, but it'll be populated with room numbers where * the pos is above the room's bounding box. * * For both arrays, the function will only consider rooms that have portals. * If this doesn't produce anything for both arrays, the function will try again * but with rooms that have no portals. * * If all of the above produces no results (ie. the pos is out of bounds) and * the bestroom pointer is not NULL, the function then finds the closest room * to pos and writes the room number to the bestroom pointer. The bestroom * pointer is a pointer to a single s16 rather than an array. */ void bgFindRoomsByPos(struct coord *posarg, s16 *inrooms, s16 *aboverooms, s32 max, s16 *bestroom) { s32 inlen = 0; s32 abovelen = 0; s32 closestroomnum = -1; struct coord pos; f32 closestdist = 0.0f; s32 i; s32 j; pos.x = posarg->x; pos.y = posarg->y; pos.z = posarg->z; // Try rooms which have portals for (i = 1; i < g_Vars.roomcount; i++) { if (g_Rooms[i].numportals > 0 && pos.x >= g_Rooms[i].bbmin[0] && pos.x <= g_Rooms[i].bbmax[0] && pos.z >= g_Rooms[i].bbmin[2] && pos.z <= g_Rooms[i].bbmax[2] && pos.y >= g_Rooms[i].bbmin[1]) { if (pos.y <= g_Rooms[i].bbmax[1]) { // Pos is inside the bbox if (inlen < max) { inrooms[inlen] = i; inlen++; } } else { // Pos is above the bbox if (abovelen < max) { aboverooms[abovelen] = i; abovelen++; } } } } // Try again but with rooms that have no portals if (inlen == 0 && abovelen == 0) { for (i = 1; i < g_Vars.roomcount; i++) { if (g_Rooms[i].numportals == 0 && pos.x >= g_Rooms[i].bbmin[0] && pos.x <= g_Rooms[i].bbmax[0] && pos.z >= g_Rooms[i].bbmin[2] && pos.z <= g_Rooms[i].bbmax[2] && pos.y >= g_Rooms[i].bbmin[1]) { if (pos.y <= g_Rooms[i].bbmax[1]) { // Pos is inside the bbox if (inlen < max) { inrooms[inlen] = i; inlen++; } } else { // Pos is above the bbox if (abovelen < max) { aboverooms[abovelen] = i; abovelen++; } } } } } inrooms[inlen] = -1; aboverooms[abovelen] = -1; if (bestroom != NULL) { if (inlen == 0 && abovelen == 0) { for (i = 1; i < g_Vars.roomcount; i++) { f32 dist = 0.0f; for (j = 0; j < 3; j++) { if (pos.f[j] < g_Rooms[i].bbmin[j] || pos.f[j] > g_Rooms[i].bbmax[j]) { f32 dist1 = pos.f[j] - g_Rooms[i].bbmin[j]; f32 dist2 = pos.f[j] - g_Rooms[i].bbmax[j]; if (dist1 < 0.0f) { dist1 = -dist1; } if (dist2 < 0.0f) { dist2 = -dist2; } if (dist2 < dist1) { dist1 = dist2; } dist += dist1; } } if (dist > 0.0f && (closestroomnum < 0 || dist < closestdist)) { closestroomnum = i; closestdist = dist; } } } *bestroom = closestroomnum >= 0 ? closestroomnum : -1; } } bool bgPushValue(bool value) { g_BgCmdStack[g_BgCmdStackIndex] = value; g_BgCmdStackIndex = (g_BgCmdStackIndex + 1) % 20; return value; } bool bgPopValue(void) { bool val = g_BgCmdStack[g_BgCmdStackIndex = (g_BgCmdStackIndex + 19) % 20]; return val; } bool bgGetNthValueFromEnd(s32 n) { return g_BgCmdStack[((g_BgCmdStackIndex - n) + 19) % 20]; } /** * BG files contain bytecode that is used to override the default portal * behaviour. They can be used to check if the camera is in particular rooms * and then force other rooms to show or hide. * * Only six BG files use of this feature. They are Villa, Chicago, Area 51, * Pelagic II, Deep Sea and Skedar Ruins. All other BG files contain a single * "end" instruction in their bytecode. * * The scripting language supports if-statements with an infinite nesting level. * The interpreter maintains a stack of boolean values which can be pushed to * or popped from the end. This can be used to build complex conditions that * combine "AND" and "OR" operations. * * All commands are interpreted in order. There is no support for loops. * * When processing conditional code the function calls itself recursively for * that branch. The execute argument denotes whether the condition passed and * these statements should be executed, or whether the condition failed and * it's just passing over them to get to the endif command. */ struct bgcmd *bgExecuteCommandsBranch(struct bgcmd *cmd, bool execute) { s32 i; g_BgCmdThrowing = false; if (!cmd) { return cmd; } while (true) { switch (cmd->type) { case BGCMD_END: return cmd; case BGCMD_PUSH: if (execute) { bgPushValue(cmd->param); } cmd += cmd->len; break; case BGCMD_POP: if (execute) { bgPopValue(); } cmd += cmd->len; break; case BGCMD_AND: if (execute) { bgPushValue(bgPopValue() & bgPopValue()); } cmd += cmd->len; break; case BGCMD_OR: if (execute) { bgPushValue(bgPopValue() | bgPopValue()); } cmd += cmd->len; break; case BGCMD_NOT: if (execute) { bgPushValue(bgPopValue() == 0); } cmd += cmd->len; break; case BGCMD_XOR: if (execute) { bgPushValue(bgPopValue() ^ bgPopValue()); } cmd += cmd->len; break; case BGCMD_PUSH_CAMINROOMRANGE: if (execute) { bgPushValue(g_CamRoom >= cmd[1].param && g_CamRoom <= cmd[2].param); } cmd += cmd->len; break; case BGCMD_SETRESULT_TRUE: if (execute) { var800a65c0.xmin = g_Vars.currentplayer->screenxminf; var800a65c0.ymin = g_Vars.currentplayer->screenyminf; var800a65c0.xmax = g_Vars.currentplayer->screenxmaxf; var800a65c0.ymax = g_Vars.currentplayer->screenymaxf; g_BgCmdResult = BGRESULT_TRUE; } cmd += cmd->len; break; case BGCMD_SETRESULT_IFPORTALINFOV: if (execute) { if (!PORTAL_IS_CLOSED(cmd[1].param)) { if (g_PortalGetScreenBbox(cmd[1].param, &g_PortalScreenBbox) == 0) { g_BgCmdResult = BGRESULT_FALSE; } else if (boxGetIntersection(&var800a65c0, &g_PortalScreenBbox) == 0) { g_BgCmdResult = BGRESULT_FALSE; } else { g_BgCmdResult = BGRESULT_TRUE; } } } cmd += cmd->len; break; case BGCMD_SETRESULT_TRUEIFTHROUGHPORTAL: if (execute) { struct screenbox portalbox; if (!PORTAL_IS_CLOSED(cmd[1].param)) { if (g_PortalGetScreenBbox(cmd[1].param, &portalbox) && boxGetIntersection(&var800a65c0, &portalbox)) { if (g_BgCmdResult != BGRESULT_TRUE) { boxCopy(&var800a65c0, &portalbox); g_BgCmdResult = BGRESULT_TRUE; } else { boxExpand(&var800a65c0, &portalbox); } } } } cmd += cmd->len; break; case BGCMD_SETRESULT_FALSEIFNOTTHROUGHPORTAL: if (execute) { if (g_BgCmdResult == BGRESULT_TRUE) { struct screenbox portalbox; if (PORTAL_IS_CLOSED(cmd[1].param)) { g_BgCmdResult = BGRESULT_FALSE; } else if (g_PortalGetScreenBbox(cmd[1].param, &portalbox) == 0) { g_BgCmdResult = BGRESULT_FALSE; } else if (boxGetIntersection(&portalbox, (struct screenbox *)&g_Vars.currentplayer->screenxminf) == 0) { g_BgCmdResult = BGRESULT_FALSE; } else if (boxGetIntersection(&g_PortalScreenBbox, &portalbox) == 0) { g_BgCmdResult = BGRESULT_FALSE; } } } cmd += cmd->len; break; case BGCMD_IFRESULT_SHOWROOM: if (execute) { if (g_BgCmdResult == BGRESULT_TRUE && func0f15cd90(cmd[1].param, &var800a65c0)) { roomSetOnscreen(cmd[1].param, 0, &var800a65c0); g_ActiveRoomNums[g_NumActiveRooms++] = cmd[1].param; } } cmd += cmd->len; break; case BGCMD_DISABLEROOM: if (execute) { g_Rooms[cmd[1].param].flags |= ROOMFLAG_DISABLEDBYSCRIPT; } cmd += cmd->len; break; case BGCMD_DISABLEROOMRANGE: if (execute) { for (i = cmd[1].param; i <= cmd[2].param; i++) { g_Rooms[i].flags |= ROOMFLAG_DISABLEDBYSCRIPT; } } cmd += cmd->len; break; case BGCMD_LOADROOM: cmd += cmd->len; break; case BGCMD_LOADROOMRANGE: cmd += cmd->len; break; case BGCMD_SETROOMTESTSDISABLED: if (execute) { g_BgRoomTestsDisabled = true; } cmd += cmd->len; break; case BGCMD_PUSH_PORTALISOPEN: if (execute) { bgPushValue(!PORTAL_IS_CLOSED(cmd[1].param)); } cmd += cmd->len; break; case BGCMD_2A: if (execute) { g_Rooms[cmd[1].param].unk07 = 0; } cmd += cmd->len; break; case BGCMD_SETRESULT_FALSE: if (execute) { g_BgCmdResult = BGRESULT_FALSE; } cmd += cmd->len; break; case BGCMD_BRANCH: cmd = bgExecuteCommandsBranch(cmd + cmd->len, execute); cmd += cmd->len; break; case BGCMD_CATCH: cmd += cmd->len; g_BgCmdThrowing = false; return cmd; case BGCMD_THROW: cmd += cmd->len; if (execute) { g_BgCmdThrowing = true; } execute = false; break; case BGCMD_IF: cmd = bgExecuteCommandsBranch(cmd + cmd->len, bgPopValue() & execute); if (g_BgCmdThrowing) { execute = false; } break; case BGCMD_ELSE: /** * Assuming this is indeed an else command, it's not safe to assume * that the execution state can be unconditionally toggled. * For example, given the following portal code: * * if (a false condition) * if (any condition) * branch 1 * else * branch 2 * endif * endif * * ...when reaching the else, execution would be turned on. * * However, this command isn't even used. */ execute ^= 1; cmd += cmd->len; break; case BGCMD_ENDIF: /** * Note the return here rather than break. */ cmd += cmd->len; return cmd; default: if (1); if (1); if (1); if (1); return cmd; } } g_BgCmdThrowing = false; return cmd; } struct bgcmd *bgExecuteCommands(struct bgcmd *cmd) { struct player *player = g_Vars.currentplayer; g_BgCmdResult = BGRESULT_TRUE; if (!cmd) { return cmd; } // This may have been used in an osSyncPrintf call bgGetNthValueFromEnd(0); var800a65c0.xmin = player->screenxminf; var800a65c0.ymin = player->screenyminf; var800a65c0.xmax = player->screenxmaxf; var800a65c0.ymax = player->screenymaxf; return bgExecuteCommandsBranch(cmd, true); } void bgTickPortalsXray(void) { struct coord vismax; struct coord vismin; struct coord eraserpos; struct coord vismid; struct player *player = g_Vars.currentplayer; s16 ymax; s16 xmax; s16 ymin; s16 xmin; struct stagetableentry *stage; s32 i; struct var800a4640 *thing; static u32 edist = 400; currentPlayerCalculateScreenProperties(); if (var800a4640.unk000); if (var8007fc34 < var8007fc30) { var8007fc34 = var8007fc30; } xmin = player->screenxminf; ymin = player->screenyminf; xmax = player->screenxmaxf; ymax = player->screenymaxf; if (bgunGetWeaponNum(HAND_RIGHT) == WEAPON_FARSIGHT && player->gunsightoff == 0) { player->eraserdepth = -500.0f / camGetLodScaleZ(); } else { player->eraserdepth = -500.0f; } eraserpos.f[0] = 0.0f; eraserpos.f[1] = 0.0f; eraserpos.f[2] = player->eraserdepth; mtx4TransformVecInPlace(camGetProjectionMtxF(), &eraserpos); player->eraserpos.f[0] = eraserpos.f[0]; player->eraserpos.f[1] = eraserpos.f[1]; player->eraserpos.f[2] = eraserpos.f[2]; mainOverrideVariable("edist", &edist); stage = stageGetCurrent(); player->eraserpropdist = stage->eraserpropdist; player->eraserbgdist = (f32) stage->eraserpropdist + stage->unk30; vismax.f[0] = eraserpos.f[0] + player->eraserbgdist; vismax.f[1] = eraserpos.f[1] + player->eraserbgdist; vismax.f[2] = eraserpos.f[2] + player->eraserbgdist; vismin.f[0] = eraserpos.f[0] - player->eraserbgdist; vismin.f[1] = eraserpos.f[1] - player->eraserbgdist; vismin.f[2] = eraserpos.f[2] - player->eraserbgdist; vismid.f[0] = eraserpos.f[0]; vismid.f[1] = eraserpos.f[1]; vismid.f[2] = eraserpos.f[2]; var8007fc2c = 0; var8007fc30 = 0; var800a4640.unk2d0.roomnum = -1; var800a4640.unk2d0.draworder = 255; var800a4640.unk2d0.box.xmin = xmin; var800a4640.unk2d0.box.ymin = ymin; var800a4640.unk2d0.box.xmax = xmax; var800a4640.unk2d0.box.ymax = ymax; var800a4ce6 = 0; var800a4ce4 = 0x7fff; for (i = 1; i < g_Vars.roomcount; i++) { if (!(vismax.f[0] < g_Rooms[i].bbmin[0]) && !(vismin.f[0] > g_Rooms[i].bbmax[0]) && !(vismax.f[2] < g_Rooms[i].bbmin[2]) && !(vismin.f[2] > g_Rooms[i].bbmax[2]) && !(vismax.f[1] < g_Rooms[i].bbmin[1]) && !(vismin.f[1] > g_Rooms[i].bbmax[1])) { s32 index = var8007fc2c; if (xmin); if (g_Rooms[i].bbmax); if (1); if (1); if (1); if (index < 60) { f32 x; f32 y; f32 z; g_Rooms[i].flags |= ROOMFLAG_ONSCREEN; var800a4640.unk000[index].roomnum = i; roomUnpauseProps(i, false); x = (g_Rooms[i].bbmin[0] + g_Rooms[i].bbmax[0]) / 2.0f - vismid.f[0]; y = (g_Rooms[i].bbmin[1] + g_Rooms[i].bbmax[1]) / 2.0f - vismid.f[1]; z = (g_Rooms[i].bbmin[2] + g_Rooms[i].bbmax[2]) / 2.0f - vismid.f[2]; var800a4640.unk000[index].draworder = sqrtf(x * x + y * y + z * z) / 100.0f; if (var800a4640.unk000[index].draworder > var800a4ce6) { var800a4ce6 = var800a4640.unk000[index].draworder; } if (var800a4640.unk000[index].draworder < var800a4ce4) { var800a4ce4 = var800a4640.unk000[index].draworder; } var800a4640.unk000[index].box.xmin = xmin; var800a4640.unk000[index].box.ymin = ymin; var800a4640.unk000[index].box.xmax = xmax; var800a4640.unk000[index].box.ymax = ymax; var8007fc2c++; var8007fc30++; g_Rooms[player->cam_room].flags |= ROOMFLAG_ONSCREEN; } else { // empty } } } bgChooseRoomsToLoad(); } void func0f1632d4(s16 roomnum1, s16 roomnum2, s16 draworder, struct screenbox *box) { struct var800a4d00 *thing; s32 i; s32 j; if (g_Rooms[roomnum2].flags & ROOMFLAG_DISABLEDBYSCRIPT) { return; } if (draworder >= 2) { if (g_Rooms[roomnum2].portalrecursioncount < 255) { g_Rooms[roomnum2].portalrecursioncount++; } if (g_Rooms[roomnum2].portalrecursioncount > g_Vars.roomportalrecursionlimit) { return; } } if (g_Rooms[roomnum2].unk06 && g_Rooms[roomnum2].unk07) { i = var800a4cf0.unk04; thing = &var800a4cf0.unk10[i]; while (i != var800a4cf0.index) { if (thing->roomnum == roomnum2) { for (j = 0; j < 5; j++) { if (thing->roomnums[j] == -1) { boxExpand(&thing->screenbox, box); thing->roomnums[j] = roomnum1; return; } } } i++; thing++; if (i == 250) { i = 0; thing = &var800a4cf0.unk10[0]; } } } thing = &var800a4cf0.unk10[var800a4cf0.index]; thing->roomnums[0] = roomnum1; thing->roomnum = roomnum2; thing->draworder = draworder; thing->roomportallistoffset = g_Rooms[roomnum2].roomportallistoffset; thing->numportals = g_Rooms[roomnum2].numportals; thing->screenbox.xmin = box->xmin; thing->screenbox.ymin = box->ymin; thing->screenbox.xmax = box->xmax; thing->screenbox.ymax = box->ymax; g_Rooms[roomnum2].unk06++; for (i = 1; i < 5; i++) { thing->roomnums[i] = -1; } var800a4cf0.index++; if (var800a4cf0.index == 250) { var800a4cf0.index = 0; } if (var800a4cf0.index == var800a4cf0.unk04) { var800a4cf0.index--; } } void func0f163528(struct var800a4d00 *arg0) { struct coord *campos; s32 i; s16 portalnum; s16 s4; s16 s6; s16 s0; s16 unk02; s16 tmp; bool pass; struct var800a4ccc *thing; struct screenbox box1; struct screenbox box2; f32 sum; g_Rooms[arg0->roomnum].unk06--; var800a4cf0.unk00++; campos = &g_Vars.currentplayer->cam_pos; s4 = 0; s6 = -1; for (i = 0; i < arg0->numportals; i++) { portalnum = g_RoomPortals[arg0->roomportallistoffset + i]; if (g_PortalThings[portalnum].unk00 != var8007fc3c) { thing = &var800a4ccc[portalnum]; sum = thing->coord.x * campos->f[0] + thing->coord.y * campos->f[1] + thing->coord.z * campos->f[2]; if (sum < thing->min) { g_PortalThings[portalnum].unk02 = 1; } else if (sum > thing->max) { g_PortalThings[portalnum].unk02 = 0; } else { g_PortalThings[portalnum].unk02 = 2; } g_PortalThings[portalnum].unk00 = var8007fc3c; } tmp = g_BgPortals[portalnum].roomnum1; unk02 = g_PortalThings[portalnum].unk02; if ((u32)tmp == arg0->roomnum) { if (unk02 == 0) { continue; } s0 = g_BgPortals[portalnum].roomnum2; } else { if (unk02 == 1) { continue; } s0 = tmp; } if (1); if (s6 != s0) { pass = s4 != 0; s4 = 0; if (pass) { roomSetOnscreen(s6, arg0->draworder, &box1); func0f1632d4(arg0->roomnum, s6, arg0->draworder + 1, &box1); } s6 = s0; } if (PORTAL_IS_CLOSED(portalnum)) { continue; } if (s0 == arg0->roomnums[0] || s0 == arg0->roomnums[1] || s0 == arg0->roomnums[2] || s0 == arg0->roomnums[3] || s0 == arg0->roomnums[4]) { continue; } if (g_BgPortals[portalnum].flags & PORTALFLAG_02) { box2.xmin = arg0->screenbox.xmin; box2.ymin = arg0->screenbox.ymin; box2.xmax = arg0->screenbox.xmax; box2.ymax = arg0->screenbox.ymax; unk02 = true; } else { unk02 = g_PortalGetScreenBbox(portalnum, &box2); } if (unk02) { boxGetIntersection(&box2, &arg0->screenbox); if (box2.xmin < box2.xmax && box2.ymin < box2.ymax) { if (s4 == 0) { box1.xmin = box2.xmin; box1.ymin = box2.ymin; box1.xmax = box2.xmax; box1.ymax = box2.ymax; } else { boxExpand(&box1, &box2); } s4++; } } } if (s4 != 0) { roomSetOnscreen(s6, arg0->draworder, &box1); func0f1632d4(arg0->roomnum, s6, arg0->draworder + 1, &box1); } } bool func0f163904(void) { if (var800a4cf0.unk04 == var800a4cf0.index) { return false; } func0f163528(&var800a4cf0.unk10[var800a4cf0.unk04]); var800a4cf0.unk04++; if (var800a4cf0.unk04 == ARRAYCOUNT(var800a4cf0.unk10)) { var800a4cf0.unk04 = 0; } return true; } /** * Choose which rooms should be placed on standby and which are candidates for * loading. * * All offscreen neighbours of onscreen rooms are placed on standby and are * nominated for loading. Any tinted glass in these rooms will be unpaused. * * If the portal between the onscreen room and the offscreen room is blocked * (ie. a closed door or opaque glass) then nominate the neighbours of the * offscreen room for loading too. This is necessary because opening the door or * destroying the glass may make many rooms visible at once, and only one room * is loaded per tick. */ void bgChooseRoomsToLoad(void) { s32 i; s32 j; u32 stack; g_BgNumRoomLoadCandidates = 0; for (i = 0; g_BgPortals[i].verticesoffset != 0; i++) { if ((g_BgPortals[i].flags & PORTALFLAG_SKIP) == 0) { s32 roomnum1 = g_BgPortals[i].roomnum1; s32 roomnum2 = g_BgPortals[i].roomnum2; s32 portalnum; if ((g_Rooms[roomnum1].flags & ROOMFLAG_ONSCREEN) && (g_Rooms[roomnum2].flags & ROOMFLAG_ONSCREEN) == 0) { // From room1 to room2 g_Rooms[roomnum2].flags |= ROOMFLAG_STANDBY; if (g_Rooms[roomnum2].loaded240 == 0) { g_Rooms[roomnum2].flags |= ROOMFLAG_LOADCANDIDATE; g_BgNumRoomLoadCandidates++; } roomUnpauseProps(roomnum2, true); if (PORTAL_IS_CLOSED(i)) { for (j = 0; j < g_Rooms[roomnum2].numportals; j++) { portalnum = g_RoomPortals[g_Rooms[roomnum2].roomportallistoffset + j]; if (roomnum2 == g_BgPortals[portalnum].roomnum1) { if (g_Rooms[g_BgPortals[portalnum].roomnum2].loaded240 == 0) { g_Rooms[g_BgPortals[portalnum].roomnum2].flags |= ROOMFLAG_LOADCANDIDATE; g_BgNumRoomLoadCandidates++; } } else { if (g_Rooms[g_BgPortals[portalnum].roomnum1].loaded240 == 0) { g_Rooms[g_BgPortals[portalnum].roomnum1].flags |= ROOMFLAG_LOADCANDIDATE; g_BgNumRoomLoadCandidates++; } } } } } else if ((g_Rooms[roomnum2].flags & ROOMFLAG_ONSCREEN) && (g_Rooms[roomnum1].flags & ROOMFLAG_ONSCREEN) == 0) { // From room2 to room1 g_Rooms[roomnum1].flags |= ROOMFLAG_STANDBY; if (g_Rooms[roomnum1].loaded240 == 0) { g_Rooms[roomnum1].flags |= ROOMFLAG_LOADCANDIDATE; g_BgNumRoomLoadCandidates++; } roomUnpauseProps(roomnum1, true); if (PORTAL_IS_CLOSED(i)) { for (j = 0; j < g_Rooms[roomnum1].numportals; j++) { portalnum = g_RoomPortals[g_Rooms[roomnum1].roomportallistoffset + j]; if (roomnum1 == g_BgPortals[portalnum].roomnum1) { if (g_Rooms[g_BgPortals[portalnum].roomnum1].loaded240 == 0) { g_Rooms[g_BgPortals[portalnum].roomnum1].flags |= ROOMFLAG_LOADCANDIDATE; g_BgNumRoomLoadCandidates++; } } else { if (g_Rooms[g_BgPortals[portalnum].roomnum1].loaded240 == 0) { g_Rooms[g_BgPortals[portalnum].roomnum2].flags |= ROOMFLAG_LOADCANDIDATE; g_BgNumRoomLoadCandidates++; } } } } } } } // Update visibility per player if (g_Vars.mplayerisrunning) { u8 flag1 = 0x01 << g_Vars.currentplayernum; u8 flag2 = 0x10 << g_Vars.currentplayernum; for (i = 0; i < g_Vars.roomcount; i++) { if (g_Rooms[i].flags & ROOMFLAG_ONSCREEN) { g_MpRoomVisibility[i] |= flag1; } else { g_MpRoomVisibility[i] &= ~flag1; } if (g_Rooms[i].flags & ROOMFLAG_STANDBY) { g_MpRoomVisibility[i] |= flag2; } else { g_MpRoomVisibility[i] &= ~flag2; } } } } void bgTickPortals(void) { s32 i; s32 room; struct screenbox box; struct player *player = g_Vars.currentplayer; currentPlayerCalculateScreenProperties(); box.xmin = player->screenxminf; box.ymin = player->screenyminf; box.xmax = player->screenxmaxf; box.ymax = player->screenymaxf; viGetZRange(&var800a4cf0.zrange); var800a4cf0.zrange.far = var800a4cf0.zrange.far / g_Vars.currentplayerstats->scale_bg2gfx; for (i = 0; i < g_Vars.roomcount; i++) { g_Rooms[i].flags &= ~(ROOMFLAG_DISABLEDBYSCRIPT | ROOMFLAG_ONSCREEN | ROOMFLAG_STANDBY | ROOMFLAG_LOADCANDIDATE); g_Rooms[i].portalrecursioncount = 0; g_Rooms[i].unk06 = 0; g_Rooms[i].unk07 = 1; } if (player->visionmode == VISIONMODE_XRAY) { bgTickPortalsXray(); } else { if (var8007fc34 < var8007fc30) { var8007fc34 = var8007fc30; } var8007fc2c = 0; var8007fc30 = 0; var800a4ce6 = 0; var800a4ce4 = 32767; var800a4640.unk2d0.roomnum = -1; var800a4640.unk2d0.draworder = 255; var800a4cf0.unk00 = 0; var800a4cf0.index = 0; var800a4cf0.unk04 = 0; g_BgRoomTestsDisabled = false; var800a4640.unk2d0.box.xmin = box.xmin; var800a4640.unk2d0.box.ymin = box.ymin; var800a4640.unk2d0.box.xmax = box.xmax; var800a4640.unk2d0.box.ymax = box.ymax; bgExecuteCommands(g_BgCommands); if (!g_BgRoomTestsDisabled) { if (g_BgPortals[0].verticesoffset == 0) { for (room = 1; room < g_Vars.roomcount; room++) { if (func0f15cd90(room, &box) && ((g_StageIndex != STAGEINDEX_INFILTRATION && g_StageIndex != STAGEINDEX_RESCUE && g_StageIndex != STAGEINDEX_ESCAPE) || room != 0xf) && (g_StageIndex != STAGEINDEX_SKEDARRUINS || room != 0x02) && ((g_StageIndex != STAGEINDEX_DEFECTION && g_StageIndex != STAGEINDEX_EXTRACTION) || room != 0x01) && (g_StageIndex != STAGEINDEX_ATTACKSHIP || room != 0x71)) { roomSetOnscreen(room, 0, &box); } } } else { roomSetOnscreen(g_CamRoom, 0, &box); var800a4cf0.unk00 = 0; var800a4cf0.index = 0; var800a4cf0.unk04 = 0; func0f1632d4(g_CamRoom, g_CamRoom, 1, &box); while (func0f163904()); } } bgChooseRoomsToLoad(); } } Gfx *func0f164150(Gfx *gdl) { gdl = bgRenderScene(gdl); gdl = currentPlayerScissorToViewport(gdl); if (g_Vars.currentplayerindex == 0) { var8007fc28 -= g_Vars.lvupdate240; } if (var8007fc28 < 0) { var8007fc28 = 0; } // Consider loading one room by finding the load candidate that is closest to the player if (var8007fc28 == 0 && var8007fc10 == 4 && g_Vars.tickmode == TICKMODE_NORMAL && IS8MB()) { struct player *player = g_Vars.currentplayer; s32 i; f32 value; struct coord dist; f32 bestvalue = MAXFLOAT; s32 bestroomnum = 0; f32 radius; if (g_BgNumRoomLoadCandidates) { for (i = 1; i < g_Vars.roomcount; i++) { if (!g_Rooms[i].loaded240 && (g_Rooms[i].flags & ROOMFLAG_LOADCANDIDATE)) { dist.x = g_Vars.currentplayer->prop->pos.x - g_Rooms[i].centre.x; dist.y = g_Vars.currentplayer->prop->pos.y - g_Rooms[i].centre.y; dist.z = g_Vars.currentplayer->prop->pos.z - g_Rooms[i].centre.z; value = dist.f[0] * dist.f[0] + dist.f[1] * dist.f[1] + dist.f[2] * dist.f[2]; radius = g_Rooms[i].radius; if (var8009dd6c + radius < player->projectionmtx->m[2][0] * g_Rooms[i].centre.f[0] + player->projectionmtx->m[2][1] * g_Rooms[i].centre.f[1] + player->projectionmtx->m[2][2] * g_Rooms[i].centre.f[2]) { value *= 3.0f; } if (var8009dd4c + radius < var8009dd40.f[0] * g_Rooms[i].centre.f[0] + var8009dd40.f[1] * g_Rooms[i].centre.f[1] + var8009dd40.f[2] * g_Rooms[i].centre.f[2]) { value *= 1.5f; } if (var8009dd5c + radius < var8009dd50.f[0] * g_Rooms[i].centre.f[0] + var8009dd50.f[1] * g_Rooms[i].centre.f[1] + var8009dd50.f[2] * g_Rooms[i].centre.f[2]) { value *= 1.5f; } if (var8009dd2c + radius < var8009dd20.f[0] * g_Rooms[i].centre.f[0] + var8009dd20.f[1] * g_Rooms[i].centre.f[1] + var8009dd20.f[2] * g_Rooms[i].centre.f[2]) { value *= 2.0f; } if (var8009dd3c + radius < var8009dd30.f[0] * g_Rooms[i].centre.f[0] + var8009dd30.f[1] * g_Rooms[i].centre.f[1] + var8009dd30.f[2] * g_Rooms[i].centre.f[2]) { value *= 2.0f; } if (value < bestvalue) { bestvalue = value; bestroomnum = i; } } } } if (bestroomnum != 0) { bgLoadRoom(bestroomnum); var8007fc28 = 64; } } return gdl; } /** * @dangerous: This function assumes that the passed len is the allocated length * minus one. ie. It assumes there is space to write the -1 terminator once the * length is reached. * * This is only called from two places, both with len=100, so you'd need to have * over 100 rooms active at the same time before this would overflow the array. */ s32 roomsGetActive(s16 *rooms, s32 len) { s32 i; for (i = 0; i < g_NumActiveRooms && i < len; i++) { rooms[i] = g_ActiveRoomNums[i]; } rooms[i] = -1; return i; } s32 roomGetNeighbours(s32 roomnum, s16 *dstrooms, s32 len) { s32 count = 0; s32 i; s32 j; for (i = 0; i < g_Rooms[roomnum].numportals; i++) { s32 portalnum = g_RoomPortals[g_Rooms[roomnum].roomportallistoffset + i]; s32 neighbournum = g_BgPortals[portalnum].roomnum1; if (neighbournum == roomnum) { neighbournum = g_BgPortals[portalnum].roomnum2; } for (j = 0; j < count; j++) { if (dstrooms[j] == neighbournum) { goto end; } } dstrooms[count] = neighbournum; count++; if (count >= len) { break; } end: ; } dstrooms[count] = -1; return count; } bool roomsAreNeighbours(s32 roomnum1, s32 roomnum2) { s32 i; for (i = 0; i < g_Rooms[roomnum1].numportals; i++) { s32 portalnum = g_RoomPortals[g_Rooms[roomnum1].roomportallistoffset + i]; if (g_BgPortals[portalnum].roomnum1 == roomnum2 || g_BgPortals[portalnum].roomnum2 == roomnum2) { return true; } } return false; } void currentPlayerCalculateScreenProperties(void) { struct player *player = g_Vars.currentplayer; f32 width = viGetWidth(); u32 stack; f32 height = viGetHeight(); u32 stack2; player->screenxminf = viGetViewLeft(); if (player->screenxminf < 0) { player->screenxminf = 0; } if (player->screenxminf > width) { player->screenxminf = width; } player->screenyminf = viGetViewTop(); if (player->screenyminf < 0) { player->screenyminf = 0; } if (player->screenyminf > height) { player->screenyminf = height; } player->screenxmaxf = viGetViewLeft() + viGetViewWidth(); if (player->screenxmaxf < 0) { player->screenxmaxf = 0; } if (player->screenxmaxf > width) { player->screenxmaxf = width; } player->screenymaxf = viGetViewTop() + viGetViewHeight(); if (player->screenymaxf < 0) { player->screenymaxf = 0; } if (player->screenymaxf > height) { player->screenymaxf = height; } } void bgExpandRoomToPortals(s32 roomnum) { s32 i; s32 j; s32 k; s32 count = 0; for (i = 0; i < g_Rooms[roomnum].numportals; i++) { s32 portalnum = g_RoomPortals[g_Rooms[roomnum].roomportallistoffset + i]; struct portalvertices *pvertices = (struct portalvertices *)((u32)g_BgPortals + g_BgPortals[portalnum].verticesoffset); for (j = 0; j < pvertices->count; j++) { for (k = 0; k < 3; k++) { f32 value = pvertices->vertices[j].f[k]; if (value < g_Rooms[roomnum].bbmin[k]) { g_Rooms[roomnum].bbmin[k] = value; count++; } if (value > g_Rooms[roomnum].bbmax[k]) { g_Rooms[roomnum].bbmax[k] = value; count++; } } } } if (count); } bool portalExists(s32 portalnum) { s32 i; for (i = 0; g_BgPortals[i].verticesoffset != 0; i++) { if (i == portalnum) { return true; } } return false; } void portalSwapRooms(s32 portal) { s16 tmp = g_BgPortals[portal].roomnum1; g_BgPortals[portal].roomnum1 = g_BgPortals[portal].roomnum2; g_BgPortals[portal].roomnum2 = tmp; } void func0f164ab8(s32 portalnum) { struct coord room1centre; struct coord room2centre; f32 tmp; struct var800a4ccc sp28; struct var800a4ccc *ptr; f32 tmp1; f32 tmp2; bool sp18; s32 roomnum1; s32 roomnum2; roomnum1 = g_BgPortals[portalnum].roomnum1; roomnum2 = g_BgPortals[portalnum].roomnum2; room1centre.x = g_Rooms[roomnum1].centre.x; room1centre.y = g_Rooms[roomnum1].centre.y; room1centre.z = g_Rooms[roomnum1].centre.z; room2centre.x = g_Rooms[roomnum2].centre.x; room2centre.y = g_Rooms[roomnum2].centre.y; room2centre.z = g_Rooms[roomnum2].centre.z; ptr = &var800a4ccc[portalnum]; sp28.coord.x = ptr->coord.x; sp28.coord.y = ptr->coord.y; sp28.coord.z = ptr->coord.z; sp28.min = ptr->min; sp28.max = ptr->max; tmp1 = sp28.coord.f[0] * room1centre.f[0] + sp28.coord.f[1] * room1centre.f[1] + sp28.coord.f[2] * room1centre.f[2]; if (tmp1); sp18 = 0; if (tmp1 > sp28.max) { sp18 = 1; portalSwapRooms(portalnum); sp28.coord.x = -sp28.coord.x; sp28.coord.y = -sp28.coord.y; sp28.coord.z = -sp28.coord.z; tmp = sp28.min; sp28.min = -sp28.max; sp28.max = -tmp; } tmp2 = sp28.coord.f[0] * room2centre.f[0] + sp28.coord.f[1] * room2centre.f[1] + sp28.coord.f[2] * room2centre.f[2]; if (tmp2 <= sp28.min && sp18) { portalSwapRooms(portalnum); } if (sp18); } void room0f164c64(s32 roomnum) { struct portalvertices *pvertices; s32 i; s32 j; s32 k; struct var800a4ccc thing; s16 portalnum; s16 portalnum2; f32 tmp; for (i = 0; i < g_Rooms[roomnum].numportals; i++) { portalnum = g_RoomPortals[g_Rooms[roomnum].roomportallistoffset + i]; thing.coord.f[0] = (var800a4ccc + portalnum)->coord.f[0]; thing.coord.f[1] = (var800a4ccc + portalnum)->coord.f[1]; thing.coord.f[2] = (var800a4ccc + portalnum)->coord.f[2]; thing.min = (var800a4ccc + portalnum)->min; thing.max = (var800a4ccc + portalnum)->max; if (roomnum == g_BgPortals[portalnum].roomnum1) { thing.coord.f[0] = -thing.coord.f[0]; thing.coord.f[1] = -thing.coord.f[1]; thing.coord.f[2] = -thing.coord.f[2]; tmp = thing.min; thing.min = -thing.max; thing.max = -tmp; } for (j = 0; j < g_Rooms[roomnum].numportals; j++) { portalnum2 = g_RoomPortals[g_Rooms[roomnum].roomportallistoffset + j]; if (portalnum2 == portalnum) { continue; } pvertices = (struct portalvertices *)((u32)g_BgPortals + g_BgPortals[portalnum2].verticesoffset); for (k = 0; k < pvertices->count; k++) { tmp = thing.coord.f[0] * pvertices->vertices[k].f[0] + thing.coord.f[1] * pvertices->vertices[k].f[1] + thing.coord.f[2] * pvertices->vertices[k].f[2]; if (tmp < thing.min) { g_Rooms[roomnum].flags |= ROOMFLAG_0010; return; } } } } } void portalSetOpen(s32 portal, bool open) { g_BgPortals[portal].flags = (g_BgPortals[portal].flags | PORTALFLAG_CLOSED) ^ (open != false); } s32 func0f164e70(s32 arg0, s32 arg1, s32 arg2) { return arg0; } void func0f164e80(s32 arg0, s32 arg1) { // empty } f32 var8007fcb4 = 0; s32 bg0f164e8c(struct coord *arg0, struct coord *arg1) { s32 bestportalnum = -1; s32 count = 0; f32 bestthing = MAXFLOAT; f32 thisthing; s32 i; for (i = 0; g_BgPortals[i].verticesoffset; i++) { if (portal00017e30(i, arg0, arg1) != 0) { thisthing = var8007fcb4; if (thisthing < 0) { thisthing = -thisthing; } if (thisthing < bestthing) { if (count); if (i); bestportalnum = i; bestthing = thisthing; count++; } } } return bestportalnum; } bool bgIsBboxOverlapping(struct coord *portalbbmin, struct coord *portalbbmax, struct coord *propbbmin, struct coord *propbbmax) { s32 i; for (i = 0; i < 3; i++) { if (propbbmin->f[i] > portalbbmax->f[i] || propbbmax->f[i] < portalbbmin->f[i]) { return false; } } return true; } void portalFindBbox(s32 portalnum, struct coord *bbmin, struct coord *bbmax) { struct portalvertices *pvertices; s32 i; s32 j; bbmin->x = MAXFLOAT; bbmin->y = MAXFLOAT; bbmin->z = MAXFLOAT; bbmax->x = MINFLOAT; bbmax->y = MINFLOAT; bbmax->z = MINFLOAT; pvertices = (struct portalvertices *)((u32)g_BgPortals + g_BgPortals[portalnum].verticesoffset); for (i = 0; i < pvertices->count; i++) { for (j = 0; j < 3; j++) { f32 value = pvertices->vertices[i].f[j]; if (value < bbmin->f[j]) { bbmin->f[j] = value; } if (value > bbmax->f[j]) { bbmax->f[j] = value; } } } } void bgFindEnteredRooms(struct coord *bbmin, struct coord *bbmax, s16 *rooms, s32 maxlen, bool arg4) { s16 room; s16 otherroom; s32 portalnum; struct coord propbbmin; struct coord propbbmax; s32 len; s32 i; s32 j; s32 k; s32 origlen; struct coord portalbbmin; struct coord portalbbmax; propbbmin.x = bbmin->x; propbbmin.y = bbmin->y; propbbmin.z = bbmin->z; propbbmax.x = bbmax->x; propbbmax.y = bbmax->y; propbbmax.z = bbmax->z; i = 0; for (len = 0; rooms[len] != -1; len++); while (true) { origlen = len; for (; i < origlen; i++) { room = rooms[i]; for (j = 0; j < g_Rooms[room].numportals; j++) { portalnum = g_RoomPortals[g_Rooms[room].roomportallistoffset + j]; if (arg4 && PORTAL_IS_CLOSED(portalnum)) { continue; } portalFindBbox(portalnum, &portalbbmin, &portalbbmax); if (bgIsBboxOverlapping(&portalbbmin, &portalbbmax, &propbbmin, &propbbmax)) { if (room == g_BgPortals[portalnum].roomnum1) { otherroom = g_BgPortals[portalnum].roomnum2; } else { otherroom = g_BgPortals[portalnum].roomnum1; } for (k = 0; k < len; k++) { if (rooms[k] == otherroom) { break; } } if (k == len) { if (len < maxlen) { rooms[len] = otherroom; len++; } if (len >= maxlen) { goto end; } } } } } if (len == origlen) { break; } } end: rooms[len] = -1; }