Rewrite how models are loaded and retrieved... yet again

This commit is contained in:
MysterD 2023-05-15 20:45:04 -07:00
parent 60d70d0d38
commit 688cd3b399
19 changed files with 255 additions and 299 deletions

View file

@ -72,8 +72,12 @@ 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);
struct GraphNode* dynos_model_load_geo(u32* aId, enum ModelPool aModelPool, void* aAsset);
struct GraphNode* dynos_model_load_dl(u32* aId, enum ModelPool aModelPool, u8 aLayer, void* aAsset);
struct GraphNode* dynos_model_store_geo(u32* aId, enum ModelPool aModelPool, void* aAsset, struct GraphNode* aGraphNode);
struct GraphNode* dynos_model_get_geo(u32 aId);
void dynos_model_overwrite_slot(u32 srcSlot, u32 dstSlot);
u32 dynos_model_get_id_from_asset(void* asset);
void dynos_model_clear_pool(enum ModelPool aModelPool);
// -- other -- //

View file

@ -963,8 +963,12 @@ 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);
struct GraphNode* DynOS_Model_LoadGeo(u32* aId, enum ModelPool aModelPool, void* aAsset);
struct GraphNode* DynOS_Model_LoadDl(u32* aId, enum ModelPool aModelPool, u8 aLayer, void* aAsset);
struct GraphNode* DynOS_Model_StoreGeo(u32* aId, enum ModelPool aModelPool, void* aAsset, struct GraphNode* aGraphNode);
struct GraphNode* DynOS_Model_GetGeo(u32 aId);
u32 DynOS_Model_GetIdFromAsset(void* asset);
void DynOS_Model_OverwriteSlot(u32 srcSlot, u32 dstSlot);
void DynOS_Model_ClearPool(enum ModelPool aModelPool);
void DynOS_Model_Update();

View file

@ -225,18 +225,34 @@ void dynos_behavior_hook_all_custom_behaviors(void) {
// -- models -- //
struct GraphNode* dynos_model_load_geo(enum ModelPool aModelPool, void* aAsset) {
return DynOS_Model_LoadGeo(aModelPool, aAsset);
struct GraphNode* dynos_model_load_geo(u32* aId, enum ModelPool aModelPool, void* aAsset) {
return DynOS_Model_LoadGeo(aId, aModelPool, aAsset);
}
struct GraphNode* dynos_model_load_dl(enum ModelPool aModelPool, u8 aLayer, void* aAsset) {
return DynOS_Model_LoadDl(aModelPool, aLayer, aAsset);
struct GraphNode* dynos_model_load_dl(u32* aId, enum ModelPool aModelPool, u8 aLayer, void* aAsset) {
return DynOS_Model_LoadDl(aId, aModelPool, aLayer, aAsset);
}
struct GraphNode* dynos_model_store_geo(u32* aId, enum ModelPool aModelPool, void* aAsset, struct GraphNode* aGraphNode) {
return DynOS_Model_StoreGeo(aId, aModelPool, aAsset, aGraphNode);
}
u32 dynos_model_get_id_from_asset(void* asset) {
return DynOS_Model_GetIdFromAsset(asset);
}
void dynos_model_clear_pool(enum ModelPool aModelPool) {
DynOS_Model_ClearPool(aModelPool);
}
struct GraphNode* dynos_model_get_geo(u32 aId) {
return DynOS_Model_GetGeo(aId);
}
void dynos_model_overwrite_slot(u32 srcSlot, u32 dstSlot) {
DynOS_Model_OverwriteSlot(srcSlot, dstSlot);
}
// -- other -- //
void dynos_mod_shutdown(void) {

View file

@ -46,10 +46,11 @@ void DynOS_Actor_AddCustom(const SysPath &aFilename, const char *aActorName) {
}
// Alloc and init the actors gfx list
u32 id = 0;
ActorGfx actorGfx = { };
actorGfx.mGfxData = _GfxData;
actorGfx.mPackIndex = MOD_PACK_INDEX;
actorGfx.mGraphNode = (GraphNode *) DynOS_Model_LoadGeo(MODEL_POOL_SESSION, geoLayout);
actorGfx.mGraphNode = (GraphNode *) DynOS_Model_LoadGeo(&id, MODEL_POOL_SESSION, geoLayout);
if (!actorGfx.mGraphNode) {
Print(" ERROR: Couldn't load graph node for \"%s\"", actorName);
free(actorName);
@ -168,7 +169,8 @@ 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 = DynOS_Model_LoadGeo(MODEL_POOL_PERMANENT, georef);
u32 id = 0;
_Object->header.gfx.sharedChild = DynOS_Model_LoadGeo(&id, MODEL_POOL_PERMANENT, georef);
}
DynOS_Actor_Override((void**)&_Object->header.gfx.sharedChild);
}

View file

@ -5,19 +5,62 @@
extern "C" {
#include "engine/geo_layout.h"
#include "engine/graph_node.h"
#include "model_ids.h"
}
enum ModelLoadType {
MLT_GEO,
MLT_DL,
MLT_STORE,
};
struct ModelInfo {
u32 id;
void* asset;
struct GraphNode* graphNode;
enum ModelPool modelPool;
};
struct ScheduledFreePool {
struct DynamicPool* pool;
u32 timeout;
};
static struct DynamicPool* sModelPools[MODEL_POOL_MAX] = { 0 };
static std::map<void*, struct GraphNode*> sGraphNodeMap[MODEL_POOL_MAX];
static std::map<u32, struct GraphNode*> sModelIdMap;
static std::map<void*, struct ModelInfo> sAssetMap[MODEL_POOL_MAX];
static std::map<u32, std::vector<struct ModelInfo>> sIdMap;
static std::map<u32, u32> sOverwriteMap;
static std::vector<struct ScheduledFreePool> sPoolsToFree;
struct GraphNode* DynOS_Model_LoadGeo(enum ModelPool aModelPool, void* aAsset) {
static u32 find_empty_id() {
u32 id = 256;
while (true) {
if (sIdMap.count(id) == 0) { return id; }
if (sIdMap[id].size() == 0) { return id; }
id++;
}
}
void DynOS_Model_Dump() {
for (auto& it : sIdMap) {
if (it.second.size() == 0 || it.second.empty()) { continue; }
printf(">> [%03x] ", it.first);
for (auto& it2 : it.second) {
switch (it2.modelPool) {
case MODEL_POOL_PERMANENT: printf("P "); break;
case MODEL_POOL_SESSION: printf("S "); break;
case MODEL_POOL_LEVEL: printf("L "); break;
case MODEL_POOL_MAX: printf("M "); break;
}
printf("%p ", it2.graphNode);
}
printf("\n");
}
}
struct GraphNode* DynOS_Model_LoadCommon(u32* aId, enum ModelPool aModelPool, void* aAsset, u8 aLayer, struct GraphNode* aGraphNode, enum ModelLoadType mlt) {
// sanity check pool
if (aModelPool >= MODEL_POOL_MAX) { return NULL; }
@ -27,40 +70,99 @@ struct GraphNode* DynOS_Model_LoadGeo(enum ModelPool aModelPool, void* aAsset) {
}
// check map
auto& map = sGraphNodeMap[aModelPool];
auto& map = sAssetMap[aModelPool];
if (map.count(aAsset)) {
return map[aAsset];
auto& found = map[aAsset];
if (*aId && *aId != found.id) {
sOverwriteMap[*aId] = found.id;
}
*aId = found.id;
return found.graphNode;
}
// load geo
struct GraphNode* node = process_geo_layout(sModelPools[aModelPool], aAsset);
struct GraphNode* node = NULL;
switch (mlt) {
case MLT_GEO:
node = process_geo_layout(sModelPools[aModelPool], aAsset);
break;
case MLT_DL:
node = (struct GraphNode *) init_graph_node_display_list(sModelPools[aModelPool], NULL, aLayer, aAsset);
break;
case MLT_STORE:
node = aGraphNode;
break;
}
if (!node) { return NULL; }
// figure out id
if (!*aId) { *aId = find_empty_id(); }
// create model info
struct ModelInfo info = {
.id = *aId,
.asset = aAsset,
.graphNode = node,
.modelPool = aModelPool
};
// store in maps
sIdMap[*aId].push_back(info);
map[aAsset] = info;
// 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; }
struct GraphNode* DynOS_Model_LoadGeo(u32* aId, enum ModelPool aModelPool, void* aAsset) {
return DynOS_Model_LoadCommon(aId, aModelPool, aAsset, 0, NULL, MLT_GEO);
}
// allocate pool
if (!sModelPools[aModelPool]) {
sModelPools[aModelPool] = dynamic_pool_init();
struct GraphNode* DynOS_Model_LoadDl(u32* aId, enum ModelPool aModelPool, u8 aLayer, void* aAsset) {
return DynOS_Model_LoadCommon(aId, aModelPool, aAsset, aLayer, NULL, MLT_DL);
}
struct GraphNode* DynOS_Model_StoreGeo(u32* aId, enum ModelPool aModelPool, void* aAsset, struct GraphNode* aGraphNode) {
return DynOS_Model_LoadCommon(aId, aModelPool, aAsset, 0, aGraphNode, MLT_STORE);
}
struct GraphNode* DynOS_Model_GetErrorGeo() {
if (!sIdMap.count(MODEL_ERROR_MODEL)) { return NULL; }
auto& vec = sIdMap[MODEL_ERROR_MODEL];
if (vec.size() == 0 || vec.empty()) {
return NULL;
}
return vec.back().graphNode;
}
struct GraphNode* DynOS_Model_GetGeo(u32 aId) {
if (!aId) { return NULL; }
if (sOverwriteMap.count(aId)) { aId = sOverwriteMap[aId]; }
if (sIdMap.count(aId) == 0) {
return DynOS_Model_GetErrorGeo();
}
// check map
auto& map = sGraphNodeMap[aModelPool];
if (map.count(aAsset)) {
return map[aAsset];
auto& vec = sIdMap[aId];
if (vec.size() == 0 || vec.empty()) {
return DynOS_Model_GetErrorGeo();
}
// load geo
struct GraphNode* node = (struct GraphNode *) init_graph_node_display_list(sModelPools[aModelPool], NULL, aLayer, aAsset);
return vec.back().graphNode;
}
// store and return geo
map[aAsset] = node;
return node;
u32 DynOS_Model_GetIdFromAsset(void* asset) {
if (!asset) { return MODEL_NONE; }
for (int i = 0; i < MODEL_POOL_MAX; i++) {
if (sAssetMap[i].count(asset)) {
return sAssetMap[i][asset].id;
}
}
return MODEL_ERROR_MODEL;
}
void DynOS_Model_OverwriteSlot(u32 srcSlot, u32 dstSlot) {
sOverwriteMap[srcSlot] = dstSlot;
}
void DynOS_Model_ClearPool(enum ModelPool aModelPool) {
@ -75,9 +177,29 @@ void DynOS_Model_ClearPool(enum ModelPool aModelPool) {
// clear pointer
sModelPools[aModelPool] = NULL;
// clear map
auto& map = sGraphNodeMap[aModelPool];
map.clear();
// clear overwrite
if (aModelPool == MODEL_POOL_LEVEL) {
sOverwriteMap.clear();
}
// clear maps
auto& assetMap = sAssetMap[aModelPool];
for (auto& asset : assetMap) {
auto& info = asset.second;
if (sIdMap.count(info.id) == 0) { continue; }
// erase from id map
auto& idMap = sIdMap[info.id];
for (auto info2 = idMap.begin(); info2 != idMap.end(); ) {
if (info.id == info2->id && info2->modelPool == aModelPool) {
info2 = idMap.erase(info2);
} else {
info2++;
}
}
}
assetMap.clear();
}
void DynOS_Model_Update() {

View file

@ -42,7 +42,8 @@ static void DynOS_Pack_ActivateActor(s32 aPackIndex, Pair<const char *, GfxData
GfxData* aGfxData = pair.second;
auto& geoNode = *(aGfxData->mGeoLayouts.end() - 1);
GraphNode* graphNode = DynOS_Model_LoadGeo(MODEL_POOL_PERMANENT, geoNode->mData);
u32 id = 0;
GraphNode* graphNode = DynOS_Model_LoadGeo(&id, MODEL_POOL_PERMANENT, geoNode->mData);
if (graphNode == NULL) { return; }
const void* georef = DynOS_Builtin_Actor_GetFromName(aActorName);

View file

@ -2,9 +2,9 @@
set -e
if [ $# -eq 0 ]; then
make DEBUG=1 DEVELOPMENT=1 STRICT=1 ASAN=1 -j
make DEBUG=1 DEVELOPMENT=1 STRICT=1 ASAN=1 COMPILER=clang -j
else
make DEBUG=1 DEVELOPMENT=1 ASAN=1 -j
make DEBUG=1 DEVELOPMENT=1 ASAN=1 COMPILER=clang -j
fi
# find file

View file

@ -64,7 +64,6 @@ static s16 sScriptStatus;
static s32 sRegister;
static struct LevelCommand *sCurrentCmd;
static u8 sLevelOwnedGraphNodes[MAX_LOADED_GRAPH_NODES] = { 0 };
static u8 sFinishedLoadingPerm = false;
static s32 eval_script_area(s32 arg) {
@ -350,7 +349,6 @@ static void level_cmd_init_level(void) {
init_graph_node_start(NULL, (struct GraphNodeStart *) &gObjParentGraphNode);
clear_objects();
clear_areas();
smlua_model_util_clear();
gSkipInterpolationTitleScreen = false;
sCurrentCmd = CMD_NEXT;
@ -361,14 +359,6 @@ static void level_cmd_clear_level(void) {
clear_area_graph_nodes();
clear_areas();
// reset the level's graph nodes to NULL
for (s32 i = 0; i < MAX_LOADED_GRAPH_NODES; i++) {
if (sLevelOwnedGraphNodes[i]) {
gLoadedGraphNodes[i] = NULL;
sLevelOwnedGraphNodes[i] = false;
}
}
sCurrentCmd = CMD_NEXT;
}
@ -388,15 +378,6 @@ static void level_reset_globals(void) {
}
static void level_cmd_alloc_level_pool(void) {
// reset level graph node ownership
for (s32 i = 0; i < MAX_LOADED_GRAPH_NODES; i++) {
if (sLevelOwnedGraphNodes[i]) {
gLoadedGraphNodes[i] = NULL;
sLevelOwnedGraphNodes[i] = false;
}
}
// reset all globals
level_reset_globals();
@ -432,7 +413,8 @@ static void level_cmd_begin_area(void) {
void *geoLayoutAddr = CMD_GET(void *, 4);
if (areaIndex < 8) {
struct GraphNodeRoot *screenArea = (struct GraphNodeRoot *) dynos_model_load_geo(MODEL_POOL_LEVEL, geoLayoutAddr);
u32 id = 0;
struct GraphNodeRoot *screenArea = (struct GraphNodeRoot *) dynos_model_load_geo(&id, MODEL_POOL_LEVEL, geoLayoutAddr);
struct GraphNodeCamera *node = (struct GraphNodeCamera *) screenArea->views[0];
sCurrAreaIndex = areaIndex;
@ -462,11 +444,8 @@ static void level_cmd_load_model_from_dl(void) {
s16 val2 = ((u16)CMD_GET(s16, 2)) >> 12;
void *val3 = CMD_GET(void *, 4);
if (val1 < MAX_LOADED_GRAPH_NODES) {
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);
}
u32 id = val1;
dynos_model_load_dl(&id, sFinishedLoadingPerm ? MODEL_POOL_LEVEL : MODEL_POOL_PERMANENT, val2, val3);
sCurrentCmd = CMD_NEXT;
}
@ -475,11 +454,8 @@ static void level_cmd_load_model_from_geo(void) {
s16 arg0 = CMD_GET(s16, 2);
void *arg1 = CMD_GET(void *, 4);
if (arg0 < MAX_LOADED_GRAPH_NODES) {
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);
}
u32 id = arg0;
dynos_model_load_geo(&id, sFinishedLoadingPerm ? MODEL_POOL_LEVEL : MODEL_POOL_PERMANENT, arg1);
sCurrentCmd = CMD_NEXT;
}
@ -496,13 +472,10 @@ static void level_cmd_23(void) {
// load an f32, but using an integer load instruction for some reason (hence the union)
arg2.i = CMD_GET(s32, 8);
if (model < MAX_LOADED_GRAPH_NODES) {
// GraphNodeScale has a GraphNode at the top. This
// is being stored to the array, so cast the pointer.
gLoadedGraphNodes[model] = (struct GraphNode *) init_graph_node_scale(gLevelPool, 0, arg0H, arg1, arg2.f);
if (sFinishedLoadingPerm) { sLevelOwnedGraphNodes[model] = true; }
smlua_model_util_remember(model, arg0H, arg1, 1);
}
u32 id = model;
dynos_model_store_geo(&id, MODEL_POOL_LEVEL, arg1, (struct GraphNode*)init_graph_node_scale(gLevelPool, 0, arg0H, arg1, arg2.f));
sCurrentCmd = CMD_NEXT;
}
@ -512,8 +485,7 @@ static void level_cmd_init_mario(void) {
behaviorArg = behaviorArg;
void* behaviorScript = CMD_GET(void*, 8);
u16 slot = CMD_GET(u8, 3);
if (slot >= MAX_LOADED_GRAPH_NODES) { slot = MODEL_NONE; }
struct GraphNode* unk18 = gLoadedGraphNodes[slot];
struct GraphNode* unk18 = dynos_model_get_geo(slot);
struct SpawnInfo* lastSpawnInfo = NULL;
for (s32 i = 0; i < MAX_PLAYERS; i++) {
@ -545,7 +517,6 @@ static void level_cmd_place_object(void) {
if (sCurrAreaIndex != -1 && (gLevelValues.disableActs || (CMD_GET(u8, 2) & val7) || CMD_GET(u8, 2) == 0x1F)) {
model = CMD_GET(u8, 3);
if (model >= MAX_LOADED_GRAPH_NODES) { model = MODEL_NONE; }
spawnInfo = dynamic_pool_alloc(gLevelPool, sizeof(struct SpawnInfo));
spawnInfo->startPos[0] = CMD_GET(s16, 4);
@ -561,7 +532,7 @@ static void level_cmd_place_object(void) {
spawnInfo->behaviorArg = CMD_GET(u32, 16);
spawnInfo->behaviorScript = CMD_GET(void *, 20);
spawnInfo->unk18 = gLoadedGraphNodes[model];
spawnInfo->unk18 = dynos_model_get_geo(model);
spawnInfo->next = gAreas[sCurrAreaIndex].objectSpawnInfos;
spawnInfo->syncID = gAreas[sCurrAreaIndex].nextSyncID;
@ -944,7 +915,6 @@ static void level_cmd_place_object_ext(void) {
if (sCurrAreaIndex != -1 && (gLevelValues.disableActs || (CMD_GET(u8, 2) & val7) || CMD_GET(u8, 2) == 0x1F)) {
u16 model = CMD_GET(u8, 3);
if (model >= MAX_LOADED_GRAPH_NODES) { model = MODEL_NONE; }
spawnInfo = dynamic_pool_alloc(gLevelPool, sizeof(struct SpawnInfo));
spawnInfo->startPos[0] = CMD_GET(s16, 4);
@ -961,7 +931,7 @@ static void level_cmd_place_object_ext(void) {
spawnInfo->behaviorArg = CMD_GET(u32, 16);
spawnInfo->behaviorScript = (BehaviorScript*)get_behavior_from_id(behId);
spawnInfo->unk18 = gLoadedGraphNodes[model];
spawnInfo->unk18 = dynos_model_get_geo(model);
spawnInfo->next = gAreas[sCurrAreaIndex].objectSpawnInfos;
spawnInfo->syncID = spawnInfo->next
@ -1031,9 +1001,8 @@ 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, MODEL_POOL_LEVEL);
if (slot >= MAX_LOADED_GRAPH_NODES) { slot = MODEL_NONE; }
spawnInfo->unk18 = gLoadedGraphNodes[slot];
u16 slot = smlua_model_util_load(modelId);
spawnInfo->unk18 = dynos_model_get_geo(slot);
spawnInfo->next = gAreas[sCurrAreaIndex].objectSpawnInfos;
spawnInfo->syncID = spawnInfo->next
@ -1049,13 +1018,11 @@ static void level_cmd_place_object_ext2(void) {
static void level_cmd_load_model_from_geo_ext(void) {
s16 modelSlot = CMD_GET(s16, 2);
const char* geoName = dynos_level_get_token(CMD_GET(u32, 4));
u32 modelId = smlua_model_util_get_id(geoName);
smlua_model_util_store_in_slot(modelSlot, geoName);
if (modelSlot < MAX_LOADED_GRAPH_NODES) {
smlua_model_util_load_with_pool_and_cache_id(modelId, MODEL_POOL_LEVEL, modelSlot);
}
// DO NOT COMMIT, this is broken
// it's supposed to load our custom model into a vanilla slot (ugh why)
sCurrentCmd = CMD_NEXT;
}

View file

@ -29,7 +29,6 @@
#include "pc/djui/djui_panel_pause.h"
struct SpawnInfo gPlayerSpawnInfos[MAX_PLAYERS];
struct GraphNode *D_8033A160[MAX_LOADED_GRAPH_NODES];
struct Area gAreaData[8];
struct WarpTransition gWarpTransition;
@ -43,7 +42,6 @@ s16 gPauseScreenMode;
s16 gSaveOptSelectIndex;
struct SpawnInfo *gMarioSpawnInfo = &gPlayerSpawnInfos[0];
struct GraphNode **gLoadedGraphNodes = D_8033A160;
struct Area *gAreas = gAreaData;
struct Area *gCurrentArea = NULL;
struct CreditsEntry *gCurrCreditsEntry = NULL;

View file

@ -7,10 +7,6 @@
#include "camera.h"
#include "engine/graph_node.h"
#define LOADED_GRAPH_NODES_VANILLA 256
#define LOADED_GRAPH_NODES_EXTENDED 512
#define MAX_LOADED_GRAPH_NODES (LOADED_GRAPH_NODES_VANILLA + LOADED_GRAPH_NODES_EXTENDED)
struct WarpNode
{
/*00*/ u8 id;
@ -128,7 +124,6 @@ struct WarpTransition
/*0x04*/ struct WarpTransitionData data;
};
extern struct GraphNode **gLoadedGraphNodes;
extern struct SpawnInfo gPlayerSpawnInfos[];
extern struct GraphNode *D_8033A160[];
extern struct Area gAreaData[];

View file

@ -379,7 +379,7 @@ void shelled_koopa_attack_handler(s32 attackType) {
* Update function for both regular and tiny shelled koopa.
*/
static void koopa_shelled_update(void) {
u8 modelId = smlua_model_util_load(E_MODEL_KOOPA_WITH_SHELL);
u16 modelId = smlua_model_util_load(E_MODEL_KOOPA_WITH_SHELL);
if (!cur_obj_has_model(modelId)) {
cur_obj_set_model(modelId);
}
@ -548,7 +548,7 @@ static void koopa_unshelled_act_unused3(void) {
* Update function for koopa after losing his shell.
*/
static void koopa_unshelled_update(void) {
u8 modelId = smlua_model_util_load(E_MODEL_KOOPA_WITHOUT_SHELL);
u16 modelId = smlua_model_util_load(E_MODEL_KOOPA_WITHOUT_SHELL);
if (!cur_obj_has_model(modelId)) {
cur_obj_set_model(modelId);
}

View file

@ -680,9 +680,7 @@ struct Object *spawn_object_at_origin(struct Object *parent, UNUSED s32 unusedAr
}
obj->globalPlayerIndex = 0;
if (model >= MAX_LOADED_GRAPH_NODES) { model = MODEL_ERROR_MODEL; }
geo_obj_init((struct GraphNodeObject *) &obj->header.gfx, gLoadedGraphNodes[model], gVec3fZero,
gVec3sZero);
geo_obj_init((struct GraphNodeObject *) &obj->header.gfx, dynos_model_get_geo(model), gVec3fZero, gVec3sZero);
smlua_call_event_hooks_object_model_param(HOOK_OBJECT_SET_MODEL, obj, model);
return obj;
@ -1436,8 +1434,7 @@ void cur_obj_set_model(s32 modelID) {
}
void obj_set_model(struct Object* obj, s32 modelID) {
if (modelID >= MAX_LOADED_GRAPH_NODES) { modelID = MODEL_ERROR_MODEL; }
obj->header.gfx.sharedChild = gLoadedGraphNodes[modelID];
obj->header.gfx.sharedChild = dynos_model_get_geo(modelID);
dynos_actor_override((void*)&obj->header.gfx.sharedChild);
smlua_call_event_hooks_object_model_param(HOOK_OBJECT_SET_MODEL, obj, modelID);
}
@ -3267,10 +3264,10 @@ s32 cur_obj_update_dialog_with_cutscene(struct MarioState* m, s32 actionArg, s32
s32 cur_obj_has_model(u16 modelID) {
if (!o) { return 0; }
if (modelID >= MAX_LOADED_GRAPH_NODES) { return FALSE; }
if (o->header.gfx.sharedChild == gLoadedGraphNodes[modelID]) {
struct GraphNode* node = dynos_model_get_geo(modelID);
if (o->header.gfx.sharedChild == node) {
return TRUE;
} else if (o->header.gfx.sharedChild && gLoadedGraphNodes[modelID] && o->header.gfx.sharedChild->georef == gLoadedGraphNodes[modelID]->georef) {
} else if (o->header.gfx.sharedChild && node && o->header.gfx.sharedChild->georef == node->georef) {
return TRUE;
} else {
return FALSE;

View file

@ -792,10 +792,8 @@ void copy_action_file_button(struct Object *copyButton, s32 copyFileButtonID) {
sFadeOutText = TRUE;
sMainMenuTimer = 0;
save_file_copy(sSelectedFileIndex, copyFileButtonID - MENU_BUTTON_COPY_MIN);
sMainMenuButtons[copyFileButtonID]->header.gfx.sharedChild =
gLoadedGraphNodes[MODEL_MAIN_MENU_MARIO_SAVE_BUTTON_FADE];
sMainMenuButtons[copyFileButtonID - MENU_BUTTON_COPY_MIN]->header.gfx.sharedChild =
gLoadedGraphNodes[MODEL_MAIN_MENU_MARIO_SAVE_BUTTON_FADE];
sMainMenuButtons[copyFileButtonID]->header.gfx.sharedChild = dynos_model_get_geo(MODEL_MAIN_MENU_MARIO_SAVE_BUTTON_FADE);
sMainMenuButtons[copyFileButtonID - MENU_BUTTON_COPY_MIN]->header.gfx.sharedChild = dynos_model_get_geo(MODEL_MAIN_MENU_MARIO_SAVE_BUTTON_FADE);
} else {
// If clicked in a existing save file, play buzz sound
if (MENU_BUTTON_COPY_FILE_A + sSelectedFileIndex == copyFileButtonID) {
@ -2258,10 +2256,8 @@ void print_erase_menu_prompt(s16 x, s16 y) {
sFadeOutText = TRUE;
sMainMenuTimer = 0;
save_file_erase(sSelectedFileIndex);
sMainMenuButtons[MENU_BUTTON_ERASE_MIN + sSelectedFileIndex]->header.gfx.sharedChild =
gLoadedGraphNodes[MODEL_MAIN_MENU_MARIO_NEW_BUTTON_FADE];
sMainMenuButtons[sSelectedFileIndex]->header.gfx.sharedChild =
gLoadedGraphNodes[MODEL_MAIN_MENU_MARIO_NEW_BUTTON_FADE];
sMainMenuButtons[MENU_BUTTON_ERASE_MIN + sSelectedFileIndex]->header.gfx.sharedChild = dynos_model_get_geo(MODEL_MAIN_MENU_MARIO_NEW_BUTTON_FADE);
sMainMenuButtons[sSelectedFileIndex]->header.gfx.sharedChild = dynos_model_get_geo(MODEL_MAIN_MENU_MARIO_NEW_BUTTON_FADE);
sEraseYesNoHoverState = MENU_ERASE_HOVER_NONE;
// ..and is hovering "NO", return back to main phase
} else if (sEraseYesNoHoverState == MENU_ERASE_HOVER_NO) {

View file

@ -197,7 +197,7 @@ void smlua_shutdown(void) {
smlua_cobject_allowlist_shutdown();
smlua_cpointer_allowlist_shutdown();
smlua_clear_hooks();
smlua_model_util_reset();
smlua_model_util_clear();
smlua_level_util_reset();
smlua_anim_util_reset();
lua_State* L = gLuaState;

View file

@ -59,18 +59,16 @@ struct ModelUtilsInfo {
enum ModelExtendedId extId;
u8 layer;
u16 loadedId;
bool permanent;
bool isDisplayList;
const void* asset;
u8 shouldFreeAsset;
};
#define UNLOADED_ID 0xFFFF
#define UNLOADED_ID 0
#define MODEL_UTIL_GEO(x, y) [x] = { .extId = x, .asset = y, .layer = LAYER_OPAQUE, .isDisplayList = false, .loadedId = UNLOADED_ID, .permanent = false }
#define MODEL_UTIL_DL(x, y, z) [x] = { .extId = x, .asset = y, .layer = z, .isDisplayList = true, .loadedId = UNLOADED_ID, .permanent = false }
#define MODEL_UTIL_GEO_PERM(x, y, w) [x] = { .extId = x, .asset = y, .layer = LAYER_OPAQUE, .isDisplayList = false, .loadedId = w, .permanent = true }
#define MODEL_UTIL_DL_PERM(x, y, z, w) [x] = { .extId = x, .asset = y, .layer = z, .isDisplayList = true, .loadedId = w, .permanent = true }
#define MODEL_UTIL_GEO(x, y) [x] = { .extId = x, .asset = y, .layer = LAYER_OPAQUE, .isDisplayList = false, .loadedId = UNLOADED_ID, }
#define MODEL_UTIL_DL(x, y, z) [x] = { .extId = x, .asset = y, .layer = z, .isDisplayList = true, .loadedId = UNLOADED_ID, }
#define MODEL_UTIL_GEO_PERM(x, y, w) [x] = { .extId = x, .asset = y, .layer = LAYER_OPAQUE, .isDisplayList = false, .loadedId = w, }
#define MODEL_UTIL_DL_PERM(x, y, z, w) [x] = { .extId = x, .asset = y, .layer = z, .isDisplayList = true, .loadedId = w, }
struct ModelUtilsInfo sModels[E_MODEL_MAX] = {
MODEL_UTIL_GEO(E_MODEL_NONE, NULL),
@ -468,172 +466,53 @@ struct ModelUtilsInfo sModels[E_MODEL_MAX] = {
struct ModelUtilsInfo sCustomModels[MAX_CUSTOM_MODELS] = { 0 };
static u16 sCustomModelsCount = 0;
struct ModelUtilsInfo* sCachedAssets[MAX_LOADED_GRAPH_NODES] = { 0 };
bool sCachedAssetTaken[MAX_LOADED_GRAPH_NODES] = { 0 };
void smlua_model_util_remember(u16 loadedId, UNUSED u8 layer, const void* asset, UNUSED u8 isDisplayList) {
struct ModelUtilsInfo* found = NULL;
// find in sModels
for (s32 i = 0; i < E_MODEL_MAX; i++) {
struct ModelUtilsInfo* m = &sModels[i];
if (m->asset != asset) { continue; }
found = m;
break;
}
// find in sCustomModels
if (!found) {
for (s32 i = 0; i < sCustomModelsCount; i++) {
struct ModelUtilsInfo* m = &sCustomModels[i];
if (m->asset != asset) { continue; }
found = m;
break;
}
}
// sanity check
if (found == NULL) {
LOG_ERROR("Could not find asset to remember!");
return;
}
// remember
if (sCachedAssetTaken[loadedId] && sCachedAssets[loadedId] != found) {
if (sCachedAssets[loadedId]->permanent) {
LOG_ERROR("Tried to override permanent model: %u -> %u", sCachedAssets[loadedId]->loadedId, loadedId);
return;
} else {
//LOG_INFO("Overriding model: loadedId %u was extId %u, now extId %u", loadedId, sCachedAssets[loadedId]->extId, found->extId);
}
sCachedAssets[loadedId]->loadedId = UNLOADED_ID;
}
found->loadedId = loadedId;
sCachedAssets[loadedId] = found;
sCachedAssetTaken[loadedId] = true;
//LOG_INFO("Remember model: %u -> %u", found->extId, loadedId);
}
void smlua_model_util_reset(void) {
smlua_model_util_clear();
for (u32 i = 0; i < sCustomModelsCount; i++) {
struct ModelUtilsInfo* m = &sCustomModels[i];
m->loadedId = UNLOADED_ID;
if (m->asset && m->shouldFreeAsset) {
free((void*)m->asset);
m->asset = NULL;
}
m->shouldFreeAsset = false;
}
void smlua_model_util_clear(void) {
sCustomModelsCount = 0;
}
void smlua_model_util_clear(void) {
for (int i = 0; i < MAX_LOADED_GRAPH_NODES; i++) {
struct ModelUtilsInfo* m = sCachedAssets[i];
if (m == NULL) { continue; }
//LOG_INFO("Forget: %u -> %u", m->extId, m->loadedId);
if (!m->permanent) {
m->loadedId = UNLOADED_ID;
if (m->asset && m->shouldFreeAsset) {
free((void*)m->asset);
m->asset = NULL;
}
}
m->shouldFreeAsset = false;
sCachedAssets[i] = NULL;
sCachedAssetTaken[i] = false;
}
//LOG_INFO("Cleared runtime model cache.");
}
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);
extId = E_MODEL_ERROR_MODEL;
}
struct ModelUtilsInfo* info = (extId >= E_MODEL_MAX)
? &sCustomModels[extId - E_MODEL_MAX]
: &sModels[extId];
// check cache
if (info->loadedId != UNLOADED_ID) {
//LOG_INFO("Found in cache - %u -> %u", extId, info->loadedId);
return info->loadedId;
}
// find cached asset
u16 pickLoadedId = loadedId;
if (loadedId == UNLOADED_ID) {
for (s32 i = 0; i < (MAX_LOADED_GRAPH_NODES-1); i++) {
struct ModelUtilsInfo* m = sCachedAssets[i];
if (m == info) {
//LOG_INFO("Found in cache (but late, confused?) - %u -> %u", extId, i);
info->loadedId = m->loadedId;
return info->loadedId;
} else if (i >= LOADED_GRAPH_NODES_VANILLA && !sCachedAssetTaken[i]) {
pickLoadedId = i;
}
}
if (pickLoadedId == UNLOADED_ID) {
LOG_ERROR("Could not find slot for extId - %u", extId);
return UNLOADED_ID;
}
}
if (pickLoadedId >= MAX_LOADED_GRAPH_NODES) {
LOG_ERROR("Could not find slot for extId - %u", extId);
return UNLOADED_ID;
}
// load
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
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, enum ModelPool pool) {
return smlua_model_util_load_with_pool_and_cache_id(extId, pool, UNLOADED_ID);
void smlua_model_util_store_in_slot(u32 slot, const char* name) {
u32 extId = smlua_model_util_get_id(name);
if (extId == E_MODEL_ERROR_MODEL) { return; }
u32 loadedId = smlua_model_util_load(extId);
dynos_model_overwrite_slot(slot, loadedId);
}
u16 smlua_model_util_load(enum ModelExtendedId extId) {
return smlua_model_util_load_with_pool(extId, MODEL_POOL_SESSION);
if (extId >= E_MODEL_MAX + sCustomModelsCount) { extId = E_MODEL_ERROR_MODEL; }
struct ModelUtilsInfo* info = (extId < E_MODEL_MAX)
? &sModels[extId]
: &sCustomModels[extId - E_MODEL_MAX];
u32 id = info->loadedId;
if (info->isDisplayList) {
dynos_model_load_dl(&id, MODEL_POOL_SESSION, info->layer, (void*)info->asset);
} else {
dynos_model_load_geo(&id, MODEL_POOL_SESSION, (void*)info->asset);
}
return (u16)id;
}
u32 smlua_model_util_get_id(const char* name) {
// find geolayout
const void* layout = dynos_geolayout_get(name);
if (layout == NULL) {
const void* asset = dynos_geolayout_get(name);
if (asset == NULL) {
LOG_ERROR("Failed to find model: %s - %u", name, E_MODEL_ERROR_MODEL);
return E_MODEL_ERROR_MODEL;
}
// find existing model
// find existing built-in model
for (u32 i = 0; i < E_MODEL_MAX; i++) {
struct ModelUtilsInfo* m = &sModels[i];
if (m->asset == layout) {
//LOG_INFO("Found existing model: %s :: %u -> %u", name, m->extId, m->loadedId);
if (m->asset == asset) {
return m->extId;
}
}
// find existing custom model
for (u32 i = 0; i < sCustomModelsCount; i++) {
struct ModelUtilsInfo* m = &sCustomModels[i];
if (m->asset == layout) {
//LOG_INFO("Found existing custom model: %s :: %u -> %u", name, m->extId, m->loadedId);
if (m->asset == asset) {
return m->extId;
}
}
@ -641,15 +520,11 @@ u32 smlua_model_util_get_id(const char* name) {
// allocate custom model
u16 customIndex = sCustomModelsCount++;
struct ModelUtilsInfo* info = &sCustomModels[customIndex];
info->asset = layout;
info->shouldFreeAsset = false;
info->asset = asset;
info->loadedId = UNLOADED_ID;
info->extId = E_MODEL_MAX + customIndex;
info->isDisplayList = false;
info->layer = LAYER_OPAQUE;
//LOG_INFO("Allocated model: %s :: %u -> %u", name, info->extId, info->loadedId);
return info->extId;
}

View file

@ -395,11 +395,8 @@ enum ModelExtendedId {
E_MODEL_MAX
};
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, enum ModelPool pool, u16 loadedId);
u16 smlua_model_util_load_with_pool(enum ModelExtendedId extId, enum ModelPool pool);
void smlua_model_util_store_in_slot(u32 slot, const char* name);
u16 smlua_model_util_load(enum ModelExtendedId extId);
u32 smlua_model_util_get_id(const char* name);

View file

@ -23,11 +23,6 @@ static struct Object* spawn_object_internal(enum BehaviorId behaviorId, enum Mod
}
u16 loadedModelId = smlua_model_util_load(modelId);
if (loadedModelId >= MAX_LOADED_GRAPH_NODES) {
LOG_ERROR("failed to load model %u", modelId);
return NULL;
}
struct Object* obj = spawn_object(gMarioStates[0].marioObj, loadedModelId, behavior);
if (obj == NULL) {
@ -95,8 +90,7 @@ s32 obj_has_behavior_id(struct Object *o, enum BehaviorId behaviorId) {
s32 obj_has_model_extended(struct Object *o, enum ModelExtendedId modelId) {
if (!o) { return 0; }
u16 slot = smlua_model_util_load(modelId);
if (slot >= MAX_LOADED_GRAPH_NODES) { return false; }
struct GraphNode *model = gLoadedGraphNodes[slot];
struct GraphNode *model = dynos_model_get_geo(slot);
return o->header.gfx.sharedChild == model;
}
@ -267,10 +261,6 @@ struct SpawnParticlesInfo* obj_get_temp_spawn_particles_info(enum ModelExtendedI
memset(&sTmpSpi, 0, sizeof(struct SpawnParticlesInfo));
u16 loadedModelId = smlua_model_util_load(modelId);
if (loadedModelId >= MAX_LOADED_GRAPH_NODES) {
LOG_ERROR("failed to load model %u", modelId);
return NULL;
}
sTmpSpi.model = loadedModelId;
return &sTmpSpi;

View file

@ -102,13 +102,7 @@ void network_send_area(struct NetworkPlayer* toNp) {
// TODO: move find model to a utility file/function
// find model
u32 model = 0;
for (s32 j = 0; j < MAX_LOADED_GRAPH_NODES; j++) {
if (so->o->header.gfx.sharedChild == gLoadedGraphNodes[j]) {
model = j;
break;
}
}
u32 model = dynos_model_get_id_from_asset(so->o->header.gfx.sharedChild);
u32 models[] = { model };
network_send_spawn_objects_to(toNp->localIndex, spawn_objects, models, 1);

View file

@ -189,10 +189,8 @@ void network_receive_spawn_objects(struct Packet* p) {
// load extended model
if (data.extendedModelId != 0xFFFF) {
u16 loadedModelId = smlua_model_util_load(data.extendedModelId);
if (loadedModelId < MAX_LOADED_GRAPH_NODES) {
data.model = loadedModelId;
}
}
void* behavior = (void*)get_behavior_from_id(data.behaviorId);
struct Object* o = NULL;