Added ability for DynOS levels to call into lua for custom objects

This commit is contained in:
MysterD 2022-04-04 18:16:36 -07:00
parent 32388bf6ff
commit abce3b3afd
20 changed files with 289 additions and 92 deletions

View file

@ -35,7 +35,7 @@ Collision* dynos_collision_get(const char* collisionName);
// -- levels -- // // -- levels -- //
void dynos_add_level(const char *modPath, const char* levelName); void dynos_add_level(s32 modIndex, const char *modPath, const char* levelName);
LevelScript* dynos_level_get(const char* levelName); LevelScript* dynos_level_get(const char* levelName);
#endif #endif

View file

@ -10,6 +10,7 @@ extern "C" {
#define FUNCTION_CODE (u32) 0x434E5546 #define FUNCTION_CODE (u32) 0x434E5546
#define POINTER_CODE (u32) 0x52544E50 #define POINTER_CODE (u32) 0x52544E50
#define LUA_VAR_CODE (u32) 0x5641554C
// //
// Enums // Enums
@ -450,8 +451,10 @@ struct GfxData : NoCopy {
u64 mLoadIndex = 0; u64 mLoadIndex = 0;
s32 mErrorCount = 0; s32 mErrorCount = 0;
u32 mModelIdentifier = 0; u32 mModelIdentifier = 0;
s32 mModIndex = 0;
SysPath mPackFolder; SysPath mPackFolder;
Array<void *> mPointerList; Array<void *> mPointerList;
Array<String> mPointerTokenList;
GfxContext mGfxContext; GfxContext mGfxContext;
Array<GfxContext> mGeoNodeStack; Array<GfxContext> mGeoNodeStack;
}; };
@ -703,8 +706,9 @@ s16 *DynOS_Level_GetWarp(s32 aLevel, s32 aArea, u8 aWarpId);
s16 *DynOS_Level_GetWarpEntry(s32 aLevel, s32 aArea); s16 *DynOS_Level_GetWarpEntry(s32 aLevel, s32 aArea);
s16 *DynOS_Level_GetWarpDeath(s32 aLevel, s32 aArea); s16 *DynOS_Level_GetWarpDeath(s32 aLevel, s32 aArea);
void DynOS_Lvl_Add(const SysPath &aPackFolder, const char *aLevelName); void DynOS_Lvl_Add(s32 modIndex, const SysPath &aPackFolder, const char *aLevelName);
LevelScript* DynOS_Lvl_Get(const char* levelName); LevelScript* DynOS_Lvl_Get(const char* levelName);
s32 DynOS_Lvl_GetModIndex(void* levelScript);
DataNode<TexData> *DynOS_Lvl_Texture_Get(void *aPtr); DataNode<TexData> *DynOS_Lvl_Texture_Get(void *aPtr);
// //

View file

@ -142,6 +142,7 @@ static void DynOS_Actor_Generate(const SysPath &aPackFolder, Array<Pair<u64, Str
_GfxData->mModelIdentifier = _GeoNode->mModelIdentifier; _GfxData->mModelIdentifier = _GeoNode->mModelIdentifier;
_GfxData->mPackFolder = aPackFolder; _GfxData->mPackFolder = aPackFolder;
_GfxData->mPointerList = { NULL }; // The NULL pointer is needed, so we add it here _GfxData->mPointerList = { NULL }; // The NULL pointer is needed, so we add it here
_GfxData->mPointerTokenList = { };
_GfxData->mGfxContext.mCurrentTexture = NULL; _GfxData->mGfxContext.mCurrentTexture = NULL;
_GfxData->mGfxContext.mCurrentPalette = NULL; _GfxData->mGfxContext.mCurrentPalette = NULL;
_GfxData->mGeoNodeStack.Clear(); _GfxData->mGeoNodeStack.Clear();

View file

@ -463,10 +463,12 @@ DataNode<Collision>* DynOS_Col_LoadFromBinary(const SysPath &aPackFolder, const
SysPath _Filename = fstring("%s/%s.col", aPackFolder.begin(), aCollisionName); SysPath _Filename = fstring("%s/%s.col", aPackFolder.begin(), aCollisionName);
FILE *_File = fopen(_Filename.c_str(), "rb"); FILE *_File = fopen(_Filename.c_str(), "rb");
if (_File) { if (_File) {
// backwards compatibility
long prevPos = ftell(_File);
u8 type = ReadBytes<u8>(_File); u8 type = ReadBytes<u8>(_File);
if (type == DATA_TYPE_COLLISION) { if (type != DATA_TYPE_COLLISION) { fseek(_File, prevPos, SEEK_SET); }
collisionNode = DynOS_Col_Load(_File, NULL); collisionNode = DynOS_Col_Load(_File, NULL);
}
fclose(_File); fclose(_File);
} }

View file

@ -1404,7 +1404,7 @@ s64 DynOS_Lvl_ParseLevelScriptConstants(const String& _Arg, bool* found) {
return 0; return 0;
} }
static LevelScript ParseLevelScriptSymbolArg(GfxData* aGfxData, DataNode<LevelScript>* aNode, u64& aTokenIndex) { static LevelScript ParseLevelScriptSymbolArgInternal(GfxData* aGfxData, DataNode<LevelScript>* aNode, u64& aTokenIndex, bool* found) {
const String& _Arg = aNode->mTokens[aTokenIndex++]; const String& _Arg = aNode->mTokens[aTokenIndex++];
// Lvl functions // Lvl functions
@ -1492,11 +1492,20 @@ static LevelScript ParseLevelScriptSymbolArg(GfxData* aGfxData, DataNode<LevelSc
return (LevelScript)rdValue; return (LevelScript)rdValue;
} }
// Unknown *found = false;
PrintError(" ERROR: Unknown lvl arg: %s", _Arg.begin());
return 0; return 0;
} }
static LevelScript ParseLevelScriptSymbolArg(GfxData* aGfxData, DataNode<LevelScript>* aNode, u64& aTokenIndex) {
bool found = true;
LevelScript value = ParseLevelScriptSymbolArgInternal(aGfxData, aNode, aTokenIndex, &found);
if (!found) {
const String& _Arg = aNode->mTokens[aTokenIndex - 1];
PrintError(" ERROR: Unknown lvl arg: %s", _Arg.begin());
}
return value;
}
#define lvl_symbol_0(symb) \ #define lvl_symbol_0(symb) \
if (_Symbol == #symb) { \ if (_Symbol == #symb) { \
LevelScript _Ls[] = { symb() }; \ LevelScript _Ls[] = { symb() }; \
@ -1589,49 +1598,6 @@ static LevelScript ParseLevelScriptSymbolArg(GfxData* aGfxData, DataNode<LevelSc
return; \ return; \
} }
#define lvl_symbol_9(symb, n1, n2, n3) \
if (_Symbol == #symb) { \
LevelScript _Arg0 = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex); \
LevelScript _Arg1 = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex); \
LevelScript _Arg2 = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex); \
LevelScript _Arg3 = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex); \
LevelScript _Arg4 = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex); \
LevelScript _Arg5 = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex); \
LevelScript _Arg6 = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex); \
LevelScript _Arg7 = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex); \
LevelScript _Arg8 = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex); \
if (n1 != 0) { aGfxData->mPointerList.Add(aHead + n1); } \
if (n2 != 0) { aGfxData->mPointerList.Add(aHead + n2); } \
if (n3 != 0) { aGfxData->mPointerList.Add(aHead + n3); } \
LevelScript _Ls[] = { symb(_Arg0, _Arg1, _Arg2, _Arg3, _Arg4, _Arg5, \
_Arg6, _Arg7, _Arg8) }; \
memcpy(aHead, _Ls, sizeof(_Ls)); \
aHead += (sizeof(_Ls) / sizeof(_Ls[0])); \
return; \
}
#define lvl_symbol_10(symb, n1, n2, n3) \
if (_Symbol == #symb) { \
LevelScript _Arg0 = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex); \
LevelScript _Arg1 = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex); \
LevelScript _Arg2 = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex); \
LevelScript _Arg3 = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex); \
LevelScript _Arg4 = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex); \
LevelScript _Arg5 = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex); \
LevelScript _Arg6 = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex); \
LevelScript _Arg7 = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex); \
LevelScript _Arg8 = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex); \
LevelScript _Arg9 = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex); \
if (n1 != 0) { aGfxData->mPointerList.Add(aHead + n1); } \
if (n2 != 0) { aGfxData->mPointerList.Add(aHead + n2); } \
if (n3 != 0) { aGfxData->mPointerList.Add(aHead + n3); } \
LevelScript _Ls[] = { symb(_Arg0, _Arg1, _Arg2, _Arg3, _Arg4, _Arg5, \
_Arg6, _Arg7, _Arg8, _Arg9) }; \
memcpy(aHead, _Ls, sizeof(_Ls)); \
aHead += (sizeof(_Ls) / sizeof(_Ls[0])); \
return; \
}
#define lvl_symbol_noop(symb, skipCount) \ #define lvl_symbol_noop(symb, skipCount) \
if (_Symbol == #symb) { \ if (_Symbol == #symb) { \
aTokenIndex += skipCount; \ aTokenIndex += skipCount; \
@ -1693,8 +1659,6 @@ static void ParseLevelScriptSymbol(GfxData* aGfxData, DataNode<LevelScript>* aNo
lvl_symbol_3(CMD23, 1, 0, 0); lvl_symbol_3(CMD23, 1, 0, 0);
// objects // objects
lvl_symbol_10(OBJECT_WITH_ACTS, 5, 0, 0);
lvl_symbol_9(OBJECT, 5, 0, 0);
lvl_symbol_3(MARIO, 2, 0, 0); lvl_symbol_3(MARIO, 2, 0, 0);
// warps // warps
@ -1732,6 +1696,91 @@ static void ParseLevelScriptSymbol(GfxData* aGfxData, DataNode<LevelScript>* aNo
lvl_symbol_0(ADV_DEMO); lvl_symbol_0(ADV_DEMO);
lvl_symbol_0(CLEAR_DEMO_PTR); lvl_symbol_0(CLEAR_DEMO_PTR);
// object
if (_Symbol == "OBJECT") {
u64 topTokenIndex = aTokenIndex;
bool foundModel = true;
bool foundBeh = true;
LevelScript model = ParseLevelScriptSymbolArgInternal(aGfxData, aNode, aTokenIndex, &foundModel);
LevelScript posX = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex);
LevelScript posY = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex);
LevelScript posZ = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex);
LevelScript angleX = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex);
LevelScript angleY = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex);
LevelScript angleZ = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex);
LevelScript behParam = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex);
LevelScript beh = ParseLevelScriptSymbolArgInternal(aGfxData, aNode, aTokenIndex, &foundBeh);
if (foundModel && foundBeh) {
aGfxData->mPointerList.Add(aHead + 5);
LevelScript _Ls[] = { OBJECT(model, posX, posY, posZ, angleX, angleY, angleZ, behParam, beh) };
memcpy(aHead, _Ls, sizeof(_Ls));
aHead += (sizeof(_Ls) / sizeof(_Ls[0]));
} else {
// remember model/beh as pointer
aGfxData->mPointerList.Add(aHead + 5);
aGfxData->mPointerList.Add(aHead + 6);
// add model/beh tokens
u32 tokenListIndex = aGfxData->mPointerTokenList.Count();
aGfxData->mPointerTokenList.Add(aNode->mTokens[topTokenIndex + 0]);
aGfxData->mPointerTokenList.Add(aNode->mTokens[topTokenIndex + 8]);
// get model/beh tokens
String& modelToken = aGfxData->mPointerTokenList[tokenListIndex + 0];
String& behToken = aGfxData->mPointerTokenList[tokenListIndex + 1];
LevelScript _Ls[] = { OBJECT_EXT(modelToken.begin(), posX, posY, posZ, angleX, angleY, angleZ, behParam, behToken.begin()) };
memcpy(aHead, _Ls, sizeof(_Ls));
aHead += (sizeof(_Ls) / sizeof(_Ls[0]));
}
return;
}
// object with acts
if (_Symbol == "OBJECT_WITH_ACTS") {
u64 topTokenIndex = aTokenIndex;
bool foundModel = true;
bool foundBeh = true;
LevelScript model = ParseLevelScriptSymbolArgInternal(aGfxData, aNode, aTokenIndex, &foundModel);
LevelScript posX = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex);
LevelScript posY = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex);
LevelScript posZ = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex);
LevelScript angleX = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex);
LevelScript angleY = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex);
LevelScript angleZ = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex);
LevelScript behParam = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex);
LevelScript beh = ParseLevelScriptSymbolArgInternal(aGfxData, aNode, aTokenIndex, &foundBeh);
LevelScript acts = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex);
if (foundModel && foundBeh) {
aGfxData->mPointerList.Add(aHead + 5);
LevelScript _Ls[] = { OBJECT_WITH_ACTS(model, posX, posY, posZ, angleX, angleY, angleZ, behParam, beh, acts) };
memcpy(aHead, _Ls, sizeof(_Ls));
aHead += (sizeof(_Ls) / sizeof(_Ls[0]));
} else {
// remember model/beh as pointer
aGfxData->mPointerList.Add(aHead + 5);
aGfxData->mPointerList.Add(aHead + 6);
// add model/beh tokens
u32 tokenListIndex = aGfxData->mPointerTokenList.Count();
aGfxData->mPointerTokenList.Add(aNode->mTokens[topTokenIndex + 0]);
aGfxData->mPointerTokenList.Add(aNode->mTokens[topTokenIndex + 8]);
// get model/beh tokens
String& modelToken = aGfxData->mPointerTokenList[tokenListIndex + 0];
String& behToken = aGfxData->mPointerTokenList[tokenListIndex + 1];
LevelScript _Ls[] = { OBJECT_WITH_ACTS_EXT(modelToken.begin(), posX, posY, posZ, angleX, angleY, angleZ, behParam, behToken.begin(), acts) };
memcpy(aHead, _Ls, sizeof(_Ls));
aHead += (sizeof(_Ls) / sizeof(_Ls[0]));
}
return;
}
// Unknown // Unknown
PrintError(" ERROR: Unknown lvl symbol: %s", _Symbol.begin()); PrintError(" ERROR: Unknown lvl symbol: %s", _Symbol.begin());
} }
@ -2014,7 +2063,7 @@ void DynOS_Lvl_GeneratePack(const SysPath &aPackFolder) {
if (!fs_sys_dir_exists(_Folder.c_str())) continue; if (!fs_sys_dir_exists(_Folder.c_str())) continue;
// Only parse folders with a 'script.c' // Only parse folders with a 'script.c'
if (!fs_sys_file_exists(fstring("%s/script.c", _Folder.c_str()).c_str())) continue; if (!fs_sys_file_exists(fstring("%s/script.c", _Folder.c_str()).c_str()) && !fs_sys_file_exists(fstring("%s/custom.script.c", _Folder.c_str()).c_str())) continue;
GfxData *_GfxData = New<GfxData>(); GfxData *_GfxData = New<GfxData>();
_GfxData->mModelIdentifier = 0; _GfxData->mModelIdentifier = 0;

View file

@ -178,6 +178,16 @@ void DynOS_Pointer_Write(FILE* aFile, const void* aPtr, GfxData* aGfxData) {
return; return;
} }
// Lua variable
for (s32 i = 0; i < aGfxData->mPointerTokenList.Count(); i++) {
if (aPtr == aGfxData->mPointerTokenList[i].begin()) {
String& token = aGfxData->mPointerTokenList[i];
WriteBytes<u32>(aFile, LUA_VAR_CODE);
token.Write(aFile);
return;
}
}
// Pointer // Pointer
PointerData _PtrData = GetDataFromPointer(aPtr, aGfxData); PointerData _PtrData = GetDataFromPointer(aPtr, aGfxData);
if (strlen(_PtrData.first.begin()) == 0) { if (strlen(_PtrData.first.begin()) == 0) {
@ -324,6 +334,14 @@ void *DynOS_Pointer_Load(FILE *aFile, GfxData *aGfxData, u32 aValue, bool isLvl)
: DynOS_Geo_GetFunctionPointerFromIndex(_FunctionIndex); : DynOS_Geo_GetFunctionPointerFromIndex(_FunctionIndex);
} }
// LUAV
if (aValue == LUA_VAR_CODE) {
String token; token.Read(aFile);
u32 index = aGfxData->mPointerTokenList.Count();
aGfxData->mPointerTokenList.Add(token);
return aGfxData->mPointerTokenList[index].begin();
}
// PNTR // PNTR
if (aValue == POINTER_CODE) { if (aValue == POINTER_CODE) {
String _PtrName; _PtrName.Read(aFile); String _PtrName; _PtrName.Read(aFile);

View file

@ -140,8 +140,8 @@ void DynOS_Read_Source(GfxData *aGfxData, const SysPath &aFilename) {
// Scanning data type // Scanning data type
if (_DataType == DATA_TYPE_NONE) { if (_DataType == DATA_TYPE_NONE) {
// skip includes // skip includes and externs
if (!strncmp(c, "#include", 8)) { if (!strncmp(c, "#include", 8) || !strncmp(c, "extern ", 7)) {
while (*c != '\n' && *c != '\0') { while (*c != '\n' && *c != '\0') {
c++; c++;
} }

View file

@ -99,8 +99,8 @@ Collision* dynos_collision_get(const char* collisionName) {
// -- levels -- // // -- levels -- //
void dynos_add_level(const char *modPath, const char* levelName) { void dynos_add_level(s32 modIndex, const char *modPath, const char* levelName) {
DynOS_Lvl_Add(modPath, levelName); DynOS_Lvl_Add(modIndex, modPath, levelName);
} }
LevelScript* dynos_level_get(const char* levelName) { LevelScript* dynos_level_get(const char* levelName) {

View file

@ -36,6 +36,7 @@ extern "C" {
#include "actors/group17.h" #include "actors/group17.h"
#include "actors/custom0.h" #include "actors/custom0.h"
#include "actors/zcustom0.h" #include "actors/zcustom0.h"
#include "levels/wf/header.h"
} }
// //
@ -607,7 +608,7 @@ Collision* DynOS_Col_Get(const char* collisionName) {
static Array<Pair<const char*, GfxData*>> sDynosCustomLevelScripts; static Array<Pair<const char*, GfxData*>> sDynosCustomLevelScripts;
void DynOS_Lvl_Add(const SysPath &aPackFolder, const char *aLevelName) { void DynOS_Lvl_Add(s32 modIndex, const SysPath &aPackFolder, const char *aLevelName) {
// check for duplicates // check for duplicates
for (s32 i = 0; i < sDynosCustomLevelScripts.Count(); ++i) { for (s32 i = 0; i < sDynosCustomLevelScripts.Count(); ++i) {
if (!strcmp(sDynosCustomLevelScripts[i].first, aLevelName)) { if (!strcmp(sDynosCustomLevelScripts[i].first, aLevelName)) {
@ -625,6 +626,9 @@ void DynOS_Lvl_Add(const SysPath &aPackFolder, const char *aLevelName) {
return; return;
} }
// remember index
_Node->mModIndex = modIndex;
// Add to levels // Add to levels
sDynosCustomLevelScripts.Add({ levelName, _Node }); sDynosCustomLevelScripts.Add({ levelName, _Node });
} }
@ -644,6 +648,16 @@ LevelScript* DynOS_Lvl_Get(const char* levelName) {
return NULL; return NULL;
} }
s32 DynOS_Lvl_GetModIndex(void* levelScript) {
for (s32 i = 0; i < sDynosCustomLevelScripts.Count(); ++i) {
auto& scripts = sDynosCustomLevelScripts[i].second->mLevelScripts;
if (levelScript == scripts[scripts.Count() - 1]->mData) {
return sDynosCustomLevelScripts[i].second->mModIndex;
}
}
return -1;
}
DataNode<TexData> *DynOS_Lvl_Texture_Get(void *aPtr) { DataNode<TexData> *DynOS_Lvl_Texture_Get(void *aPtr) {
for (s32 i = 0; i < sDynosCustomLevelScripts.Count(); ++i) { for (s32 i = 0; i < sDynosCustomLevelScripts.Count(); ++i) {
auto &mTextures = sDynosCustomLevelScripts[i].second->mTextures; auto &mTextures = sDynosCustomLevelScripts[i].second->mTextures;

View file

@ -11,6 +11,7 @@ extern "C" {
#include "game/sound_init.h" #include "game/sound_init.h"
#include "game/object_list_processor.h" #include "game/object_list_processor.h"
#include "game/options_menu.h" #include "game/options_menu.h"
#include "engine/level_script.h"
extern s8 gDialogBoxState; extern s8 gDialogBoxState;
extern s16 gMenuMode; extern s16 gMenuMode;
extern s32 gWdwWaterLevelSet; extern s32 gWdwWaterLevelSet;
@ -248,7 +249,9 @@ static void *DynOS_Warp_UpdateWarp(void *aCmd, bool aIsLevelInitDone) {
sWarpDest.areaIdx = gCurrAreaIndex; sWarpDest.areaIdx = gCurrAreaIndex;
sWarpDest.nodeId = 0; sWarpDest.nodeId = 0;
sWarpDest.arg = 0; sWarpDest.arg = 0;
return (void *) DynOS_Level_GetScript(gCurrLevelNum); void* levelScript = (void *) DynOS_Level_GetScript(gCurrLevelNum);
gLevelScriptModIndex = DynOS_Lvl_GetModIndex(levelScript);
return levelScript;
} else { } else {

View file

@ -282,4 +282,16 @@
#define CLEAR_DEMO_PTR() \ #define CLEAR_DEMO_PTR() \
CMD_BBH(0x3E, 0x04, 0x0000) CMD_BBH(0x3E, 0x04, 0x0000)
// coop
#define OBJECT_WITH_ACTS_EXT(model, posX, posY, posZ, angleX, angleY, angleZ, behParam, beh, acts) \
CMD_BBBB(0x3F, 0x1C, acts, 0), \
CMD_HHHHHH(posX, posY, posZ, angleX, angleY, angleZ), \
CMD_W(behParam), \
CMD_PTR(model), \
CMD_PTR(beh)
#define OBJECT_EXT(model, posX, posY, posZ, angleX, angleY, angleZ, behParam, beh) \
OBJECT_WITH_ACTS_EXT(model, posX, posY, posZ, angleX, angleY, angleZ, behParam, beh, 0x1F)
#endif // LEVEL_COMMANDS_H #endif // LEVEL_COMMANDS_H

View file

@ -24,6 +24,7 @@
#include "surface_load.h" #include "surface_load.h"
#include "level_table.h" #include "level_table.h"
#include "src/pc/lua/utils/smlua_model_utils.h" #include "src/pc/lua/utils/smlua_model_utils.h"
#include "src/pc/lua/smlua.h"
#define CMD_GET(type, offset) (*(type *) (CMD_PROCESS_OFFSET(offset) + (u8 *) sCurrentCmd)) #define CMD_GET(type, offset) (*(type *) (CMD_PROCESS_OFFSET(offset) + (u8 *) sCurrentCmd))
@ -39,6 +40,8 @@ struct LevelCommand {
enum ScriptStatus { SCRIPT_RUNNING = 1, SCRIPT_PAUSED = 0, SCRIPT_PAUSED2 = -1 }; enum ScriptStatus { SCRIPT_RUNNING = 1, SCRIPT_PAUSED = 0, SCRIPT_PAUSED2 = -1 };
s32 gLevelScriptModIndex = -1;
static uintptr_t sStack[32]; static uintptr_t sStack[32];
static struct AllocOnlyPool *sLevelPool = NULL; static struct AllocOnlyPool *sLevelPool = NULL;
@ -820,6 +823,51 @@ static void level_cmd_cleardemoptr(void)
sCurrentCmd = CMD_NEXT; sCurrentCmd = CMD_NEXT;
} }
// coop
static void level_cmd_place_object_ext(void) {
u8 val7 = 1 << (gCurrActNum - 1);
struct SpawnInfo *spawnInfo;
u16 modIndex = gLevelScriptModIndex;
char* modelStr = CMD_GET(char*, 20);
char* behStr = CMD_GET(char*, 24);
gSmLuaConvertSuccess = true;
enum ModelExtendedId modelId = smlua_get_mod_variable(modIndex, modelStr);
enum BehaviorId behId = smlua_get_mod_variable(modIndex, behStr);
if ((gLevelScriptModIndex == -1) || !gSmLuaConvertSuccess) {
LOG_ERROR("Failed to place custom object: %u, %u", modelId, behId);
sCurrentCmd = CMD_NEXT;
return;
}
if (sCurrAreaIndex != -1 && ((CMD_GET(u8, 2) & val7) || CMD_GET(u8, 2) == 0x1F)) {
spawnInfo = alloc_only_pool_alloc(sLevelPool, sizeof(struct SpawnInfo));
spawnInfo->startPos[0] = CMD_GET(s16, 4);
spawnInfo->startPos[1] = CMD_GET(s16, 6);
spawnInfo->startPos[2] = CMD_GET(s16, 8);
spawnInfo->startAngle[0] = CMD_GET(s16, 10) * 0x8000 / 180;
spawnInfo->startAngle[1] = CMD_GET(s16, 12) * 0x8000 / 180;
spawnInfo->startAngle[2] = CMD_GET(s16, 14) * 0x8000 / 180;
spawnInfo->areaIndex = sCurrAreaIndex;
spawnInfo->activeAreaIndex = sCurrAreaIndex;
spawnInfo->behaviorArg = CMD_GET(u32, 16);
spawnInfo->behaviorScript = (BehaviorScript*)get_behavior_from_id(behId);
spawnInfo->unk18 = gLoadedGraphNodes[smlua_model_util_load_with_pool(modelId, sLevelPool)];
spawnInfo->next = gAreas[sCurrAreaIndex].objectSpawnInfos;
gAreas[sCurrAreaIndex].objectSpawnInfos = spawnInfo;
}
sCurrentCmd = CMD_NEXT;
}
static void (*LevelScriptJumpTable[])(void) = { static void (*LevelScriptJumpTable[])(void) = {
/*00*/ level_cmd_load_and_execute, /*00*/ level_cmd_load_and_execute,
/*01*/ level_cmd_exit_and_execute, /*01*/ level_cmd_exit_and_execute,
@ -884,6 +932,9 @@ static void (*LevelScriptJumpTable[])(void) = {
/*3C*/ level_cmd_get_or_set_var, /*3C*/ level_cmd_get_or_set_var,
/*3D*/ level_cmd_advdemo, /*3D*/ level_cmd_advdemo,
/*3E*/ level_cmd_cleardemoptr, /*3E*/ level_cmd_cleardemoptr,
// coop
/*3F*/ level_cmd_place_object_ext,
}; };
struct LevelCommand *level_script_execute(struct LevelCommand *cmd) { struct LevelCommand *level_script_execute(struct LevelCommand *cmd) {

View file

@ -5,6 +5,8 @@
struct LevelCommand; struct LevelCommand;
extern s32 gLevelScriptModIndex;
extern u8 level_script_entry[]; extern u8 level_script_entry[];
struct LevelCommand *level_script_execute(struct LevelCommand *cmd); struct LevelCommand *level_script_execute(struct LevelCommand *cmd);

View file

@ -1,4 +1,5 @@
#include "smlua.h" #include "smlua.h"
#include "src/pc/mods/mods.h"
u8 gSmLuaConvertSuccess = false; u8 gSmLuaConvertSuccess = false;
@ -191,6 +192,7 @@ void* smlua_to_cpointer(lua_State* L, int index, u16 lvt) {
gSmLuaConvertSuccess = true; gSmLuaConvertSuccess = true;
return pointer; return pointer;
} }
struct LSTNetworkType smlua_to_lnt(lua_State* L, int index) { struct LSTNetworkType smlua_to_lnt(lua_State* L, int index) {
struct LSTNetworkType lnt = { 0 }; struct LSTNetworkType lnt = { 0 };
int valueType = lua_type(L, index); int valueType = lua_type(L, index);
@ -366,6 +368,26 @@ lua_Number smlua_get_number_field(int index, char* name) {
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
s64 smlua_get_mod_variable(u16 modIndex, char* variable) {
lua_State* L = gLuaState;
// figure out entry
struct Mod* mod = gActiveMods.entries[modIndex];
if (mod == NULL) {
LOG_ERROR("Could not find mod list entry for modIndex: %u", modIndex);
return 0;
}
lua_getglobal(L, "_G"); // get global table
lua_getfield(L, LUA_REGISTRYINDEX, mod->relativePath); // get the file's "global" table
lua_remove(L, -2); // remove global table
// push variable
return smlua_get_integer_field(-1, variable);
}
///////////////////////////////////////////////////////////////////////////////////////////
char* smlua_lnt_to_str(struct LSTNetworkType* lnt) { char* smlua_lnt_to_str(struct LSTNetworkType* lnt) {
static char sLntStr[32] = ""; static char sLntStr[32] = "";
switch (lnt->type) { switch (lnt->type) {

View file

@ -33,6 +33,9 @@ lua_Integer smlua_get_integer_field(int index, char* name);
lua_Number smlua_get_number_field(int index, char* name); lua_Number smlua_get_number_field(int index, char* name);
char* smlua_lnt_to_str(struct LSTNetworkType* lnt); char* smlua_lnt_to_str(struct LSTNetworkType* lnt);
s64 smlua_get_mod_variable(u16 modIndex, char* variable) ;
void smlua_logline(void); void smlua_logline(void);
void smlua_dump_stack(void); void smlua_dump_stack(void);
void smlua_dump_globals(void); void smlua_dump_globals(void);

View file

@ -480,7 +480,7 @@ void smlua_model_util_clear(void) {
} }
} }
u8 smlua_model_util_load(enum ModelExtendedId id) { u8 smlua_model_util_load_with_pool(enum ModelExtendedId id, struct AllocOnlyPool* pool) {
if (id == E_MODEL_NONE) { return MODEL_NONE; } 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) { LOG_ERROR("id invalid"); return MODEL_NONE; }
if (id > E_MODEL_MAX + sCustomModelsCount) { LOG_ERROR("id invalid"); return MODEL_NONE; } if (id > E_MODEL_MAX + sCustomModelsCount) { LOG_ERROR("id invalid"); return MODEL_NONE; }
@ -514,14 +514,21 @@ u8 smlua_model_util_load(enum ModelExtendedId id) {
} }
// load // load
struct AllocOnlyPool* pool = alloc_only_pool_init(main_pool_available() - sizeof(struct AllocOnlyPool), MEMORY_POOL_LEFT); bool resizePool = false;
if (pool == NULL) {
pool = alloc_only_pool_init(main_pool_available() - sizeof(struct AllocOnlyPool), MEMORY_POOL_LEFT);
resizePool = true;
}
if (info->isDisplayList) { if (info->isDisplayList) {
gLoadedGraphNodes[emptyCacheId] = (struct GraphNode *) init_graph_node_display_list(pool, NULL, info->layer, (void*)info->asset); gLoadedGraphNodes[emptyCacheId] = (struct GraphNode *) init_graph_node_display_list(pool, NULL, info->layer, (void*)info->asset);
} else { } else {
gLoadedGraphNodes[emptyCacheId] = process_geo_layout(pool, (void*)info->asset); gLoadedGraphNodes[emptyCacheId] = process_geo_layout(pool, (void*)info->asset);
} }
if (resizePool) {
alloc_only_pool_resize(pool, pool->usedSpace); alloc_only_pool_resize(pool, pool->usedSpace);
//LOG_INFO("Loaded at runtime"); }
// remember // remember
smlua_model_util_remember(emptyCacheId, info->layer, info->asset, info->isDisplayList); smlua_model_util_remember(emptyCacheId, info->layer, info->asset, info->isDisplayList);
@ -530,6 +537,10 @@ u8 smlua_model_util_load(enum ModelExtendedId id) {
return emptyCacheId; return emptyCacheId;
} }
u8 smlua_model_util_load(enum ModelExtendedId id) {
return smlua_model_util_load_with_pool(id, NULL);
}
u32 smlua_model_util_get_id(const char* name) { u32 smlua_model_util_get_id(const char* name) {
// find geolayout // find geolayout
const void* layout = dynos_geolayout_get(name); const void* layout = dynos_geolayout_get(name);

View file

@ -1,6 +1,8 @@
#ifndef SMLUA_MODEL_UTILS_H #ifndef SMLUA_MODEL_UTILS_H
#define SMLUA_MODEL_UTILS_H #define SMLUA_MODEL_UTILS_H
#include "src/game/memory.h"
enum ModelExtendedId { enum ModelExtendedId {
E_MODEL_NONE, E_MODEL_NONE,
@ -390,6 +392,7 @@ enum ModelExtendedId {
void smlua_model_util_remember(u8 modelId, u8 layer, const void* asset, u8 isDisplayList); void smlua_model_util_remember(u8 modelId, u8 layer, const void* asset, u8 isDisplayList);
void smlua_model_util_clear(void); void smlua_model_util_clear(void);
u8 smlua_model_util_load_with_pool(enum ModelExtendedId id, struct AllocOnlyPool* pool);
u8 smlua_model_util_load(enum ModelExtendedId id); u8 smlua_model_util_load(enum ModelExtendedId id);
u32 smlua_model_util_get_id(const char* name); u32 smlua_model_util_get_id(const char* name);

View file

@ -88,7 +88,7 @@ static void mod_activate_lvl(struct Mod* mod, struct ModFile* file) {
} }
// Add to levels // Add to levels
dynos_add_level(dynosPath, lvlName); dynos_add_level(mod->index, dynosPath, lvlName);
LOG_INFO("Activating DynOS lvl: '%s', '%s'", dynosPath, lvlName); LOG_INFO("Activating DynOS lvl: '%s', '%s'", dynosPath, lvlName);
} }

View file

@ -23,6 +23,7 @@ struct Mod {
char relativePath[SYS_MAX_PATH]; char relativePath[SYS_MAX_PATH];
char basePath[SYS_MAX_PATH]; char basePath[SYS_MAX_PATH];
struct ModFile* files; struct ModFile* files;
s32 index;
u16 fileCount; u16 fileCount;
bool isDirectory; bool isDirectory;
bool enabled; bool enabled;

View file

@ -64,6 +64,7 @@ void mods_activate(struct Mods* mods) {
for (int i = 0; i < mods->entryCount; i++) { for (int i = 0; i < mods->entryCount; i++) {
struct Mod* mod = mods->entries[i]; struct Mod* mod = mods->entries[i];
if (mod->enabled) { if (mod->enabled) {
mod->index = gActiveMods.entryCount;
gActiveMods.entries[gActiveMods.entryCount++] = mod; gActiveMods.entries[gActiveMods.entryCount++] = mod;
mod_activate(mod); mod_activate(mod);
} }