Preload BG rooms

This commit is contained in:
Ryan Dwyer 2022-11-05 23:14:53 +10:00
parent 607dd25b3d
commit c6b448331d
6 changed files with 38 additions and 243 deletions

View File

@ -3196,7 +3196,6 @@ void bgBuildTables(s32 stagenum)
void bgStop(void)
{
bgUnloadAllRooms();
mtx00016748(1);
}
@ -3271,10 +3270,6 @@ void bgTick(void)
func0f15c920();
if (g_Vars.currentplayerindex == 0) {
bgTickRooms();
}
tickmode = g_Vars.tickmode;
if (tickmode == TICKMODE_NORMAL) {
@ -4968,17 +4963,9 @@ void bgLoadRoom(s32 roomnum)
// 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;
} else {
size = memaGetLongestFree();
}
size = g_Rooms[roomnum].gfxdatalen;
// Try to free enough bytes
bgGarbageCollectRooms(size, false);
// Make the allocation
allocation = memaAlloc(size);
allocation = mempAlloc(size, MEMPOOL_STAGE);
if (allocation != NULL) {
dyntexSetCurrentRoom(roomnum);
@ -5128,7 +5115,7 @@ void bgLoadRoom(s32 roomnum)
g_Rooms[roomnum].loaded240 = 1;
if (g_Rooms[roomnum].gfxdatalen != size) {
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
@ -5210,134 +5197,6 @@ 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;
@ -5584,7 +5443,7 @@ void bgFindRoomVtxBatches(s32 roomnum)
batchindex += xlucount;
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);
@ -7460,75 +7319,8 @@ void bgChooseRoomsToLoad(void)
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;
@ -8127,3 +7919,12 @@ void bgFindEnteredRooms(struct coord *bbmin, struct coord *bbmax, s16 *rooms, s3
end:
rooms[len] = -1;
}
void bgPreload(void)
{
s32 i;
for (i = 1; i < g_Vars.roomcount; i++) {
bgLoadRoom(i);
}
}

View File

@ -48,7 +48,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)));
}

View File

@ -413,6 +413,7 @@ void lvReset(s32 stagenum)
portalsReset();
lightsReset();
setCurrentPlayerNum(0);
bgPreload();
}
if (g_Vars.lvmpbotlevel) {
@ -944,9 +945,6 @@ Gfx *lvPrintRateText(Gfx *gdl)
}
x = 10;
sprintf(buffer, "mema free %d KB\n", memaGetLongestFree() / 1024);
gdl = textRender(gdl, &x, &y, buffer, g_CharsHandelGothicXs, g_FontHandelGothicXs, 0x00ff00a0, 0x000000a0, viGetWidth(), viGetHeight(), 0, 0);
sprintf(buffer, "memp free %d KB\n", mempGetStageFree() / 1024);
gdl = textRender(gdl, &x, &y, buffer, g_CharsHandelGothicXs, g_FontHandelGothicXs, 0x00ff00a0, 0x000000a0, viGetWidth(), viGetHeight(), 0, 0);
}

View File

@ -102,5 +102,6 @@ s32 bg0f164e8c(struct coord *arg0, struct coord *arg1);
bool bgIsBboxOverlapping(struct coord *arg0, struct coord *arg1, struct coord *arg2, struct coord *arg3);
void portalFindBbox(s32 portalnum, struct coord *bbmin, struct coord *bbmax);
void bgFindEnteredRooms(struct coord *bbmin, struct coord *upper, s16 *rooms, s32 maxlen, bool arg4);
void bgPreload(void);
#endif

View File

@ -71,22 +71,22 @@ bool g_MainIsEndscreen = false;
s32 g_DoBootPakMenu = 0;
struct stageallocation g_StageAllocations8Mb[] = {
{ STAGE_MP_SKEDAR, "-ml0 -me0 -mgfx200 -mvtx200 -ma400" },
{ STAGE_MP_RAVINE, "-ml0 -me0 -mgfx200 -mvtx200 -ma400" },
{ STAGE_MP_PIPES, "-ml0 -me0 -mgfx200 -mvtx200 -ma400" },
{ STAGE_MP_G5BUILDING, "-ml0 -me0 -mgfx200 -mvtx200 -ma400" },
{ STAGE_MP_SEWERS, "-ml0 -me0 -mgfx200 -mvtx200 -ma400" },
{ STAGE_MP_WAREHOUSE, "-ml0 -me0 -mgfx200 -mvtx200 -ma400" },
{ STAGE_MP_BASE, "-ml0 -me0 -mgfx200 -mvtx200 -ma400" },
{ STAGE_MP_COMPLEX, "-ml0 -me0 -mgfx200 -mvtx200 -ma400" },
{ STAGE_MP_TEMPLE, "-ml0 -me0 -mgfx200 -mvtx200 -ma400" },
{ STAGE_MP_FELICITY, "-ml0 -me0 -mgfx200 -mvtx200 -ma400" },
{ STAGE_MP_AREA52, "-ml0 -me0 -mgfx200 -mvtx200 -ma400" },
{ STAGE_MP_GRID, "-ml0 -me0 -mgfx200 -mvtx200 -ma400" },
{ STAGE_MP_CARPARK, "-ml0 -me0 -mgfx200 -mvtx200 -ma400" },
{ STAGE_MP_RUINS, "-ml0 -me0 -mgfx200 -mvtx200 -ma400" },
{ STAGE_MP_FORTRESS, "-ml0 -me0 -mgfx200 -mvtx200 -ma400" },
{ STAGE_MP_VILLA, "-ml0 -me0 -mgfx200 -mvtx200 -ma400" },
{ STAGE_MP_SKEDAR, "-ml0 -me0 -mgfx200 -mvtx200 -ma0" },
{ STAGE_MP_RAVINE, "-ml0 -me0 -mgfx200 -mvtx200 -ma0" },
{ STAGE_MP_PIPES, "-ml0 -me0 -mgfx200 -mvtx200 -ma0" },
{ STAGE_MP_G5BUILDING, "-ml0 -me0 -mgfx200 -mvtx200 -ma0" },
{ STAGE_MP_SEWERS, "-ml0 -me0 -mgfx200 -mvtx200 -ma0" },
{ STAGE_MP_WAREHOUSE, "-ml0 -me0 -mgfx200 -mvtx200 -ma0" },
{ STAGE_MP_BASE, "-ml0 -me0 -mgfx200 -mvtx200 -ma0" },
{ STAGE_MP_COMPLEX, "-ml0 -me0 -mgfx200 -mvtx200 -ma0" },
{ STAGE_MP_TEMPLE, "-ml0 -me0 -mgfx200 -mvtx200 -ma0" },
{ STAGE_MP_FELICITY, "-ml0 -me0 -mgfx200 -mvtx200 -ma0" },
{ STAGE_MP_AREA52, "-ml0 -me0 -mgfx200 -mvtx200 -ma0" },
{ STAGE_MP_GRID, "-ml0 -me0 -mgfx200 -mvtx200 -ma0" },
{ STAGE_MP_CARPARK, "-ml0 -me0 -mgfx200 -mvtx200 -ma0" },
{ STAGE_MP_RUINS, "-ml0 -me0 -mgfx200 -mvtx200 -ma0" },
{ STAGE_MP_FORTRESS, "-ml0 -me0 -mgfx200 -mvtx200 -ma0" },
{ STAGE_MP_VILLA, "-ml0 -me0 -mgfx200 -mvtx200 -ma0" },
{ STAGE_4MBMENU, "-mgfx100 -mvtx50 -ma50" },
{ STAGE_TITLE, "-ml0 -me0 -mgfx80 -mvtx20 -ma001" },
{ 0, "-ml0 -me0 -mgfx120 -mvtx98 -ma300" },
@ -902,7 +902,12 @@ void mainLoop(void)
g_MainMemaHeapSize = strtol(argFindByPrefix(1, "-ma"), NULL, 0) * 1024;
}
memaReset(mempAlloc(g_MainMemaHeapSize, MEMPOOL_STAGE), g_MainMemaHeapSize);
if (g_MainMemaHeapSize) {
memaReset(mempAlloc(g_MainMemaHeapSize, MEMPOOL_STAGE), g_MainMemaHeapSize);
} else {
memaReset(NULL, 0);
}
langReset(g_StageNum);
playermgrReset();

View File

@ -217,15 +217,6 @@ void memaReset(void *heapaddr, u32 heapsize)
{
struct memaspace *space;
#if VERSION != VERSION_NTSC_BETA && VERSION != VERSION_PAL_BETA
// Adding an amount to the heap size here means that mema can allocate past
// the end of its heap. This would overflow into the gun names language
// file. Maybe this code was intended to be temporary while a developer
// figured out how much memory was needed, but they forgot to remove it?
// @dangerous
heapsize += 0x8e0;
#endif
g_MemaHeap.unk000 = 0;
g_MemaHeap.start.addr = 0;