From 161bdd9583e66ffa8962257fa32fb2f60c74ce12 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Thu, 11 May 2023 22:26:21 +1000 Subject: [PATCH] Preload BG rooms for Area 51 stages --- src/game/bg.c | 399 ++++++++++---------------------------------- src/game/filelist.c | 1 - src/lib/main.c | 8 +- 3 files changed, 92 insertions(+), 316 deletions(-) diff --git a/src/game/bg.c b/src/game/bg.c index 8e55d9127..085c0f944 100644 --- a/src/game/bg.c +++ b/src/game/bg.c @@ -50,10 +50,8 @@ static void currentPlayerCalculateScreenProperties(void); static void bgFindRoomVtxBatches(s32 roomnum); static Gfx *bgRenderRoomXlu(Gfx *gdl, s32 roomnum); static Gfx *bgRenderRoomOpaque(Gfx *gdl, s32 roomnum); -static void bgTickRooms(void); static void bgChooseRoomsToLoad(void); static void bgLoadRoom(s32 roomnum); -static void bgUnloadAllRooms(void); static void boxExpand(struct screenbox *a, struct screenbox *b); static Gfx *currentPlayerScissorWithinViewportF(Gfx *gdl, f32 viewleft, f32 viewtop, f32 viewright, f32 viewbottom); static void func0f15cd28(void); @@ -119,7 +117,6 @@ struct portalthing *g_PortalThings; struct var800a4cf0 var800a4cf0; s32 g_BgAlwaysRoom; -bool g_BgPreload = false; s32 g_StageIndex = 1; s16 var8007fc0c = 0; @@ -127,11 +124,9 @@ s16 var8007fc10 = 0; s32 g_NumRoomsWithGlares = 0; 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; @@ -1272,18 +1267,6 @@ void bgReset(s32 stagenum) g_BgUnloadDelay240 = 120; g_BgUnloadDelay240_2 = 120; - switch (g_Vars.stagenum) { - case STAGE_INFILTRATION: - case STAGE_RESCUE: - case STAGE_ESCAPE: - case STAGE_MAIANSOS: - g_BgPreload = false; - break; - default: - g_BgPreload = true; - break; - } - g_StageIndex = stageGetIndex2(stagenum); if (g_StageIndex < 0) { @@ -1771,7 +1754,6 @@ void bgBuildTables(s32 stagenum) void bgStop(void) { - bgUnloadAllRooms(); var8005ef10[0] = 65536; } @@ -1804,10 +1786,6 @@ void bgTick(void) func0f15c920(); - if (!g_BgPreload && g_Vars.currentplayerindex == 0) { - bgTickRooms(); - } - tickmode = g_Vars.tickmode; if (tickmode == TICKMODE_NORMAL) { @@ -2588,15 +2566,7 @@ static void bgLoadRoom(s32 roomnum) // It must be big enough to fit both the inflated and compressed room data. size = g_Rooms[roomnum].gfxdatalen; - if (g_BgPreload) { - allocation = mempAlloc(size, MEMPOOL_STAGE); - } else { - // Try to free enough bytes - bgGarbageCollectRooms(size, false); - - // Make the allocation - allocation = memaAlloc(size); - } + allocation = mempAlloc(size, MEMPOOL_STAGE); if (allocation != NULL) { dyntexSetCurrentRoom(roomnum); @@ -2739,11 +2709,7 @@ static void bgLoadRoom(s32 roomnum) g_Rooms[roomnum].loaded240 = 1; if (g_Rooms[roomnum].gfxdatalen != size) { - if (g_BgPreload) { - mempRealloc(allocation, g_Rooms[roomnum].gfxdatalen, MEMPOOL_STAGE); - } else { - memaRealloc((s32) allocation, size, g_Rooms[roomnum].gfxdatalen); - } + mempRealloc(allocation, g_Rooms[roomnum].gfxdatalen, MEMPOOL_STAGE); } // Update gdl pointers in the gfxdata so they point to the ones @@ -2796,132 +2762,6 @@ static void bgLoadRoom(s32 roomnum) } } - -static void bgUnloadRoom(s32 roomnum) -{ - u32 size; - - if (g_BgPreload) { - return; - } - - 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; -} - -static 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; - - if (g_BgPreload) { - return; - } - - 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 (g_Rooms[i].loaded240 > 8) { - 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. - */ -static void bgTickRooms(void) -{ - s32 numunloaded = 0; - s32 i; - - for (i = 1; i < g_Vars.roomcount; i++) { - if (g_Rooms[i].loaded240) { - g_Rooms[i].loaded240++; - - 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); - memaDefrag(); - numunloaded++; - } - } - } -} - static Gfx *bgRenderRoomPass(Gfx *gdl, s32 roomnum, struct roomblock *block, bool arg3) { u32 v0; @@ -3168,11 +3008,7 @@ static void bgFindRoomVtxBatches(s32 roomnum) batchindex += xlucount; - if (g_BgPreload) { - batches = mempAlloc((batchindex * sizeof(struct vtxbatch) + 0xf) & ~0xf, MEMPOOL_STAGE); - } else { - batches = memaAlloc((batchindex * sizeof(struct vtxbatch) + 0xf) & ~0xf); - } + batches = mempAlloc((batchindex * sizeof(struct vtxbatch) + 0xf) & ~0xf, MEMPOOL_STAGE); if (batches != NULL) { gdl = roomGetNextGdlInLayer(roomnum, NULL, VTXBATCHTYPE_OPA); @@ -5594,77 +5430,6 @@ static void bgChooseRoomsToLoad(void) s32 j; u32 stack; - g_BgNumRoomLoadCandidates = 0; - - if (!g_BgPreload) { - 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; @@ -5761,77 +5526,6 @@ static 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 (g_BgNumRoomLoadCandidates && var8007fc28 == 0 && var8007fc10 == 4 && g_Vars.tickmode == TICKMODE_NORMAL) { - struct player *player = g_Vars.currentplayer; - s32 i; - f32 value; - struct coord dist; - f32 bestvalue = MAXFLOAT; - s32 bestroomnum = 0; - f32 radius; - - 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; } @@ -6255,11 +5949,94 @@ end: rooms[len] = -1; } +u8 g_BgPreloadInfiltration[][2] = { + {0x01, 0x2a}, + {0x2e, 0x2e}, + {0x31, 0x31}, + {0x35, 0x36}, + {0x3b, 0x3b}, + {0x40, 0x52}, + {0x58, 0x58}, + {0x5f, 0x66}, + {0x78, 0x78}, + {0x8c, 0x8d}, + {0x8f, 0x9a}, + {0xfc, 0xff}, +}; + +u16 g_BgPreloadRescue[][2] = { + {0x01, 0x0f}, + {0x16, 0x1d}, + {0x21, 0x22}, + {0x2e, 0x2e}, + {0x31, 0x31}, + {0x37, 0x37}, + {0x3b, 0x3b}, + {0x3f, 0x4b}, + {0x4d, 0x4d}, + {0x4f, 0xcc}, + {0xdd, 0xdd}, + {0xe0, 0xe4}, + {0xf2, 0x10e}, +}; + +u16 g_BgPreloadEscape[][2] = { + {0x0f, 0x16}, + {0x23, 0x40}, + {0x45, 0x47}, + {0x59, 0x5e}, + {0x63, 0x72}, + {0x78, 0x9f}, + {0xa5, 0xad}, + {0xb9, 0xb9}, + {0xbd, 0xbd}, + {0xbf, 0x10e}, +}; + +u16 g_BgPreloadMaianSos[][2] = { + {0x01, 0x03}, + {0x05, 0x08}, + {0x0f, 0x0f}, + {0x18, 0x1d}, + {0x21, 0x22}, + {0x26, 0x4d}, + {0x4f, 0xd3}, + {0xd5, 0xd8}, + {0xdd, 0xdd}, + {0xe0, 0xe5}, + {0xf2, 0x10e}, +}; + void bgPreload(void) { - if (g_BgPreload) { - s32 i; + s32 i; + s32 j; + if (g_Vars.stagenum == STAGE_INFILTRATION) { + for (i = 0; i < ARRAYCOUNT(g_BgPreloadInfiltration); i++) { + for (j = g_BgPreloadInfiltration[i][0]; j <= g_BgPreloadInfiltration[i][1]; j++) { + bgLoadRoom(j); + } + } + } else if (g_Vars.stagenum == STAGE_RESCUE) { + for (i = 0; i < ARRAYCOUNT(g_BgPreloadRescue); i++) { + for (j = g_BgPreloadRescue[i][0]; j <= g_BgPreloadRescue[i][1]; j++) { + bgLoadRoom(j); + } + } + } else if (g_Vars.stagenum == STAGE_ESCAPE) { + for (i = 0; i < ARRAYCOUNT(g_BgPreloadEscape); i++) { + for (j = g_BgPreloadEscape[i][0]; j <= g_BgPreloadEscape[i][1]; j++) { + bgLoadRoom(j); + } + } + } else if (g_Vars.stagenum == STAGE_MAIANSOS) { + for (i = 0; i < ARRAYCOUNT(g_BgPreloadMaianSos); i++) { + for (j = g_BgPreloadMaianSos[i][0]; j <= g_BgPreloadMaianSos[i][1]; j++) { + bgLoadRoom(j); + } + } + } else { for (i = 1; i < g_Vars.roomcount; i++) { bgLoadRoom(i); } diff --git a/src/game/filelist.c b/src/game/filelist.c index 3f8a10a27..a9d0c55bb 100644 --- a/src/game/filelist.c +++ b/src/game/filelist.c @@ -46,7 +46,6 @@ void func0f110bf8(void) void filelistCreate(s32 listnum, u8 filetype) { if (g_FileLists[listnum] == NULL) { - bgGarbageCollectRooms(ALIGN16(sizeof(struct filelist)), 1); g_FileLists[listnum] = memaAlloc(ALIGN16(sizeof(struct filelist))); } diff --git a/src/lib/main.c b/src/lib/main.c index 3b61e2775..2971f6b3f 100644 --- a/src/lib/main.c +++ b/src/lib/main.c @@ -81,9 +81,9 @@ struct stageallocation g_StageAllocations8Mb[] = { { STAGE_CHICAGO, 110, 80, 100, 100 }, { STAGE_G5BUILDING, 110, 80, 100, 100 }, { STAGE_VILLA, 110, 80, 100, 100 }, - { STAGE_INFILTRATION, 110, 80, 100, 500 }, - { STAGE_RESCUE, 110, 80, 100, 500 }, - { STAGE_ESCAPE, 110, 80, 100, 500 }, + { STAGE_INFILTRATION, 110, 80, 100, 100 }, + { STAGE_RESCUE, 110, 80, 100, 100 }, + { STAGE_ESCAPE, 110, 80, 100, 100 }, { STAGE_AIRBASE, 110, 80, 100, 100 }, { STAGE_AIRFORCEONE, 110, 80, 100, 100 }, { STAGE_CRASHSITE, 110, 80, 100, 100 }, @@ -93,7 +93,7 @@ struct stageallocation g_StageAllocations8Mb[] = { { STAGE_ATTACKSHIP, 110, 80, 100, 200 }, { STAGE_SKEDARRUINS, 110, 80, 100, 200 }, { STAGE_MBR, 120, 0, 100, 100 }, - { STAGE_MAIANSOS, 120, 0, 100, 500 }, + { STAGE_MAIANSOS, 120, 0, 100, 100 }, { STAGE_WAR, 120, 0, 98, 100 }, { STAGE_DUEL, 120, 0, 100, 100 }, { STAGE_MP_SKEDAR, 200, 0, 200, 100 },