diff --git a/data/dynos.cpp.h b/data/dynos.cpp.h index 0e7b8114..9b3152c1 100644 --- a/data/dynos.cpp.h +++ b/data/dynos.cpp.h @@ -5,6 +5,7 @@ #include "dynos.h" extern "C" { #include "engine/math_util.h" +#include "src/game/moving_texture.h" } #define FUNCTION_CODE (u32) 0x434E5546 @@ -30,6 +31,8 @@ enum { DATA_TYPE_LEVEL_SCRIPT, DATA_TYPE_MACRO_OBJECT, DATA_TYPE_TRAJECTORY, + DATA_TYPE_MOVTEX, + DATA_TYPE_MOVTEXQC, DATA_TYPE_UNUSED, }; @@ -365,6 +368,7 @@ template using Pair = std::pair; typedef std::string SysPath; +typedef struct MovtexQuadCollection MovtexQC; class NoCopy { protected: @@ -428,6 +432,8 @@ struct GfxData : NoCopy { DataNodes mLevelScripts; DataNodes mMacroObjects; DataNodes mTrajectories; + DataNodes mMovtexs; + DataNodes mMovtexQCs; // Animation data Array *> mAnimValues; @@ -759,6 +765,14 @@ DataNode* DynOS_Trajectory_Parse(GfxData* aGfxData, DataNode *aNode); DataNode* DynOS_Trajectory_Load(FILE *aFile, GfxData *aGfxData); +DataNode* DynOS_Movtex_Parse(GfxData* aGfxData, DataNode* aNode, bool aDisplayPercent); +void DynOS_Movtex_Write(FILE* aFile, GfxData* aGfxData, DataNode *aNode); +DataNode* DynOS_Movtex_Load(FILE *aFile, GfxData *aGfxData); + +DataNode* DynOS_MovtexQC_Parse(GfxData* aGfxData, DataNode* aNode); +void DynOS_MovtexQC_Write(FILE* aFile, GfxData* aGfxData, DataNode *aNode); +DataNode* DynOS_MovtexQC_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 be32ab7a..ed183076 100644 --- a/data/dynos_bin_lvl.cpp +++ b/data/dynos_bin_lvl.cpp @@ -1442,6 +1442,20 @@ static LevelScript ParseLevelScriptSymbolArg(GfxData* aGfxData, DataNodemMovtexs) { + if (_Arg == _Node->mName) { + return (LevelScript) DynOS_Movtex_Parse(aGfxData, _Node, false)->mData; + } + } + + // MovtexQCs + for (auto& _Node : aGfxData->mMovtexQCs) { + if (_Arg == _Node->mName) { + return (LevelScript) DynOS_MovtexQC_Parse(aGfxData, _Node)->mData; + } + } + // Integers s32 x; if ((_Arg[1] == 'x' && sscanf(_Arg.begin(), "%x", &x) == 1) || (sscanf(_Arg.begin(), "%d", &x) == 1)) { @@ -1455,7 +1469,6 @@ static LevelScript ParseLevelScriptSymbolArg(GfxData* aGfxData, DataNodemMovtexs) { + if (_Node->mLoadIndex == i) { + DynOS_Movtex_Write(_File, aGfxData, _Node); + } + } + for (auto &_Node : aGfxData->mMovtexQCs) { + if (_Node->mLoadIndex == i) { + DynOS_MovtexQC_Write(_File, aGfxData, _Node); + } + } } fclose(_File); return true; diff --git a/data/dynos_bin_movtex.cpp b/data/dynos_bin_movtex.cpp new file mode 100644 index 00000000..b941e4f8 --- /dev/null +++ b/data/dynos_bin_movtex.cpp @@ -0,0 +1,199 @@ +#include "dynos.cpp.h" + +extern "C" { +#include "include/moving_texture_macros.h" +} + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wnarrowing" + + ///////////// + // Parsing // +///////////// + +#define MOVTEX_SIZE_PER_TOKEN 4 + +#define movtex_constant(x) if (_Arg == #x) { return (s64) (x); } +static s64 ParseMovtexSymbolArg(GfxData* aGfxData, DataNode* aNode, u64& aTokenIndex) { + const String& _Arg = aNode->mTokens[aTokenIndex++]; + + // texture constants + movtex_constant(TEXTURE_WATER); + movtex_constant(TEXTURE_MIST); + movtex_constant(TEXTURE_JRB_WATER); + movtex_constant(TEXTURE_UNK_WATER); + movtex_constant(TEXTURE_LAVA); + movtex_constant(TEX_QUICKSAND_SSL); + movtex_constant(TEX_PYRAMID_SAND_SSL); + movtex_constant(TEX_YELLOW_TRI_TTC); + movtex_constant(ROTATE_CLOCKWISE); + movtex_constant(ROTATE_COUNTER_CLOCKWISE); + + // Other constants + movtex_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 movtex arg: %s", _Arg.begin()); + return 0; +} + +#define movtex_symbol_0(symb) \ + if (_Symbol == #symb) { \ + Movtex _Mt[] = { symb() }; \ + memcpy(aHead, _Mt, sizeof(_Mt)); \ + aHead += (sizeof(_Mt) / sizeof(_Mt[0])); \ + return; \ + } + +#define movtex_symbol_1(symb) \ + if (_Symbol == #symb) { \ + s64 _Arg0 = ParseMovtexSymbolArg(aGfxData, aNode, aTokenIndex); \ + Movtex _Mt[] = { symb(_Arg0) }; \ + memcpy(aHead, _Mt, sizeof(_Mt)); \ + aHead += (sizeof(_Mt) / sizeof(_Mt[0])); \ + return; \ + } + +#define movtex_symbol_2(symb) \ + if (_Symbol == #symb) { \ + s64 _Arg0 = ParseMovtexSymbolArg(aGfxData, aNode, aTokenIndex); \ + s64 _Arg1 = ParseMovtexSymbolArg(aGfxData, aNode, aTokenIndex); \ + Movtex _Mt[] = { symb(_Arg0, _Arg1) }; \ + memcpy(aHead, _Mt, sizeof(_Mt)); \ + aHead += (sizeof(_Mt) / sizeof(_Mt[0])); \ + return; \ + } + +#define movtex_symbol_5(symb) \ + if (_Symbol == #symb) { \ + s64 _Arg0 = ParseMovtexSymbolArg(aGfxData, aNode, aTokenIndex); \ + s64 _Arg1 = ParseMovtexSymbolArg(aGfxData, aNode, aTokenIndex); \ + s64 _Arg2 = ParseMovtexSymbolArg(aGfxData, aNode, aTokenIndex); \ + s64 _Arg3 = ParseMovtexSymbolArg(aGfxData, aNode, aTokenIndex); \ + s64 _Arg4 = ParseMovtexSymbolArg(aGfxData, aNode, aTokenIndex); \ + Movtex _Mt[] = { symb(_Arg0, _Arg1, _Arg2, _Arg3, _Arg4) }; \ + memcpy(aHead, _Mt, sizeof(_Mt)); \ + aHead += (sizeof(_Mt) / sizeof(_Mt[0])); \ + return; \ + } + +#define movtex_symbol_6(symb) \ + if (_Symbol == #symb) { \ + s64 _Arg0 = ParseMovtexSymbolArg(aGfxData, aNode, aTokenIndex); \ + s64 _Arg1 = ParseMovtexSymbolArg(aGfxData, aNode, aTokenIndex); \ + s64 _Arg2 = ParseMovtexSymbolArg(aGfxData, aNode, aTokenIndex); \ + s64 _Arg3 = ParseMovtexSymbolArg(aGfxData, aNode, aTokenIndex); \ + s64 _Arg4 = ParseMovtexSymbolArg(aGfxData, aNode, aTokenIndex); \ + s64 _Arg5 = ParseMovtexSymbolArg(aGfxData, aNode, aTokenIndex); \ + Movtex _Mt[] = { symb(_Arg0, _Arg1, _Arg2, _Arg3, _Arg4, \ + _Arg5) }; \ + memcpy(aHead, _Mt, sizeof(_Mt)); \ + aHead += (sizeof(_Mt) / sizeof(_Mt[0])); \ + return; \ + } + +#define movtex_symbol_8(symb) \ + if (_Symbol == #symb) { \ + s64 _Arg0 = ParseMovtexSymbolArg(aGfxData, aNode, aTokenIndex); \ + s64 _Arg1 = ParseMovtexSymbolArg(aGfxData, aNode, aTokenIndex); \ + s64 _Arg2 = ParseMovtexSymbolArg(aGfxData, aNode, aTokenIndex); \ + s64 _Arg3 = ParseMovtexSymbolArg(aGfxData, aNode, aTokenIndex); \ + s64 _Arg4 = ParseMovtexSymbolArg(aGfxData, aNode, aTokenIndex); \ + s64 _Arg5 = ParseMovtexSymbolArg(aGfxData, aNode, aTokenIndex); \ + s64 _Arg6 = ParseMovtexSymbolArg(aGfxData, aNode, aTokenIndex); \ + s64 _Arg7 = ParseMovtexSymbolArg(aGfxData, aNode, aTokenIndex); \ + Movtex _Mt[] = { symb(_Arg0, _Arg1, _Arg2, _Arg3, _Arg4, \ + _Arg5, _Arg6, _Arg7) }; \ + memcpy(aHead, _Mt, sizeof(_Mt)); \ + aHead += (sizeof(_Mt) / sizeof(_Mt[0])); \ + return; \ + } + +static void ParseMovtexSymbol(GfxData* aGfxData, DataNode* aNode, Movtex*& aHead, u64& aTokenIndex, Array& aSwitchNodes) { + const String& _Symbol = aNode->mTokens[aTokenIndex++]; + + movtex_symbol_1(MOV_TEX_INIT_LOAD); + movtex_symbol_2(MOV_TEX_4_BOX_TRIS); + movtex_symbol_1(MOV_TEX_DEFINE); + movtex_symbol_1(MOV_TEX_SPD); + movtex_symbol_1(MOV_TEX_ROT_SPEED); + movtex_symbol_1(MOV_TEX_ROT_SCALE); + movtex_symbol_1(MOV_TEX_ROT); + movtex_symbol_1(MOV_TEX_ALPHA); + movtex_symbol_5(MOV_TEX_TRIS); + movtex_symbol_8(MOV_TEX_ROT_TRIS); + movtex_symbol_6(MOV_TEX_LIGHT_TRIS); + movtex_symbol_0(MOV_TEX_END); + movtex_symbol_0(MOV_TEX_ROT_END); + + // Unknown + PrintError(" ERROR: Unknown movtex symbol: %s", _Symbol.begin()); +} + +DataNode* DynOS_Movtex_Parse(GfxData* aGfxData, DataNode* aNode, bool aDisplayPercent) { + if (aNode->mData) return aNode; + + // Movtex data + aNode->mData = New(aNode->mTokens.Count() * MOVTEX_SIZE_PER_TOKEN); + Movtex* _Head = aNode->mData; + Array _SwitchNodes; + for (u64 _TokenIndex = 0; _TokenIndex < aNode->mTokens.Count();) { // Don't increment _TokenIndex here! + ParseMovtexSymbol(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_Movtex_Write(FILE* aFile, GfxData* aGfxData, DataNode *aNode) { + if (!aNode->mData) return; + + // Name + WriteBytes(aFile, DATA_TYPE_MOVTEX); + 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_Movtex_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->mMovtexs.Add(_Node); + } + + return _Node; +} diff --git a/data/dynos_bin_movtexqc.cpp b/data/dynos_bin_movtexqc.cpp new file mode 100644 index 00000000..2d1f5f05 --- /dev/null +++ b/data/dynos_bin_movtexqc.cpp @@ -0,0 +1,97 @@ +#include "dynos.cpp.h" + +extern "C" { +#include "include/level_misc_macros.h" +#include "src/game/moving_texture.h" +} + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wnarrowing" + + ///////////// + // Parsing // +///////////// + +#define movtexqc_constant(x) if (_Arg == #x) { return (s64) (x); } +static Movtex* ParseMovtexQCSymbolArg(GfxData* aGfxData, DataNode* aNode, u64 aTokenIndex) { + const String& _Arg = aNode->mTokens[aTokenIndex]; + + // Other constants + movtexqc_constant(NULL); + + // Movtexs + for (auto& _Node : aGfxData->mMovtexs) { + if (_Arg == _Node->mName) { + return DynOS_Movtex_Parse(aGfxData, _Node, false)->mData; + } + } + + // Unknown + PrintError(" ERROR: Unknown movtexqc arg: %s", _Arg.begin()); + return NULL; +} + +DataNode* DynOS_MovtexQC_Parse(GfxData* aGfxData, DataNode* aNode) { + if (aNode->mData) return aNode; + + // MovtexQC data + aNode->mSize = (u32) (aNode->mTokens.Count() / 2); + aNode->mData = New(aNode->mSize); + for (u32 i = 0; i != aNode->mSize; ++i) { + s16 id = (s16) aNode->mTokens[2 * i + 0].ParseInt(); + Movtex* quadArraySegmented = ParseMovtexQCSymbolArg(aGfxData, aNode, 2 * i + 1); + aNode->mData[i] = { id, quadArraySegmented }; + aGfxData->mPointerList.Add(aNode->mData[i].quadArraySegmented); + } + aNode->mLoadIndex = aGfxData->mLoadIndex++; + return aNode; +} + +#pragma GCC diagnostic pop + + ///////////// + // Writing // +///////////// + +void DynOS_MovtexQC_Write(FILE* aFile, GfxData* aGfxData, DataNode *aNode) { + if (!aNode->mData) return; + + // Name + WriteBytes(aFile, DATA_TYPE_MOVTEXQC); + aNode->mName.Write(aFile); + + // Data + WriteBytes(aFile, aNode->mSize); + for (u32 i = 0; i != aNode->mSize; ++i) { + WriteBytes(aFile, aNode->mData[i].id); + DynOS_Pointer_Write(aFile, (const void *) (aNode->mData[i].quadArraySegmented), aGfxData); + } +} + + ///////////// + // Reading // +///////////// + +DataNode* DynOS_MovtexQC_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].id = ReadBytes(aFile); + u32 _Value = ReadBytes(aFile); + void *_Ptr = DynOS_Pointer_Load(aFile, aGfxData, _Value, false); + _Node->mData[i].quadArraySegmented = (Movtex*)_Ptr; + } + + // Add it + if (aGfxData != NULL) { + aGfxData->mMovtexQCs.Add(_Node); + } + + return _Node; +} diff --git a/data/dynos_bin_pointer.cpp b/data/dynos_bin_pointer.cpp index 17f37abc..8c7d2b75 100644 --- a/data/dynos_bin_pointer.cpp +++ b/data/dynos_bin_pointer.cpp @@ -92,6 +92,20 @@ static PointerData GetDataFromPointer(const void* aPtr, GfxData* aGfxData) { } } + // Movtexs + for (auto& _Node : aGfxData->mMovtexs) { + if (_Node->mData == aPtr) { + return { _Node->mName, 0 }; + } + } + + // MovtexQCs + for (auto& _Node : aGfxData->mMovtexQCs) { + 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) { @@ -160,7 +174,7 @@ void DynOS_Pointer_Write(FILE* aFile, const void* aPtr, GfxData* aGfxData) { // Pointer PointerData _PtrData = GetDataFromPointer(aPtr, aGfxData); if (strlen(_PtrData.first.begin()) == 0) { - _PtrData = _PtrData; + _PtrData = _PtrData; // DO NOT COMMIT } WriteBytes(aFile, POINTER_CODE); _PtrData.first.Write(aFile); @@ -242,6 +256,20 @@ static void *GetPointerFromData(GfxData *aGfxData, const String &aPtrName, u32 a } } + // Movtexs + for (auto &_Node : aGfxData->mMovtexs) { + if (_Node->mName == aPtrName) { + return (void *) _Node->mData; + } + } + + // MovtexQCs + for (auto &_Node : aGfxData->mMovtexQCs) { + 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 6370c024..e760cf45 100644 --- a/data/dynos_bin_read.cpp +++ b/data/dynos_bin_read.cpp @@ -171,6 +171,8 @@ void DynOS_Read_Source(GfxData *aGfxData, const SysPath &aFilename) { // Ignore ALIGNED8 keyword } else if (_Buffer == "UNUSED") { // Ignore UNUSED keyword + } else if (_Buffer == "struct") { + // Ignore struct keyword } else if (_Buffer == "u64") { _DataType = DATA_TYPE_UNUSED; } else if (_Buffer == "Lights1") { @@ -193,6 +195,10 @@ void DynOS_Read_Source(GfxData *aGfxData, const SysPath &aFilename) { _DataType = DATA_TYPE_MACRO_OBJECT; } else if (_Buffer == "Trajectory") { _DataType = DATA_TYPE_TRAJECTORY; + } else if (_Buffer == "Movtex") { + _DataType = DATA_TYPE_MOVTEX; + } else if (_Buffer == "MovtexQuadCollection") { + _DataType = DATA_TYPE_MOVTEXQC; } else { PrintError(" ERROR: Unknown type name: %s", _Buffer.begin()); } @@ -220,6 +226,8 @@ void DynOS_Read_Source(GfxData *aGfxData, const SysPath &aFilename) { 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_MOVTEX: AppendNewNode(aGfxData, aGfxData->mMovtexs, _Buffer, pDataName, pDataTokens); break; + case DATA_TYPE_MOVTEXQC: AppendNewNode(aGfxData, aGfxData->mMovtexQCs, _Buffer, pDataName, pDataTokens); break; case DATA_TYPE_UNUSED: pDataTokens = (Array *) 1; break; } _Buffer.Clear(); diff --git a/data/dynos_bin_utils.cpp b/data/dynos_bin_utils.cpp index 5d59092d..4b68b70f 100644 --- a/data/dynos_bin_utils.cpp +++ b/data/dynos_bin_utils.cpp @@ -46,6 +46,14 @@ void DynOS_Gfx_Free(GfxData* aGfxData) { Delete(_Node->mData); Delete(_Node); } + for (auto& _Node : aGfxData->mMovtexs) { + Delete(_Node->mData); + Delete(_Node); + } + for (auto& _Node : aGfxData->mMovtexQCs) { + Delete(_Node->mData); + Delete(_Node); + } Delete(aGfxData); } } diff --git a/data/dynos_level.cpp b/data/dynos_level.cpp index 64df1a5a..bd88e511 100644 --- a/data/dynos_level.cpp +++ b/data/dynos_level.cpp @@ -226,6 +226,7 @@ s32 DynOS_Level_GetCourse(s32 aLevel) { const void *DynOS_Level_GetScript(s32 aLevel) { DynOS_Level_Init(); + return DynOS_Lvl_Get("level_bob_entry"); // DO NOT COMMIT return sDynosLevelScripts[aLevel]; }