summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlouist103 <35883445+louist103@users.noreply.github.com>2024-01-30 19:08:37 -0500
committerlouist103 <35883445+louist103@users.noreply.github.com>2024-01-30 19:08:37 -0500
commit1db7c31a7648939d47ec7957888ebebba0c86db2 (patch)
tree2aa058f22da8ee40c15fc515021c95da8c48f82c
parent1ac9c36e84faa2baaf2b4c2ec4b5085290e923ee (diff)
parentbd3e38a4e048c382d0cb3aba9a925cd2d8d5e3eb (diff)
conflict
-rw-r--r--.github/workflows/main.yml83
-rw-r--r--ZAPD/OtherStructs/CutsceneMM_Commands.cpp51
-rw-r--r--ZAPD/OtherStructs/CutsceneMM_Commands.h16
-rw-r--r--ZAPD/ZAPD.vcxproj6
-rw-r--r--ZAPD/ZAPD.vcxproj.filters12
-rw-r--r--ZAPD/ZCKeyFrame.cpp302
-rw-r--r--ZAPD/ZCKeyFrame.h121
-rw-r--r--ZAPD/ZCKeyFrameAnim.cpp219
-rw-r--r--ZAPD/ZCkeyFrameAnim.h52
-rw-r--r--ZAPD/ZResource.h4
10 files changed, 840 insertions, 26 deletions
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
new file mode 100644
index 0000000..4c35dfa
--- /dev/null
+++ b/.github/workflows/main.yml
@@ -0,0 +1,83 @@
+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: |
+ git clone https://github.com/zeldaret/oot.git
+ cd oot
+ git submodule update --init --recursive
+
+ - name: Checkout mm
+ run: |
+ git clone https://github.com/zeldaret/mm.git
+ cd mm
+
+ - name: Set up repos
+ run: echo "Set up repos"
+
+ - name: Setup OOT
+ run: |
+ cd oot
+ mkdir -p baseroms/gc-eu-mq-dbg
+ cp ~/baserom_original.z64 ./baseroms/gc-eu-mq-dbg/baserom.z64
+ make venv
+ make -C tools -j
+ cp ../ZAPD.out tools/ZAPD/
+ .venv/bin/python3 tools/decompress_baserom.py gc-eu-mq-dbg
+ .venv/bin/python3 extract_baserom.py
+ .venv/bin/python3 extract_assets.py -j 4
+
+ - name: Install Python dependencies
+ run: |
+ cd mm
+ python3 -m venv .mm-env
+ source .mm-env/bin/activate
+ python3 -m pip install -r requirements.txt
+
+ - name: Setup MM
+ run: |
+ cd mm
+ cp ~/baserom.mm.us.rev1.z64 ./baserom.mm.us.rev1.z64
+ make -C tools -j
+ cp ../ZAPD.out tools/ZAPD/
+ 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 oot
+ make venv
+ make -j
+
+ - name: Build mm
+ run: |
+ cd mm
+ make -j disasm
+ make -j
+
+ - name: Clean workspace
+ run: git clean -fdX
diff --git a/ZAPD/OtherStructs/CutsceneMM_Commands.cpp b/ZAPD/OtherStructs/CutsceneMM_Commands.cpp
index e98cd8b..401e7d6 100644
--- a/ZAPD/OtherStructs/CutsceneMM_Commands.cpp
+++ b/ZAPD/OtherStructs/CutsceneMM_Commands.cpp
@@ -128,8 +128,9 @@ std::string CutsceneMMCommand_GenericCmd::GetCommandMacro() const
/**** CAMERA ****/
-CutsceneSubCommandEntry_SplineCamPoint::CutsceneSubCommandEntry_SplineCamPoint(const std::vector<uint8_t>& rawData,
- offset_t rawDataIndex): CutsceneSubCommandEntry(rawData, rawDataIndex)
+CutsceneSubCommandEntry_SplineCamPoint::CutsceneSubCommandEntry_SplineCamPoint(
+ const std::vector<uint8_t>& rawData, offset_t rawDataIndex)
+ : CutsceneSubCommandEntry(rawData, rawDataIndex)
{
interpType = BitConverter::ToUInt8BE(rawData, rawDataIndex + 0);
weight = BitConverter::ToUInt8BE(rawData, rawDataIndex + 1);
@@ -145,7 +146,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
@@ -153,9 +156,9 @@ size_t CutsceneSubCommandEntry_SplineCamPoint::GetRawSize() const
return 0x0C;
}
-
-CutsceneSubCommandEntry_SplineMiscPoint::CutsceneSubCommandEntry_SplineMiscPoint(const std::vector<uint8_t>& rawData,
- offset_t rawDataIndex): CutsceneSubCommandEntry(rawData, rawDataIndex)
+CutsceneSubCommandEntry_SplineMiscPoint::CutsceneSubCommandEntry_SplineMiscPoint(
+ const std::vector<uint8_t>& rawData, offset_t rawDataIndex)
+ : CutsceneSubCommandEntry(rawData, rawDataIndex)
{
unused0 = BitConverter::ToUInt16BE(rawData, rawDataIndex + 0);
roll = BitConverter::ToUInt16BE(rawData, rawDataIndex + 2);
@@ -165,7 +168,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
@@ -173,8 +177,9 @@ size_t CutsceneSubCommandEntry_SplineMiscPoint::GetRawSize() const
return 0x08;
}
-CutsceneSubCommandEntry_SplineHeader::CutsceneSubCommandEntry_SplineHeader(const std::vector<uint8_t>& rawData,
- offset_t rawDataIndex): CutsceneSubCommandEntry(rawData, rawDataIndex)
+CutsceneSubCommandEntry_SplineHeader::CutsceneSubCommandEntry_SplineHeader(
+ const std::vector<uint8_t>& rawData, offset_t rawDataIndex)
+ : CutsceneSubCommandEntry(rawData, rawDataIndex)
{
numEntries = BitConverter::ToUInt16BE(rawData, rawDataIndex + 0);
unused0 = BitConverter::ToUInt16BE(rawData, rawDataIndex + 2);
@@ -184,8 +189,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
@@ -193,16 +198,19 @@ size_t CutsceneSubCommandEntry_SplineHeader::GetRawSize() const
return 0x08;
}
-CutsceneSubCommandEntry_SplineFooter::CutsceneSubCommandEntry_SplineFooter(const std::vector<uint8_t>& rawData,
- offset_t rawDataIndex): CutsceneSubCommandEntry(rawData, rawDataIndex)
+CutsceneSubCommandEntry_SplineFooter::CutsceneSubCommandEntry_SplineFooter(
+ const std::vector<uint8_t>& 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));
}
}
@@ -224,8 +232,10 @@ CutsceneMMCommand_Spline::CutsceneMMCommand_Spline(const std::vector<uint8_t>& r
totalCommands = 0;
rawDataIndex += 4;
- while(1) {
- if (BitConverter::ToUInt16BE(rawData, rawDataIndex) == 0xFFFF) {
+ while (1)
+ {
+ if (BitConverter::ToUInt16BE(rawData, rawDataIndex) == 0xFFFF)
+ {
break;
}
numHeaders++;
@@ -233,7 +243,7 @@ CutsceneMMCommand_Spline::CutsceneMMCommand_Spline(const std::vector<uint8_t>& 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++)
@@ -270,7 +280,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;
}
diff --git a/ZAPD/OtherStructs/CutsceneMM_Commands.h b/ZAPD/OtherStructs/CutsceneMM_Commands.h
index 9891a24..597f678 100644
--- a/ZAPD/OtherStructs/CutsceneMM_Commands.h
+++ b/ZAPD/OtherStructs/CutsceneMM_Commands.h
@@ -282,7 +282,8 @@ public:
uint16_t posZ;
uint16_t relTo;
- CutsceneSubCommandEntry_SplineCamPoint(const std::vector<uint8_t>& rawData, offset_t rawDataIndex);
+ CutsceneSubCommandEntry_SplineCamPoint(const std::vector<uint8_t>& 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<uint8_t>& rawData, offset_t rawDataIndex);
+
+ CutsceneSubCommandEntry_SplineMiscPoint(const std::vector<uint8_t>& 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<uint8_t>& rawData, offset_t rawDataIndex);
+public:
+ CutsceneSubCommandEntry_SplineFooter(const std::vector<uint8_t>& 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<uint8_t>& rawData, offset_t rawDataIndex);
+ CutsceneSubCommandEntry_SplineHeader(const std::vector<uint8_t>& rawData,
+ offset_t rawDataIndex);
std::string GetBodySourceCode() const override;
diff --git a/ZAPD/ZAPD.vcxproj b/ZAPD/ZAPD.vcxproj
index 22bc720..26a0b70 100644
--- a/ZAPD/ZAPD.vcxproj
+++ b/ZAPD/ZAPD.vcxproj
@@ -45,6 +45,7 @@
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
+ <EnableASAN>false</EnableASAN>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
@@ -52,6 +53,7 @@
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
+ <EnableASAN>false</EnableASAN>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@@ -194,6 +196,8 @@ mkdir build\ZAPD
<ClCompile Include="ZActorList.cpp" />
<ClCompile Include="ZArray.cpp" />
<ClCompile Include="ZBackground.cpp" />
+ <ClCompile Include="ZCKeyFrame.cpp" />
+ <ClCompile Include="ZCKeyFrameAnim.cpp" />
<ClCompile Include="ZCollisionPoly.cpp" />
<ClCompile Include="ZLimb.cpp" />
<ClCompile Include="ZMtx.cpp" />
@@ -289,6 +293,8 @@ mkdir build\ZAPD
<ClInclude Include="ZArray.h" />
<ClInclude Include="ZBackground.h" />
<ClInclude Include="ZBlob.h" />
+ <ClInclude Include="ZCKeyFrame.h" />
+ <ClInclude Include="ZCkeyFrameAnim.h" />
<ClInclude Include="ZCollision.h" />
<ClInclude Include="ZCollisionPoly.h" />
<ClInclude Include="ZCutscene.h" />
diff --git a/ZAPD/ZAPD.vcxproj.filters b/ZAPD/ZAPD.vcxproj.filters
index f693a74..5172330 100644
--- a/ZAPD/ZAPD.vcxproj.filters
+++ b/ZAPD/ZAPD.vcxproj.filters
@@ -300,6 +300,12 @@
<ClCompile Include="ZRoom\Commands\SetCutsceneEntryList.cpp">
<Filter>Source Files\Z64\ZRoom\Commands</Filter>
</ClCompile>
+ <ClCompile Include="ZCKeyFrame.cpp">
+ <Filter>Source Files\Z64</Filter>
+ </ClCompile>
+ <ClCompile Include="ZCKeyFrameAnim.cpp">
+ <Filter>Source Files\Z64</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="ZRoom\ZRoom.h">
@@ -575,6 +581,12 @@
<ClInclude Include="ZRoom\Commands\SetCutsceneEntryList.h">
<Filter>Header Files\Z64\ZRoom\Commands</Filter>
</ClInclude>
+ <ClInclude Include="ZCKeyFrame.h">
+ <Filter>Header Files\Z64</Filter>
+ </ClInclude>
+ <ClInclude Include="ZCkeyFrameAnim.h">
+ <Filter>Header Files\Z64</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<Text Include="..\SymbolMap_OoTMqDbg.txt">
diff --git a/ZAPD/ZCKeyFrame.cpp b/ZAPD/ZCKeyFrame.cpp
new file mode 100644
index 0000000..387f8ad
--- /dev/null
+++ b/ZAPD/ZCKeyFrame.cpp
@@ -0,0 +1,302 @@
+#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<ZKeyFrameLimbList>(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
+{
+ 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/ZAPD/ZCKeyFrame.h b/ZAPD/ZCKeyFrame.h
new file mode 100644
index 0000000..417d7cc
--- /dev/null
+++ b/ZAPD/ZCKeyFrame.h
@@ -0,0 +1,121 @@
+#pragma once
+
+#include <cstdint>
+#include <string>
+#include <vector>
+#include <memory>
+
+#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<ZKeyFrameLimb*> 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<ZKeyFrameLimbList> 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/ZAPD/ZCKeyFrameAnim.cpp b/ZAPD/ZCKeyFrameAnim.cpp
new file mode 100644
index 0000000..0b07471
--- /dev/null
+++ b/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<ZKeyFrameSkel*>(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 <typename T>
+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/ZAPD/ZCkeyFrameAnim.h b/ZAPD/ZCkeyFrameAnim.h
new file mode 100644
index 0000000..64f95b1
--- /dev/null
+++ b/ZAPD/ZCkeyFrameAnim.h
@@ -0,0 +1,52 @@
+#pragma once
+#include <cstdint>
+#include <string>
+#include <vector>
+#include <memory>
+
+#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<uint8_t> bitFlags; // Standard only
+ std::vector<uint16_t> bitFlagsFlex; // Flex only
+
+ std::vector<KeyFrame> keyFrames;
+ std::vector<int16_t> kfNums;
+ std::vector<int16_t> 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 <typename T>
+ uint32_t GetSetBits(T data) const;
+};
diff --git a/ZAPD/ZResource.h b/ZAPD/ZResource.h
index 9f1587b..3371573 100644
--- a/ZAPD/ZResource.h
+++ b/ZAPD/ZResource.h
@@ -59,6 +59,10 @@ enum class ZResourceType
Waterbox,
Text,
TextMM,
+ KeyFrameFlexLimb,
+ KeyFrameStandardLimb,
+ KeyFrameSkel,
+ KeyFrameAnimation,
};
class ResourceAttribute