diff --git a/src/game/lv.c b/src/game/lv.c index 5ea78bb55..4cb45c4b9 100644 --- a/src/game/lv.c +++ b/src/game/lv.c @@ -1767,7 +1767,6 @@ void lvTick(void) sndTick(); pakExecuteDebugOperations(); lightingTick(); - modelmgrPrintCounts(); boltbeamsTick(); amTick(); menuTick(); diff --git a/src/game/modelmgr.c b/src/game/modelmgr.c index d701ff3ee..c29577cea 100644 --- a/src/game/modelmgr.c +++ b/src/game/modelmgr.c @@ -15,6 +15,12 @@ struct modelrwdatabinding *g_ModelRwdataBindings[3]; s32 g_MaxModels = 0; s32 g_MaxAnims = 0; +s32 g_MaxRwdataType1 = 0; +s32 g_MaxRwdataType2 = 0; +s32 g_MaxRwdataType3 = 0; +s32 g_Rwdata1EntrySizeInWords = 0; +s32 g_Rwdata2EntrySizeInWords = 0; +s32 g_Rwdata3EntrySizeInWords = 0; bool g_ModelIsLvResetting = false; s32 g_ModelMostType1 = 0; s32 g_ModelMostType2 = 0; @@ -22,86 +28,12 @@ s32 g_ModelMostType3 = 0; s32 g_ModelMostModels = 0; s32 g_ModelMostAnims = 0; -#define NUMTYPE1() (IS4MB() ? 0 : 35) -#define NUMTYPE2() (IS4MB() ? 24 : 25) -#define NUMTYPE3() (IS4MB() ? 0 : 20) - bool modelmgrCanSlotFitRwdata(struct model *modelslot, struct modelfiledata *modeldef) { return modeldef->rwdatalen <= 0 || (modelslot->rwdatas != NULL && modelslot->rwdatalen >= modeldef->rwdatalen); } -void modelmgrPrintCounts(void) -{ - s32 i; - s32 numtype1 = 0; - s32 numtype2 = 0; - s32 numtype3 = 0; - s32 nummodels = 0; - s32 numanims = 0; - - for (i = 0; i < NUMTYPE1(); i++) { - if (g_ModelRwdataBindings[0][i].model) { - numtype1++; - } - } - - for (i = 0; i < NUMTYPE2(); i++) { - if (g_ModelRwdataBindings[1][i].model) { - numtype2++; - } - } - - for (i = 0; i < NUMTYPE3(); i++) { - if (g_ModelRwdataBindings[2][i].model) { - numtype3++; - } - } - - for (i = 0; i < g_MaxModels; i++) { - if (g_ModelSlots[i].filedata) { - nummodels++; - } - } - - for (i = 0; i < g_MaxAnims; i++) { - if (g_AnimSlots[i].animnum != -1) { - numanims++; - } - } - - if (numtype1 > g_ModelMostType1) { - g_ModelMostType1 = numtype1; - } - - if (numtype2 > g_ModelMostType2) { - g_ModelMostType2 = numtype2; - } - - if (numtype3 > g_ModelMostType3) { - g_ModelMostType3 = numtype3; - } - - if (nummodels > g_ModelMostModels) { - g_ModelMostModels = nummodels; - } - - if (numanims > g_ModelMostAnims) { - g_ModelMostAnims = numanims; - } - - osSyncPrintf("MOT : Type 1 = %d/%d (%d)"); - osSyncPrintf("MOT : Type 2 = %d/%d (%d)"); - osSyncPrintf("MOT : Type 3 = %d/%d (%d)"); - osSyncPrintf("MOT : Type OI = %d/%d/%d/%d"); - osSyncPrintf("MOT : Type OA = %d/%d/%d/%d"); - osSyncPrintf("MOT : g_ObjCount = %d"); - osSyncPrintf("MOT : g_AnimCount = %d"); - - if (IS4MB()); -} - struct model *modelmgrInstantiateModel(struct modelfiledata *modeldef, bool withanim) { struct model *model = NULL; @@ -146,13 +78,13 @@ struct model *modelmgrInstantiateModel(struct modelfiledata *modeldef, bool with } else { // At this point, it's during gameplay. A model instance slot has // been found or allocated, but rwdata needs to be allocated. - if (modeldef->rwdatalen < 256) { + if (modeldef->rwdatalen < g_Rwdata3EntrySizeInWords) { bool done = false; u32 stack; - // 4 words (0x10 bytes) or less -> try type 1 - if (modeldef->rwdatalen <= 4) { - for (i = 0; i < NUMTYPE1(); i++) { + // Try type 1 + if (modeldef->rwdatalen <= g_Rwdata1EntrySizeInWords) { + for (i = 0; i < g_MaxRwdataType1; i++) { if (g_ModelRwdataBindings[0][i].model == NULL) { osSyncPrintf("MotInst: Using cache entry type 1 %d (0x%08x) - Bytes=%d\n"); rwdatas = g_ModelRwdataBindings[0][i].rwdata; @@ -163,12 +95,11 @@ struct model *modelmgrInstantiateModel(struct modelfiledata *modeldef, bool with } } - // 52 words (0xd0 bytes) or less -> try type 2 - if (!done && modeldef->rwdatalen <= 52) { - for (i = 0; i < NUMTYPE2(); i++) { + // Try type 2 + if (!done && modeldef->rwdatalen <= g_Rwdata2EntrySizeInWords) { + for (i = 0; i < g_MaxRwdataType2; i++) { if (g_ModelRwdataBindings[1][i].model == NULL) { osSyncPrintf("MotInst: Using cache entry type 2 %d (0x%08x) - Bytes=%d\n"); - if (IS4MB()); rwdatas = g_ModelRwdataBindings[1][i].rwdata; g_ModelRwdataBindings[1][i].model = model; done = true; @@ -177,13 +108,12 @@ struct model *modelmgrInstantiateModel(struct modelfiledata *modeldef, bool with } } - // 256 words (0x400 bytes) or less -> try type 3 + // Try type 3 // First looking for unused slots with an existing rwdata allocation - if (!done && modeldef->rwdatalen <= 256) { - for (i = 0; i < NUMTYPE3(); i++) { + if (!done && modeldef->rwdatalen <= g_Rwdata3EntrySizeInWords) { + for (i = 0; i < g_MaxRwdataType3; i++) { if (g_ModelRwdataBindings[2][i].model == NULL && g_ModelRwdataBindings[2][i].rwdata != NULL) { osSyncPrintf("MotInst: Using cache entry type 3 %d (0x%08x) - Bytes=%d\n"); - if (IS4MB()); rwdatas = g_ModelRwdataBindings[2][i].rwdata; g_ModelRwdataBindings[2][i].model = model; done = true; @@ -193,10 +123,10 @@ struct model *modelmgrInstantiateModel(struct modelfiledata *modeldef, bool with } // Type 3 again, but looking for null rwdata allocations - if (!done && modeldef->rwdatalen <= 256) { - for (i = 0; i < NUMTYPE3(); i++) { + if (!done && modeldef->rwdatalen <= g_Rwdata3EntrySizeInWords) { + for (i = 0; i < g_MaxRwdataType3; i++) { if (g_ModelRwdataBindings[2][i].model == NULL && g_ModelRwdataBindings[2][i].rwdata == NULL) { - g_ModelRwdataBindings[2][i].rwdata = mempAlloc(256 * 4, MEMPOOL_STAGE); + g_ModelRwdataBindings[2][i].rwdata = mempAlloc(g_Rwdata3EntrySizeInWords * 4, MEMPOOL_STAGE); rwdatas = g_ModelRwdataBindings[2][i].rwdata; g_ModelRwdataBindings[2][i].model = model; break; @@ -207,11 +137,7 @@ struct model *modelmgrInstantiateModel(struct modelfiledata *modeldef, bool with // empty } - if (withanim) { - datalen = 256; - } else { - datalen = IS4MB() ? 52 : 256; - } + datalen = 256; if (datalen < modeldef->rwdatalen) { datalen = modeldef->rwdatalen; @@ -259,7 +185,7 @@ void modelmgrFreeModel(struct model *model) bool done = false; s32 i; - for (i = 0; i < NUMTYPE1(); i++) { + for (i = 0; i < g_MaxRwdataType1; i++) { if (g_ModelRwdataBindings[0][i].model == model) { g_ModelRwdataBindings[0][i].model = NULL; @@ -272,12 +198,11 @@ void modelmgrFreeModel(struct model *model) } if (!done) { - for (i = 0; i < NUMTYPE2(); i++) { + for (i = 0; i < g_MaxRwdataType2; i++) { if (g_ModelRwdataBindings[1][i].model == model) { osSyncPrintf("\nMotInst: Freeing type 2 cache entry %d (0x%08x)\n\n"); g_ModelRwdataBindings[1][i].model = NULL; - model->rwdatas = NULL; model->rwdatalen = -1; @@ -288,7 +213,7 @@ void modelmgrFreeModel(struct model *model) } if (!done) { - for (i = 0; i < NUMTYPE3(); i++) { + for (i = 0; i < g_MaxRwdataType3; i++) { if (g_ModelRwdataBindings[2][i].model == model) { osSyncPrintf("\nMotInst: Freeing type 3 cache entry %d (0x%08x)\n\n"); g_ModelRwdataBindings[2][i].model = NULL; diff --git a/src/game/modelmgrreset.c b/src/game/modelmgrreset.c index 452e0f67c..732c612f5 100644 --- a/src/game/modelmgrreset.c +++ b/src/game/modelmgrreset.c @@ -23,10 +23,12 @@ #include "data.h" #include "types.h" -#define NUMTYPE1() (IS4MB() ? 0 : 35) -#define NUMTYPE2() (IS4MB() ? 24 : 25) -#define NUMTYPE3() (IS4MB() ? 0 : 20) -#define NUMSPARE() (IS4MB() ? 40 : 60) +extern s32 g_MaxRwdataType1; +extern s32 g_MaxRwdataType2; +extern s32 g_MaxRwdataType3; +extern s32 g_Rwdata1EntrySizeInWords; +extern s32 g_Rwdata2EntrySizeInWords; +extern s32 g_Rwdata3EntrySizeInWords; void modelmgrReset(void) { @@ -56,7 +58,7 @@ void modelmgrSetLvResetting(bool value) * (eg. for thrown weapons), and a further 20 model and 20 anim slots are * allocated for animated objects. */ -void modelmgrAllocateSlots(s32 numobjs, s32 numchrs) +void modelmgrAllocateSlots(s32 numobjs, s32 numchrs, bool haslaptops) { s32 rwdata2sizetotal; s32 rwdata1sizetotal; @@ -67,25 +69,47 @@ void modelmgrAllocateSlots(s32 numobjs, s32 numchrs) s32 totalsize; s32 modelssize; s32 animssize; - s32 rwdata1sizeeach = 0x10; - s32 rwdata2sizeeach = 0xd0; - s32 rwdata3sizeeach = 0; - s32 maxanimatedobjs = 20; - s32 numspare; g_ModelNumObjs = numobjs; g_ModelNumChrs = numchrs; - numspare = NUMSPARE(); - g_MaxModels = numobjs + numspare + numchrs + maxanimatedobjs; - g_MaxAnims = numchrs + maxanimatedobjs; + if (g_Vars.stagenum == STAGE_TITLE) { + g_MaxRwdataType1 = 35; + g_MaxRwdataType2 = 25; + g_MaxRwdataType3 = 20; + g_Rwdata1EntrySizeInWords = 4; + g_Rwdata2EntrySizeInWords = 52; + g_Rwdata3EntrySizeInWords = 0; - i = NUMTYPE2(); - bindingssize = (NUMTYPE1() + i + NUMTYPE3()) * sizeof(struct modelrwdatabinding); + g_MaxModels = 60; + g_MaxAnims = 20; + } else { + g_Rwdata1EntrySizeInWords = 3; + g_Rwdata2EntrySizeInWords = 10; + g_Rwdata3EntrySizeInWords = 0; - rwdata1sizetotal = NUMTYPE1() * rwdata1sizeeach; - rwdata2sizetotal = NUMTYPE2() * rwdata2sizeeach; - rwdata3sizetotal = NUMTYPE3() * rwdata3sizeeach; + // Type 1 will be used for third person gun models. + // Chrs can equip two guns, and we need to consider dropped items too. + // Guns that spawn on the ground store their rwdata elsewhere. + g_MaxRwdataType1 = numchrs * 2 + MAX_DROPPED_ITEMS; + + // Each deployed laptop uses 10 slots of rwdata + g_MaxRwdataType2 = haslaptops ? numchrs : 0; + + // Type 3 is allocated on the fly and shouldn't happen, + // but if it does these slots will track the model-rwdata bindings + // and hopefully prevent any memory leaks. + g_MaxRwdataType3 = 20; + + g_MaxModels = numobjs + numchrs + MAX_DROPPED_ITEMS; + g_MaxAnims = numchrs; + } + + bindingssize = (g_MaxRwdataType1 + g_MaxRwdataType2 + g_MaxRwdataType3) * sizeof(struct modelrwdatabinding); + + rwdata1sizetotal = g_MaxRwdataType1 * g_Rwdata1EntrySizeInWords * 4; + rwdata2sizetotal = g_MaxRwdataType2 * g_Rwdata2EntrySizeInWords * 4; + rwdata3sizetotal = g_MaxRwdataType3 * g_Rwdata3EntrySizeInWords * 4; modelssize = ALIGN16(g_MaxModels * sizeof(struct model)); animssize = ALIGN16(g_MaxAnims * sizeof(struct anim)); @@ -98,19 +122,19 @@ void modelmgrAllocateSlots(s32 numobjs, s32 numchrs) ptr = mempAlloc(totalsize, MEMPOOL_STAGE); - if (NUMTYPE1()) { + if (g_MaxRwdataType1) { g_ModelRwdataBindings[0] = (struct modelrwdatabinding *) ptr; - ptr += NUMTYPE1() * 8; + ptr += g_MaxRwdataType1 * 8; } - if (NUMTYPE2()) { + if (g_MaxRwdataType2) { g_ModelRwdataBindings[1] = (struct modelrwdatabinding *) ptr; - ptr += NUMTYPE2() * 8; + ptr += g_MaxRwdataType2 * 8; } - if (NUMTYPE3()) { + if (g_MaxRwdataType3) { g_ModelRwdataBindings[2] = (struct modelrwdatabinding *) ptr; - ptr += NUMTYPE3() * 8; + ptr += g_MaxRwdataType3 * 8; } g_ModelSlots = (struct model *) ptr; @@ -118,25 +142,25 @@ void modelmgrAllocateSlots(s32 numobjs, s32 numchrs) g_AnimSlots = (struct anim *) ptr; ptr += animssize; - for (i = 0; i < NUMTYPE1(); i++) { + for (i = 0; i < g_MaxRwdataType1; i++) { g_ModelRwdataBindings[0][i].rwdata = ptr; g_ModelRwdataBindings[0][i].model = NULL; - ptr += rwdata1sizeeach; + ptr += g_Rwdata1EntrySizeInWords * 4; } - for (i = 0; i < NUMTYPE2(); i++) { + for (i = 0; i < g_MaxRwdataType2; i++) { g_ModelRwdataBindings[1][i].rwdata = ptr; g_ModelRwdataBindings[1][i].model = NULL; - ptr += rwdata2sizeeach; + ptr += g_Rwdata2EntrySizeInWords * 4; } - for (i = 0; i < NUMTYPE3(); i++) { + for (i = 0; i < g_MaxRwdataType3; i++) { g_ModelRwdataBindings[2][i].rwdata = NULL; g_ModelRwdataBindings[2][i].model = NULL; - ptr += rwdata3sizeeach; + ptr += g_Rwdata3EntrySizeInWords * 4; } for (i = 0; i < g_MaxModels; i++) { diff --git a/src/game/setup.c b/src/game/setup.c index ef37fb9df..30b79b5e6 100644 --- a/src/game/setup.c +++ b/src/game/setup.c @@ -845,7 +845,7 @@ void setupAllocateEverything(void) g_NumBots = setupCalculateMaxBots(numbotsrequested, haslaptops); // Allocate everything - modelmgrAllocateSlots(g_ModelNumObjs, PLAYERCOUNT() + g_NumBots); + modelmgrAllocateSlots(g_ModelNumObjs, PLAYERCOUNT() + g_NumBots, haslaptops); g_Vars.maxprops += PLAYERCOUNT() + g_NumBots; diff --git a/src/include/game/playerreset.h b/src/include/game/playerreset.h index bfa2ffb9f..061d93edd 100644 --- a/src/include/game/playerreset.h +++ b/src/include/game/playerreset.h @@ -6,7 +6,7 @@ void modelmgrReset(void); void modelmgrSetLvResetting(bool value); -void modelmgrAllocateSlots(s32 numobjs, s32 numchrs); +void modelmgrAllocateSlots(s32 numobjs, s32 numchrs, bool haslaptops); bool modelmgrLoadProjectileModeldefs(s32 weaponnum); void playerInitEyespy(void); void playerReset(void);