mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2026-07-04 21:46:45 +00:00
Some checks are pending
this fixes the giant memory leak that happens due to not freeing custom level data when closing a lobby. `DynOS_Lvl_ModShutdown` was not freeing the data nodes for the level data, it was only freeing the surface data. To fix this, I have made it use `DynOS_Gfx_Free` to free the `GfxData` correctly. I found that the level script VM will still be trying to warp from the custom level after `DynOS_Lvl_ModShutdown` is executed, so I added a schedule to simply free it the next frame. I've made it force the level script to change to a vanilla level during mod shutdown. This is critical to ensure the VM doesn't continue to read from a freed level script. Removed the explicit deletion of data nodes in `DynOS_MovtexQC_ModShutdown` because `DynOS_Gfx_Free` already frees that, and it's actually data owned by the data node, so it's more appropriate in `DynOS_Gfx_Free`
74 lines
2 KiB
C++
74 lines
2 KiB
C++
#include "dynos.cpp.h"
|
|
extern "C" {
|
|
#include "game/area.h"
|
|
}
|
|
|
|
struct RegisteredMovtexQC {
|
|
DataNode<MovtexQC>* dataNode;
|
|
s16 level;
|
|
s16 area;
|
|
s16 type;
|
|
};
|
|
|
|
static std::vector<RegisteredMovtexQC> &DynosRegisteredMovtexQCs() {
|
|
static std::vector<RegisteredMovtexQC> sDynosRegisteredMovtexQCs;
|
|
return sDynosRegisteredMovtexQCs;
|
|
}
|
|
|
|
void DynOS_MovtexQC_Register(const char* name, s16 level, s16 area, s16 type) {
|
|
auto& _DynosRegisteredMovtexQCs = DynosRegisteredMovtexQCs();
|
|
|
|
// check for duplicates
|
|
for (auto& registered : _DynosRegisteredMovtexQCs) {
|
|
if (registered.level == level && registered.area == area && registered.type == type) { return; }
|
|
}
|
|
|
|
// find it in the levels
|
|
for (auto& lvlPair : DynOS_Lvl_GetArray()) {
|
|
auto node = lvlPair.second->mMovtexQCs.Find(name);
|
|
if (node) {
|
|
// add it
|
|
_DynosRegisteredMovtexQCs.push_back({
|
|
.dataNode = node,
|
|
.level = level,
|
|
.area = area,
|
|
.type = type
|
|
});
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
DataNode<MovtexQC>* DynOS_MovtexQC_GetFromId(u32 id) {
|
|
auto& _DynosRegisteredMovtexQCs = DynosRegisteredMovtexQCs();
|
|
|
|
// find the datanode
|
|
s16 type = (id & 0xF);
|
|
for (auto& registered : _DynosRegisteredMovtexQCs) {
|
|
if (registered.level == gCurrLevelNum && registered.area == gCurrAreaIndex && registered.type == type) {
|
|
return registered.dataNode;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
DataNode<MovtexQC>* DynOS_MovtexQC_GetFromIndex(s32 index) {
|
|
GfxData* gfxData = DynOS_Lvl_GetActiveGfx();
|
|
if (gfxData == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
auto &mMovtexQCs = gfxData->mMovtexQCs;
|
|
|
|
// Sanity check the index we passed.
|
|
if (index < 0 || index >= mMovtexQCs.Count()) {
|
|
return NULL;
|
|
}
|
|
|
|
return mMovtexQCs[index];
|
|
}
|
|
|
|
void DynOS_MovtexQC_ModShutdown() {
|
|
auto& _DynosRegisteredMovtexQCs = DynosRegisteredMovtexQCs();
|
|
_DynosRegisteredMovtexQCs.clear();
|
|
}
|