From 69fcdfbed7dbb65343d103c8dcbbe3ad3895a746 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Tue, 23 Mar 2021 19:28:26 +0100 Subject: [PATCH] ksys/res: Start adding AnimInfo not going to do parse() for now, it's a major pain --- data/uking_functions.csv | 36 ++--- .../Resource/resResourceAnimInfo.cpp | 127 ++++++++++++++++++ src/KingSystem/Resource/resResourceAnimInfo.h | 46 +++++++ 3 files changed, 191 insertions(+), 18 deletions(-) diff --git a/data/uking_functions.csv b/data/uking_functions.csv index 5d91bb8b..78652f56 100644 --- a/data/uking_functions.csv +++ b/data/uking_functions.csv @@ -96462,26 +96462,26 @@ 0x00000071012ec0d4,sub_71012EC0D4,52, 0x00000071012ec108,sub_71012EC108,40, 0x00000071012ec130,sub_71012EC130,372, -0x00000071012ec2a4,sub_71012EC2A4,240, -0x00000071012ec394,sub_71012EC394,316, -0x00000071012ec4d0,sub_71012EC4D0,8, -0x00000071012ec4d8,sub_71012EC4D8,8, -0x00000071012ec4e0,sub_71012EC4E0,36, -0x00000071012ec504,sub_71012EC504,40, -0x00000071012ec52c,sub_71012EC52C,40, -0x00000071012ec554,nullsub_4829,4, -0x00000071012ec558,nullsub_4830,4, +0x00000071012ec2a4,sub_71012EC2A4,240,_ZN4ksys3res8AnimInfoC1Ev +0x00000071012ec394,sub_71012EC394,316,_ZN4ksys3res8AnimInfoD1Ev +0x00000071012ec4d0,sub_71012EC4D0,8,_ZThn632_N4ksys3res8AnimInfoD1Ev +0x00000071012ec4d8,sub_71012EC4D8,8,_ZThn664_N4ksys3res8AnimInfoD1Ev +0x00000071012ec4e0,sub_71012EC4E0,36,_ZN4ksys3res8AnimInfoD0Ev +0x00000071012ec504,sub_71012EC504,40,_ZThn632_N4ksys3res8AnimInfoD0Ev +0x00000071012ec52c,sub_71012EC52C,40,_ZThn664_N4ksys3res8AnimInfoD0Ev +0x00000071012ec554,nullsub_4829,4,_ZN4ksys3res8AnimInfo9doCreate_EPhjPN4sead4HeapE +0x00000071012ec558,nullsub_4830,4,_ZThn632_N4ksys3res8AnimInfo9doCreate_EPhjPN4sead4HeapE 0x00000071012ec55c,sub_71012EC55C,2428, 0x00000071012eced8,sub_71012ECED8,8, -0x00000071012ecee0,sub_71012ECEE0,68, -0x00000071012ecf24,sub_71012ECF24,400, -0x00000071012ed0b4,sub_71012ED0B4,8, -0x00000071012ed0bc,sub_71012ED0BC,92, -0x00000071012ed118,sub_71012ED118,8, -0x00000071012ed120,sub_71012ED120,8, -0x00000071012ed128,sub_71012ED128,92, -0x00000071012ed184,sub_71012ED184,8, -0x00000071012ed18c,sub_71012ED18C,372, +0x00000071012ecee0,sub_71012ECEE0,68,_ZNK4ksys3res8AnimInfo7getAnimERKN4sead14SafeStringBaseIcEE +0x00000071012ecf24,sub_71012ECF24,400,_ZNK4ksys3res8AnimInfo13findAnimIndexERKN4sead14SafeStringBaseIcEE +0x00000071012ed0b4,sub_71012ED0B4,8,_ZNK4ksys3res8AnimInfo27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE +0x00000071012ed0bc,sub_71012ED0BC,92,_ZNK4ksys3res8AnimInfo18getRuntimeTypeInfoEv +0x00000071012ed118,sub_71012ED118,8,_ZNK4ksys3res8AnimInfo10needsParseEv +0x00000071012ed120,sub_71012ED120,8,_ZThn632_NK4ksys3res8AnimInfo27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE +0x00000071012ed128,sub_71012ED128,92,_ZThn632_NK4ksys3res8AnimInfo18getRuntimeTypeInfoEv +0x00000071012ed184,sub_71012ED184,8,_ZThn632_NK4ksys3res8AnimInfo10needsParseEv +0x00000071012ed18c,sub_71012ED18C,372,_ZN4ksys3res8AnimInfo33checkDerivedRuntimeTypeInfoStaticEPKN4sead15RuntimeTypeInfo9InterfaceE 0x00000071012ed300,sub_71012ED300,104, 0x00000071012ed368,sub_71012ED368,32, 0x00000071012ed388,sub_71012ED388,32, diff --git a/src/KingSystem/Resource/resResourceAnimInfo.cpp b/src/KingSystem/Resource/resResourceAnimInfo.cpp index b70e4e2d..edee3386 100644 --- a/src/KingSystem/Resource/resResourceAnimInfo.cpp +++ b/src/KingSystem/Resource/resResourceAnimInfo.cpp @@ -1 +1,128 @@ #include "KingSystem/Resource/resResourceAnimInfo.h" +#include "KingSystem/Utils/Byaml/Byaml.h" +#include "KingSystem/Utils/SafeDelete.h" + +namespace ksys::res { + +AnimInfo::AnimInfo() : ParamIO("animinfo", 0) {} + +AnimInfo::~AnimInfo() { + mAnims.freeBuffer(); + + if (mSwordBlurInfo) { + mSwordBlurInfo->finalize(); + util::safeDelete(mSwordBlurInfo); + } +} + +void AnimInfo::SwordBlurInfo::finalize() { + if (!entries) + return; + + for (int i = 0; i < num_entries; ++i) { + SwordBlur& entry = entries[i]; + auto* h = heap; + if (entry.frames) { + h->free(entry.frames); + entry.frames = nullptr; + } + if (entry._18) { + h->free(entry._18); + entry._18 = nullptr; + } + } + + heap->free(entries); + entries = nullptr; +} + +void AnimInfo::doCreate_(u8* buffer, u32 buffer_size, sead::Heap* heap) {} + +bool AnimInfo::parse_(u8* data, size_t size, sead::Heap* heap) { + al::ByamlIter root_iter{data}; + + const int num_entries = root_iter.getSize(); + int num_anims = num_entries - 1; + if (num_entries < 1) + return true; + + al::ByamlIter iter; + int double_attack_anm_num = 0; + int num = 0; + bool allocate_anims = false; + if (root_iter.isExistKey("_sword_blur")) { + iter = root_iter.getIterByKey("_sword_blur"); + const int num_sword_blurs = iter.getSize(); + iter.tryGetIntByKey(&double_attack_anm_num, "double_attack_anm_num"); + num = num_sword_blurs - 1; + if (num_entries > 1) + allocate_anims = true; + } else { + num = 0; + num_anims = num_entries; + allocate_anims = true; + } + + if (allocate_anims) { + if (!mAnims.tryAllocBuffer(num_anims, heap)) + return false; + + for (int i = 0; i < num_anims; ++i) { + auto& anim = mAnims[i]; + anim.scale.e.fill(0.0); + + al::ByamlIter entry_iter; + if (root_iter.tryGetIterByIndex(&entry_iter, i)) { + const char* name_c; + if (root_iter.getKeyName(&name_c, i)) { + if (std::strcmp(name_c, "_sword_blur") == 0) + continue; + anim.name = name_c; + } else { + anim.name = ""; + } + entry_iter.tryGetFloatByKey(&anim.scale.x, "scaleX"); + entry_iter.tryGetFloatByKey(&anim.scale.y, "scaleY"); + entry_iter.tryGetFloatByKey(&anim.scale.z, "scaleZ"); + } else { + anim.name = ""; + } + } + } + + if (num >= 1) { + if (!mSwordBlurInfo) { + auto* info = new (heap) SwordBlurInfo; + info->entries = nullptr; + mSwordBlurInfo = info; + info->heap = heap; + info->num_entries = double_attack_anm_num; + /// @bug SwordBlur is not trivially constructible and not trivially copyable. + /// The only reason using SwordBlur::name doesn't crash is that Clang and GHS + /// are smart enough to devirtualize sead::SafeString virtual function calls, + /// which removes the need to go through the vtable. + info->entries = static_cast( + heap->tryAlloc(sizeof(SwordBlur) * info->num_entries, alignof(SwordBlur))); + std::memset(info->entries, 0, sizeof(SwordBlur) * info->num_entries); + } + + // TODO / FIXME: finish this + } + + return true; +} + +const AnimInfo::Anim* AnimInfo::getAnim(const sead::SafeString& name) const { + const auto idx = findAnimIndex(name); + if (idx < 0) + return nullptr; + return &mAnims[idx]; +} + +int AnimInfo::findAnimIndex(const sead::SafeString& name) const { + return mAnims.binarySearch( + name, + +[](const Anim& anim, const sead::SafeString& key) { return anim.name.compare(key); }); +} + +} // namespace ksys::res diff --git a/src/KingSystem/Resource/resResourceAnimInfo.h b/src/KingSystem/Resource/resResourceAnimInfo.h index d25f9203..b27e28a7 100644 --- a/src/KingSystem/Resource/resResourceAnimInfo.h +++ b/src/KingSystem/Resource/resResourceAnimInfo.h @@ -1,13 +1,59 @@ #pragma once +#include +#include +#include +#include #include "KingSystem/Resource/resResource.h" #include "KingSystem/Utils/ParamIO.h" +#include "KingSystem/Utils/Types.h" namespace ksys::res { // TODO class AnimInfo : public ParamIO, public Resource { SEAD_RTTI_OVERRIDE(AnimInfo, Resource) +public: + struct Anim { + sead::SafeString name; + sead::Vector3f scale; + }; + KSYS_CHECK_SIZE_NX150(Anim, 0x20); + + struct SwordBlur { + int frame_num; + int start; + int end; + sead::Matrix34f* frames; + float* _18; + sead::SafeString name; + }; + KSYS_CHECK_SIZE_NX150(SwordBlur, 0x30); + + AnimInfo(); + ~AnimInfo() override; + + bool needsParse() const override { return true; } + void doCreate_(u8* buffer, u32 buffer_size, sead::Heap* heap) override; + bool parse_(u8* data, size_t size, sead::Heap* heap) override; + + const sead::Buffer& getAnims() const { return mAnims; } + + const Anim* getAnim(const sead::SafeString& name) const; + int findAnimIndex(const sead::SafeString& name) const; + +private: + struct SwordBlurInfo { + void finalize(); + + sead::Heap* heap; + int num_entries; + SwordBlur* entries; + }; + KSYS_CHECK_SIZE_NX150(SwordBlurInfo, 0x18); + + sead::Buffer mAnims; + SwordBlurInfo* mSwordBlurInfo = nullptr; }; } // namespace ksys::res