diff --git a/data/dynos.cpp.h b/data/dynos.cpp.h index a33d85f0..20ef31af 100644 --- a/data/dynos.cpp.h +++ b/data/dynos.cpp.h @@ -29,6 +29,7 @@ enum { DATA_TYPE_COLLISION, DATA_TYPE_LEVEL_SCRIPT, DATA_TYPE_MACRO_OBJECT, + DATA_TYPE_TRAJECTORY, DATA_TYPE_UNUSED, }; @@ -426,6 +427,7 @@ struct GfxData : NoCopy { DataNodes mCollisions; DataNodes mLevelScripts; DataNodes mMacroObjects; + DataNodes mTrajectories; // Animation data Array *> mAnimValues; @@ -753,6 +755,10 @@ DataNode* DynOS_MacroObject_Parse(GfxData* aGfxData, DataNode *aNode); DataNode* DynOS_MacroObject_Load(FILE *aFile, GfxData *aGfxData); +DataNode* DynOS_Trajectory_Parse(GfxData* aGfxData, DataNode* aNode, bool aDisplayPercent); +void DynOS_Trajectory_Write(FILE* aFile, GfxData* aGfxData, DataNode *aNode); +DataNode* DynOS_Trajectory_Load(FILE *aFile, GfxData *aGfxData); + DataNode* DynOS_Tex_Parse(GfxData* aGfxData, DataNode* aNode); void DynOS_Tex_Write(FILE* aFile, GfxData* aGfxData, DataNode *aNode); void DynOS_Tex_Load(FILE *aFile, GfxData *aGfxData); diff --git a/data/dynos_bin_lvl.cpp b/data/dynos_bin_lvl.cpp index 60a0c86d..1c63de52 100644 --- a/data/dynos_bin_lvl.cpp +++ b/data/dynos_bin_lvl.cpp @@ -1207,6 +1207,13 @@ static LevelScript ParseLevelScriptSymbolArg(GfxData* aGfxData, DataNodemTrajectories) { + if (_Arg == _Node->mName) { + return (s64) DynOS_Trajectory_Parse(aGfxData, _Node, false)->mData; + } + } + // Integers s32 x; if ((_Arg[1] == 'x' && sscanf(_Arg.begin(), "%x", &x) == 1) || (sscanf(_Arg.begin(), "%d", &x) == 1)) { @@ -1562,6 +1569,11 @@ static bool DynOS_Lvl_WriteBinary(const SysPath &aOutputFilename, GfxData *aGfxD DynOS_MacroObject_Write(_File, aGfxData, _Node); } } + for (auto &_Node : aGfxData->mTrajectories) { + if (_Node->mLoadIndex == i) { + DynOS_Trajectory_Write(_File, aGfxData, _Node); + } + } } fclose(_File); return true; diff --git a/data/dynos_bin_pointer.cpp b/data/dynos_bin_pointer.cpp index 9d7b13e6..b0832c1a 100644 --- a/data/dynos_bin_pointer.cpp +++ b/data/dynos_bin_pointer.cpp @@ -60,6 +60,13 @@ static PointerData GetDataFromPointer(const void* aPtr, GfxData* aGfxData) { } } + // Trajectories + for (auto& _Node : aGfxData->mTrajectories) { + if (_Node->mData == aPtr) { + return { _Node->mName, 0 }; + } + } + // Behaviors enum BehaviorId id = get_id_from_vanilla_behavior((const BehaviorScript*) aPtr); if (id >= 0 && id < id_bhv_max_count) { @@ -181,6 +188,13 @@ static void *GetPointerFromData(GfxData *aGfxData, const String &aPtrName, u32 a } } + // Trajectories + for (auto &_Node : aGfxData->mTrajectories) { + if (_Node->mName == aPtrName) { + return (void *) _Node->mData; + } + } + // Behaviors enum BehaviorId id = get_id_from_behavior_name(aPtrName.begin()); if (id >= 0 && id < id_bhv_max_count) { diff --git a/data/dynos_bin_read.cpp b/data/dynos_bin_read.cpp index 65a90cad..6370c024 100644 --- a/data/dynos_bin_read.cpp +++ b/data/dynos_bin_read.cpp @@ -191,6 +191,8 @@ void DynOS_Read_Source(GfxData *aGfxData, const SysPath &aFilename) { _DataType = DATA_TYPE_LEVEL_SCRIPT; } else if (_Buffer == "MacroObject") { _DataType = DATA_TYPE_MACRO_OBJECT; + } else if (_Buffer == "Trajectory") { + _DataType = DATA_TYPE_TRAJECTORY; } else { PrintError(" ERROR: Unknown type name: %s", _Buffer.begin()); } @@ -217,6 +219,7 @@ void DynOS_Read_Source(GfxData *aGfxData, const SysPath &aFilename) { case DATA_TYPE_COLLISION: AppendNewNode(aGfxData, aGfxData->mCollisions, _Buffer, pDataName, pDataTokens); break; case DATA_TYPE_LEVEL_SCRIPT: AppendNewNode(aGfxData, aGfxData->mLevelScripts, _Buffer, pDataName, pDataTokens); break; case DATA_TYPE_MACRO_OBJECT: AppendNewNode(aGfxData, aGfxData->mMacroObjects, _Buffer, pDataName, pDataTokens); break; + case DATA_TYPE_TRAJECTORY: AppendNewNode(aGfxData, aGfxData->mTrajectories, _Buffer, pDataName, pDataTokens); break; case DATA_TYPE_UNUSED: pDataTokens = (Array *) 1; break; } _Buffer.Clear(); diff --git a/data/dynos_bin_trajectory.cpp b/data/dynos_bin_trajectory.cpp new file mode 100644 index 00000000..18cf63d7 --- /dev/null +++ b/data/dynos_bin_trajectory.cpp @@ -0,0 +1,124 @@ +#include "dynos.cpp.h" + +extern "C" { +#include "include/level_misc_macros.h" +} + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wnarrowing" + + ///////////// + // Parsing // +///////////// + +#define TRAJECTORY_SIZE_PER_TOKEN 4 + +#define trajectory_constant(x) if (_Arg == #x) { return (s64) (x); } +static s64 ParseTrajectorySymbolArg(GfxData* aGfxData, DataNode* aNode, u64& aTokenIndex) { + const String& _Arg = aNode->mTokens[aTokenIndex++]; + + // Other constants + trajectory_constant(NULL); + + // Integers + s32 x; + if ((_Arg[1] == 'x' && sscanf(_Arg.begin(), "%x", &x) == 1) || (sscanf(_Arg.begin(), "%d", &x) == 1)) { + return (s64) x; + } + + // Unknown + PrintError(" ERROR: Unknown trajectory arg: %s", _Arg.begin()); + return 0; +} + +#define trajectory_symbol_0(symb) \ + if (_Symbol == #symb) { \ + Trajectory _Tr[] = { symb() }; \ + memcpy(aHead, _Tr, sizeof(_Tr)); \ + aHead += (sizeof(_Tr) / sizeof(_Tr[0])); \ + return; \ + } + +#define trajectory_symbol_4(symb) \ + if (_Symbol == #symb) { \ + s64 _Arg0 = ParseTrajectorySymbolArg(aGfxData, aNode, aTokenIndex); \ + s64 _Arg1 = ParseTrajectorySymbolArg(aGfxData, aNode, aTokenIndex); \ + s64 _Arg2 = ParseTrajectorySymbolArg(aGfxData, aNode, aTokenIndex); \ + s64 _Arg3 = ParseTrajectorySymbolArg(aGfxData, aNode, aTokenIndex); \ + Trajectory _Tr[] = { symb(_Arg0, _Arg1, _Arg2, _Arg3) }; \ + memcpy(aHead, _Tr, sizeof(_Tr)); \ + aHead += (sizeof(_Tr) / sizeof(_Tr[0])); \ + return; \ + } + +static void ParseTrajectorySymbol(GfxData* aGfxData, DataNode* aNode, Trajectory*& aHead, u64& aTokenIndex, Array& aSwitchNodes) { + const String& _Symbol = aNode->mTokens[aTokenIndex++]; + + trajectory_symbol_4(TRAJECTORY_POS); + trajectory_symbol_0(TRAJECTORY_END); + + // Unknown + PrintError(" ERROR: Unknown trajectory symbol: %s", _Symbol.begin()); +} + +DataNode* DynOS_Trajectory_Parse(GfxData* aGfxData, DataNode* aNode, bool aDisplayPercent) { + if (aNode->mData) return aNode; + + // Trajectory data + aNode->mData = New(aNode->mTokens.Count() * TRAJECTORY_SIZE_PER_TOKEN); + Trajectory* _Head = aNode->mData; + Array _SwitchNodes; + for (u64 _TokenIndex = 0; _TokenIndex < aNode->mTokens.Count();) { // Don't increment _TokenIndex here! + ParseTrajectorySymbol(aGfxData, aNode, _Head, _TokenIndex, _SwitchNodes); + if (aDisplayPercent && aGfxData->mErrorCount == 0) { PrintNoNewLine("%3d%%\b\b\b\b", (s32) (_TokenIndex * 100) / aNode->mTokens.Count()); } + } + if (aDisplayPercent && aGfxData->mErrorCount == 0) { Print("100%%"); } + aNode->mSize = (u32)(_Head - aNode->mData); + aNode->mLoadIndex = aGfxData->mLoadIndex++; + return aNode; +} + +#pragma GCC diagnostic pop + + ///////////// + // Writing // +///////////// + +void DynOS_Trajectory_Write(FILE* aFile, GfxData* aGfxData, DataNode *aNode) { + if (!aNode->mData) return; + + // Name + WriteBytes(aFile, DATA_TYPE_TRAJECTORY); + aNode->mName.Write(aFile); + + // Data + WriteBytes(aFile, aNode->mSize); + for (u32 i = 0; i != aNode->mSize; ++i) { + WriteBytes(aFile, aNode->mData[i]); + } +} + + ///////////// + // Reading // +///////////// + +DataNode* DynOS_Trajectory_Load(FILE *aFile, GfxData *aGfxData) { + DataNode *_Node = New>(); + + // Name + _Node->mName.Read(aFile); + + // Data + _Node->mSize = ReadBytes(aFile); + _Node->mData = New(_Node->mSize); + for (u32 i = 0; i != _Node->mSize; ++i) { + _Node->mData[i] = ReadBytes(aFile); + } + + // Add it + if (aGfxData != NULL) { + aGfxData->mTrajectories.Add(_Node); + } + + return _Node; +} diff --git a/data/dynos_bin_utils.cpp b/data/dynos_bin_utils.cpp index ae926905..f466c92c 100644 --- a/data/dynos_bin_utils.cpp +++ b/data/dynos_bin_utils.cpp @@ -42,6 +42,10 @@ void DynOS_Gfx_Free(GfxData* aGfxData) { Delete(_Node->mData); Delete(_Node); } + for (auto& _Node : aGfxData->mTrajectories) { + Delete(_Node->mData); + Delete(_Node); + } Delete(aGfxData); } }