From bd776e6bf5e05602fde82a65f62f7d19c91a2def Mon Sep 17 00:00:00 2001 From: Derek Hensley Date: Sun, 28 Jul 2024 09:31:28 -0700 Subject: [PATCH] Extract Keyframe Assets data (#1664) * git subrepo pull --force tools/ZAPD subrepo: subdir: "tools/ZAPD" merged: "c31c5e9fe" upstream: origin: "https://github.com/zeldaret/ZAPD.git" branch: "master" commit: "c31c5e9fe" git-subrepo: version: "0.4.6" origin: "git@github.com:ingydotnet/git-subrepo.git" commit: "110b9eb" * extract keyframe data * initialize typo --- assets/xml/objects/gameplay_keep.xml | 21 +- assets/xml/objects/object_fall2.xml | 5 +- assets/xml/objects/object_moonend.xml | 12 +- assets/xml/objects/object_syoten.xml | 9 +- include/z64keyframe.h | 2 + .../actors/ovl_Demo_Moonend/z_demo_moonend.c | 10 +- .../actors/ovl_Demo_Syoten/z_demo_syoten.c | 6 +- .../actors/ovl_Door_Warp1/z_door_warp1.c | 1 - .../actors/ovl_Eff_Change/z_eff_change.c | 6 +- src/overlays/actors/ovl_En_Fall2/z_en_fall2.c | 6 +- src/overlays/actors/ovl_En_Ot/z_en_ot.c | 1 - src/overlays/actors/ovl_En_Test/z_en_test.c | 6 +- src/overlays/actors/ovl_En_Test7/z_en_test7.c | 6 +- tools/ZAPD/.github/workflows/main.yml | 98 ++++++ tools/ZAPD/.gitrepo | 4 +- tools/ZAPD/README.md | 10 + tools/ZAPD/ZAPD/Globals.h | 13 + tools/ZAPD/ZAPD/Main.cpp | 78 ++++- .../ZAPD/OtherStructs/CutsceneMM_Commands.cpp | 70 ++-- .../ZAPD/OtherStructs/CutsceneMM_Commands.h | 16 +- .../OtherStructs/CutsceneOoT_Commands.cpp | 31 +- tools/ZAPD/ZAPD/ZAPD.vcxproj | 6 + tools/ZAPD/ZAPD/ZAPD.vcxproj.filters | 12 + tools/ZAPD/ZAPD/ZCKeyFrame.cpp | 312 ++++++++++++++++++ tools/ZAPD/ZAPD/ZCKeyFrame.h | 121 +++++++ tools/ZAPD/ZAPD/ZCKeyFrameAnim.cpp | 219 ++++++++++++ tools/ZAPD/ZAPD/ZCkeyFrameAnim.h | 52 +++ tools/ZAPD/ZAPD/ZCutscene.cpp | 26 +- tools/ZAPD/ZAPD/ZCutscene.h | 4 + tools/ZAPD/ZAPD/ZFile.cpp | 18 + tools/ZAPD/ZAPD/ZResource.h | 4 + tools/ZAPD/ZAPDUtils/Utils/StringHelper.h | 15 + 32 files changed, 1093 insertions(+), 107 deletions(-) create mode 100644 tools/ZAPD/.github/workflows/main.yml create mode 100644 tools/ZAPD/ZAPD/ZCKeyFrame.cpp create mode 100644 tools/ZAPD/ZAPD/ZCKeyFrame.h create mode 100644 tools/ZAPD/ZAPD/ZCKeyFrameAnim.cpp create mode 100644 tools/ZAPD/ZAPD/ZCkeyFrameAnim.h diff --git a/assets/xml/objects/gameplay_keep.xml b/assets/xml/objects/gameplay_keep.xml index 5881fcb37e..d7c6a93753 100644 --- a/assets/xml/objects/gameplay_keep.xml +++ b/assets/xml/objects/gameplay_keep.xml @@ -970,15 +970,12 @@ - - - + - - + @@ -1333,10 +1330,7 @@ - - - - + @@ -1345,8 +1339,7 @@ - - + @@ -1450,8 +1443,7 @@ - - + @@ -1482,8 +1474,7 @@ - - + diff --git a/assets/xml/objects/object_fall2.xml b/assets/xml/objects/object_fall2.xml index 70c8ca2d4c..1ad99a8a33 100644 --- a/assets/xml/objects/object_fall2.xml +++ b/assets/xml/objects/object_fall2.xml @@ -12,8 +12,7 @@ - - + @@ -30,6 +29,6 @@ - + diff --git a/assets/xml/objects/object_moonend.xml b/assets/xml/objects/object_moonend.xml index c23659dce4..9b9e078a27 100644 --- a/assets/xml/objects/object_moonend.xml +++ b/assets/xml/objects/object_moonend.xml @@ -1,8 +1,6 @@  - - - + @@ -21,10 +19,8 @@ - - - - + + @@ -34,7 +30,7 @@ - + diff --git a/assets/xml/objects/object_syoten.xml b/assets/xml/objects/object_syoten.xml index 63a0619719..2516167574 100644 --- a/assets/xml/objects/object_syoten.xml +++ b/assets/xml/objects/object_syoten.xml @@ -1,8 +1,6 @@  - - - + @@ -14,10 +12,7 @@ - - - - + diff --git a/include/z64keyframe.h b/include/z64keyframe.h index 10d7f85096..ac350c125c 100644 --- a/include/z64keyframe.h +++ b/include/z64keyframe.h @@ -70,6 +70,8 @@ typedef struct { // Array of bitflags for each limb indicating whether to do keyframe interpolation // or pull from fixed values that do not change throughout the animation. union { + // Used to initialize bitflags without warnings + /* 0x00 */ void* data; // For standard the bit layout in each array element is: // [5] X Translation (root limb only) // [4] Y Translation (root limb only) diff --git a/src/overlays/actors/ovl_Demo_Moonend/z_demo_moonend.c b/src/overlays/actors/ovl_Demo_Moonend/z_demo_moonend.c index 91d6c2377a..798de67563 100644 --- a/src/overlays/actors/ovl_Demo_Moonend/z_demo_moonend.c +++ b/src/overlays/actors/ovl_Demo_Moonend/z_demo_moonend.c @@ -46,9 +46,9 @@ void DemoMoonend_Init(Actor* thisx, PlayState* play) { this->actionFunc = func_80C17B60; } else { Actor_SetScale(&this->actor, 0.095f); - Keyframe_InitFlex(&this->kfSkelAnime, (KeyFrameFlexSkeleton*)&object_moonend_Blob_00B5A0, - (KeyFrameAnimation*)&object_moonend_Blob_001214, this->jointTable, this->morphTable, NULL); - Keyframe_FlexPlayOnce(&this->kfSkelAnime, (KeyFrameAnimation*)&object_moonend_Blob_001214); + Keyframe_InitFlex(&this->kfSkelAnime, &object_moonend_KFSkel_00B5A0, &object_moonened_KFAnim_001214, + this->jointTable, this->morphTable, NULL); + Keyframe_FlexPlayOnce(&this->kfSkelAnime, &object_moonened_KFAnim_001214); this->cueType = CS_CMD_ACTOR_CUE_560; this->actionFunc = func_80C17C48; this->actor.home.rot.z = 0; @@ -110,13 +110,13 @@ void func_80C17C48(DemoMoonend* this, PlayState* play) { switch (this->cueId) { case 1: this->actor.draw = DemoMoonend_Draw; - Keyframe_FlexPlayOnce(&this->kfSkelAnime, (KeyFrameAnimation*)&object_moonend_Blob_001214); + Keyframe_FlexPlayOnce(&this->kfSkelAnime, &object_moonened_KFAnim_001214); this->kfSkelAnime.frameCtrl.speed = 0.0f; break; case 2: this->actor.draw = DemoMoonend_Draw; - Keyframe_FlexPlayOnce(&this->kfSkelAnime, (KeyFrameAnimation*)&object_moonend_Blob_001214); + Keyframe_FlexPlayOnce(&this->kfSkelAnime, &object_moonened_KFAnim_001214); this->kfSkelAnime.frameCtrl.speed = 2.0f / 3.0f; Actor_PlaySfx(&this->actor, NA_SE_EV_MOON_EXPLOSION); this->actor.home.rot.z = 1; diff --git a/src/overlays/actors/ovl_Demo_Syoten/z_demo_syoten.c b/src/overlays/actors/ovl_Demo_Syoten/z_demo_syoten.c index 3780c075c5..5f25137f5d 100644 --- a/src/overlays/actors/ovl_Demo_Syoten/z_demo_syoten.c +++ b/src/overlays/actors/ovl_Demo_Syoten/z_demo_syoten.c @@ -73,9 +73,9 @@ void DemoSyoten_Init(Actor* thisx, PlayState* play) { switch (DEMOSYOTEN_GET_F(&this->actor)) { case DEMOSYOTEN_F_0: - Keyframe_InitFlex(&this->kfSkelAnime, (KeyFrameFlexSkeleton*)&object_syoten_Blob_001328, - (KeyFrameAnimation*)&object_syoten_Blob_00023C, this->jointTable, this->morphTable, NULL); - Keyframe_FlexPlayLoop(&this->kfSkelAnime, (KeyFrameAnimation*)&object_syoten_Blob_00023C); + Keyframe_InitFlex(&this->kfSkelAnime, &object_syoten_KFSkel_001328, &object_syoten_KFAnim_00023C, + this->jointTable, this->morphTable, NULL); + Keyframe_FlexPlayLoop(&this->kfSkelAnime, &object_syoten_KFAnim_00023C); this->actor.draw = NULL; this->actionFunc = func_80C16A74; this->actor.child = diff --git a/src/overlays/actors/ovl_Door_Warp1/z_door_warp1.c b/src/overlays/actors/ovl_Door_Warp1/z_door_warp1.c index 81bdd2d376..18e019b281 100644 --- a/src/overlays/actors/ovl_Door_Warp1/z_door_warp1.c +++ b/src/overlays/actors/ovl_Door_Warp1/z_door_warp1.c @@ -4,7 +4,6 @@ * Description: Blue warp portal and crystal, and the Majora's Mask-shaped boss warp platform */ -#include "prevent_bss_reordering.h" #include "z_door_warp1.h" #include "objects/object_warp1/object_warp1.h" diff --git a/src/overlays/actors/ovl_Eff_Change/z_eff_change.c b/src/overlays/actors/ovl_Eff_Change/z_eff_change.c index 24a079632f..0a1b46e84b 100644 --- a/src/overlays/actors/ovl_Eff_Change/z_eff_change.c +++ b/src/overlays/actors/ovl_Eff_Change/z_eff_change.c @@ -50,9 +50,9 @@ void EffChange_Init(Actor* thisx, PlayState* play) { EffChange_SetColors(this, EFFCHANGE_GET_COLORS(thisx)); Actor_SetScale(&this->actor, 0.075f); this->primColors[3] = 0; - Keyframe_InitFlex(&this->kfSkelAnime, (KeyFrameFlexSkeleton*)&gameplay_keep_Blob_02900C, - (KeyFrameAnimation*)&gameplay_keep_Blob_0281DC, this->jointTable, this->morphTable, NULL); - Keyframe_FlexPlayOnce(&this->kfSkelAnime, (KeyFrameAnimation*)&gameplay_keep_Blob_0281DC); + Keyframe_InitFlex(&this->kfSkelAnime, &gameplay_keep_KFSkel_02900C, &gameplay_keep_KFAnim_0281DC, this->jointTable, + this->morphTable, NULL); + Keyframe_FlexPlayOnce(&this->kfSkelAnime, &gameplay_keep_KFAnim_0281DC); this->step = 0; this->actor.shape.rot.y = 0; this->kfSkelAnime.frameCtrl.speed = 2.0f / 3.0f; diff --git a/src/overlays/actors/ovl_En_Fall2/z_en_fall2.c b/src/overlays/actors/ovl_En_Fall2/z_en_fall2.c index b1a67d9e0d..6d282e2d12 100644 --- a/src/overlays/actors/ovl_En_Fall2/z_en_fall2.c +++ b/src/overlays/actors/ovl_En_Fall2/z_en_fall2.c @@ -35,9 +35,9 @@ void EnFall2_Init(Actor* thisx, PlayState* play) { Actor_SetScale(&this->actor, 1.0f); this->actionFunc = EnFall2_DoNothing; - Keyframe_InitFlex(&this->kfSkelAnime, (KeyFrameFlexSkeleton*)&object_fall2_Blob_008898, - (KeyFrameAnimation*)&object_fall2_Blob_005EF4, this->jointTable, this->morphTable, NULL); - Keyframe_FlexPlayLoop(&this->kfSkelAnime, (KeyFrameAnimation*)&object_fall2_Blob_005EF4); + Keyframe_InitFlex(&this->kfSkelAnime, &object_fall2_KFSkel_008898, &object_fall2_KFAnim_005EF4, this->jointTable, + this->morphTable, NULL); + Keyframe_FlexPlayLoop(&this->kfSkelAnime, &object_fall2_KFAnim_005EF4); this->unk2DC = Lib_SegmentedToVirtual(object_fall2_Matanimheader_008840); Actor_SetScale(&this->actor, 0.02f); this->actionFunc = EnFall2_HandleCutscene; diff --git a/src/overlays/actors/ovl_En_Ot/z_en_ot.c b/src/overlays/actors/ovl_En_Ot/z_en_ot.c index 89d32e6e23..ed200e1976 100644 --- a/src/overlays/actors/ovl_En_Ot/z_en_ot.c +++ b/src/overlays/actors/ovl_En_Ot/z_en_ot.c @@ -4,7 +4,6 @@ * Description: Seahorse */ -#include "prevent_bss_reordering.h" #include "z_en_ot.h" #include "objects/gameplay_keep/gameplay_keep.h" diff --git a/src/overlays/actors/ovl_En_Test/z_en_test.c b/src/overlays/actors/ovl_En_Test/z_en_test.c index 6cff068b32..4bef57063b 100644 --- a/src/overlays/actors/ovl_En_Test/z_en_test.c +++ b/src/overlays/actors/ovl_En_Test/z_en_test.c @@ -186,9 +186,9 @@ void EnTest_Init(Actor* thisx, PlayState* play2) { this->surfaceMaterial = SurfaceType_GetMaterial(&play->colCtx, thisx->floorPoly, bgId); } - Keyframe_InitFlex(&this->kfSkelAnime, (KeyFrameFlexSkeleton*)&gameplay_keep_Blob_06EB70, - (KeyFrameAnimation*)&gameplay_keep_Blob_06BB0C, this->jointTable, this->morphTable, NULL); - Keyframe_FlexPlayOnce(&this->kfSkelAnime, (KeyFrameAnimation*)&gameplay_keep_Blob_06BB0C); + Keyframe_InitFlex(&this->kfSkelAnime, &gameplay_keep_KFSkel_06EB70, &gameplay_keep_KFAnim_06BB0C, this->jointTable, + this->morphTable, NULL); + Keyframe_FlexPlayOnce(&this->kfSkelAnime, &gameplay_keep_KFAnim_06BB0C); this->kfSkelAnime.frameCtrl.curTime = 9.0f; func_80862B70(this->unk_20C); } diff --git a/src/overlays/actors/ovl_En_Test7/z_en_test7.c b/src/overlays/actors/ovl_En_Test7/z_en_test7.c index da2aab1d5f..b96b8d8b70 100644 --- a/src/overlays/actors/ovl_En_Test7/z_en_test7.c +++ b/src/overlays/actors/ovl_En_Test7/z_en_test7.c @@ -383,9 +383,9 @@ void EnTest7_Init(Actor* thisx, PlayState* play2) { this->playerScaleZ = player->actor.scale.z; // Keyframe animations - Keyframe_InitFlex(&this->kfSkelAnime, (KeyFrameFlexSkeleton*)&gameplay_keep_Blob_085640, - (KeyFrameAnimation*)&gameplay_keep_Blob_083534, this->jointTable, this->morphTable, NULL); - Keyframe_FlexPlayOnce(&this->kfSkelAnime, (KeyFrameAnimation*)&gameplay_keep_Blob_083534); + Keyframe_InitFlex(&this->kfSkelAnime, &gameplay_keep_KFSkel_085640, &gameplay_keep_KFAnim_083534, this->jointTable, + this->morphTable, NULL); + Keyframe_FlexPlayOnce(&this->kfSkelAnime, &gameplay_keep_KFAnim_083534); EnTest7_InitFeathers(this->feathers); EnTest7_InitWindCapsule(&this->windCapsule); diff --git a/tools/ZAPD/.github/workflows/main.yml b/tools/ZAPD/.github/workflows/main.yml new file mode 100644 index 0000000000..604c18c961 --- /dev/null +++ b/tools/ZAPD/.github/workflows/main.yml @@ -0,0 +1,98 @@ +name: Build ZAPD + +on: + push: + pull_request: + branches: + - master + +jobs: + build: + runs-on: self-hosted-runner + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Build ZAPD + run: make -j WERROR=1 + + - name: Checkout Repos + run: echo "Checkout Repos" + + - name: Checkout oot + run: | + cd ../ + rm -rf oot/ + git clone https://github.com/zeldaret/oot.git + cd oot + echo $(pwd) + git submodule update --init --recursive + + - name: Checkout mm + run: | + cd ../ + rm -rf mm/ + git clone https://github.com/zeldaret/mm.git + cd mm + echo $(pwd) + + - name: Set up repos + run: echo "Set up repos" + + - name: Setup OOT + run: | + cd ../ + cd oot + echo $(pwd) + mkdir -p baseroms/gc-eu-mq-dbg/segments + cp ~/baserom_original.z64 ./baseroms/gc-eu-mq-dbg/baserom.z64 + cd tools + rm -rf ZAPD/ + ln -s ../../ZAPD + cd ../ + make -j $(nproc) setup + + - name: Setup MM + run: | + cd ../ + cd mm + echo $(pwd) + python3 -m venv .mm-env + source .mm-env/bin/activate + python3 -m pip install -r requirements.txt + cp ~/baserom.mm.us.rev1.z64 ./baserom.mm.us.rev1.z64 + cd tools + rm -rf ZAPD/ + ln -s ../../ZAPD + cd ../ + make -C tools -j + python3 tools/fixbaserom.py + python3 tools/extract_baserom.py + python3 tools/decompress_yars.py + python3 extract_assets.py -j $(nproc) + + - name: Build Repos + run: echo "Build Repos" + + - name: Build oot + run: | + cd ../ + cd oot + echo $(pwd) + make venv + make -j + + - name: Build mm + run: | + cd ../ + cd mm + echo $(pwd) + python3 -m venv .mm-env + source .mm-env/bin/activate + python3 -m pip install -r requirements.txt + make -j disasm + make -j + + - name: Clean workspace + run: git clean -fdX diff --git a/tools/ZAPD/.gitrepo b/tools/ZAPD/.gitrepo index 7eb187efc7..d5596db31b 100644 --- a/tools/ZAPD/.gitrepo +++ b/tools/ZAPD/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/zeldaret/ZAPD.git branch = master - commit = 9601f2699c142bb8273d33763ef4d84e8a7d650f - parent = 3e1207d5e7818ab6676422cda10f206b180126db + commit = c31c5e9fec72863e38cdfef8c0b1915140234253 + parent = 1685597d9aded6ee06f4e191954940331e34f346 method = merge cmdver = 0.4.6 diff --git a/tools/ZAPD/README.md b/tools/ZAPD/README.md index 76dfbd1e95..5006f8d4b5 100644 --- a/tools/ZAPD/README.md +++ b/tools/ZAPD/README.md @@ -117,6 +117,16 @@ ZAPD also accepts the following list of extra parameters: - `-us` / `--unaccounted-static` : Mark unaccounted data as `static` - `-s` / `--static` : Mark every asset as `static`. - This behaviour can be overridden per asset using `Static=` in the respective XML node. +- `--cs-float` : How cutscene floats should be extracted. +- Valid values: + - `hex`: `0x42280000` + - `float`: `42.0f` + - `both`: `CS_FLOAT(0x42280000, 42.0f)` + - `hex-commented-left`: `/* 42.0f */ 0x42280000` + - `hex-commented-right`: `0x42280000 /* 42.0f */` +- `--base-address ADDRESS`: Override base virtual address for input files. +- `--start-offset OFFSET`: Override start offset for input files. +- `--end-offset OFFSET`: Override end offset for input files. - `-W...`: warning flags, see below Additionally, you can pass the flag `--version` to see the current ZAPD version. If that flag is passed, ZAPD will ignore any other parameter passed. diff --git a/tools/ZAPD/ZAPD/Globals.h b/tools/ZAPD/ZAPD/Globals.h index 0bfcaeec72..2cc9c2d4db 100644 --- a/tools/ZAPD/ZAPD/Globals.h +++ b/tools/ZAPD/ZAPD/Globals.h @@ -16,6 +16,15 @@ enum class VerbosityLevel VERBOSITY_DEBUG }; +enum class CsFloatType +{ + HexOnly, + FloatOnly, + HexAndFloat, + HexAndCommentedFloatLeft, + HexAndCommentedFloatRight, +}; + class Globals { public: @@ -31,6 +40,10 @@ public: ZFileMode fileMode; fs::path baseRomPath, inputPath, outputPath, sourceOutputPath, cfgPath; TextureType texType; + CsFloatType floatType = CsFloatType::FloatOnly; + int64_t baseAddress = -1; + int64_t startOffset = -1; + int64_t endOffset = -1; ZGame game; GameConfig cfg; bool verboseUnaccounted = false; diff --git a/tools/ZAPD/ZAPD/Main.cpp b/tools/ZAPD/ZAPD/Main.cpp index 40a38bc601..19d10d7d96 100644 --- a/tools/ZAPD/ZAPD/Main.cpp +++ b/tools/ZAPD/ZAPD/Main.cpp @@ -36,11 +36,15 @@ void Arg_SetExporter(int& i, char* argv[]); void Arg_EnableGCCCompat(int& i, char* argv[]); void Arg_ForceStatic(int& i, char* argv[]); void Arg_ForceUnaccountedStatic(int& i, char* argv[]); +void Arg_CsFloatMode(int& i, char* argv[]); +void Arg_BaseAddress(int& i, char* argv[]); +void Arg_StartOffset(int& i, char* argv[]); +void Arg_EndOffset(int& i, char* argv[]); int main(int argc, char* argv[]); bool Parse(const fs::path& xmlFilePath, const fs::path& basePath, const fs::path& outPath, - ZFileMode fileMode); + ZFileMode fileMode); void ParseArgs(int& argc, char* argv[]); @@ -114,7 +118,7 @@ int main(int argc, char* argv[]) returnCode = HandleExtract(fileMode, exporterSet); else if (fileMode == ZFileMode::BuildTexture) BuildAssetTexture(Globals::Instance->inputPath, Globals::Instance->texType, - Globals::Instance->outputPath); + Globals::Instance->outputPath); else if (fileMode == ZFileMode::BuildBackground) BuildAssetBackground(Globals::Instance->inputPath, Globals::Instance->outputPath); else if (fileMode == ZFileMode::BuildBlob) @@ -125,7 +129,7 @@ int main(int argc, char* argv[]) } bool Parse(const fs::path& xmlFilePath, const fs::path& basePath, const fs::path& outPath, - ZFileMode fileMode) + ZFileMode fileMode) { tinyxml2::XMLDocument doc; tinyxml2::XMLError eResult = doc.LoadFile(xmlFilePath.string().c_str()); @@ -134,7 +138,7 @@ bool Parse(const fs::path& xmlFilePath, const fs::path& basePath, const fs::path { // TODO: use XMLDocument::ErrorIDToName to get more specific error messages here HANDLE_ERROR(WarningType::InvalidXML, - StringHelper::Sprintf("invalid XML file: '%s'", xmlFilePath.c_str()), ""); + StringHelper::Sprintf("invalid XML file: '%s'", xmlFilePath.c_str()), ""); return false; } @@ -149,7 +153,7 @@ bool Parse(const fs::path& xmlFilePath, const fs::path& basePath, const fs::path } for (tinyxml2::XMLElement* child = root->FirstChildElement(); child != NULL; - child = child->NextSiblingElement()) + child = child->NextSiblingElement()) { if (std::string_view(child->Name()) == "File") { @@ -252,6 +256,10 @@ void ParseArgs(int& argc, char* argv[]) {"--static", &Arg_ForceStatic}, {"-us", &Arg_ForceUnaccountedStatic}, {"--unaccounted-static", &Arg_ForceUnaccountedStatic}, + {"--cs-float", &Arg_CsFloatMode}, + {"--base-address", &Arg_BaseAddress}, + {"--start-offset", &Arg_StartOffset}, + {"--end-offset", &Arg_EndOffset}, }; for (int32_t i = 2; i < argc; i++) @@ -392,6 +400,62 @@ void Arg_ForceUnaccountedStatic([[maybe_unused]] int& i, [[maybe_unused]] char* Globals::Instance->forceUnaccountedStatic = true; } +void Arg_CsFloatMode([[maybe_unused]] int& i, [[maybe_unused]] char* argv[]) +{ + i++; + if (std::strcmp(argv[i], "hex") == 0) + { + Globals::Instance->floatType = CsFloatType::HexOnly; + } + else if (std::strcmp(argv[i], "float") == 0) + { + Globals::Instance->floatType = CsFloatType::FloatOnly; + } + else if (std::strcmp(argv[i], "both") == 0) + { + Globals::Instance->floatType = CsFloatType::HexAndFloat; + } + else if (std::strcmp(argv[i], "hex-commented-left") == 0) + { + Globals::Instance->floatType = CsFloatType::HexAndCommentedFloatLeft; + } + else if (std::strcmp(argv[i], "hex-commented-right") == 0) + { + Globals::Instance->floatType = CsFloatType::HexAndCommentedFloatRight; + } + else + { + Globals::Instance->floatType = CsFloatType::FloatOnly; + HANDLE_WARNING( + WarningType::Always, "Invalid CS Float Type", + StringHelper::Sprintf("Invalid CS float type entered. Expected \"hex\", \"float\", " + "\"both\", \"hex-commented-left\" or \"hex-commented-right\". " + "Got %s.\n Defaulting to \"float\".", + argv[i])); + } +} + +uint32_t ParseU32Hex(char* str) +{ + static_assert(sizeof(uint32_t) <= sizeof(unsigned long)); + return (uint32_t)std::stoul(str, nullptr, 16); +} + +void Arg_BaseAddress(int& i, char* argv[]) +{ + Globals::Instance->baseAddress = ParseU32Hex(argv[++i]); +} + +void Arg_StartOffset(int& i, char* argv[]) +{ + Globals::Instance->startOffset = ParseU32Hex(argv[++i]); +} + +void Arg_EndOffset(int& i, char* argv[]) +{ + Globals::Instance->endOffset = ParseU32Hex(argv[++i]); +} + int HandleExtract(ZFileMode fileMode, ExporterSet* exporterSet) { bool procFileModeSuccess = false; @@ -412,14 +476,14 @@ int HandleExtract(ZFileMode fileMode, ExporterSet* exporterSet) printf("Parsing external file from config: '%s'\n", externalXmlFilePath.c_str()); parseSuccessful = Parse(externalXmlFilePath, Globals::Instance->baseRomPath, - extFile.outPath, ZFileMode::ExternalFile); + extFile.outPath, ZFileMode::ExternalFile); if (!parseSuccessful) return 1; } parseSuccessful = Parse(Globals::Instance->inputPath, Globals::Instance->baseRomPath, - Globals::Instance->outputPath, fileMode); + Globals::Instance->outputPath, fileMode); if (!parseSuccessful) return 1; } diff --git a/tools/ZAPD/ZAPD/OtherStructs/CutsceneMM_Commands.cpp b/tools/ZAPD/ZAPD/OtherStructs/CutsceneMM_Commands.cpp index b47bc40e16..960404e598 100644 --- a/tools/ZAPD/ZAPD/OtherStructs/CutsceneMM_Commands.cpp +++ b/tools/ZAPD/ZAPD/OtherStructs/CutsceneMM_Commands.cpp @@ -6,6 +6,8 @@ #include "Utils/StringHelper.h" #include "WarningHandler.h" +#include "ZCutscene.h" + /**** GENERIC ****/ // Specific for command lists where each entry has size 8 bytes @@ -127,8 +129,9 @@ std::string CutsceneMMCommand_GenericCmd::GetCommandMacro() const /**** CAMERA ****/ -CutsceneSubCommandEntry_SplineCamPoint::CutsceneSubCommandEntry_SplineCamPoint(const std::vector& rawData, - offset_t rawDataIndex): CutsceneSubCommandEntry(rawData, rawDataIndex) +CutsceneSubCommandEntry_SplineCamPoint::CutsceneSubCommandEntry_SplineCamPoint( + const std::vector& rawData, offset_t rawDataIndex) + : CutsceneSubCommandEntry(rawData, rawDataIndex) { interpType = BitConverter::ToUInt8BE(rawData, rawDataIndex + 0); weight = BitConverter::ToUInt8BE(rawData, rawDataIndex + 1); @@ -144,7 +147,9 @@ std::string CutsceneSubCommandEntry_SplineCamPoint::GetBodySourceCode() const const auto interpTypeMap = &Globals::Instance->cfg.enumData.interpType; const auto relToMap = &Globals::Instance->cfg.enumData.relTo; - return StringHelper::Sprintf("CS_CAM_POINT(%s, 0x%02X, 0x%04X, 0x%04X, 0x%04X, 0x%04X, %s)", interpTypeMap->at(interpType).c_str(), weight, duration, posX, posY, posZ, relToMap->at(relTo).c_str()); + return StringHelper::Sprintf("CS_CAM_POINT(%s, 0x%02X, 0x%04X, 0x%04X, 0x%04X, 0x%04X, %s)", + interpTypeMap->at(interpType).c_str(), weight, duration, posX, + posY, posZ, relToMap->at(relTo).c_str()); } size_t CutsceneSubCommandEntry_SplineCamPoint::GetRawSize() const @@ -152,9 +157,9 @@ size_t CutsceneSubCommandEntry_SplineCamPoint::GetRawSize() const return 0x0C; } - -CutsceneSubCommandEntry_SplineMiscPoint::CutsceneSubCommandEntry_SplineMiscPoint(const std::vector& rawData, - offset_t rawDataIndex): CutsceneSubCommandEntry(rawData, rawDataIndex) +CutsceneSubCommandEntry_SplineMiscPoint::CutsceneSubCommandEntry_SplineMiscPoint( + const std::vector& rawData, offset_t rawDataIndex) + : CutsceneSubCommandEntry(rawData, rawDataIndex) { unused0 = BitConverter::ToUInt16BE(rawData, rawDataIndex + 0); roll = BitConverter::ToUInt16BE(rawData, rawDataIndex + 2); @@ -164,7 +169,8 @@ CutsceneSubCommandEntry_SplineMiscPoint::CutsceneSubCommandEntry_SplineMiscPoint std::string CutsceneSubCommandEntry_SplineMiscPoint::GetBodySourceCode() const { - return StringHelper::Sprintf("CS_CAM_MISC(0x%04X, 0x%04X, 0x%04X, 0x%04X)", unused0, roll, fov, unused1); + return StringHelper::Sprintf("CS_CAM_MISC(0x%04X, 0x%04X, 0x%04X, 0x%04X)", unused0, roll, fov, + unused1); } size_t CutsceneSubCommandEntry_SplineMiscPoint::GetRawSize() const @@ -172,8 +178,9 @@ size_t CutsceneSubCommandEntry_SplineMiscPoint::GetRawSize() const return 0x08; } -CutsceneSubCommandEntry_SplineHeader::CutsceneSubCommandEntry_SplineHeader(const std::vector& rawData, - offset_t rawDataIndex): CutsceneSubCommandEntry(rawData, rawDataIndex) +CutsceneSubCommandEntry_SplineHeader::CutsceneSubCommandEntry_SplineHeader( + const std::vector& rawData, offset_t rawDataIndex) + : CutsceneSubCommandEntry(rawData, rawDataIndex) { numEntries = BitConverter::ToUInt16BE(rawData, rawDataIndex + 0); unused0 = BitConverter::ToUInt16BE(rawData, rawDataIndex + 2); @@ -183,8 +190,8 @@ CutsceneSubCommandEntry_SplineHeader::CutsceneSubCommandEntry_SplineHeader(const std::string CutsceneSubCommandEntry_SplineHeader::GetBodySourceCode() const { - return StringHelper::Sprintf("CS_CAM_SPLINE(0x%04X, 0x%04X, 0x%04X, 0x%04X)", numEntries, unused0, unused1, duration); - + return StringHelper::Sprintf("CS_CAM_SPLINE(0x%04X, 0x%04X, 0x%04X, 0x%04X)", numEntries, + unused0, unused1, duration); } size_t CutsceneSubCommandEntry_SplineHeader::GetRawSize() const @@ -192,16 +199,19 @@ size_t CutsceneSubCommandEntry_SplineHeader::GetRawSize() const return 0x08; } -CutsceneSubCommandEntry_SplineFooter::CutsceneSubCommandEntry_SplineFooter(const std::vector& rawData, - offset_t rawDataIndex): CutsceneSubCommandEntry(rawData, rawDataIndex) +CutsceneSubCommandEntry_SplineFooter::CutsceneSubCommandEntry_SplineFooter( + const std::vector& rawData, offset_t rawDataIndex) + : CutsceneSubCommandEntry(rawData, rawDataIndex) { uint16_t firstHalfWord = BitConverter::ToUInt16BE(rawData, rawDataIndex); uint16_t secondHalfWord = BitConverter::ToUInt16BE(rawData, rawDataIndex + 2); - if (firstHalfWord != 0xFFFF || secondHalfWord != 4) { + if (firstHalfWord != 0xFFFF || secondHalfWord != 4) + { HANDLE_ERROR(WarningType::InvalidExtractedData, "Invalid Spline Footer", - StringHelper::Sprintf("Invalid Spline footer. Was expecting 0xFFFF, 0x0004. Got 0x%04X, 0x%04X", - firstHalfWord, secondHalfWord)); + StringHelper::Sprintf( + "Invalid Spline footer. Was expecting 0xFFFF, 0x0004. Got 0x%04X, 0x%04X", + firstHalfWord, secondHalfWord)); } } @@ -223,8 +233,10 @@ CutsceneMMCommand_Spline::CutsceneMMCommand_Spline(const std::vector& r totalCommands = 0; rawDataIndex += 4; - while(1) { - if (BitConverter::ToUInt16BE(rawData, rawDataIndex) == 0xFFFF) { + while (1) + { + if (BitConverter::ToUInt16BE(rawData, rawDataIndex) == 0xFFFF) + { break; } numHeaders++; @@ -232,7 +244,7 @@ CutsceneMMCommand_Spline::CutsceneMMCommand_Spline(const std::vector& r auto* header = new CutsceneSubCommandEntry_SplineHeader(rawData, rawDataIndex); rawDataIndex += header->GetRawSize(); entries.push_back(header); - + totalCommands += header->numEntries; for (uint32_t i = 0; i < header->numEntries; i++) @@ -269,7 +281,8 @@ std::string CutsceneMMCommand_Spline::GetCommandMacro() const size_t CutsceneMMCommand_Spline::GetCommandSize() const { - // 8 Bytes once for the spline command, 8 Bytes per spline the header, two groups of size 12, 1 group of size 8, 4 bytes for the footer. + // 8 Bytes once for the spline command, 8 Bytes per spline the header, two groups of size 12, 1 + // group of size 8, 4 bytes for the footer. return 8 + (8 * numHeaders) + ((totalCommands * 2) * 0xC) + (totalCommands * 8) + 4; } @@ -545,22 +558,29 @@ CutsceneMMSubCommandEntry_ActorCue::CutsceneMMSubCommandEntry_ActorCue( std::string CutsceneMMSubCommandEntry_ActorCue::GetBodySourceCode() const { EnumData* enumData = &Globals::Instance->cfg.enumData; + std::string normalXStr = + ZCutscene::GetCsEncodedFloat(normalX, Globals::Instance->floatType, true); + std::string normalYStr = + ZCutscene::GetCsEncodedFloat(normalY, Globals::Instance->floatType, true); + std::string normalZStr = + ZCutscene::GetCsEncodedFloat(normalZ, Globals::Instance->floatType, true); if (static_cast(commandID) == CutsceneMM_CommandType::CS_CMD_PLAYER_CUE) { return StringHelper::Sprintf("CS_PLAYER_CUE(%s, %i, %i, 0x%04X, 0x%04X, 0x%04X, %i, %i, " - "%i, %i, %i, %i, %.8ef, %.8ef, %.8ef)", + "%i, %i, %i, %i, %s, %s, %s)", enumData->playerCueId[base].c_str(), startFrame, endFrame, rotX, rotY, rotZ, startPosX, startPosY, startPosZ, endPosX, - endPosY, endPosZ, normalX, normalY, normalZ); + endPosY, endPosZ, normalXStr.c_str(), normalYStr.c_str(), + normalZStr.c_str()); } else { return StringHelper::Sprintf("CS_ACTOR_CUE(%i, %i, %i, 0x%04X, 0x%04X, 0x%04X, %i, %i, " - "%i, %i, %i, %i, %.8ef, %.8ef, %.8ef)", + "%i, %i, %i, %i, %s, %s, %s)", base, startFrame, endFrame, rotX, rotY, rotZ, startPosX, - startPosY, startPosZ, endPosX, endPosY, endPosZ, normalX, - normalY, normalZ); + startPosY, startPosZ, endPosX, endPosY, endPosZ, + normalXStr.c_str(), normalYStr.c_str(), normalZStr.c_str()); } } diff --git a/tools/ZAPD/ZAPD/OtherStructs/CutsceneMM_Commands.h b/tools/ZAPD/ZAPD/OtherStructs/CutsceneMM_Commands.h index 9891a24ac4..597f6788bc 100644 --- a/tools/ZAPD/ZAPD/OtherStructs/CutsceneMM_Commands.h +++ b/tools/ZAPD/ZAPD/OtherStructs/CutsceneMM_Commands.h @@ -282,7 +282,8 @@ public: uint16_t posZ; uint16_t relTo; - CutsceneSubCommandEntry_SplineCamPoint(const std::vector& rawData, offset_t rawDataIndex); + CutsceneSubCommandEntry_SplineCamPoint(const std::vector& rawData, + offset_t rawDataIndex); std::string GetBodySourceCode() const override; @@ -296,8 +297,9 @@ public: uint16_t roll; uint16_t fov; uint16_t unused1; - - CutsceneSubCommandEntry_SplineMiscPoint(const std::vector& rawData, offset_t rawDataIndex); + + CutsceneSubCommandEntry_SplineMiscPoint(const std::vector& rawData, + offset_t rawDataIndex); std::string GetBodySourceCode() const override; @@ -306,8 +308,9 @@ public: class CutsceneSubCommandEntry_SplineFooter : public CutsceneSubCommandEntry { -public: - CutsceneSubCommandEntry_SplineFooter(const std::vector& rawData, offset_t rawDataIndex); +public: + CutsceneSubCommandEntry_SplineFooter(const std::vector& rawData, + offset_t rawDataIndex); std::string GetBodySourceCode() const override; @@ -321,7 +324,8 @@ public: uint16_t unused0; uint16_t unused1; uint16_t duration; - CutsceneSubCommandEntry_SplineHeader(const std::vector& rawData, offset_t rawDataIndex); + CutsceneSubCommandEntry_SplineHeader(const std::vector& rawData, + offset_t rawDataIndex); std::string GetBodySourceCode() const override; diff --git a/tools/ZAPD/ZAPD/OtherStructs/CutsceneOoT_Commands.cpp b/tools/ZAPD/ZAPD/OtherStructs/CutsceneOoT_Commands.cpp index 8c530f796e..668657e7aa 100644 --- a/tools/ZAPD/ZAPD/OtherStructs/CutsceneOoT_Commands.cpp +++ b/tools/ZAPD/ZAPD/OtherStructs/CutsceneOoT_Commands.cpp @@ -6,6 +6,8 @@ #include "Utils/BitConverter.h" #include "Utils/StringHelper.h" +#include "ZCutscene.h" + /**** GENERIC ****/ // Specific for command lists where each entry has size 0x30 bytes @@ -13,7 +15,7 @@ const std::unordered_map csCom {CutsceneOoT_CommandType::CS_CMD_MISC, {"CS_MISC", "(%s, %i, %i, %i, %i, %i, %i, %i, %i, %i, %i, %i, %i, %i)"}}, {CutsceneOoT_CommandType::CS_CMD_LIGHT_SETTING, - {"CS_LIGHT_SETTING", "(0x%02X, %i, %i, %i, %i, %i, %i, %i, %i, %i, %i)"}}, + {"CS_LIGHT_SETTING", "(0x%02X, %i, %i, %i, %i, %i, %i, %i, %i, %i, %i, %i, %i, %i)"}}, {CutsceneOoT_CommandType::CS_CMD_START_SEQ, {"CS_START_SEQ", "(%s, %i, %i, %i, %i, %i, %i, %i, %i, %i, %i)"}}, {CutsceneOoT_CommandType::CS_CMD_STOP_SEQ, @@ -139,9 +141,11 @@ std::string CutsceneOoTCommand_CameraPoint::GetBodySourceCode() const if (continueFlag != 0) continueMacro = "CS_CAM_STOP"; - return StringHelper::Sprintf("CS_CAM_POINT(%s, 0x%02X, %i, %ff, %i, %i, %i, 0x%04X)", - continueMacro.c_str(), cameraRoll, nextPointFrame, viewAngle, posX, - posY, posZ, unused); + return StringHelper::Sprintf( + "CS_CAM_POINT(%s, 0x%02X, %i, %s, %i, %i, %i, 0x%04X)", continueMacro.c_str(), cameraRoll, + nextPointFrame, + ZCutscene::GetCsEncodedFloat(viewAngle, Globals::Instance->floatType, false).c_str(), posX, + posY, posZ, unused); } size_t CutsceneOoTCommand_CameraPoint::GetRawSize() const @@ -334,27 +338,34 @@ CutsceneOoTSubCommandEntry_ActorCue::CutsceneOoTSubCommandEntry_ActorCue( normalY = BitConverter::ToFloatBE(rawData, rawDataIndex + 0x28); normalZ = BitConverter::ToFloatBE(rawData, rawDataIndex + 0x2C); } - std::string CutsceneOoTSubCommandEntry_ActorCue::GetBodySourceCode() const { EnumData* enumData = &Globals::Instance->cfg.enumData; + std::string normalXStr = + ZCutscene::GetCsEncodedFloat(normalX, Globals::Instance->floatType, true); + std::string normalYStr = + ZCutscene::GetCsEncodedFloat(normalY, Globals::Instance->floatType, true); + std::string normalZStr = + ZCutscene::GetCsEncodedFloat(normalZ, Globals::Instance->floatType, true); + if (static_cast(commandID) == CutsceneOoT_CommandType::CS_CMD_PLAYER_CUE) { return StringHelper::Sprintf("CS_PLAYER_CUE(%s, %i, %i, 0x%04X, 0x%04X, 0x%04X, %i, %i, " - "%i, %i, %i, %i, %.8ef, %.8ef, %.8ef)", + "%i, %i, %i, %i, %s, %s, %s)", enumData->playerCueId[base].c_str(), startFrame, endFrame, rotX, rotY, rotZ, startPosX, startPosY, startPosZ, endPosX, - endPosY, endPosZ, normalX, normalY, normalZ); + endPosY, endPosZ, normalXStr.c_str(), normalYStr.c_str(), + normalZStr.c_str()); } else { return StringHelper::Sprintf("CS_ACTOR_CUE(%i, %i, %i, 0x%04X, 0x%04X, 0x%04X, %i, %i, " - "%i, %i, %i, %i, %.8ef, %.8ef, %.8ef)", + "%i, %i, %i, %i, %s, %s, %s)", base, startFrame, endFrame, rotX, rotY, rotZ, startPosX, - startPosY, startPosZ, endPosX, endPosY, endPosZ, normalX, - normalY, normalZ); + startPosY, startPosZ, endPosX, endPosY, endPosZ, + normalXStr.c_str(), normalYStr.c_str(), normalZStr.c_str()); } } diff --git a/tools/ZAPD/ZAPD/ZAPD.vcxproj b/tools/ZAPD/ZAPD/ZAPD.vcxproj index 22bc720e9d..26a0b70363 100644 --- a/tools/ZAPD/ZAPD/ZAPD.vcxproj +++ b/tools/ZAPD/ZAPD/ZAPD.vcxproj @@ -45,6 +45,7 @@ true v142 MultiByte + false Application @@ -52,6 +53,7 @@ v142 true MultiByte + false @@ -194,6 +196,8 @@ mkdir build\ZAPD + + @@ -289,6 +293,8 @@ mkdir build\ZAPD + + diff --git a/tools/ZAPD/ZAPD/ZAPD.vcxproj.filters b/tools/ZAPD/ZAPD/ZAPD.vcxproj.filters index f693a749d2..51723306b4 100644 --- a/tools/ZAPD/ZAPD/ZAPD.vcxproj.filters +++ b/tools/ZAPD/ZAPD/ZAPD.vcxproj.filters @@ -300,6 +300,12 @@ Source Files\Z64\ZRoom\Commands + + Source Files\Z64 + + + Source Files\Z64 + @@ -575,6 +581,12 @@ Header Files\Z64\ZRoom\Commands + + Header Files\Z64 + + + Header Files\Z64 + diff --git a/tools/ZAPD/ZAPD/ZCKeyFrame.cpp b/tools/ZAPD/ZAPD/ZCKeyFrame.cpp new file mode 100644 index 0000000000..3893394f5c --- /dev/null +++ b/tools/ZAPD/ZAPD/ZCKeyFrame.cpp @@ -0,0 +1,312 @@ +#include "ZCKeyFrame.h" + +#include "Globals.h" +#include "Utils/BitConverter.h" +#include "Utils/StringHelper.h" +#include "WarningHandler.h" + +REGISTER_ZFILENODE(KeyFrameSkel, ZKeyFrameSkel); +REGISTER_ZFILENODE(KeyFrameLimbList, ZKeyFrameLimbList); + +ZKeyFrameSkel::ZKeyFrameSkel(ZFile* nParent) : ZResource(nParent) +{ + RegisterRequiredAttribute("LimbType"); +} + +ZKeyFrameSkel::~ZKeyFrameSkel() +{ +} + +ZKeyFrameLimb::ZKeyFrameLimb(ZFile* nParent) : ZResource(nParent) +{ +} + +ZKeyFrameStandardLimb::ZKeyFrameStandardLimb(ZFile* nParent) : ZKeyFrameLimb(nParent) +{ +} + +ZKeyFrameFlexLimb::ZKeyFrameFlexLimb(ZFile* nParent) : ZKeyFrameLimb(nParent) +{ +} + +ZKeyFrameLimbList::ZKeyFrameLimbList(ZFile* nParent) : ZResource(nParent) +{ + RegisterRequiredAttribute("LimbType"); + RegisterRequiredAttribute("LimbCount"); +} + +ZKeyFrameLimbList::ZKeyFrameLimbList(ZFile* nParent, uint32_t limbCount, ZKeyframeSkelType type) + : ZResource(nParent) +{ + numLimbs = limbCount; + limbType = type; +} + +ZKeyFrameLimbList::~ZKeyFrameLimbList() +{ + for (const auto l : limbs) + delete l; +} + +void ZKeyFrameSkel::ParseXML(tinyxml2::XMLElement* reader) +{ + ZResource::ParseXML(reader); + + std::string limbTypeStr = registeredAttributes.at("LimbType").value; + + limbType = ZKeyFrameLimbList::ParseLimbTypeStr(limbTypeStr); + if (limbType == ZKeyframeSkelType::Error) + HANDLE_ERROR_RESOURCE( + WarningType::InvalidXML, parent, this, rawDataIndex, "Invalid limb type", + StringHelper::Sprintf("Invalid limb type. Was expecting 'Flex' or 'Normal'. Got %s.", + limbTypeStr.c_str())); +} +void ZKeyFrameLimbList::ParseXML(tinyxml2::XMLElement* reader) +{ + ZResource::ParseXML(reader); + + std::string limbTypeStr = registeredAttributes.at("LimbType").value; + std::string numLimbStr = registeredAttributes.at("LimbCount").value; + + limbType = ParseLimbTypeStr(limbTypeStr); + + if (limbType == ZKeyframeSkelType::Error) + HANDLE_ERROR_RESOURCE( + WarningType::InvalidXML, parent, this, rawDataIndex, "Invalid limb type", + StringHelper::Sprintf("Invalid limb type. Was expecting 'Flex' or 'Normal'. Got %s.", + limbTypeStr.c_str())); + + numLimbs = (uint8_t)StringHelper::StrToL(numLimbStr); +} + +void ZKeyFrameSkel::ParseRawData() +{ + ZResource::ParseRawData(); + + const auto& rawData = parent->GetRawData(); + limbCount = BitConverter::ToUInt8BE(rawData, rawDataIndex + 0); + dListCount = BitConverter::ToUInt8BE(rawData, rawDataIndex + 1); + limbsPtr = BitConverter::ToUInt32BE(rawData, rawDataIndex + 4); + + limbList = std::make_unique(parent, limbCount, limbType); + limbList->SetRawDataIndex(GETSEGOFFSET(limbsPtr)); + limbList->ParseRawData(); +} + +void ZKeyFrameSkel::DeclareReferences(const std::string& prefix) +{ + std::string defaultPrefix = name; + std::string declaration; + + if (defaultPrefix == "") + defaultPrefix = prefix; + + ZResource::DeclareReferences(defaultPrefix); + declaration += limbList->GetBodySourceCode(); + parent->AddDeclarationArray( + GETSEGOFFSET(limbsPtr), DeclarationAlignment::Align4, limbList->GetRawDataSize(), + limbList->GetSourceTypeName(), + StringHelper::Sprintf("%s_KeyFrameLimbs_%06X", prefix.c_str(), rawDataIndex), + limbList->limbs.size(), declaration); +} + +std::string ZKeyFrameSkel::GetBodySourceCode() const +{ + std::string limbStr; + + if (limbType == ZKeyframeSkelType::Normal) + Globals::Instance->GetSegmentedPtrName(limbsPtr, parent, "KeyFrameStandardLimb", limbStr); + else + Globals::Instance->GetSegmentedPtrName(limbsPtr, parent, "KeyFrameFlexLimb", limbStr); + + return StringHelper::Sprintf("\n\t0x%02X, 0x%02X, %s\n", limbCount, dListCount, + limbStr.c_str()); +} + +size_t ZKeyFrameSkel::GetRawDataSize() const +{ + return 0x8; +} + +std::string ZKeyFrameSkel::GetSourceTypeName() const +{ + switch (limbType) + { + case ZKeyframeSkelType::Normal: + return "KeyFrameSkeleton"; + + case ZKeyframeSkelType::Flex: + return "KeyFrameFlexSkeleton"; + + default: + return "KeyFrameSkeleton"; + } +} + +ZResourceType ZKeyFrameSkel::GetResourceType() const +{ + return ZResourceType::KeyFrameSkel; +} + +size_t ZKeyFrameStandardLimb::GetRawDataSize() const +{ + return 0xC; +} + +size_t ZKeyFrameFlexLimb::GetRawDataSize() const +{ + return 0x8; +} + +size_t ZKeyFrameLimbList::GetRawDataSize() const +{ + size_t limbSize; + if (limbType == ZKeyframeSkelType::Flex) + limbSize = 0x8; + else + limbSize = 0xC; + + return limbSize * numLimbs; +} + +ZKeyframeSkelType ZKeyFrameLimbList::ParseLimbTypeStr(const std::string& typeStr) +{ + if (typeStr == "Flex") + return ZKeyframeSkelType::Flex; + else if (typeStr == "Normal") + return ZKeyframeSkelType::Normal; + else + return ZKeyframeSkelType::Error; +} + +void ZKeyFrameLimb::ParseRawData() +{ + const auto& rawData = parent->GetRawData(); + + dlist = BitConverter::ToUInt32BE(rawData, rawDataIndex + 0x0); + numChildren = BitConverter::ToUInt8BE(rawData, rawDataIndex + 0x4); + flags = BitConverter::ToUInt8BE(rawData, rawDataIndex + 0x5); +} + +void ZKeyFrameStandardLimb::ParseRawData() +{ + const auto& rawData = parent->GetRawData(); + + ZKeyFrameLimb::ParseRawData(); + translation.x = BitConverter::ToUInt16BE(rawData, rawDataIndex + 0x6); + translation.y = BitConverter::ToUInt16BE(rawData, rawDataIndex + 0x8); + translation.z = BitConverter::ToUInt16BE(rawData, rawDataIndex + 0xA); +} + +void ZKeyFrameFlexLimb::ParseRawData() +{ + const auto& rawData = parent->GetRawData(); + + ZKeyFrameLimb::ParseRawData(); + callbackIndex = BitConverter::ToUInt8BE(rawData, rawDataIndex + 0x6); +} + +void ZKeyFrameLimbList::ParseRawData() +{ + limbs.reserve(numLimbs); + rawDataIndex = GetRawDataIndex(); + + for (uint32_t i = 0; i < numLimbs; i++) + { + ZKeyFrameLimb* limb; + if (limbType == ZKeyframeSkelType::Flex) + limb = new ZKeyFrameFlexLimb(parent); + else + limb = new ZKeyFrameStandardLimb(parent); + + limb->SetRawDataIndex(rawDataIndex + (offset_t)(i * limb->GetRawDataSize())); + limb->ParseRawData(); + limbs.push_back(limb); + } +} + +std::string ZKeyFrameLimbList::GetBodySourceCode() const +{ + std::string declaration; + + for (const auto l : limbs) + declaration += StringHelper::Sprintf("\t{ %s },\n", l->GetBodySourceCode().c_str()); + // Remove last newline + return declaration.substr(0, declaration.length() - 1); +} + +std::string ZKeyFrameStandardLimb::GetBodySourceCode() const +{ + std::string declaration; + std::string dlString; + + Globals::Instance->GetSegmentedArrayIndexedName(dlist, 8, parent, "Gfx", dlString); + + declaration += + StringHelper::Sprintf("%s, 0x%02X, 0x%02X, { 0x%04X, 0x%04X, 0x%04X},", dlString.c_str(), + numChildren, flags, translation.x, translation.y, translation.z); + return declaration; +} + +std::string ZKeyFrameFlexLimb::GetBodySourceCode() const +{ + std::string declaration; + + std::string dlString; + + Globals::Instance->GetSegmentedArrayIndexedName(dlist, 8, parent, "Gfx", dlString); + + declaration += StringHelper::Sprintf("%s, 0x%02X, 0x%02X, 0x%02X", dlString.c_str(), + numChildren, flags, callbackIndex); + return declaration; +} + +std::string ZKeyFrameStandardLimb::GetSourceTypeName() const +{ + return "KeyFrameStandardLimb"; +} + +std::string ZKeyFrameFlexLimb::GetSourceTypeName() const +{ + return "KeyFrameFlexLimb"; +} + +std::string ZKeyFrameLimbList::GetSourceTypeName() const +{ + switch (limbType) + { + case ZKeyframeSkelType::Flex: + return "KeyFrameFlexLimb"; + case ZKeyframeSkelType::Normal: + return "KeyFrameStandardLimb"; + default: + HANDLE_ERROR_RESOURCE(WarningType::InvalidXML, parent, this, rawDataIndex, + "Invalid limb type", ""); + break; + } +} + +ZResourceType ZKeyFrameStandardLimb::GetResourceType() const +{ + return ZResourceType::KeyFrameStandardLimb; +} + +ZResourceType ZKeyFrameFlexLimb::GetResourceType() const +{ + return ZResourceType::KeyFrameFlexLimb; +} + +ZResourceType ZKeyFrameLimbList::GetResourceType() const +{ + switch (limbType) + { + case ZKeyframeSkelType::Flex: + return ZResourceType::KeyFrameFlexLimb; + case ZKeyframeSkelType::Normal: + return ZResourceType::KeyFrameStandardLimb; + default: + HANDLE_ERROR_RESOURCE(WarningType::InvalidXML, parent, this, rawDataIndex, + "Invalid limb type", ""); + break; + } +} diff --git a/tools/ZAPD/ZAPD/ZCKeyFrame.h b/tools/ZAPD/ZAPD/ZCKeyFrame.h new file mode 100644 index 0000000000..417d7cc686 --- /dev/null +++ b/tools/ZAPD/ZAPD/ZCKeyFrame.h @@ -0,0 +1,121 @@ +#pragma once + +#include +#include +#include +#include + +#include "ZFile.h" + +class ZKeyFrameLimb; + +struct Vec3s +{ + int16_t x; + int16_t y; + int16_t z; +}; + +enum class ZKeyframeSkelType +{ + Normal, + Flex, + Error, +}; + +class ZKeyFrameLimbList : public ZResource +{ +public: + ZKeyFrameLimbList(); + ZKeyFrameLimbList(ZFile* nParent); + ZKeyFrameLimbList(ZFile* nParent, uint32_t limbCount, ZKeyframeSkelType type); + + ~ZKeyFrameLimbList(); + + void ParseRawData() override; + + std::string GetBodySourceCode() const override; + void ParseXML(tinyxml2::XMLElement* reader) override; + + std::string GetSourceTypeName() const override; + ZResourceType GetResourceType() const override; + + size_t GetRawDataSize() const override; + + static ZKeyframeSkelType ParseLimbTypeStr(const std::string& typeStr); + + std::vector limbs; + ZKeyframeSkelType limbType; + uint8_t numLimbs; +}; + +class ZKeyFrameLimb : public ZResource +{ +public: + segptr_t dlist; + uint8_t numChildren; + uint8_t flags; + + ZKeyFrameLimb(ZFile* nParent); + void ParseRawData() override; +}; + +class ZKeyFrameStandardLimb : public ZKeyFrameLimb +{ +public: + Vec3s translation; + + ZKeyFrameStandardLimb(ZFile* nParent); + void ParseRawData() override; + + std::string GetBodySourceCode() const override; + + + std::string GetSourceTypeName() const override; + ZResourceType GetResourceType() const override; + + size_t GetRawDataSize() const override; +}; + +class ZKeyFrameFlexLimb : public ZKeyFrameLimb +{ +public: + uint8_t callbackIndex; + + ZKeyFrameFlexLimb(ZFile* nParent); + // void ParseXML(tinyxml2::XMLElement* reader) override; + void ParseRawData() override; + + std::string GetBodySourceCode() const override; + + // std::string GetSourceOutputHeader(const std::string& prefix) override; + + std::string GetSourceTypeName() const override; + ZResourceType GetResourceType() const override; + + size_t GetRawDataSize() const override; +}; + +class ZKeyFrameSkel : public ZResource +{ +public: + std::unique_ptr limbList; + segptr_t limbsPtr; + ZKeyframeSkelType limbType; + uint8_t limbCount; + uint8_t dListCount; + + ZKeyFrameSkel(ZFile* nParent); + ~ZKeyFrameSkel(); + + void ParseXML(tinyxml2::XMLElement* reader) override; + void ParseRawData() override; + void DeclareReferences(const std::string& prefix) override; + + std::string GetBodySourceCode() const override; + + std::string GetSourceTypeName() const override; + ZResourceType GetResourceType() const override; + + size_t GetRawDataSize() const override; +}; diff --git a/tools/ZAPD/ZAPD/ZCKeyFrameAnim.cpp b/tools/ZAPD/ZAPD/ZCKeyFrameAnim.cpp new file mode 100644 index 0000000000..0b07471333 --- /dev/null +++ b/tools/ZAPD/ZAPD/ZCKeyFrameAnim.cpp @@ -0,0 +1,219 @@ +#include "ZCkeyFrameAnim.h" +#include "ZCKeyFrame.h" +#include "Globals.h" + +#include "Utils/BitConverter.h" + +REGISTER_ZFILENODE(KeyFrameAnimation, ZKeyFrameAnim); + +ZKeyFrameAnim::ZKeyFrameAnim(ZFile* nParent) : ZResource(nParent) +{ + RegisterRequiredAttribute("Skel"); +} + +ZKeyFrameAnim::~ZKeyFrameAnim() +{ +} + +void ZKeyFrameAnim::ParseXML(tinyxml2::XMLElement* reader) +{ + ZResource::ParseXML(reader); + + std::string skelAddrStr = registeredAttributes.at("Skel").value; + skelOffset = (offset_t)StringHelper::StrToL(skelAddrStr, 16); +} + +void ZKeyFrameAnim::DeclareReferencesLate(const std::string& prefix) +{ + std::string defaultPrefix = name; + std::string declaration; + + if (defaultPrefix == "") + defaultPrefix = prefix; + + ZResource::DeclareReferences(defaultPrefix); + + declaration += "\t"; + + if (skel->limbType == ZKeyframeSkelType::Normal) + { + for (const auto b : bitFlags) + { + declaration += StringHelper::Sprintf("0x%02X, ", b); + parent->AddDeclarationArray( + GETSEGOFFSET(bitFlagsAddr), DeclarationAlignment::Align4, bitFlags.size(), "u8", + StringHelper::Sprintf("%s_bitFlags_%06X", prefix.c_str(), rawDataIndex), + bitFlags.size(), declaration); + } + } + else + { + for (const auto b : bitFlagsFlex) + { + declaration += StringHelper::Sprintf("0x%04X, ", b); + parent->AddDeclarationArray( + GETSEGOFFSET(bitFlagsAddr), DeclarationAlignment::Align4, bitFlagsFlex.size() * 2, + "u16", StringHelper::Sprintf("%s_flexBitFlags_%06X", prefix.c_str(), rawDataIndex), + bitFlagsFlex.size(), declaration); + } + } + declaration.clear(); + + for (const auto kf : keyFrames) + { + declaration += + StringHelper::Sprintf(" \t { %i, %i, %i, },\n", kf.frame, kf.value, kf.velocity); + } + // Remove last new line to prevent an extra line after the last element + declaration = declaration.substr(0, declaration.length() - 1); + parent->AddDeclarationArray( + GETSEGOFFSET(keyFramesAddr), DeclarationAlignment::Align4, keyFrames.size() * 6, "KeyFrame", + StringHelper::Sprintf("%s_KeyFrame_%06X", prefix.c_str(), rawDataIndex), keyFrames.size(), + declaration); + + declaration.clear(); + + declaration += "\t"; + + for (const auto kfNum : kfNums) + { + declaration += StringHelper::Sprintf("0x%04X, ", kfNum); + } + + parent->AddDeclarationArray( + GETSEGOFFSET(kfNumsAddr), DeclarationAlignment::Align4, kfNums.size() * 2, "s16", + StringHelper::Sprintf("%s_kfNums_%06X", prefix.c_str(), rawDataIndex), kfNums.size(), + declaration); + declaration += "\n"; + + declaration.clear(); + + declaration += "\t"; + + for (const auto pv : presetValues) + { + declaration += StringHelper::Sprintf("0x%04X, ", pv); + } + declaration += "\n"; + parent->AddDeclarationArray( + GETSEGOFFSET(presentValuesAddr), DeclarationAlignment::Align4, presetValues.size() * 2, + "s16", StringHelper::Sprintf("%s_presetValues_%06X", prefix.c_str(), rawDataIndex), + presetValues.size(), declaration); + +} + +// ParseRawDataLate is used because we need to make sure the flex skel has been processed first. +void ZKeyFrameAnim::ParseRawDataLate() +{ + const auto& rawData = parent->GetRawData(); + + skel = static_cast(parent->FindResource(skelOffset)); + size_t numLimbs = skel->limbCount; + + bitFlagsAddr = BitConverter::ToUInt32BE(rawData, rawDataIndex + 0x0); + keyFramesAddr = BitConverter::ToUInt32BE(rawData, rawDataIndex + 0x4); + kfNumsAddr = BitConverter::ToUInt32BE(rawData, rawDataIndex + 0x8); + presentValuesAddr = BitConverter::ToUInt32BE(rawData, rawDataIndex + 0xC); + + uint32_t kfNumsSize = 0; + uint32_t presetValuesSize = 0; + uint32_t keyFramesCount = 0; + if (skel->limbType == ZKeyframeSkelType::Normal) + { + bitFlags.reserve(numLimbs); + for (size_t i = 0; i < numLimbs; i++) + { + uint8_t e = BitConverter::ToUInt8BE(rawData, GETSEGOFFSET(bitFlagsAddr) + i); + bitFlags.push_back(e); + kfNumsSize += GetSetBits((uint8_t)(e & 0b111111)); + presetValuesSize += GetSetBits((uint8_t)((e ^ 0xFF) & 0b111111)); + } + } + else + { + bitFlagsFlex.reserve(numLimbs); + for (size_t i = 0; i < numLimbs; i++) + { + uint16_t e = BitConverter::ToUInt16BE(rawData, GETSEGOFFSET(bitFlagsAddr) + (i * 2)); + bitFlagsFlex.push_back(e); + kfNumsSize += GetSetBits((uint16_t)(e & 0b111111111)); + presetValuesSize += GetSetBits((uint16_t)((e ^ 0xFFFF) & 0b111111111)); + } + } + + kfNums.reserve(kfNumsSize); + for (uint32_t i = 0; i < kfNumsSize; i++) + { + int16_t kfNum = BitConverter::ToUInt16BE(rawData, GETSEGOFFSET(kfNumsAddr) + (i * 2)); + keyFramesCount += kfNum; + kfNums.push_back(kfNum); + } + + keyFrames.reserve(keyFramesCount); + for (uint32_t i = 0; i < keyFramesCount; i++) + { + KeyFrame kf; + kf.frame = BitConverter::ToInt16BE(rawData, (GETSEGOFFSET(keyFramesAddr) + 0) + (i * 6)); + kf.value = BitConverter::ToInt16BE(rawData, (GETSEGOFFSET(keyFramesAddr) + 2) + (i * 6)); + kf.velocity = BitConverter::ToInt16BE(rawData, (GETSEGOFFSET(keyFramesAddr) + 4) + (i * 6)); + keyFrames.push_back(kf); + } + + presetValues.reserve(presetValuesSize); + for (uint32_t i = 0; i < presetValuesSize; i++) + { + presetValues.push_back( + BitConverter::ToInt16BE(rawData, GETSEGOFFSET(presentValuesAddr) + (i * 2))); + } + + unk_10 = BitConverter::ToInt16BE(rawData, GETSEGOFFSET(rawDataIndex) + 0x10); + duration = BitConverter::ToInt16BE(rawData, GETSEGOFFSET(rawDataIndex) + 0x12); +} + +std::string ZKeyFrameAnim::GetBodySourceCode() const +{ + std::string declaration; + + std::string bitFlagsStr; + std::string keyFrameStr; + std::string kfNumsStr; + std::string presetValuesStr; + + Globals::Instance->GetSegmentedPtrName(bitFlagsAddr, parent, "", bitFlagsStr); + Globals::Instance->GetSegmentedPtrName(keyFramesAddr, parent, "", keyFrameStr); + Globals::Instance->GetSegmentedPtrName(kfNumsAddr, parent, "", kfNumsStr); + Globals::Instance->GetSegmentedPtrName(presentValuesAddr, parent, "", presetValuesStr); + + return StringHelper::Sprintf("\n\t%s, %s, %s, %s, 0x%04X, 0x%04X\n", bitFlagsStr.c_str(), + keyFrameStr.c_str(), kfNumsStr.c_str(), presetValuesStr.c_str(), + unk_10, duration); +} + +std::string ZKeyFrameAnim::GetSourceTypeName() const +{ + return "KeyFrameAnimation"; +} + +ZResourceType ZKeyFrameAnim::GetResourceType() const +{ + return ZResourceType::KeyFrameAnimation; +} + +size_t ZKeyFrameAnim::GetRawDataSize() const +{ + return 0x14; +} + +template +uint32_t ZKeyFrameAnim::GetSetBits(T data) const +{ + uint32_t num = 0; + + for (size_t i = 0; i < sizeof(T) * 8; i++) + { + if ((data >> i) & 1) + num++; + } + + return num; +} \ No newline at end of file diff --git a/tools/ZAPD/ZAPD/ZCkeyFrameAnim.h b/tools/ZAPD/ZAPD/ZCkeyFrameAnim.h new file mode 100644 index 0000000000..64f95b13ae --- /dev/null +++ b/tools/ZAPD/ZAPD/ZCkeyFrameAnim.h @@ -0,0 +1,52 @@ +#pragma once +#include +#include +#include +#include + +#include "ZFile.h" + +class ZKeyFrameSkel; + +typedef struct +{ + int16_t frame; + int16_t value; + int16_t velocity; +} KeyFrame; + +class ZKeyFrameAnim : public ZResource +{ +public: + ZKeyFrameSkel* skel; + std::vector bitFlags; // Standard only + std::vector bitFlagsFlex; // Flex only + + std::vector keyFrames; + std::vector kfNums; + std::vector presetValues; + + uint16_t unk_10; + int16_t duration; + + ZKeyFrameAnim(ZFile* nParent); + ~ZKeyFrameAnim(); + void ParseXML(tinyxml2::XMLElement* reader) override; + void DeclareReferencesLate(const std::string& prefix) override; + void ParseRawDataLate() override; + std::string GetBodySourceCode() const override; + + std::string GetSourceTypeName() const override; + ZResourceType GetResourceType() const override; + + size_t GetRawDataSize() const override; + +private: + offset_t skelOffset; + segptr_t bitFlagsAddr; + segptr_t keyFramesAddr; + segptr_t kfNumsAddr; + segptr_t presentValuesAddr; + template + uint32_t GetSetBits(T data) const; +}; diff --git a/tools/ZAPD/ZAPD/ZCutscene.cpp b/tools/ZAPD/ZAPD/ZCutscene.cpp index b90fb872d6..7ae431ebab 100644 --- a/tools/ZAPD/ZAPD/ZCutscene.cpp +++ b/tools/ZAPD/ZAPD/ZCutscene.cpp @@ -24,7 +24,7 @@ std::string ZCutscene::GetBodySourceCode() const { std::string output = ""; - output += StringHelper::Sprintf(" CS_BEGIN_CUTSCENE(%i, %i),\n", commands.size(), endFrame); + output += StringHelper::Sprintf(" CS_BEGIN_CUTSCENE(%i, %i),\n", numCommands, endFrame); for (size_t i = 0; i < commands.size(); i++) { @@ -32,7 +32,7 @@ std::string ZCutscene::GetBodySourceCode() const output += " " + cmd->GenerateSourceCode(); } - output += StringHelper::Sprintf(" CS_END(),", commands.size(), endFrame); + output += StringHelper::Sprintf(" CS_END(),"); return output; } @@ -372,3 +372,25 @@ ZResourceType ZCutscene::GetResourceType() const { return ZResourceType::Cutscene; } + +std::string ZCutscene::GetCsEncodedFloat(float f, CsFloatType type, bool useSciNotation) +{ + uint32_t i; + std::memcpy(&i, &f, sizeof(i)); + + switch (type) + { + default: + // This default case will NEVER be reached, but GCC still gives a warning. + case CsFloatType::HexOnly: + return StringHelper::Sprintf("0x%08X", i); + case CsFloatType::FloatOnly: + return StringHelper::Sprintf(useSciNotation ? "%.8ef" : "%ff", f); + case CsFloatType::HexAndFloat: + return StringHelper::Sprintf(useSciNotation ? "CS_FLOAT(0x%08X, %.8ef)" : "CS_FLOAT(0x%08X, %ff)", i, f); + case CsFloatType::HexAndCommentedFloatLeft: + return StringHelper::Sprintf(useSciNotation ? "/* %.8ef */ 0x%08X" : "/* %ff */ 0x%08X", f, i); + case CsFloatType::HexAndCommentedFloatRight: + return StringHelper::Sprintf(useSciNotation ? "0x%08X /* %.8ef */" : "0x%08X /* %ff */", i, f); + } +} diff --git a/tools/ZAPD/ZAPD/ZCutscene.h b/tools/ZAPD/ZAPD/ZCutscene.h index 5b54426cea..5dbf475c33 100644 --- a/tools/ZAPD/ZAPD/ZCutscene.h +++ b/tools/ZAPD/ZAPD/ZCutscene.h @@ -10,6 +10,8 @@ #include "ZFile.h" #include "ZResource.h" +enum class CsFloatType; + class ZCutscene : public ZResource { public: @@ -27,6 +29,8 @@ public: std::string GetSourceTypeName() const override; ZResourceType GetResourceType() const override; + static std::string GetCsEncodedFloat(float f, CsFloatType type, bool useSciNotation); + int32_t numCommands; int32_t endFrame; std::vector commands; diff --git a/tools/ZAPD/ZAPD/ZFile.cpp b/tools/ZAPD/ZAPD/ZFile.cpp index 0b2a4d631c..db2d251a5c 100644 --- a/tools/ZAPD/ZAPD/ZFile.cpp +++ b/tools/ZAPD/ZAPD/ZFile.cpp @@ -120,6 +120,9 @@ void ZFile::ParseXML(tinyxml2::XMLElement* reader, const std::string& filename) if (reader->Attribute("BaseAddress") != nullptr) baseAddress = StringHelper::StrToL(reader->Attribute("BaseAddress"), 16); + if (mode == ZFileMode::Extract && Globals::Instance->baseAddress != -1) + baseAddress = Globals::Instance->baseAddress; + if (reader->Attribute("RangeStart") != nullptr) rangeStart = StringHelper::StrToL(reader->Attribute("RangeStart"), 16); @@ -197,6 +200,9 @@ void ZFile::ParseXML(tinyxml2::XMLElement* reader, const std::string& filename) } rawData = File::ReadAllBytes((basePath / name).string()); + if (mode == ZFileMode::Extract && Globals::Instance->startOffset != -1 && Globals::Instance->endOffset != -1) + rawData = std::vector(rawData.begin() + Globals::Instance->startOffset, + rawData.begin() + Globals::Instance->endOffset); if (reader->Attribute("RangeEnd") == nullptr) rangeEnd = rawData.size(); @@ -585,6 +591,12 @@ Declaration* ZFile::AddDeclarationIncludeArray(offset_t address, std::string& in includePath = "assets/" + StringHelper::Split(includePath, "assets/extracted/")[1]; if (StringHelper::StartsWith(includePath, "assets/custom/")) includePath = "assets/" + StringHelper::Split(includePath, "assets/custom/")[1]; + // Hack for OOT: don't prefix include paths with extracted/VERSION/ + if (StringHelper::StartsWith(includePath, "extracted/")) { + std::vector parts = StringHelper::Split(includePath, "/"); + parts.erase(parts.begin(), parts.begin() + 2); + includePath = StringHelper::Join(parts, "/"); + } Declaration* decl = GetDeclaration(address); if (decl == nullptr) @@ -621,6 +633,12 @@ Declaration* ZFile::AddDeclarationIncludeArray(offset_t address, std::string& in includePath = "assets/" + StringHelper::Split(includePath, "assets/extracted/")[1]; if (StringHelper::StartsWith(includePath, "assets/custom/")) includePath = "assets/" + StringHelper::Split(includePath, "assets/custom/")[1]; + // Hack for OOT: don't prefix include paths with extracted/VERSION/ + if (StringHelper::StartsWith(includePath, "extracted/")) { + std::vector parts = StringHelper::Split(includePath, "/"); + parts.erase(parts.begin(), parts.begin() + 2); + includePath = StringHelper::Join(parts, "/"); + } Declaration* decl = GetDeclaration(address); if (decl == nullptr) diff --git a/tools/ZAPD/ZAPD/ZResource.h b/tools/ZAPD/ZAPD/ZResource.h index 9754013984..768b785441 100644 --- a/tools/ZAPD/ZAPD/ZResource.h +++ b/tools/ZAPD/ZAPD/ZResource.h @@ -55,6 +55,10 @@ enum class ZResourceType Vector, Vertex, Waterbox, + KeyFrameFlexLimb, + KeyFrameStandardLimb, + KeyFrameSkel, + KeyFrameAnimation, }; class ResourceAttribute diff --git a/tools/ZAPD/ZAPDUtils/Utils/StringHelper.h b/tools/ZAPD/ZAPDUtils/Utils/StringHelper.h index c4e012eb06..942d0bcc9e 100644 --- a/tools/ZAPD/ZAPDUtils/Utils/StringHelper.h +++ b/tools/ZAPD/ZAPDUtils/Utils/StringHelper.h @@ -30,6 +30,21 @@ public: return result; } + static std::string Join(const std::vector parts, const std::string& delimiter) + { + std::string result; + + for (size_t i = 0; i < parts.size(); i++) + { + result += parts[i]; + + if (i != parts.size() - 1) + result += delimiter; + } + + return result; + } + static std::string Strip(std::string s, const std::string& delimiter) { size_t pos = 0;