mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2024-11-25 05:25:14 +00:00
Added ability for DynOS levels to call into lua for custom objects
This commit is contained in:
parent
32388bf6ff
commit
abce3b3afd
20 changed files with 289 additions and 92 deletions
|
@ -35,7 +35,7 @@ Collision* dynos_collision_get(const char* collisionName);
|
|||
|
||||
// -- 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);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -10,6 +10,7 @@ extern "C" {
|
|||
|
||||
#define FUNCTION_CODE (u32) 0x434E5546
|
||||
#define POINTER_CODE (u32) 0x52544E50
|
||||
#define LUA_VAR_CODE (u32) 0x5641554C
|
||||
|
||||
//
|
||||
// Enums
|
||||
|
@ -450,8 +451,10 @@ struct GfxData : NoCopy {
|
|||
u64 mLoadIndex = 0;
|
||||
s32 mErrorCount = 0;
|
||||
u32 mModelIdentifier = 0;
|
||||
s32 mModIndex = 0;
|
||||
SysPath mPackFolder;
|
||||
Array<void *> mPointerList;
|
||||
Array<String> mPointerTokenList;
|
||||
GfxContext mGfxContext;
|
||||
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_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);
|
||||
s32 DynOS_Lvl_GetModIndex(void* levelScript);
|
||||
DataNode<TexData> *DynOS_Lvl_Texture_Get(void *aPtr);
|
||||
|
||||
//
|
||||
|
|
|
@ -142,6 +142,7 @@ static void DynOS_Actor_Generate(const SysPath &aPackFolder, Array<Pair<u64, Str
|
|||
_GfxData->mModelIdentifier = _GeoNode->mModelIdentifier;
|
||||
_GfxData->mPackFolder = aPackFolder;
|
||||
_GfxData->mPointerList = { NULL }; // The NULL pointer is needed, so we add it here
|
||||
_GfxData->mPointerTokenList = { };
|
||||
_GfxData->mGfxContext.mCurrentTexture = NULL;
|
||||
_GfxData->mGfxContext.mCurrentPalette = NULL;
|
||||
_GfxData->mGeoNodeStack.Clear();
|
||||
|
|
|
@ -463,10 +463,12 @@ DataNode<Collision>* DynOS_Col_LoadFromBinary(const SysPath &aPackFolder, const
|
|||
SysPath _Filename = fstring("%s/%s.col", aPackFolder.begin(), aCollisionName);
|
||||
FILE *_File = fopen(_Filename.c_str(), "rb");
|
||||
if (_File) {
|
||||
// backwards compatibility
|
||||
long prevPos = ftell(_File);
|
||||
u8 type = ReadBytes<u8>(_File);
|
||||
if (type == DATA_TYPE_COLLISION) {
|
||||
collisionNode = DynOS_Col_Load(_File, NULL);
|
||||
}
|
||||
if (type != DATA_TYPE_COLLISION) { fseek(_File, prevPos, SEEK_SET); }
|
||||
|
||||
collisionNode = DynOS_Col_Load(_File, NULL);
|
||||
fclose(_File);
|
||||
}
|
||||
|
||||
|
|
|
@ -1404,7 +1404,7 @@ s64 DynOS_Lvl_ParseLevelScriptConstants(const String& _Arg, bool* found) {
|
|||
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++];
|
||||
|
||||
// Lvl functions
|
||||
|
@ -1492,11 +1492,20 @@ static LevelScript ParseLevelScriptSymbolArg(GfxData* aGfxData, DataNode<LevelSc
|
|||
return (LevelScript)rdValue;
|
||||
}
|
||||
|
||||
// Unknown
|
||||
PrintError(" ERROR: Unknown lvl arg: %s", _Arg.begin());
|
||||
*found = false;
|
||||
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) \
|
||||
if (_Symbol == #symb) { \
|
||||
LevelScript _Ls[] = { symb() }; \
|
||||
|
@ -1541,95 +1550,52 @@ static LevelScript ParseLevelScriptSymbolArg(GfxData* aGfxData, DataNode<LevelSc
|
|||
return; \
|
||||
}
|
||||
|
||||
#define lvl_symbol_4(symb, n1, n2, n3) \
|
||||
if (_Symbol == #symb) { \
|
||||
#define lvl_symbol_4(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); \
|
||||
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) }; \
|
||||
memcpy(aHead, _Ls, sizeof(_Ls)); \
|
||||
aHead += (sizeof(_Ls) / sizeof(_Ls[0])); \
|
||||
return; \
|
||||
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) }; \
|
||||
memcpy(aHead, _Ls, sizeof(_Ls)); \
|
||||
aHead += (sizeof(_Ls) / sizeof(_Ls[0])); \
|
||||
return; \
|
||||
}
|
||||
|
||||
#define lvl_symbol_5(symb, n1, n2, n3) \
|
||||
if (_Symbol == #symb) { \
|
||||
#define lvl_symbol_5(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); \
|
||||
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) }; \
|
||||
memcpy(aHead, _Ls, sizeof(_Ls)); \
|
||||
aHead += (sizeof(_Ls) / sizeof(_Ls[0])); \
|
||||
return; \
|
||||
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) }; \
|
||||
memcpy(aHead, _Ls, sizeof(_Ls)); \
|
||||
aHead += (sizeof(_Ls) / sizeof(_Ls[0])); \
|
||||
return; \
|
||||
}
|
||||
|
||||
#define lvl_symbol_6(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); \
|
||||
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) }; \
|
||||
memcpy(aHead, _Ls, sizeof(_Ls)); \
|
||||
aHead += (sizeof(_Ls) / sizeof(_Ls[0])); \
|
||||
return; \
|
||||
}
|
||||
|
||||
#define lvl_symbol_9(symb, n1, n2, n3) \
|
||||
if (_Symbol == #symb) { \
|
||||
#define lvl_symbol_6(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; \
|
||||
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) }; \
|
||||
memcpy(aHead, _Ls, sizeof(_Ls)); \
|
||||
aHead += (sizeof(_Ls) / sizeof(_Ls[0])); \
|
||||
return; \
|
||||
}
|
||||
|
||||
#define lvl_symbol_noop(symb, skipCount) \
|
||||
|
@ -1693,8 +1659,6 @@ static void ParseLevelScriptSymbol(GfxData* aGfxData, DataNode<LevelScript>* aNo
|
|||
lvl_symbol_3(CMD23, 1, 0, 0);
|
||||
|
||||
// objects
|
||||
lvl_symbol_10(OBJECT_WITH_ACTS, 5, 0, 0);
|
||||
lvl_symbol_9(OBJECT, 5, 0, 0);
|
||||
lvl_symbol_3(MARIO, 2, 0, 0);
|
||||
|
||||
// warps
|
||||
|
@ -1732,6 +1696,91 @@ static void ParseLevelScriptSymbol(GfxData* aGfxData, DataNode<LevelScript>* aNo
|
|||
lvl_symbol_0(ADV_DEMO);
|
||||
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
|
||||
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;
|
||||
|
||||
// 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->mModelIdentifier = 0;
|
||||
|
|
|
@ -178,6 +178,16 @@ void DynOS_Pointer_Write(FILE* aFile, const void* aPtr, GfxData* aGfxData) {
|
|||
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
|
||||
PointerData _PtrData = GetDataFromPointer(aPtr, aGfxData);
|
||||
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);
|
||||
}
|
||||
|
||||
// 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
|
||||
if (aValue == POINTER_CODE) {
|
||||
String _PtrName; _PtrName.Read(aFile);
|
||||
|
|
|
@ -140,8 +140,8 @@ void DynOS_Read_Source(GfxData *aGfxData, const SysPath &aFilename) {
|
|||
// Scanning data type
|
||||
if (_DataType == DATA_TYPE_NONE) {
|
||||
|
||||
// skip includes
|
||||
if (!strncmp(c, "#include", 8)) {
|
||||
// skip includes and externs
|
||||
if (!strncmp(c, "#include", 8) || !strncmp(c, "extern ", 7)) {
|
||||
while (*c != '\n' && *c != '\0') {
|
||||
c++;
|
||||
}
|
||||
|
|
|
@ -99,8 +99,8 @@ Collision* dynos_collision_get(const char* collisionName) {
|
|||
|
||||
// -- levels -- //
|
||||
|
||||
void dynos_add_level(const char *modPath, const char* levelName) {
|
||||
DynOS_Lvl_Add(modPath, levelName);
|
||||
void dynos_add_level(s32 modIndex, const char *modPath, const char* levelName) {
|
||||
DynOS_Lvl_Add(modIndex, modPath, levelName);
|
||||
}
|
||||
|
||||
LevelScript* dynos_level_get(const char* levelName) {
|
||||
|
|
|
@ -36,6 +36,7 @@ extern "C" {
|
|||
#include "actors/group17.h"
|
||||
#include "actors/custom0.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;
|
||||
|
||||
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
|
||||
for (s32 i = 0; i < sDynosCustomLevelScripts.Count(); ++i) {
|
||||
if (!strcmp(sDynosCustomLevelScripts[i].first, aLevelName)) {
|
||||
|
@ -625,6 +626,9 @@ void DynOS_Lvl_Add(const SysPath &aPackFolder, const char *aLevelName) {
|
|||
return;
|
||||
}
|
||||
|
||||
// remember index
|
||||
_Node->mModIndex = modIndex;
|
||||
|
||||
// Add to levels
|
||||
sDynosCustomLevelScripts.Add({ levelName, _Node });
|
||||
}
|
||||
|
@ -644,6 +648,16 @@ LevelScript* DynOS_Lvl_Get(const char* levelName) {
|
|||
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) {
|
||||
for (s32 i = 0; i < sDynosCustomLevelScripts.Count(); ++i) {
|
||||
auto &mTextures = sDynosCustomLevelScripts[i].second->mTextures;
|
||||
|
|
|
@ -11,6 +11,7 @@ extern "C" {
|
|||
#include "game/sound_init.h"
|
||||
#include "game/object_list_processor.h"
|
||||
#include "game/options_menu.h"
|
||||
#include "engine/level_script.h"
|
||||
extern s8 gDialogBoxState;
|
||||
extern s16 gMenuMode;
|
||||
extern s32 gWdwWaterLevelSet;
|
||||
|
@ -248,7 +249,9 @@ static void *DynOS_Warp_UpdateWarp(void *aCmd, bool aIsLevelInitDone) {
|
|||
sWarpDest.areaIdx = gCurrAreaIndex;
|
||||
sWarpDest.nodeId = 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 {
|
||||
|
||||
|
|
|
@ -282,4 +282,16 @@
|
|||
#define CLEAR_DEMO_PTR() \
|
||||
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
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "surface_load.h"
|
||||
#include "level_table.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))
|
||||
|
||||
|
@ -39,6 +40,8 @@ struct LevelCommand {
|
|||
|
||||
enum ScriptStatus { SCRIPT_RUNNING = 1, SCRIPT_PAUSED = 0, SCRIPT_PAUSED2 = -1 };
|
||||
|
||||
s32 gLevelScriptModIndex = -1;
|
||||
|
||||
static uintptr_t sStack[32];
|
||||
|
||||
static struct AllocOnlyPool *sLevelPool = NULL;
|
||||
|
@ -820,6 +823,51 @@ static void level_cmd_cleardemoptr(void)
|
|||
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) = {
|
||||
/*00*/ level_cmd_load_and_execute,
|
||||
/*01*/ level_cmd_exit_and_execute,
|
||||
|
@ -884,6 +932,9 @@ static void (*LevelScriptJumpTable[])(void) = {
|
|||
/*3C*/ level_cmd_get_or_set_var,
|
||||
/*3D*/ level_cmd_advdemo,
|
||||
/*3E*/ level_cmd_cleardemoptr,
|
||||
|
||||
// coop
|
||||
/*3F*/ level_cmd_place_object_ext,
|
||||
};
|
||||
|
||||
struct LevelCommand *level_script_execute(struct LevelCommand *cmd) {
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
|
||||
struct LevelCommand;
|
||||
|
||||
extern s32 gLevelScriptModIndex;
|
||||
|
||||
extern u8 level_script_entry[];
|
||||
|
||||
struct LevelCommand *level_script_execute(struct LevelCommand *cmd);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "smlua.h"
|
||||
#include "src/pc/mods/mods.h"
|
||||
|
||||
u8 gSmLuaConvertSuccess = false;
|
||||
|
||||
|
@ -191,6 +192,7 @@ void* smlua_to_cpointer(lua_State* L, int index, u16 lvt) {
|
|||
gSmLuaConvertSuccess = true;
|
||||
return pointer;
|
||||
}
|
||||
|
||||
struct LSTNetworkType smlua_to_lnt(lua_State* L, int index) {
|
||||
struct LSTNetworkType lnt = { 0 };
|
||||
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) {
|
||||
static char sLntStr[32] = "";
|
||||
switch (lnt->type) {
|
||||
|
|
|
@ -33,6 +33,9 @@ lua_Integer smlua_get_integer_field(int index, char* name);
|
|||
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) ;
|
||||
|
||||
void smlua_logline(void);
|
||||
void smlua_dump_stack(void);
|
||||
void smlua_dump_globals(void);
|
||||
|
|
|
@ -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_MAX) { 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
|
||||
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) {
|
||||
gLoadedGraphNodes[emptyCacheId] = (struct GraphNode *) init_graph_node_display_list(pool, NULL, info->layer, (void*)info->asset);
|
||||
} else {
|
||||
gLoadedGraphNodes[emptyCacheId] = process_geo_layout(pool, (void*)info->asset);
|
||||
}
|
||||
alloc_only_pool_resize(pool, pool->usedSpace);
|
||||
//LOG_INFO("Loaded at runtime");
|
||||
|
||||
if (resizePool) {
|
||||
alloc_only_pool_resize(pool, pool->usedSpace);
|
||||
}
|
||||
|
||||
// remember
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
// find geolayout
|
||||
const void* layout = dynos_geolayout_get(name);
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef SMLUA_MODEL_UTILS_H
|
||||
#define SMLUA_MODEL_UTILS_H
|
||||
|
||||
#include "src/game/memory.h"
|
||||
|
||||
enum ModelExtendedId {
|
||||
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_clear(void);
|
||||
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);
|
||||
|
||||
|
|
|
@ -88,7 +88,7 @@ static void mod_activate_lvl(struct Mod* mod, struct ModFile* file) {
|
|||
}
|
||||
|
||||
// Add to levels
|
||||
dynos_add_level(dynosPath, lvlName);
|
||||
dynos_add_level(mod->index, dynosPath, lvlName);
|
||||
LOG_INFO("Activating DynOS lvl: '%s', '%s'", dynosPath, lvlName);
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ struct Mod {
|
|||
char relativePath[SYS_MAX_PATH];
|
||||
char basePath[SYS_MAX_PATH];
|
||||
struct ModFile* files;
|
||||
s32 index;
|
||||
u16 fileCount;
|
||||
bool isDirectory;
|
||||
bool enabled;
|
||||
|
|
|
@ -64,6 +64,7 @@ void mods_activate(struct Mods* mods) {
|
|||
for (int i = 0; i < mods->entryCount; i++) {
|
||||
struct Mod* mod = mods->entries[i];
|
||||
if (mod->enabled) {
|
||||
mod->index = gActiveMods.entryCount;
|
||||
gActiveMods.entries[gActiveMods.entryCount++] = mod;
|
||||
mod_activate(mod);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue