mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2024-11-21 19:45:10 +00:00
More progress toward custom DynOS levels
This commit is contained in:
parent
df3618f521
commit
046c595f92
22 changed files with 1017 additions and 582 deletions
|
@ -2,7 +2,7 @@ import os
|
|||
|
||||
usf_types = ['u8', 'u16', 'u32', 'u64', 's8', 's16', 's32', 's64', 'f32']
|
||||
vec3_types = ['Vec3s', 'Vec3f']
|
||||
typedef_pointers = ['BehaviorScript', 'ObjectAnimPointer', 'Collision']
|
||||
typedef_pointers = ['BehaviorScript', 'ObjectAnimPointer', 'Collision', 'LevelScript']
|
||||
|
||||
exclude_structs = [
|
||||
'SPTask',
|
||||
|
|
|
@ -4171,6 +4171,12 @@ function hud_show()
|
|||
-- ...
|
||||
end
|
||||
|
||||
--- @param name string
|
||||
--- @return Pointer_LevelScript
|
||||
function smlua_level_util_get(name)
|
||||
-- ...
|
||||
end
|
||||
|
||||
--- @param aDelay integer
|
||||
--- @return boolean
|
||||
function warp_exit_level(aDelay)
|
||||
|
@ -4507,3 +4513,4 @@ end
|
|||
--- @class Pointer_number
|
||||
--- @class Pointer_integer
|
||||
--- @class Pointer_Collision
|
||||
--- @class Pointer_LevelScript
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -30,9 +30,14 @@ void dynos_add_actor_custom(const char *modPath, const char* geoName);
|
|||
const void* dynos_geolayout_get(const char *name);
|
||||
|
||||
// -- collisions -- //
|
||||
void dynos_add_collision_custom(const char *modPath, const char* collisionName);
|
||||
void dynos_add_collision(const char *modPath, const char* collisionName);
|
||||
Collision* dynos_collision_get(const char* collisionName);
|
||||
|
||||
// -- levels -- //
|
||||
|
||||
void dynos_add_level(const char *modPath, const char* levelName);
|
||||
LevelScript* dynos_level_get(const char* levelName);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
@ -693,6 +693,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);
|
||||
LevelScript* DynOS_Lvl_Get(const char* levelName);
|
||||
|
||||
//
|
||||
// Warps
|
||||
//
|
||||
|
@ -709,8 +712,8 @@ const char *DynOS_Warp_GetParamName(s32 aLevel, s32 aIndex);
|
|||
// Collisions
|
||||
//
|
||||
|
||||
void DynOS_Col_AddCollisionCustom(const SysPath &aPackFolder, const char *aCollisionName);
|
||||
Collision* DynOS_Col_GetCollision(const char* collisionName);
|
||||
void DynOS_Col_Add(const SysPath &aPackFolder, const char *aCollisionName);
|
||||
Collision* DynOS_Col_Get(const char* collisionName);
|
||||
|
||||
//
|
||||
// Bin
|
||||
|
@ -729,6 +732,7 @@ void DynOS_Anim_Table_Load(FILE *aFile, GfxData *aGfxData);
|
|||
|
||||
DataNode<Collision>* DynOS_Col_Parse(GfxData* aGfxData, DataNode<Collision>* aNode, bool aDisplayPercent);
|
||||
void DynOS_Col_Write(FILE* aFile, GfxData* aGfxData, DataNode<Collision> *aNode);
|
||||
DataNode<Collision>* DynOS_Col_Load(FILE *aFile, GfxData *aGfxData);
|
||||
DataNode<Collision>* DynOS_Col_LoadFromBinary(const SysPath &aPackFolder, const char *aCollisionName);
|
||||
void DynOS_Col_Generate(const SysPath &aPackFolder, Array<Pair<u64, String>> _ActorsFolders, GfxData *_GfxData);
|
||||
|
||||
|
@ -745,8 +749,8 @@ void DynOS_Lights_Write(FILE* aFile, GfxData* aGfxData, DataNode<Lights1> *aNode
|
|||
void DynOS_Lights_Load(FILE *aFile, GfxData *aGfxData);
|
||||
|
||||
DataNode<MacroObject>* DynOS_MacroObject_Parse(GfxData* aGfxData, DataNode<MacroObject>* aNode, bool aDisplayPercent);
|
||||
// TODO: DynOS_MacroObject_Write
|
||||
// TODO: DynOS_MacroObject_Load
|
||||
void DynOS_MacroObject_Write(FILE* aFile, GfxData* aGfxData, DataNode<MacroObject> *aNode);
|
||||
DataNode<MacroObject>* DynOS_MacroObject_Load(FILE *aFile, GfxData *aGfxData);
|
||||
|
||||
DataNode<TexData>* DynOS_Tex_Parse(GfxData* aGfxData, DataNode<TexData>* aNode);
|
||||
void DynOS_Tex_Write(FILE* aFile, GfxData* aGfxData, DataNode<TexData> *aNode);
|
||||
|
@ -758,7 +762,7 @@ void DynOS_Vtx_Write(FILE* aFile, GfxData* aGfxData, DataNode<Vtx> *aNode);
|
|||
void DynOS_Vtx_Load(FILE *aFile, GfxData *aGfxData);
|
||||
|
||||
void DynOS_Pointer_Write(FILE* aFile, const void* aPtr, GfxData* aGfxData);
|
||||
void *DynOS_Pointer_Load(FILE *aFile, GfxData *aGfxData, u32 aValue);
|
||||
void *DynOS_Pointer_Load(FILE *aFile, GfxData *aGfxData, u32 aValue, bool isLvl);
|
||||
|
||||
void DynOS_GfxDynCmd_Load(FILE *aFile, GfxData *aGfxData);
|
||||
|
||||
|
@ -766,9 +770,10 @@ GfxData *DynOS_Actor_LoadFromBinary(const SysPath &aPackFolder, const char *aAct
|
|||
void DynOS_Actor_GeneratePack(const SysPath &aPackFolder);
|
||||
|
||||
DataNode<LevelScript>* DynOS_Lvl_Parse(GfxData* aGfxData, DataNode<LevelScript>* aNode, bool aDisplayPercent);
|
||||
// TODO: DynOS_Lvl_Write
|
||||
// TODO: DynOS_Lvl_Load
|
||||
GfxData *DynOS_Lvl_LoadFromBinary(const SysPath &aPackFolder, const char *aLevelName);
|
||||
void DynOS_Lvl_GeneratePack(const SysPath &aPackFolder);
|
||||
s32 DynOS_Lvl_GetFunctionIndex(const void *aPtr);
|
||||
void *DynOS_Lvl_GetFunctionPointerFromIndex(s32 aIndex);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -436,7 +436,7 @@ static bool DynOS_Col_WriteBinary(const SysPath &aOutputFilename, GfxData *aGfxD
|
|||
// Loading //
|
||||
/////////////
|
||||
|
||||
static DataNode<Collision>* LoadCollisionData(FILE *aFile) {
|
||||
DataNode<Collision>* DynOS_Col_Load(FILE *aFile, GfxData *aGfxData) {
|
||||
DataNode<Collision> *_Node = New<DataNode<Collision>>();
|
||||
|
||||
// Name
|
||||
|
@ -449,6 +449,11 @@ static DataNode<Collision>* LoadCollisionData(FILE *aFile) {
|
|||
_Node->mData[i] = ReadBytes<Collision>(aFile);
|
||||
}
|
||||
|
||||
// Add it
|
||||
if (aGfxData != NULL) {
|
||||
aGfxData->mCollisions.Add(_Node);
|
||||
}
|
||||
|
||||
return _Node;
|
||||
}
|
||||
|
||||
|
@ -460,7 +465,7 @@ DataNode<Collision>* DynOS_Col_LoadFromBinary(const SysPath &aPackFolder, const
|
|||
if (_File) {
|
||||
u8 type = ReadBytes<u8>(_File);
|
||||
if (type == DATA_TYPE_COLLISION) {
|
||||
collisionNode = LoadCollisionData(_File);
|
||||
collisionNode = DynOS_Col_Load(_File, NULL);
|
||||
}
|
||||
fclose(_File);
|
||||
}
|
||||
|
|
|
@ -398,7 +398,7 @@ void DynOS_Geo_Load(FILE *aFile, GfxData *aGfxData) {
|
|||
_Node->mData = New<GeoLayout>(_Node->mSize);
|
||||
for (u32 i = 0; i != _Node->mSize; ++i) {
|
||||
u32 _Value = ReadBytes<u32>(aFile);
|
||||
void *_Ptr = DynOS_Pointer_Load(aFile, aGfxData, _Value);
|
||||
void *_Ptr = DynOS_Pointer_Load(aFile, aGfxData, _Value, false);
|
||||
if (_Ptr) {
|
||||
_Node->mData[i] = (uintptr_t) _Ptr;
|
||||
} else {
|
||||
|
|
|
@ -894,7 +894,7 @@ void DynOS_Gfx_Load(FILE *aFile, GfxData *aGfxData) {
|
|||
for (u32 i = 0; i != _Node->mSize; ++i) {
|
||||
u32 _WordsW0 = ReadBytes<u32>(aFile);
|
||||
u32 _WordsW1 = ReadBytes<u32>(aFile);
|
||||
void *_Ptr = DynOS_Pointer_Load(aFile, aGfxData, _WordsW1);
|
||||
void *_Ptr = DynOS_Pointer_Load(aFile, aGfxData, _WordsW1, false);
|
||||
if (_Ptr) {
|
||||
_Node->mData[i].words.w0 = (uintptr_t) _WordsW0;
|
||||
_Node->mData[i].words.w1 = (uintptr_t) _Ptr;
|
||||
|
|
|
@ -33,14 +33,27 @@ return sLvlFunctions;
|
|||
#define sLvlFunctions __LvlFunctions()
|
||||
|
||||
void *DynOS_Lvl_GetFunctionPointerFromName(const String &aName) {
|
||||
for (const auto &_GeoFunction : sLvlFunctions) {
|
||||
if (aName == _GeoFunction.first) {
|
||||
return _GeoFunction.second;
|
||||
for (const auto &_LvlFunction : sLvlFunctions) {
|
||||
if (aName == _LvlFunction.first) {
|
||||
return _LvlFunction.second;
|
||||
}
|
||||
};
|
||||
return NULL;
|
||||
}
|
||||
|
||||
s32 DynOS_Lvl_GetFunctionIndex(const void *aPtr) {
|
||||
for (const auto &_LvlFunction : sLvlFunctions) {
|
||||
if (_LvlFunction.second == aPtr) {
|
||||
return (s32) (&_LvlFunction - sLvlFunctions.begin());
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void *DynOS_Lvl_GetFunctionPointerFromIndex(s32 aIndex) {
|
||||
return sLvlFunctions[aIndex].second;
|
||||
}
|
||||
|
||||
/////////////
|
||||
// Parsing //
|
||||
/////////////
|
||||
|
@ -1478,6 +1491,149 @@ static DataNode<LevelScript> *GetLevelScript(GfxData *aGfxData, const String& aG
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/////////////
|
||||
// Writing //
|
||||
/////////////
|
||||
|
||||
static void DynOS_Lvl_Write(FILE* aFile, GfxData* aGfxData, DataNode<LevelScript> *aNode) {
|
||||
if (!aNode->mData) return;
|
||||
|
||||
// Name
|
||||
WriteBytes<u8>(aFile, DATA_TYPE_LEVEL_SCRIPT);
|
||||
aNode->mName.Write(aFile);
|
||||
|
||||
// Data
|
||||
WriteBytes<u32>(aFile, aNode->mSize);
|
||||
for (u32 i = 0; i != aNode->mSize; ++i) {
|
||||
LevelScript *_Head = &aNode->mData[i];
|
||||
if (aGfxData->mPointerList.Find((void *) _Head) != -1) {
|
||||
DynOS_Pointer_Write(aFile, (const void *) (*_Head), aGfxData);
|
||||
} else {
|
||||
WriteBytes<u32>(aFile, *((u32 *) _Head));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool DynOS_Lvl_WriteBinary(const SysPath &aOutputFilename, GfxData *aGfxData) {
|
||||
FILE *_File = fopen(aOutputFilename.c_str(), "wb");
|
||||
if (!_File) {
|
||||
PrintError(" ERROR: Unable to create file \"%s\"", aOutputFilename.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
for (u64 i = 0; i != aGfxData->mLoadIndex; ++i) {
|
||||
for (auto &_Node : aGfxData->mLights) {
|
||||
if (_Node->mLoadIndex == i) {
|
||||
DynOS_Lights_Write(_File, aGfxData, _Node);
|
||||
}
|
||||
}
|
||||
for (auto &_Node : aGfxData->mTextures) {
|
||||
if (_Node->mLoadIndex == i) {
|
||||
DynOS_Tex_Write(_File, aGfxData, _Node);
|
||||
}
|
||||
}
|
||||
for (auto &_Node : aGfxData->mVertices) {
|
||||
if (_Node->mLoadIndex == i) {
|
||||
DynOS_Vtx_Write(_File, aGfxData, _Node);
|
||||
}
|
||||
}
|
||||
for (auto &_Node : aGfxData->mDisplayLists) {
|
||||
if (_Node->mLoadIndex == i) {
|
||||
DynOS_Gfx_Write(_File, aGfxData, _Node);
|
||||
}
|
||||
}
|
||||
for (auto &_Node : aGfxData->mGeoLayouts) {
|
||||
if (_Node->mLoadIndex == i) {
|
||||
DynOS_Geo_Write(_File, aGfxData, _Node);
|
||||
}
|
||||
}
|
||||
for (auto &_Node : aGfxData->mCollisions) {
|
||||
if (_Node->mLoadIndex == i) {
|
||||
DynOS_Col_Write(_File, aGfxData, _Node);
|
||||
}
|
||||
}
|
||||
for (auto &_Node : aGfxData->mLevelScripts) {
|
||||
if (_Node->mLoadIndex == i) {
|
||||
DynOS_Lvl_Write(_File, aGfxData, _Node);
|
||||
}
|
||||
}
|
||||
for (auto &_Node : aGfxData->mMacroObjects) {
|
||||
if (_Node->mLoadIndex == i) {
|
||||
DynOS_MacroObject_Write(_File, aGfxData, _Node);
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(_File);
|
||||
return true;
|
||||
}
|
||||
|
||||
/////////////
|
||||
// Reading //
|
||||
/////////////
|
||||
|
||||
static DataNode<LevelScript>* DynOS_Lvl_Load(FILE *aFile, GfxData *aGfxData) {
|
||||
DataNode<LevelScript> *_Node = New<DataNode<LevelScript>>();
|
||||
|
||||
// Name
|
||||
_Node->mName.Read(aFile);
|
||||
|
||||
// Data
|
||||
_Node->mSize = ReadBytes<u32>(aFile);
|
||||
_Node->mData = New<LevelScript>(_Node->mSize);
|
||||
for (u32 i = 0; i != _Node->mSize; ++i) {
|
||||
u32 _Value = ReadBytes<u32>(aFile);
|
||||
void *_Ptr = DynOS_Pointer_Load(aFile, aGfxData, _Value, true);
|
||||
if (_Ptr) {
|
||||
_Node->mData[i] = (uintptr_t) _Ptr;
|
||||
} else {
|
||||
_Node->mData[i] = (uintptr_t) _Value;
|
||||
}
|
||||
}
|
||||
|
||||
// Add it
|
||||
if (aGfxData != NULL) {
|
||||
aGfxData->mLevelScripts.Add(_Node);
|
||||
}
|
||||
|
||||
return _Node;
|
||||
}
|
||||
|
||||
GfxData *DynOS_Lvl_LoadFromBinary(const SysPath &aPackFolder, const char *aLevelName) {
|
||||
struct DynosGfxDataCache { SysPath mPackFolder; Array<Pair<const char *, GfxData *>> mGfxData; };
|
||||
static Array<DynosGfxDataCache *> sDynosGfxDataCache;
|
||||
|
||||
// Load data from binary file
|
||||
GfxData *_GfxData = NULL;
|
||||
SysPath _Filename = fstring("%s/%s.lvl", aPackFolder.begin(), aLevelName);
|
||||
FILE *_File = fopen(_Filename.c_str(), "rb");
|
||||
if (_File) {
|
||||
_GfxData = New<GfxData>();
|
||||
for (bool _Done = false; !_Done;) {
|
||||
switch (ReadBytes<u8>(_File)) {
|
||||
case DATA_TYPE_LIGHT: DynOS_Lights_Load (_File, _GfxData); break;
|
||||
case DATA_TYPE_TEXTURE: DynOS_Tex_Load (_File, _GfxData); break;
|
||||
case DATA_TYPE_VERTEX: DynOS_Vtx_Load (_File, _GfxData); break;
|
||||
case DATA_TYPE_DISPLAY_LIST: DynOS_Gfx_Load (_File, _GfxData); break;
|
||||
case DATA_TYPE_GEO_LAYOUT: DynOS_Geo_Load (_File, _GfxData); break;
|
||||
case DATA_TYPE_ANIMATION: DynOS_Anim_Load (_File, _GfxData); break;
|
||||
case DATA_TYPE_ANIMATION_TABLE: DynOS_Anim_Table_Load (_File, _GfxData); break;
|
||||
case DATA_TYPE_GFXDYNCMD: DynOS_GfxDynCmd_Load (_File, _GfxData); break;
|
||||
case DATA_TYPE_COLLISION: DynOS_Col_Load (_File, _GfxData); break;
|
||||
case DATA_TYPE_LEVEL_SCRIPT: DynOS_Lvl_Load (_File, _GfxData); break;
|
||||
case DATA_TYPE_MACRO_OBJECT: DynOS_MacroObject_Load(_File, _GfxData); break;
|
||||
default: _Done = true; break;
|
||||
}
|
||||
}
|
||||
fclose(_File);
|
||||
}
|
||||
|
||||
return _GfxData;
|
||||
}
|
||||
|
||||
//////////////
|
||||
// Generate //
|
||||
//////////////
|
||||
|
||||
static bool DynOS_Lvl_GeneratePack_Internal(const SysPath &aPackFolder, Array<Pair<u64, String>> _ActorsFolders, GfxData *_GfxData) {
|
||||
bool generated = false;
|
||||
for (auto &_LvlNode : _GfxData->mLevelScripts) {
|
||||
|
@ -1501,7 +1657,7 @@ static bool DynOS_Lvl_GeneratePack_Internal(const SysPath &aPackFolder, Array<Pa
|
|||
|
||||
// Write if no error
|
||||
if (_GfxData->mErrorCount == 0) {
|
||||
//DynOS_Lvl_WriteBinary(_LvlFilename, _GfxData, _LvlRoot);
|
||||
DynOS_Lvl_WriteBinary(_LvlFilename, _GfxData);
|
||||
} else {
|
||||
Print(" %u error(s): Unable to parse data", _GfxData->mErrorCount);
|
||||
}
|
||||
|
@ -1513,10 +1669,6 @@ static bool DynOS_Lvl_GeneratePack_Internal(const SysPath &aPackFolder, Array<Pa
|
|||
return generated;
|
||||
}
|
||||
|
||||
//////////////
|
||||
// Generate //
|
||||
//////////////
|
||||
|
||||
void DynOS_Lvl_GeneratePack(const SysPath &aPackFolder) {
|
||||
Print("---------- Level pack folder: \"%s\" ----------", aPackFolder.c_str());
|
||||
Array<Pair<u64, String>> _ActorsFolders;
|
||||
|
|
|
@ -464,3 +464,46 @@ DataNode<MacroObject>* DynOS_MacroObject_Parse(GfxData* aGfxData, DataNode<Macro
|
|||
}
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
/////////////
|
||||
// Writing //
|
||||
/////////////
|
||||
|
||||
void DynOS_MacroObject_Write(FILE* aFile, GfxData* aGfxData, DataNode<MacroObject> *aNode) {
|
||||
if (!aNode->mData) return;
|
||||
|
||||
// Name
|
||||
WriteBytes<u8>(aFile, DATA_TYPE_MACRO_OBJECT);
|
||||
aNode->mName.Write(aFile);
|
||||
|
||||
// Data
|
||||
WriteBytes<u32>(aFile, aNode->mSize);
|
||||
for (u32 i = 0; i != aNode->mSize; ++i) {
|
||||
WriteBytes<MacroObject>(aFile, aNode->mData[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////
|
||||
// Reading //
|
||||
/////////////
|
||||
|
||||
DataNode<MacroObject>* DynOS_MacroObject_Load(FILE *aFile, GfxData *aGfxData) {
|
||||
DataNode<MacroObject> *_Node = New<DataNode<MacroObject>>();
|
||||
|
||||
// Name
|
||||
_Node->mName.Read(aFile);
|
||||
|
||||
// Data
|
||||
_Node->mSize = ReadBytes<u32>(aFile);
|
||||
_Node->mData = New<MacroObject>(_Node->mSize);
|
||||
for (u32 i = 0; i != _Node->mSize; ++i) {
|
||||
_Node->mData[i] = ReadBytes<MacroObject>(aFile);
|
||||
}
|
||||
|
||||
// Add it
|
||||
if (aGfxData != NULL) {
|
||||
aGfxData->mMacroObjects.Add(_Node);
|
||||
}
|
||||
|
||||
return _Node;
|
||||
}
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
#include "dynos.cpp.h"
|
||||
|
||||
extern "C" {
|
||||
#include "behavior_table.h"
|
||||
}
|
||||
/////////////
|
||||
// Writing //
|
||||
/////////////
|
||||
|
||||
typedef Pair<String, u32> PointerData;
|
||||
static PointerData GetDataFromPointer(const void* aPtr, GfxData* aGfxData) {
|
||||
|
||||
// Lights
|
||||
for (auto& _Node : aGfxData->mLights) {
|
||||
if (&_Node->mData->l[0] == aPtr) { // Light *, not Lights1 *
|
||||
|
@ -59,6 +60,12 @@ static PointerData GetDataFromPointer(const void* aPtr, GfxData* aGfxData) {
|
|||
}
|
||||
}
|
||||
|
||||
// Behaviors
|
||||
enum BehaviorId id = get_id_from_vanilla_behavior((const BehaviorScript*) aPtr);
|
||||
if (id >= 0 && id < id_bhv_max_count) {
|
||||
return { get_behavior_name_from_id(id), 0 };
|
||||
}
|
||||
|
||||
// Vertices
|
||||
String _VtxArrayName = "";
|
||||
uintptr_t _VtxArrayStart = 0;
|
||||
|
@ -91,6 +98,14 @@ void DynOS_Pointer_Write(FILE* aFile, const void* aPtr, GfxData* aGfxData) {
|
|||
return;
|
||||
}
|
||||
|
||||
// Lvl function
|
||||
s32 _LvlFunctionIndex = DynOS_Lvl_GetFunctionIndex(aPtr);
|
||||
if (_LvlFunctionIndex != -1) {
|
||||
WriteBytes<u32>(aFile, FUNCTION_CODE);
|
||||
WriteBytes<s32>(aFile, _LvlFunctionIndex);
|
||||
return;
|
||||
}
|
||||
|
||||
// Pointer
|
||||
PointerData _PtrData = GetDataFromPointer(aPtr, aGfxData);
|
||||
WriteBytes<u32>(aFile, POINTER_CODE);
|
||||
|
@ -166,17 +181,25 @@ static void *GetPointerFromData(GfxData *aGfxData, const String &aPtrName, u32 a
|
|||
}
|
||||
}
|
||||
|
||||
// Behaviors
|
||||
enum BehaviorId id = get_id_from_behavior_name(aPtrName.begin());
|
||||
if (id >= 0 && id < id_bhv_max_count) {
|
||||
return (void*)get_behavior_from_id(id);
|
||||
}
|
||||
|
||||
// Error
|
||||
sys_fatal("Pointer not found: %s", aPtrName.begin());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *DynOS_Pointer_Load(FILE *aFile, GfxData *aGfxData, u32 aValue) {
|
||||
void *DynOS_Pointer_Load(FILE *aFile, GfxData *aGfxData, u32 aValue, bool isLvl) {
|
||||
|
||||
// FUNC
|
||||
if (aValue == FUNCTION_CODE) {
|
||||
s32 _GeoFunctionIndex = ReadBytes<s32>(aFile);
|
||||
return DynOS_Geo_GetFunctionPointerFromIndex(_GeoFunctionIndex);
|
||||
s32 _FunctionIndex = ReadBytes<s32>(aFile);
|
||||
return isLvl
|
||||
? DynOS_Lvl_GetFunctionPointerFromIndex(_FunctionIndex)
|
||||
: DynOS_Geo_GetFunctionPointerFromIndex(_FunctionIndex);
|
||||
}
|
||||
|
||||
// PNTR
|
||||
|
|
|
@ -146,6 +146,8 @@ void DynOS_Read_Source(GfxData *aGfxData, const SysPath &aFilename) {
|
|||
} else if (!_DataIgnore) {
|
||||
_Buffer.Add(*c);
|
||||
}
|
||||
} else if (*c == '<' || *c == '>') {
|
||||
_DataIgnore = !_DataIgnore;
|
||||
}
|
||||
|
||||
// Retrieving data type
|
||||
|
|
|
@ -89,12 +89,22 @@ const void* dynos_geolayout_get(const char *name) {
|
|||
|
||||
// -- collisions -- //
|
||||
|
||||
void dynos_add_collision_custom(const char *modPath, const char* collisionName) {
|
||||
DynOS_Col_AddCollisionCustom(modPath, collisionName);
|
||||
void dynos_add_collision(const char *modPath, const char* collisionName) {
|
||||
DynOS_Col_Add(modPath, collisionName);
|
||||
}
|
||||
|
||||
Collision* dynos_collision_get(const char* collisionName) {
|
||||
return DynOS_Col_GetCollision(collisionName);
|
||||
return DynOS_Col_Get(collisionName);
|
||||
}
|
||||
|
||||
// -- levels -- //
|
||||
|
||||
void dynos_add_level(const char *modPath, const char* levelName) {
|
||||
DynOS_Lvl_Add(modPath, levelName);
|
||||
}
|
||||
|
||||
LevelScript* dynos_level_get(const char* levelName) {
|
||||
return DynOS_Lvl_Get(levelName);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -564,14 +564,16 @@ void *DynOS_Geo_GetGraphNode(const void *aGeoLayout, bool aKeepInMemory) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
// Collisions
|
||||
////////////////
|
||||
// Collisions //
|
||||
////////////////
|
||||
|
||||
static Array<Pair<const char*, DataNode<Collision>*>> sDynosCustomCollisions;
|
||||
static Array<Pair<const char*, DataNode<Collision>*>> sDynosCollisions;
|
||||
|
||||
void DynOS_Col_AddCollisionCustom(const SysPath &aPackFolder, const char *aCollisionName) {
|
||||
void DynOS_Col_Add(const SysPath &aPackFolder, const char *aCollisionName) {
|
||||
// check for duplicates
|
||||
for (s32 i = 0; i < sDynosCustomCollisions.Count(); ++i) {
|
||||
if (!strcmp(sDynosCustomCollisions[i].first, aCollisionName)) {
|
||||
for (s32 i = 0; i < sDynosCollisions.Count(); ++i) {
|
||||
if (!strcmp(sDynosCollisions[i].first, aCollisionName)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -586,14 +588,52 @@ void DynOS_Col_AddCollisionCustom(const SysPath &aPackFolder, const char *aColli
|
|||
return;
|
||||
}
|
||||
|
||||
// Add to custom collisions
|
||||
sDynosCustomCollisions.Add({ collisionName, _Node });
|
||||
// Add to collisions
|
||||
sDynosCollisions.Add({ collisionName, _Node });
|
||||
}
|
||||
|
||||
Collision* DynOS_Col_GetCollision(const char* collisionName) {
|
||||
for (s32 i = 0; i < sDynosCustomCollisions.Count(); ++i) {
|
||||
if (!strcmp(sDynosCustomCollisions[i].first, collisionName)) {
|
||||
return sDynosCustomCollisions[i].second->mData;
|
||||
Collision* DynOS_Col_Get(const char* collisionName) {
|
||||
for (s32 i = 0; i < sDynosCollisions.Count(); ++i) {
|
||||
if (!strcmp(sDynosCollisions[i].first, collisionName)) {
|
||||
return sDynosCollisions[i].second->mData;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
////////////
|
||||
// Levels //
|
||||
////////////
|
||||
|
||||
static Array<Pair<const char*, GfxData*>> sDynosCustomLevelScripts;
|
||||
|
||||
void DynOS_Lvl_Add(const SysPath &aPackFolder, const char *aLevelName) {
|
||||
// check for duplicates
|
||||
for (s32 i = 0; i < sDynosCustomLevelScripts.Count(); ++i) {
|
||||
if (!strcmp(sDynosCustomLevelScripts[i].first, aLevelName)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
u16 levelLen = strlen(aLevelName);
|
||||
char* levelName = (char*)calloc(1, sizeof(char) * (levelLen + 1));
|
||||
strcpy(levelName, aLevelName);
|
||||
|
||||
GfxData* _Node = DynOS_Lvl_LoadFromBinary(aPackFolder, levelName);
|
||||
if (!_Node) {
|
||||
free(levelName);
|
||||
return;
|
||||
}
|
||||
|
||||
// Add to levels
|
||||
sDynosCustomLevelScripts.Add({ levelName, _Node });
|
||||
}
|
||||
|
||||
LevelScript* DynOS_Lvl_Get(const char* levelName) {
|
||||
for (s32 i = 0; i < sDynosCustomLevelScripts.Count(); ++i) {
|
||||
if (!strcmp(sDynosCustomLevelScripts[i].first, levelName)) {
|
||||
auto& scripts = sDynosCustomLevelScripts[i].second->mLevelScripts;
|
||||
return scripts[scripts.Count() - 1]->mData;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
|
|
|
@ -733,6 +733,7 @@
|
|||
- [get_network_area_timer](#get_network_area_timer)
|
||||
- [hud_hide](#hud_hide)
|
||||
- [hud_show](#hud_show)
|
||||
- [smlua_level_util_get](#smlua_level_util_get)
|
||||
- [warp_exit_level](#warp_exit_level)
|
||||
- [warp_restart_level](#warp_restart_level)
|
||||
- [warp_to_castle](#warp_to_castle)
|
||||
|
@ -13775,6 +13776,26 @@ The `reliable` field will ensure that the packet arrives, but should be used spa
|
|||
|
||||
<br />
|
||||
|
||||
## [smlua_level_util_get](#smlua_level_util_get)
|
||||
|
||||
### Lua Example
|
||||
`local PointerValue = smlua_level_util_get(name)`
|
||||
|
||||
### Parameters
|
||||
| Field | Type |
|
||||
| ----- | ---- |
|
||||
| name | `string` |
|
||||
|
||||
### Returns
|
||||
- `Pointer` <`LevelScript`>
|
||||
|
||||
### C Prototype
|
||||
`LevelScript* smlua_level_util_get(const char* name);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [warp_exit_level](#warp_exit_level)
|
||||
|
||||
### Lua Example
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
|
||||
#include "behavior_data.h"
|
||||
|
||||
extern const BehaviorScript* gBehaviorTable[];
|
||||
|
||||
enum BehaviorId {
|
||||
id_bhvStarDoor,
|
||||
id_bhvMrI,
|
||||
|
@ -524,6 +522,9 @@ enum BehaviorId {
|
|||
};
|
||||
|
||||
enum BehaviorId get_id_from_behavior(const BehaviorScript* behavior);
|
||||
enum BehaviorId get_id_from_vanilla_behavior(const BehaviorScript* behavior);
|
||||
const BehaviorScript* get_behavior_from_id(enum BehaviorId id);
|
||||
const char* get_behavior_name_from_id(enum BehaviorId id);
|
||||
enum BehaviorId get_id_from_behavior_name(const char* name);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -375,6 +375,7 @@ static int smlua__get_field(lua_State* L) {
|
|||
case LVT_BEHAVIORSCRIPT: lua_pushinteger(L, *(s32*)p); break;
|
||||
case LVT_OBJECTANIMPOINTER: lua_pushinteger(L, *(s32*)p); break;
|
||||
case LVT_COLLISION: lua_pushinteger(L, *(s32*)p); break;
|
||||
case LVT_LEVELSCRIPT: lua_pushinteger(L, *(s32*)p); break;
|
||||
|
||||
// pointers
|
||||
case LVT_U8_P:
|
||||
|
@ -387,6 +388,7 @@ static int smlua__get_field(lua_State* L) {
|
|||
case LVT_BEHAVIORSCRIPT_P:
|
||||
case LVT_OBJECTANIMPOINTER_P:
|
||||
case LVT_COLLISION_P:
|
||||
case LVT_LEVELSCRIPT_P:
|
||||
smlua_push_pointer(L, data->valueType, *(u8**)p);
|
||||
break;
|
||||
|
||||
|
|
|
@ -27,6 +27,8 @@ enum LuaValueType {
|
|||
LVT_OBJECTANIMPOINTER_P,
|
||||
LVT_COLLISION,
|
||||
LVT_COLLISION_P,
|
||||
LVT_LEVELSCRIPT,
|
||||
LVT_LEVELSCRIPT_P,
|
||||
LVT_LUAFUNCTION,
|
||||
LVT_POINTER,
|
||||
LVT_MAX,
|
||||
|
|
|
@ -9266,6 +9266,17 @@ int smlua_func_hud_show(UNUSED lua_State* L) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
int smlua_func_smlua_level_util_get(lua_State* L) {
|
||||
if(!smlua_functions_valid_param_count(L, 1)) { return 0; }
|
||||
|
||||
const char* name = smlua_to_string(L, 1);
|
||||
if (!gSmLuaConvertSuccess) { return 0; }
|
||||
|
||||
smlua_push_pointer(L, LVT_LEVELSCRIPT_P, (void*)smlua_level_util_get(name));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int smlua_func_warp_exit_level(lua_State* L) {
|
||||
if(!smlua_functions_valid_param_count(L, 1)) { return 0; }
|
||||
|
||||
|
@ -10709,6 +10720,7 @@ void smlua_bind_functions_autogen(void) {
|
|||
smlua_bind_function(L, "get_network_area_timer", smlua_func_get_network_area_timer);
|
||||
smlua_bind_function(L, "hud_hide", smlua_func_hud_hide);
|
||||
smlua_bind_function(L, "hud_show", smlua_func_hud_show);
|
||||
smlua_bind_function(L, "smlua_level_util_get", smlua_func_smlua_level_util_get);
|
||||
smlua_bind_function(L, "warp_exit_level", smlua_func_warp_exit_level);
|
||||
smlua_bind_function(L, "warp_restart_level", smlua_func_warp_restart_level);
|
||||
smlua_bind_function(L, "warp_to_castle", smlua_func_warp_to_castle);
|
||||
|
|
|
@ -54,3 +54,7 @@ f32 get_hand_foot_pos_z(struct MarioState* m, u8 index) {
|
|||
if (index >= 4) { index = 0; }
|
||||
return m->marioBodyState->handFootPos[index][2];
|
||||
}
|
||||
|
||||
LevelScript* smlua_level_util_get(const char* name) {
|
||||
return dynos_level_get(name);
|
||||
}
|
||||
|
|
|
@ -17,4 +17,6 @@ f32 get_hand_foot_pos_x(struct MarioState* m, u8 index);
|
|||
f32 get_hand_foot_pos_y(struct MarioState* m, u8 index);
|
||||
f32 get_hand_foot_pos_z(struct MarioState* m, u8 index);
|
||||
|
||||
LevelScript* smlua_level_util_get(const char* name);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -59,10 +59,39 @@ static void mod_activate_col(struct Mod* mod, struct ModFile* file) {
|
|||
}
|
||||
|
||||
// Add to custom actors
|
||||
dynos_add_collision_custom(dynosPath, colName);
|
||||
dynos_add_collision(dynosPath, colName);
|
||||
LOG_INFO("Activating DynOS col: '%s', '%s'", dynosPath, colName);
|
||||
}
|
||||
|
||||
static void mod_activate_lvl(struct Mod* mod, struct ModFile* file) {
|
||||
char dynosPath[SYS_MAX_PATH] = { 0 };
|
||||
if (snprintf(dynosPath, SYS_MAX_PATH - 1, "%s/levels", mod->basePath) < 0) {
|
||||
LOG_ERROR("Failed to concat dynos path");
|
||||
return;
|
||||
}
|
||||
|
||||
// copy geo name
|
||||
char lvlName[64] = { 0 };
|
||||
if (snprintf(lvlName, 63, "%s", path_basename(file->relativePath)) < 0) {
|
||||
LOG_ERROR("Truncated lvl name");
|
||||
return;
|
||||
}
|
||||
|
||||
// remove '.lvl'
|
||||
char* g = lvlName;
|
||||
while (*g != '\0') {
|
||||
if (*g == '.') {
|
||||
*g = '\0';
|
||||
break;
|
||||
}
|
||||
g++;
|
||||
}
|
||||
|
||||
// Add to levels
|
||||
dynos_add_level(dynosPath, lvlName);
|
||||
LOG_INFO("Activating DynOS lvl: '%s', '%s'", dynosPath, lvlName);
|
||||
}
|
||||
|
||||
void mod_activate(struct Mod* mod) {
|
||||
// activate dynos models
|
||||
for (int i = 0; i < mod->fileCount; i++) {
|
||||
|
@ -73,6 +102,9 @@ void mod_activate(struct Mod* mod) {
|
|||
if (str_ends_with(file->relativePath, ".col")) {
|
||||
mod_activate_col(mod, file);
|
||||
}
|
||||
if (str_ends_with(file->relativePath, ".lvl")) {
|
||||
mod_activate_lvl(mod, file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -200,34 +232,69 @@ static bool mod_load_files(struct Mod* mod, char* modName, char* fullPath) {
|
|||
// open actors directory
|
||||
struct dirent* dir = NULL;
|
||||
DIR* d = opendir(actorsPath);
|
||||
if (!d) {
|
||||
return true;
|
||||
}
|
||||
if (d) {
|
||||
// iterate mod directory
|
||||
char path[SYS_MAX_PATH] = { 0 };
|
||||
char relativePath[SYS_MAX_PATH] = { 0 };
|
||||
while ((dir = readdir(d)) != NULL) {
|
||||
// sanity check / fill path[]
|
||||
if (!directory_sanity_check(dir, actorsPath, path)) { continue; }
|
||||
if (snprintf(relativePath, SYS_MAX_PATH - 1, "actors/%s", dir->d_name) < 0) {
|
||||
LOG_ERROR("Could not concat actor path!");
|
||||
return false;
|
||||
}
|
||||
|
||||
// iterate mod directory
|
||||
char path[SYS_MAX_PATH] = { 0 };
|
||||
char relativePath[SYS_MAX_PATH] = { 0 };
|
||||
while ((dir = readdir(d)) != NULL) {
|
||||
// sanity check / fill path[]
|
||||
if (!directory_sanity_check(dir, actorsPath, path)) { continue; }
|
||||
if (snprintf(relativePath, SYS_MAX_PATH - 1, "actors/%s", dir->d_name) < 0) {
|
||||
LOG_ERROR("Could not concat actor path!");
|
||||
return false;
|
||||
// only consider bin, and col files
|
||||
if (!str_ends_with(path, ".bin") && !str_ends_with(path, ".col")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// allocate file
|
||||
struct ModFile* file = mod_allocate_file(mod, relativePath);
|
||||
if (file == NULL) { return false; }
|
||||
}
|
||||
|
||||
// only consider bin and col files
|
||||
if (!str_ends_with(path, ".bin") && !str_ends_with(path, ".col")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// allocate file
|
||||
struct ModFile* file = mod_allocate_file(mod, relativePath);
|
||||
if (file == NULL) { return false; }
|
||||
closedir(d);
|
||||
}
|
||||
|
||||
closedir(d);
|
||||
}
|
||||
|
||||
// deal with levels directory
|
||||
{
|
||||
// concat levels directory
|
||||
char levelsPath[SYS_MAX_PATH] = { 0 };
|
||||
if (!concat_path(levelsPath, fullPath, "levels")) {
|
||||
LOG_ERROR("Could not concat directory '%s' + '%s'", fullPath, "levels");
|
||||
return false;
|
||||
}
|
||||
|
||||
// open levels directory
|
||||
struct dirent* dir = NULL;
|
||||
DIR* d = opendir(levelsPath);
|
||||
if (d) {
|
||||
// iterate mod directory
|
||||
char path[SYS_MAX_PATH] = { 0 };
|
||||
char relativePath[SYS_MAX_PATH] = { 0 };
|
||||
while ((dir = readdir(d)) != NULL) {
|
||||
// sanity check / fill path[]
|
||||
if (!directory_sanity_check(dir, levelsPath, path)) { continue; }
|
||||
if (snprintf(relativePath, SYS_MAX_PATH - 1, "levels/%s", dir->d_name) < 0) {
|
||||
LOG_ERROR("Could not concat level path!");
|
||||
return false;
|
||||
}
|
||||
|
||||
// only consider lvl files
|
||||
if (!str_ends_with(path, ".lvl")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// allocate file
|
||||
struct ModFile* file = mod_allocate_file(mod, relativePath);
|
||||
if (file == NULL) { return false; }
|
||||
}
|
||||
|
||||
closedir(d);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue