Fixed token corruption in DynOS, added support for runtime LOAD_MODEL_FROM_GEO

This commit is contained in:
MysterD 2022-04-07 08:21:19 -07:00
parent 3731ab31af
commit 4956f0dd95
15 changed files with 133 additions and 35 deletions

View file

@ -37,6 +37,7 @@ Collision* dynos_collision_get(const char* collisionName);
// -- levels -- //
void dynos_add_level(s32 modIndex, const char *modPath, const char* levelName);
LevelScript* dynos_level_get(const char* levelName);
const char* dynos_level_get_token(u32 index);
struct MovtexQuadCollection *dynos_level_movtexqc_getfromindex(s32 index);
void dynos_level_load_background(void *ptr);

View file

@ -717,6 +717,7 @@ s16 *DynOS_Level_GetWarpDeath(s32 aLevel, s32 aArea);
void DynOS_Lvl_Add(s32 modIndex, const SysPath &aPackFolder, const char *aLevelName);
LevelScript* DynOS_Lvl_Get(const char* levelName);
s32 DynOS_Lvl_GetModIndex(void* levelScript);
const char* DynOS_Lvl_Get_Token(u32 index);
DataNode<TexData> *DynOS_Lvl_Texture_Get(void *aPtr);
DataNode<MovtexQC> *DynOS_Lvl_MovtexQuadCollection_GetFromIndex(s32 index);
void DynOS_Lvl_Load_Background(void *aPtr);

View file

@ -1665,7 +1665,6 @@ static void ParseLevelScriptSymbol(GfxData* aGfxData, DataNode<LevelScript>* aNo
// models
lvl_symbol_3(LOAD_MODEL_FROM_DL, 1, 0, 0);
lvl_symbol_2(LOAD_MODEL_FROM_GEO, 1, 0);
lvl_symbol_3(CMD23, 1, 0, 0);
// objects
@ -1779,6 +1778,26 @@ static void ParseLevelScriptSymbol(GfxData* aGfxData, DataNode<LevelScript>* aNo
return;
}
// LOAD_MODEL_FROM_GEO
if (_Symbol == "LOAD_MODEL_FROM_GEO") {
u64 topTokenIndex = aTokenIndex;
bool foundGeo = true;
LevelScript model = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex);
LevelScript geo = ParseLevelScriptSymbolArgInternal(aGfxData, aNode, aTokenIndex, &foundGeo);
if (foundGeo) {
aGfxData->mPointerList.Add(aHead + 1);
LevelScript _Ls[] = { LOAD_MODEL_FROM_GEO(model, geo) };
memcpy(aHead, _Ls, sizeof(_Ls));
aHead += (sizeof(_Ls) / sizeof(_Ls[0]));
} else {
u32 geoIndex = DynOS_Lua_RememberVariable(aGfxData, aHead + 1, aNode->mTokens[topTokenIndex + 1]);
LevelScript _Ls[] = { LOAD_MODEL_FROM_GEO_EXT(model, geo) };
memcpy(aHead, _Ls, sizeof(_Ls));
aHead += (sizeof(_Ls) / sizeof(_Ls[0]));
}
return;
}
// Unknown
PrintError(" ERROR: Unknown lvl symbol: %s", _Symbol.begin());
}

View file

@ -393,9 +393,14 @@ void *DynOS_Pointer_Load(FILE *aFile, GfxData *aGfxData, u32 aValue, bool isLvl)
// LUAV
if (aValue == LUA_VAR_CODE) {
String token; token.Read(aFile);
for (s32 i = 0; i < aGfxData->mLuaTokenList.Count(); i++) {
if (token == aGfxData->mLuaTokenList[i]) {
return (void*)(uintptr_t)(i+1);
}
}
u32 index = aGfxData->mLuaTokenList.Count();
aGfxData->mLuaTokenList.Add(token);
return aGfxData->mLuaTokenList[index].begin();
return (void*)(uintptr_t)(index+1);
}
// FUNC

View file

@ -108,6 +108,10 @@ LevelScript* dynos_level_get(const char* levelName) {
return DynOS_Lvl_Get(levelName);
}
const char* dynos_level_get_token(u32 index) {
return DynOS_Lvl_Get_Token(index);
}
struct MovtexQuadCollection *dynos_level_movtexqc_getfromindex(s32 index) {
DataNode<MovtexQC> *node = DynOS_Lvl_MovtexQuadCollection_GetFromIndex(index);
if (node == NULL) { return NULL; }

View file

@ -404,6 +404,8 @@ const void *DynOS_Geo_GetActorLayout(s32 aIndex) {
}
const void *DynOS_Geo_GetActorLayoutFromName(const char *aActorName) {
if (aActorName == NULL) { return NULL; }
// check levels
for (auto& lvl : sDynosCustomLevelScripts) {
for (auto& geo : lvl.second->mGeoLayouts) {
@ -698,19 +700,47 @@ DataNode<TexData> *DynOS_Lvl_Texture_Get(void *aPtr) {
return NULL;
}
static GfxData* DynOS_Lvl_Get_Active_Gfx(void) {
for (s32 i = 0; i < sDynosCustomLevelScripts.Count(); ++i) {
auto& gfxData = sDynosCustomLevelScripts[i].second;
auto& scripts = gfxData->mLevelScripts;
if (gLevelScriptActive == scripts[scripts.Count() - 1]->mData) {
return gfxData;
}
}
return NULL;
}
const char* DynOS_Lvl_Get_Token(u32 index) {
GfxData* gfxData = DynOS_Lvl_Get_Active_Gfx();
if (gfxData == NULL) {
return NULL;
}
// have to 1-index due to to pointer read code
index = index - 1;
if (index >= gfxData->mLuaTokenList.Count()) {
return NULL;
}
return gfxData->mLuaTokenList[index].begin();
}
DataNode<MovtexQC> *DynOS_Lvl_MovtexQuadCollection_GetFromIndex(s32 index) {
s32 modIndex = gLevelScriptModIndex - 1;
// Sanity check our currently loaded mod.
if (modIndex < 0 || modIndex >= sDynosCustomLevelScripts.Count()) { return NULL; }
auto &mMovtexQCs = sDynosCustomLevelScripts[modIndex].second->mMovtexQCs;
GfxData* gfxData = DynOS_Lvl_Get_Active_Gfx();
if (gfxData == NULL) {
return NULL;
}
auto &mMovtexQCs = gfxData->mMovtexQCs;
// Sanity check the index we passed.
if (index < 0 || index >= mMovtexQCs.Count()) { return NULL; }
if (index < 0 || index >= mMovtexQCs.Count()) {
return NULL;
}
auto &movetexQC = mMovtexQCs[index];
return movetexQC;
return mMovtexQCs[index];
}
void DynOS_Lvl_Load_Background(void *aPtr) {

View file

@ -251,6 +251,7 @@ static void *DynOS_Warp_UpdateWarp(void *aCmd, bool aIsLevelInitDone) {
sWarpDest.arg = 0;
void* levelScript = (void *) DynOS_Level_GetScript(gCurrLevelNum);
gLevelScriptModIndex = DynOS_Lvl_GetModIndex(levelScript);
gLevelScriptActive = (LevelScript*)levelScript;
return levelScript;
} else {

View file

@ -303,4 +303,8 @@
#define OBJECT_EXT2(model, posX, posY, posZ, angleX, angleY, angleZ, behParam, beh) \
OBJECT_WITH_ACTS_EXT2(model, posX, posY, posZ, angleX, angleY, angleZ, behParam, beh, 0x1F)
#define LOAD_MODEL_FROM_GEO_EXT(model, geo) \
CMD_BBH(0x41, 0x08, model), \
CMD_PTR(geo)
#endif // LEVEL_COMMANDS_H

View file

@ -41,6 +41,7 @@ struct LevelCommand {
enum ScriptStatus { SCRIPT_RUNNING = 1, SCRIPT_PAUSED = 0, SCRIPT_PAUSED2 = -1 };
s32 gLevelScriptModIndex = -1;
LevelScript* gLevelScriptActive = NULL;
static uintptr_t sStack[32];
@ -829,7 +830,7 @@ static void level_cmd_place_object_ext(void) {
struct SpawnInfo *spawnInfo;
u16 modIndex = gLevelScriptModIndex;
char* behStr = CMD_GET(char*, 20);
const char* behStr = dynos_level_get_token(CMD_GET(u32, 20));
gSmLuaConvertSuccess = true;
enum BehaviorId behId = smlua_get_mod_variable(modIndex, behStr);
@ -872,8 +873,8 @@ static void level_cmd_place_object_ext2(void) {
struct SpawnInfo *spawnInfo;
u16 modIndex = gLevelScriptModIndex;
char* modelStr = CMD_GET(char*, 20);
char* behStr = CMD_GET(char*, 24);
const char* modelStr = dynos_level_get_token(CMD_GET(u32, 20));
const char* behStr = dynos_level_get_token(CMD_GET(u32, 24));
gSmLuaConvertSuccess = true;
enum ModelExtendedId modelId = smlua_get_mod_variable(modIndex, modelStr);
@ -911,6 +912,19 @@ static void level_cmd_place_object_ext2(void) {
sCurrentCmd = CMD_NEXT;
}
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);
if (modelSlot < 256) {
smlua_model_util_load_with_pool_and_cache_id(modelId, sLevelPool, modelSlot);
}
sCurrentCmd = CMD_NEXT;
}
static void (*LevelScriptJumpTable[])(void) = {
/*00*/ level_cmd_load_and_execute,
/*01*/ level_cmd_exit_and_execute,
@ -979,6 +993,7 @@ static void (*LevelScriptJumpTable[])(void) = {
// coop
/*3F*/ level_cmd_place_object_ext,
/*40*/ level_cmd_place_object_ext2,
/*41*/ level_cmd_load_model_from_geo_ext,
};
struct LevelCommand *level_script_execute(struct LevelCommand *cmd) {

View file

@ -6,6 +6,7 @@
struct LevelCommand;
extern s32 gLevelScriptModIndex;
extern LevelScript* gLevelScriptActive;
extern u8 level_script_entry[];

View file

@ -798,26 +798,34 @@ void cur_obj_scale(f32 scale) {
void cur_obj_init_animation(s32 animIndex) {
struct Animation **anims = o->oAnimations;
geo_obj_init_animation(&o->header.gfx, &anims[animIndex]);
if (anims != NULL) {
geo_obj_init_animation(&o->header.gfx, &anims[animIndex]);
}
}
void cur_obj_init_animation_with_sound(s32 animIndex) {
struct Animation **anims = o->oAnimations;
geo_obj_init_animation(&o->header.gfx, &anims[animIndex]);
if (anims != NULL) {
geo_obj_init_animation(&o->header.gfx, &anims[animIndex]);
}
o->oSoundStateID = animIndex;
}
void cur_obj_init_animation_with_accel_and_sound(s32 animIndex, f32 accel) {
struct Animation **anims = o->oAnimations;
s32 animAccel = (s32)(accel * 65536.0f);
geo_obj_init_animation_accel(&o->header.gfx, &anims[animIndex], animAccel);
if (anims != NULL) {
s32 animAccel = (s32)(accel * 65536.0f);
geo_obj_init_animation_accel(&o->header.gfx, &anims[animIndex], animAccel);
}
o->oSoundStateID = animIndex;
}
void obj_init_animation_with_sound(struct Object *obj, const struct Animation * const* animations, s32 animIndex) {
struct Animation **anims = (struct Animation **)animations;
obj->oAnimations = (struct Animation **)animations;
geo_obj_init_animation(&obj->header.gfx, &anims[animIndex]);
if (anims != NULL) {
geo_obj_init_animation(&obj->header.gfx, &anims[animIndex]);
}
obj->oSoundStateID = animIndex;
}

View file

@ -372,7 +372,7 @@ lua_Number smlua_get_number_field(int index, char* name) {
///////////////////////////////////////////////////////////////////////////////////////////
s64 smlua_get_mod_variable(u16 modIndex, char* variable) {
s64 smlua_get_mod_variable(u16 modIndex, const char* variable) {
lua_State* L = gLuaState;
// figure out entry
@ -385,7 +385,7 @@ s64 smlua_get_mod_variable(u16 modIndex, char* variable) {
int prevTop = lua_gettop(L);
lua_getglobal(L, "_G"); // get global table
lua_getfield(L, LUA_REGISTRYINDEX, mod->relativePath); // get the file's "global" table
s64 value = smlua_get_integer_field(-1, variable);
s64 value = smlua_get_integer_field(-1, (char*)variable);
lua_settop(L, prevTop);
// return variable

View file

@ -34,7 +34,7 @@ lua_Number smlua_get_number_field(int index, char* name);
char* smlua_lnt_to_str(struct LSTNetworkType* lnt);
s64 smlua_get_mod_variable(u16 modIndex, char* variable) ;
s64 smlua_get_mod_variable(u16 modIndex, const char* variable) ;
void smlua_logline(void);
void smlua_dump_stack(void);

View file

@ -480,7 +480,7 @@ void smlua_model_util_clear(void) {
}
}
u8 smlua_model_util_load_with_pool(enum ModelExtendedId id, struct AllocOnlyPool* pool) {
u8 smlua_model_util_load_with_pool_and_cache_id(enum ModelExtendedId id, struct AllocOnlyPool* pool, u8 cacheId) {
if (id == E_MODEL_NONE) { return MODEL_NONE; }
if (id == E_MODEL_MAX) { LOG_ERROR("id invalid"); return MODEL_NONE; }
if (id > E_MODEL_MAX + sCustomModelsCount) { LOG_ERROR("id invalid"); return MODEL_NONE; }
@ -496,21 +496,25 @@ u8 smlua_model_util_load_with_pool(enum ModelExtendedId id, struct AllocOnlyPool
}
// find cached asset
bool foundEmptyCacheId = false;
u8 emptyCacheId = 0;
for (int i = 0; i < 255; i++) {
if (sCachedAssets[i].asset == info->asset) {
//LOG_INFO("Found in cached assets");
return sCachedAssets[i].id;
if (cacheId == 0) {
bool foundEmptyCacheId = false;
for (int i = 0; i < 255; i++) {
if (sCachedAssets[i].asset == info->asset) {
//LOG_INFO("Found in cached assets");
return sCachedAssets[i].id;
}
if (sCachedAssets[i].asset == NULL) {
foundEmptyCacheId = true;
emptyCacheId = i;
}
}
if (sCachedAssets[i].asset == NULL) {
foundEmptyCacheId = true;
emptyCacheId = i;
if (!foundEmptyCacheId) {
LOG_ERROR("No empty cache");
return 0xFF;
}
}
if (!foundEmptyCacheId) {
LOG_ERROR("No empty cache");
return 0xFF;
} else {
emptyCacheId = cacheId;
}
// load
@ -537,6 +541,10 @@ u8 smlua_model_util_load_with_pool(enum ModelExtendedId id, struct AllocOnlyPool
return emptyCacheId;
}
u8 smlua_model_util_load_with_pool(enum ModelExtendedId id, struct AllocOnlyPool* pool) {
return smlua_model_util_load_with_pool_and_cache_id(id, pool, 0);
}
u8 smlua_model_util_load(enum ModelExtendedId id) {
return smlua_model_util_load_with_pool(id, NULL);
}

View file

@ -392,6 +392,7 @@ enum ModelExtendedId {
void smlua_model_util_remember(u8 modelId, u8 layer, const void* asset, u8 isDisplayList);
void smlua_model_util_clear(void);
u8 smlua_model_util_load_with_pool_and_cache_id(enum ModelExtendedId id, struct AllocOnlyPool* pool, u8 cacheId);
u8 smlua_model_util_load_with_pool(enum ModelExtendedId id, struct AllocOnlyPool* pool);
u8 smlua_model_util_load(enum ModelExtendedId id);
u32 smlua_model_util_get_id(const char* name);