diff --git a/data/dynos_mgr_models.cpp b/data/dynos_mgr_models.cpp index d06f796e..f2033cac 100644 --- a/data/dynos_mgr_models.cpp +++ b/data/dynos_mgr_models.cpp @@ -21,18 +21,12 @@ struct ModelInfo { enum ModelPool modelPool; }; -struct ScheduledFreePool { - struct DynamicPool* pool; -}; - static struct DynamicPool* sModelPools[MODEL_POOL_MAX] = { 0 }; static std::map sAssetMap[MODEL_POOL_MAX]; static std::map> sIdMap; static std::map sOverwriteMap; -static std::vector sPoolsToFree; - static u32 find_empty_id() { u32 id = 256; while (true) { @@ -168,12 +162,7 @@ void DynOS_Model_ClearPool(enum ModelPool aModelPool) { if (!sModelPools[aModelPool]) { return; } // schedule pool to be freed - sPoolsToFree.push_back({ - .pool = sModelPools[aModelPool], - }); - - // clear pointer - sModelPools[aModelPool] = NULL; + dynamic_pool_free_pool(sModelPools[aModelPool]); // clear overwrite if (aModelPool == MODEL_POOL_LEVEL) { @@ -202,12 +191,4 @@ void DynOS_Model_ClearPool(enum ModelPool aModelPool) { void DynOS_Model_Update() { - // only free a pool when we've scheduled at least 3 - // this is required because the way that sm64 loads areas is actually insane - // if we free immediately, the camera graph node is incorrect on the star selection screen - if (sPoolsToFree.size() <= 2) { return; } - - auto& it = sPoolsToFree[0]; - dynamic_pool_free_pool(it.pool); - sPoolsToFree.erase(sPoolsToFree.begin()); } \ No newline at end of file diff --git a/src/engine/level_script.c b/src/engine/level_script.c index 60959a1c..02777d16 100644 --- a/src/engine/level_script.c +++ b/src/engine/level_script.c @@ -366,7 +366,6 @@ static void level_reset_globals(void) { // free previous level pool if (gLevelPool != NULL) { dynamic_pool_free_pool(gLevelPool); - gLevelPool = NULL; } // reset envfx diff --git a/src/game/envfx_snow.c b/src/game/envfx_snow.c index 765b3ec1..6f95af83 100644 --- a/src/game/envfx_snow.c +++ b/src/game/envfx_snow.c @@ -156,11 +156,8 @@ void envfx_update_snowflake_count(s32 mode, Vec3s marioPos) { * Deallocate the buffer storing snow particles and set the environment effect * to none. */ -void envfx_cleanup_snow(void *snowParticleArray) { +void envfx_cleanup_snow(UNUSED void *snowParticleArray) { if (gEnvFxMode) { - if (snowParticleArray) { - dynamic_pool_free(gLevelPool, snowParticleArray); - } gEnvFxMode = ENVFX_MODE_NONE; } } diff --git a/src/game/memory.c b/src/game/memory.c index 49743206..01f1f3d2 100644 --- a/src/game/memory.c +++ b/src/game/memory.c @@ -16,6 +16,7 @@ struct DynamicPool* dynamic_pool_init(void) { struct DynamicPool* pool = calloc(1, sizeof(struct DynamicPool)); pool->usedSpace = 0; pool->tail = NULL; + pool->nextFree = NULL; return pool; } @@ -75,14 +76,19 @@ bool dynamic_pool_contains(struct DynamicPool *pool, void* ptr) { void dynamic_pool_free_pool(struct DynamicPool *pool) { if (!pool) { return; } - struct DynamicPoolNode* node = pool->tail; + + struct DynamicPoolNode* node = pool->nextFree; while (node) { struct DynamicPoolNode* prev = node->prev; free(node->ptr); free(node); node = prev; } - free(pool); + + // schedule current pool to be free'd on the next call + pool->nextFree = pool->tail; + pool->tail = NULL; + pool->usedSpace = 0; } ////////////////// diff --git a/src/game/memory.h b/src/game/memory.h index 910ae91c..9fc0d7a9 100644 --- a/src/game/memory.h +++ b/src/game/memory.h @@ -14,6 +14,7 @@ struct DynamicPool { u32 usedSpace; + struct DynamicPoolNode* nextFree; struct DynamicPoolNode* tail; }; diff --git a/src/game/paintings.c b/src/game/paintings.c index e930800d..eb6a187b 100644 --- a/src/game/paintings.c +++ b/src/game/paintings.c @@ -1526,8 +1526,14 @@ Gfx *display_painting_rippling(struct Painting *painting) { } // The mesh data is freed every frame. - dynamic_pool_free(gLevelPool, painting->ripples.paintingMesh); - dynamic_pool_free(gLevelPool, painting->ripples.paintingTriNorms); + if (painting->ripples.paintingMesh) { + dynamic_pool_free(gLevelPool, painting->ripples.paintingMesh); + painting->ripples.paintingMesh = NULL; + } + if (painting->ripples.paintingTriNorms) { + dynamic_pool_free(gLevelPool, painting->ripples.paintingTriNorms); + painting->ripples.paintingTriNorms = NULL; + } return dlist; }