From bd3e38a4e048c382d0cb3aba9a925cd2d8d5e3eb Mon Sep 17 00:00:00 2001 From: louist103 <35883445+louist103@users.noreply.github.com> Date: Tue, 30 Jan 2024 18:48:52 -0500 Subject: [PATCH] Implement CKeyframe (#315) * KeyFrameSkels * KeyFrameAnimation * Cleanup text output * format * PR Fixes. --- ZAPD/OtherStructs/CutsceneMM_Commands.cpp | 51 ++-- ZAPD/OtherStructs/CutsceneMM_Commands.h | 16 +- ZAPD/ZAPD.vcxproj | 6 + ZAPD/ZAPD.vcxproj.filters | 12 + ZAPD/ZCKeyFrame.cpp | 302 ++++++++++++++++++++++ ZAPD/ZCKeyFrame.h | 121 +++++++++ ZAPD/ZCKeyFrameAnim.cpp | 219 ++++++++++++++++ ZAPD/ZCkeyFrameAnim.h | 52 ++++ ZAPD/ZResource.h | 4 + 9 files changed, 757 insertions(+), 26 deletions(-) create mode 100644 ZAPD/ZCKeyFrame.cpp create mode 100644 ZAPD/ZCKeyFrame.h create mode 100644 ZAPD/ZCKeyFrameAnim.cpp create mode 100644 ZAPD/ZCkeyFrameAnim.h diff --git a/ZAPD/OtherStructs/CutsceneMM_Commands.cpp b/ZAPD/OtherStructs/CutsceneMM_Commands.cpp index b47bc40e1..5a10ab411 100644 --- a/ZAPD/OtherStructs/CutsceneMM_Commands.cpp +++ b/ZAPD/OtherStructs/CutsceneMM_Commands.cpp @@ -127,8 +127,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 +145,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 +155,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 +167,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 +176,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 +188,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 +197,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 +231,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 +242,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 +279,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 9891a24ac..597f6788b 100644 --- a/ZAPD/OtherStructs/CutsceneMM_Commands.h +++ b/ZAPD/OtherStructs/CutsceneMM_Commands.h @@ -282,7 +282,8 @@ class CutsceneSubCommandEntry_SplineCamPoint : public CutsceneSubCommandEntry 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 @@ class CutsceneSubCommandEntry_SplineMiscPoint : public CutsceneSubCommandEntry 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 @@ class CutsceneSubCommandEntry_SplineMiscPoint : public CutsceneSubCommandEntry 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 @@ class CutsceneSubCommandEntry_SplineHeader : public CutsceneSubCommandEntry 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/ZAPD/ZAPD.vcxproj b/ZAPD/ZAPD.vcxproj index 22bc720e9..26a0b7036 100644 --- a/ZAPD/ZAPD.vcxproj +++ b/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/ZAPD/ZAPD.vcxproj.filters b/ZAPD/ZAPD.vcxproj.filters index f693a749d..51723306b 100644 --- a/ZAPD/ZAPD.vcxproj.filters +++ b/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/ZAPD/ZCKeyFrame.cpp b/ZAPD/ZCKeyFrame.cpp new file mode 100644 index 000000000..387f8ad2f --- /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(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 000000000..417d7cc68 --- /dev/null +++ b/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/ZAPD/ZCKeyFrameAnim.cpp b/ZAPD/ZCKeyFrameAnim.cpp new file mode 100644 index 000000000..0b0747133 --- /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(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/ZAPD/ZCkeyFrameAnim.h b/ZAPD/ZCkeyFrameAnim.h new file mode 100644 index 000000000..64f95b13a --- /dev/null +++ b/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/ZAPD/ZResource.h b/ZAPD/ZResource.h index 975401398..768b78544 100644 --- a/ZAPD/ZResource.h +++ b/ZAPD/ZResource.h @@ -55,6 +55,10 @@ enum class ZResourceType Vector, Vertex, Waterbox, + KeyFrameFlexLimb, + KeyFrameStandardLimb, + KeyFrameSkel, + KeyFrameAnimation, }; class ResourceAttribute