diff --git a/data/dynos.c.h b/data/dynos.c.h index daf47b17..c24f762d 100644 --- a/data/dynos.c.h +++ b/data/dynos.c.h @@ -71,6 +71,11 @@ s32 dynos_behavior_get_active_mod_index(BehaviorScript *bhvScript); const char *dynos_behavior_get_token(BehaviorScript *bhvScript, u32 index); void dynos_behavior_hook_all_custom_behaviors(void); +// -- models -- // +struct GraphNode* dynos_model_load_geo(enum ModelPool aModelPool, void* aAsset); +struct GraphNode* dynos_model_load_dl(enum ModelPool aModelPool, u8 aLayer, void* aAsset); +void dynos_model_clear_pool(enum ModelPool aModelPool); + // -- other -- // void dynos_mod_shutdown(void); void dynos_add_scroll_target(u32 index, const char *name, u32 offset, u32 size); diff --git a/data/dynos.cpp.h b/data/dynos.cpp.h index c5f10c8c..9c6d0ede 100644 --- a/data/dynos.cpp.h +++ b/data/dynos.cpp.h @@ -805,8 +805,6 @@ s32 DynOS_String_Width(const u8 *aStr64); // Geo // -void *DynOS_Geo_GetGraphNode(const void *aGeoLayout, bool aKeepInMemory); - // // Levels // @@ -961,6 +959,14 @@ DataNode* DynOS_MovtexQC_GetFromId(u32 id); DataNode* DynOS_MovtexQC_GetFromIndex(s32 index); void DynOS_MovtexQC_ModShutdown(); +// +// Model Manager +// + +struct GraphNode* DynOS_Model_LoadGeo(enum ModelPool aModelPool, void* aAsset); +struct GraphNode* DynOS_Model_LoadDl(enum ModelPool aModelPool, u8 aLayer, void* aAsset); +void DynOS_Model_ClearPool(enum ModelPool aModelPool); + // // Bin // diff --git a/data/dynos.h b/data/dynos.h index 1a76512d..ec051d5c 100644 --- a/data/dynos.h +++ b/data/dynos.h @@ -37,4 +37,11 @@ extern "C" { #define DYNOS_AT_STARTUP __attribute__((constructor)) #define DYNOS_AT_EXIT __attribute__((destructor)) +enum ModelPool { + MODEL_POOL_PERMANENT, + MODEL_POOL_SESSION, + MODEL_POOL_LEVEL, + MODEL_POOL_MAX, +}; + #endif diff --git a/data/dynos_c.cpp b/data/dynos_c.cpp index f673ea70..09f7f2bf 100644 --- a/data/dynos_c.cpp +++ b/data/dynos_c.cpp @@ -121,10 +121,6 @@ const void* dynos_geolayout_get(const char *name) { return DynOS_Actor_GetLayoutFromName(name); } -void *dynos_geolayout_to_graphnode(const void *geoLayout, bool keepInMemory) { - return DynOS_Geo_GetGraphNode(geoLayout, keepInMemory); -} - // -- collisions -- // void dynos_add_collision(const char *filePath, const char* collisionName) { @@ -226,7 +222,22 @@ void dynos_behavior_hook_all_custom_behaviors(void) { DynOS_Bhv_HookAllCustomBehaviors(); } +// -- models -- // + +struct GraphNode* dynos_model_load_geo(enum ModelPool aModelPool, void* aAsset) { + return DynOS_Model_LoadGeo(aModelPool, aAsset); +} + +struct GraphNode* dynos_model_load_dl(enum ModelPool aModelPool, u8 aLayer, void* aAsset) { + return DynOS_Model_LoadDl(aModelPool, aLayer, aAsset); +} + +void dynos_model_clear_pool(enum ModelPool aModelPool) { + DynOS_Model_ClearPool(aModelPool); +} + // -- other -- // + void dynos_mod_shutdown(void) { DynOS_Mod_Shutdown(); } diff --git a/data/dynos_mgr_actor.cpp b/data/dynos_mgr_actor.cpp index 6871f275..ff8ea9fc 100644 --- a/data/dynos_mgr_actor.cpp +++ b/data/dynos_mgr_actor.cpp @@ -49,7 +49,7 @@ void DynOS_Actor_AddCustom(const SysPath &aFilename, const char *aActorName) { ActorGfx actorGfx = { }; actorGfx.mGfxData = _GfxData; actorGfx.mPackIndex = MOD_PACK_INDEX; - actorGfx.mGraphNode = (GraphNode *) DynOS_Geo_GetGraphNode(geoLayout, false); + actorGfx.mGraphNode = (GraphNode *) DynOS_Model_LoadGeo(MODEL_POOL_SESSION, geoLayout); if (!actorGfx.mGraphNode) { Print(" ERROR: Couldn't load graph node for \"%s\"", actorName); free(actorName); @@ -167,7 +167,7 @@ void DynOS_Actor_Override_All(void) { for (struct Object *_Object = (struct Object *) _Head->header.next; _Object != _Head; _Object = (struct Object *) _Object->header.next) { if (_Object->header.gfx.sharedChild != NULL && _Object->header.gfx.sharedChild->georef != NULL) { GraphNode* georef = (GraphNode*)_Object->header.gfx.sharedChild->georef; - _Object->header.gfx.sharedChild = (GraphNode *) DynOS_Geo_GetGraphNode(georef, true); + _Object->header.gfx.sharedChild = DynOS_Model_LoadGeo(MODEL_POOL_PERMANENT, georef); } DynOS_Actor_Override((void**)&_Object->header.gfx.sharedChild); } diff --git a/data/dynos_mgr_models.cpp b/data/dynos_mgr_models.cpp new file mode 100644 index 00000000..f3fecbb9 --- /dev/null +++ b/data/dynos_mgr_models.cpp @@ -0,0 +1,68 @@ +#include +#include "dynos.cpp.h" + +extern "C" { +#include "engine/geo_layout.h" +#include "engine/graph_node.h" +} + +static struct AllocOnlyPool* sModelPools[MODEL_POOL_MAX] = { 0 }; +static std::map sModelMap[MODEL_POOL_MAX]; + +struct GraphNode* DynOS_Model_LoadGeo(enum ModelPool aModelPool, void* aAsset) { + // sanity check pool + if (aModelPool >= MODEL_POOL_MAX) { return NULL; } + + // allocate pool + if (!sModelPools[aModelPool]) { + sModelPools[aModelPool] = alloc_only_pool_init(); + } + + // check map + auto& map = sModelMap[aModelPool]; + if (map.count(aAsset)) { + return map[aAsset]; + } + + // load geo + struct GraphNode* node = process_geo_layout(sModelPools[aModelPool], aAsset); + + // store and return geo + map[aAsset] = node; + return node; +} + +struct GraphNode* DynOS_Model_LoadDl(enum ModelPool aModelPool, u8 aLayer, void* aAsset) { + // sanity check pool + if (aModelPool >= MODEL_POOL_MAX) { return NULL; } + + // allocate pool + if (!sModelPools[aModelPool]) { + sModelPools[aModelPool] = alloc_only_pool_init(); + } + + // check map + auto& map = sModelMap[aModelPool]; + if (map.count(aAsset)) { + return map[aAsset]; + } + + // load geo + struct GraphNode* node = (struct GraphNode *) init_graph_node_display_list(sModelPools[aModelPool], NULL, aLayer, aAsset); + + // store and return geo + map[aAsset] = node; + return node; +} + +void DynOS_Model_ClearPool(enum ModelPool aModelPool) { + if (!sModelPools[aModelPool]) { return; } + + // free and realloc pool + alloc_only_pool_free(sModelPools[aModelPool]); + sModelPools[aModelPool] = NULL; + + // clear map + auto& map = sModelMap[aModelPool]; + map.clear(); +} diff --git a/data/dynos_mgr_pack.cpp b/data/dynos_mgr_pack.cpp index a6fa559d..facfa8ca 100644 --- a/data/dynos_mgr_pack.cpp +++ b/data/dynos_mgr_pack.cpp @@ -42,7 +42,7 @@ static void DynOS_Pack_ActivateActor(s32 aPackIndex, PairmGeoLayouts.end() - 1); - GraphNode* graphNode = (GraphNode *) DynOS_Geo_GetGraphNode(geoNode->mData, false); + GraphNode* graphNode = DynOS_Model_LoadGeo(MODEL_POOL_PERMANENT, geoNode->mData); if (graphNode == NULL) { return; } const void* georef = DynOS_Builtin_Actor_GetFromName(aActorName); diff --git a/data/dynos_misc.cpp b/data/dynos_misc.cpp index 05fd7c61..57090653 100644 --- a/data/dynos_misc.cpp +++ b/data/dynos_misc.cpp @@ -137,44 +137,6 @@ static void _RelocateGraphNodePointers(struct GraphNode *aHead, u64 aOffset) { } while (_Node != aHead); } -static Array> sLoadedGraphNodes = {}; - -// DO NOT COMMIT: -// need to separate pools into one that will be free'd and one that wont be and when -void *DynOS_Geo_GetGraphNode(const void *aGeoLayout, bool aKeepInMemory) { - if (aKeepInMemory) { - s32 _LoadedGraphNodeIndex = sLoadedGraphNodes.FindIf([&aGeoLayout](const Pair &aLoadedGraphNode) { return aLoadedGraphNode.first == aGeoLayout; }); - if (_LoadedGraphNodeIndex != -1) { - return sLoadedGraphNodes[_LoadedGraphNodeIndex].second; - } - } - - // Process the geo layout on a large pool of memory (16 MB) - struct AllocOnlyPool *_Pool = alloc_only_pool_init(); - void *_Processed = process_geo_layout(_Pool, (void *) aGeoLayout); - - // Copy the graph node data to the minimum amount of memory needed - if (_Processed && _Pool->usedSpace != 0) { - /*struct GraphNode *_Node = (struct GraphNode *) calloc(1, _Pool->usedSpace); - memcpy(_Node, _Pool->startPtr, _Pool->usedSpace); - - // Relocate all graph pointers - u64 _Offset = (u64) _Node - (u64) _Pool->startPtr; - _RelocateGraphNodePointers(_Node, _Offset);*/ - - // Add it to loaded graph nodes - if (aKeepInMemory || true) { // DO NOT COMMIT - //sLoadedGraphNodes.Add({ (void *) aGeoLayout, (void *) _Node }); - sLoadedGraphNodes.Add({ (void *) aGeoLayout, (void *) _Processed }); - } - - return _Processed; - } else { - alloc_only_pool_free(_Pool); - } - return NULL; -} - // // Scroll Targets // diff --git a/src/engine/geo_layout.c b/src/engine/geo_layout.c index fba334b5..7ddacaf2 100644 --- a/src/engine/geo_layout.c +++ b/src/engine/geo_layout.c @@ -48,8 +48,8 @@ GeoLayoutCommandProc GeoLayoutJumpTable[] = { }; struct GraphNode gObjParentGraphNode; -struct AllocOnlyPool *gGraphNodePool; -struct GraphNode *gCurRootGraphNode; +struct AllocOnlyPool *gGraphNodePool = NULL; +struct GraphNode *gCurRootGraphNode = NULL; UNUSED s32 D_8038BCA8; diff --git a/src/engine/level_script.c b/src/engine/level_script.c index be186698..ad75527b 100644 --- a/src/engine/level_script.c +++ b/src/engine/level_script.c @@ -399,6 +399,7 @@ static void level_cmd_alloc_level_pool(void) { alloc_only_pool_free(sLevelPool); sLevelPool = NULL; } + dynos_model_clear_pool(MODEL_POOL_LEVEL); // allocate new level pool if (sLevelPool == NULL) { @@ -432,8 +433,7 @@ static void level_cmd_begin_area(void) { void *geoLayoutAddr = CMD_GET(void *, 4); if (areaIndex < 8) { - struct GraphNodeRoot *screenArea = - (struct GraphNodeRoot *) process_geo_layout(sLevelPool, geoLayoutAddr); + struct GraphNodeRoot *screenArea = (struct GraphNodeRoot *) dynos_model_load_geo(MODEL_POOL_LEVEL, geoLayoutAddr); struct GraphNodeCamera *node = (struct GraphNodeCamera *) screenArea->views[0]; sCurrAreaIndex = areaIndex; @@ -464,7 +464,7 @@ static void level_cmd_load_model_from_dl(void) { void *val3 = CMD_GET(void *, 4); if (val1 < MAX_LOADED_GRAPH_NODES) { - gLoadedGraphNodes[val1] = (struct GraphNode *) init_graph_node_display_list(sLevelPool, 0, val2, val3); + gLoadedGraphNodes[val1] = dynos_model_load_dl(sFinishedLoadingPerm ? MODEL_POOL_LEVEL : MODEL_POOL_PERMANENT, val2, val3); if (sFinishedLoadingPerm) { sLevelOwnedGraphNodes[val1] = true; } smlua_model_util_remember(val1, val2, val3, 1); } @@ -477,7 +477,7 @@ static void level_cmd_load_model_from_geo(void) { void *arg1 = CMD_GET(void *, 4); if (arg0 < MAX_LOADED_GRAPH_NODES) { - gLoadedGraphNodes[arg0] = process_geo_layout(sLevelPool, arg1); + gLoadedGraphNodes[arg0] = dynos_model_load_geo(sFinishedLoadingPerm ? MODEL_POOL_LEVEL : MODEL_POOL_PERMANENT, arg1); if (sFinishedLoadingPerm) { sLevelOwnedGraphNodes[arg0] = true; } smlua_model_util_remember(arg0, LAYER_OPAQUE, arg1, 0); } @@ -1032,7 +1032,7 @@ static void level_cmd_place_object_ext2(void) { spawnInfo->behaviorArg = CMD_GET(u32, 16); spawnInfo->behaviorScript = (BehaviorScript*)get_behavior_from_id(behId); - u16 slot = smlua_model_util_load_with_pool(modelId, sLevelPool); + u16 slot = smlua_model_util_load_with_pool(modelId, MODEL_POOL_LEVEL); if (slot >= MAX_LOADED_GRAPH_NODES) { slot = MODEL_NONE; } spawnInfo->unk18 = gLoadedGraphNodes[slot]; spawnInfo->next = gAreas[sCurrAreaIndex].objectSpawnInfos; @@ -1055,7 +1055,7 @@ static void level_cmd_load_model_from_geo_ext(void) { u32 modelId = smlua_model_util_get_id(geoName); if (modelSlot < MAX_LOADED_GRAPH_NODES) { - smlua_model_util_load_with_pool_and_cache_id(modelId, sLevelPool, modelSlot); + smlua_model_util_load_with_pool_and_cache_id(modelId, MODEL_POOL_LEVEL, modelSlot); } sCurrentCmd = CMD_NEXT; diff --git a/src/game/memory.c b/src/game/memory.c index 71df74d9..93945380 100644 --- a/src/game/memory.c +++ b/src/game/memory.c @@ -351,20 +351,6 @@ void mem_pool_free(struct MemoryPool *pool, void *addr) { } } -void *alloc_display_list(u32 size) { - void *ptr = NULL; - - size = ALIGN8(size); - if (gGfxPoolEnd - size >= (u8 *) gDisplayListHead) { - gGfxPoolEnd -= size; - ptr = gGfxPoolEnd; - memset(ptr, 0, size); - } else { - LOG_ERROR("Failed to allocate display list of size 0x%X!", size); - } - return ptr; -} - static struct MarioAnimDmaRelatedThing *func_802789F0(u8 *srcAddr) { struct MarioAnimDmaRelatedThing *sp1C = dynamic_dma_read(srcAddr, srcAddr + sizeof(u32), MEMORY_POOL_LEFT); diff --git a/src/game/memory.h b/src/game/memory.h index 2b69bfc9..eccb2e0d 100644 --- a/src/game/memory.h +++ b/src/game/memory.h @@ -56,7 +56,6 @@ u32 main_pool_pop_state(void); struct AllocOnlyPool* alloc_only_pool_init(void); void* alloc_only_pool_alloc(struct AllocOnlyPool *pool, u32 size); -struct AllocOnlyPool* alloc_only_pool_resize(struct AllocOnlyPool *pool, u32 size); void alloc_only_pool_free(struct AllocOnlyPool *pool); struct MemoryPool *mem_pool_init(u32 size, u32 side); diff --git a/src/game/memory_dynamic.c b/src/game/memory_dynamic.c index 109c35fc..c6507956 100644 --- a/src/game/memory_dynamic.c +++ b/src/game/memory_dynamic.c @@ -1,18 +1,6 @@ #include -#include - -#include "sm64.h" - -#define INCLUDED_FROM_MEMORY_C - -#include "buffers/buffers.h" -#include "decompress.h" -#include "game_init.h" -#include "main.h" #include "memory.h" -#include "segment_symbols.h" -#include "segments.h" -#include "pc/debuglog.h" +#include "rendering_graph_node.h" struct AllocOnlyPool* alloc_only_pool_init(void) { struct AllocOnlyPool* pool = calloc(1, sizeof(struct AllocOnlyPool)); @@ -22,6 +10,8 @@ struct AllocOnlyPool* alloc_only_pool_init(void) { } void* alloc_only_pool_alloc(struct AllocOnlyPool *pool, u32 size) { + if (!pool) { return NULL; } + struct AllocOnlyNode* node = calloc(1, sizeof(struct AllocOnlyNode)); node->ptr = calloc(1, size); node->prev = pool->tail; @@ -32,11 +22,8 @@ void* alloc_only_pool_alloc(struct AllocOnlyPool *pool, u32 size) { return node->ptr; } -struct AllocOnlyPool* alloc_only_pool_resize(UNUSED struct AllocOnlyPool* pool, UNUSED u32 size) { - return NULL; -} - void alloc_only_pool_free(struct AllocOnlyPool *pool) { + if (!pool) { return; } struct AllocOnlyNode* node = pool->tail; while (node) { struct AllocOnlyNode* prev = node->prev; @@ -45,4 +32,8 @@ void alloc_only_pool_free(struct AllocOnlyPool *pool) { node = prev; } free(pool); -} \ No newline at end of file +} + +void *alloc_display_list(u32 size) { + return alloc_only_pool_alloc(gDisplayListHeap, size); +} diff --git a/src/game/rendering_graph_node.c b/src/game/rendering_graph_node.c index 20912e4f..46db70b6 100644 --- a/src/game/rendering_graph_node.c +++ b/src/game/rendering_graph_node.c @@ -1620,11 +1620,12 @@ void geo_process_root(struct GraphNodeRoot *node, Vp *b, Vp *c, s32 clearColor) geo_clear_interp_variables(); if (node->node.flags & GRAPH_RENDER_ACTIVE) { + if (gDisplayListHeap) { alloc_only_pool_free(gDisplayListHeap); } + gDisplayListHeap = alloc_only_pool_init(); + Vp *viewport = alloc_display_list(sizeof(*viewport)); if (viewport == NULL) { return; } - gDisplayListHeap = alloc_only_pool_init(); - Mtx *initialMatrix = alloc_display_list(sizeof(*initialMatrix)); if (initialMatrix == NULL) { return; } @@ -1668,6 +1669,5 @@ void geo_process_root(struct GraphNodeRoot *node, Vp *b, Vp *c, s32 clearColor) //if (gShowDebugText) { // print_text_fmt_int(180, 36, "MEM %d", gDisplayListHeap->totalSpace - gDisplayListHeap->usedSpace); //} - alloc_only_pool_free(gDisplayListHeap); } } \ No newline at end of file diff --git a/src/game/rendering_graph_node.h b/src/game/rendering_graph_node.h index 625df498..38a8d1cd 100644 --- a/src/game/rendering_graph_node.h +++ b/src/game/rendering_graph_node.h @@ -9,6 +9,7 @@ extern f32 gProjectionMaxNearValue; extern s16 gProjectionVanillaNearValue; extern s16 gProjectionVanillaFarValue; +extern struct AllocOnlyPool *gDisplayListHeap; extern struct GraphNodeRoot *gCurGraphNodeRoot; extern struct GraphNodeMasterList *gCurGraphNodeMasterList; extern struct GraphNodePerspective *gCurGraphNodeCamFrustum; diff --git a/src/pc/lua/utils/smlua_model_utils.c b/src/pc/lua/utils/smlua_model_utils.c index 57961007..fde9e25b 100644 --- a/src/pc/lua/utils/smlua_model_utils.c +++ b/src/pc/lua/utils/smlua_model_utils.c @@ -548,12 +548,7 @@ void smlua_model_util_clear(void) { //LOG_INFO("Cleared runtime model cache."); } -// DO NOT COMMIT -// smlua_model_util_load_with_pool_and_cache_id() needs to be reworked to use dynamic pools correctly -// DO NOT COMMIT - - -u16 smlua_model_util_load_with_pool_and_cache_id(enum ModelExtendedId extId, struct AllocOnlyPool* pool, u16 loadedId) { +u16 smlua_model_util_load_with_pool_and_cache_id(enum ModelExtendedId extId, enum ModelPool pool, u16 loadedId) { if (extId == E_MODEL_NONE) { return MODEL_NONE; } if (extId >= (u16)(E_MODEL_MAX + sCustomModelsCount)) { LOG_ERROR("Tried to load invalid extId: %u >= %u (%u)", extId, (E_MODEL_MAX + sCustomModelsCount), sCustomModelsCount); @@ -596,52 +591,27 @@ u16 smlua_model_util_load_with_pool_and_cache_id(enum ModelExtendedId extId, str } // load - bool resizePool = false; - if (pool == NULL) { - pool = alloc_only_pool_init(); - resizePool = true; - } - info->shouldFreeAsset = false; - - if (pool != NULL) { - if (info->isDisplayList) { - gLoadedGraphNodes[pickLoadedId] = (struct GraphNode *) init_graph_node_display_list(pool, NULL, info->layer, (void*)info->asset); - } else { - gLoadedGraphNodes[pickLoadedId] = process_geo_layout(pool, (void*)info->asset); - } - - if (resizePool) { - alloc_only_pool_resize(pool, pool->usedSpace); - } - } - - // If no pool is available, use DynOS to generate the graph node - else { - - // Turn the display list into a geo layout - if (info->isDisplayList) { - const GeoLayout displayListToGeoLayout[] = { GEO_NODE_START(), GEO_DISPLAY_LIST(info->layer, info->asset), GEO_END() }; - info->asset = memcpy(calloc(1, sizeof(displayListToGeoLayout)), displayListToGeoLayout, sizeof(displayListToGeoLayout)); - info->shouldFreeAsset = true; - info->isDisplayList = false; - } - gLoadedGraphNodes[pickLoadedId] = dynos_geolayout_to_graphnode(info->asset, true); - LOG_ERROR("Out of memory in the main pool - using dynos"); - } + struct GraphNode* node = NULL; + node = (info->isDisplayList) + ? dynos_model_load_dl(pool, info->layer, (void*)info->asset) + : dynos_model_load_geo(pool, (void*) info->asset); + gLoadedGraphNodes[pickLoadedId] = node; // remember - smlua_model_util_remember(pickLoadedId, info->layer, info->asset, info->isDisplayList); + if (node) { + smlua_model_util_remember(pickLoadedId, info->layer, info->asset, info->isDisplayList); + } //LOG_INFO("Loaded custom model - %u -> %u", extId, pickLoadedId); return pickLoadedId; } -u16 smlua_model_util_load_with_pool(enum ModelExtendedId extId, struct AllocOnlyPool* pool) { +u16 smlua_model_util_load_with_pool(enum ModelExtendedId extId, enum ModelPool pool) { return smlua_model_util_load_with_pool_and_cache_id(extId, pool, UNLOADED_ID); } u16 smlua_model_util_load(enum ModelExtendedId extId) { - return smlua_model_util_load_with_pool(extId, NULL); + return smlua_model_util_load_with_pool(extId, MODEL_POOL_SESSION); } u32 smlua_model_util_get_id(const char* name) { diff --git a/src/pc/lua/utils/smlua_model_utils.h b/src/pc/lua/utils/smlua_model_utils.h index 730b3cc8..f004050a 100644 --- a/src/pc/lua/utils/smlua_model_utils.h +++ b/src/pc/lua/utils/smlua_model_utils.h @@ -398,8 +398,8 @@ enum ModelExtendedId { void smlua_model_util_remember(u16 loadedId, u8 layer, const void* asset, u8 isDisplayList); void smlua_model_util_reset(void); void smlua_model_util_clear(void); -u16 smlua_model_util_load_with_pool_and_cache_id(enum ModelExtendedId extId, struct AllocOnlyPool* pool, u16 loadedId); -u16 smlua_model_util_load_with_pool(enum ModelExtendedId extId, struct AllocOnlyPool* pool); +u16 smlua_model_util_load_with_pool_and_cache_id(enum ModelExtendedId extId, enum ModelPool pool, u16 loadedId); +u16 smlua_model_util_load_with_pool(enum ModelExtendedId extId, enum ModelPool pool); u16 smlua_model_util_load(enum ModelExtendedId extId); u32 smlua_model_util_get_id(const char* name); diff --git a/src/pc/network/network.c b/src/pc/network/network.c index 7e3619b6..b540c53c 100644 --- a/src/pc/network/network.c +++ b/src/pc/network/network.c @@ -613,6 +613,8 @@ void network_shutdown(bool sendLeaving, bool exiting, bool popup, bool reconnect gNetworkType = NT_NONE; } + dynos_model_clear_pool(MODEL_POOL_SESSION); + if (exiting) { return; } // reset other stuff