diff --git a/data/uking_functions.csv b/data/uking_functions.csv index 15580b80..8a53e2bd 100644 --- a/data/uking_functions.csv +++ b/data/uking_functions.csv @@ -96595,10 +96595,10 @@ 0x00000071012f1ef8,sub_71012F1EF8,896,_ZN4ksys3res9ASSetting10BoneParams5parseERKNS0_13ASParamParser9ParseArgsE 0x00000071012f2278,sub_71012F2278,300,_ZNK4ksys3res9ASSetting10BoneParams13getBoneWeightERKN4sead14SafeStringBaseIcEE 0x00000071012f23a4,sub_71012F23A4,132,_ZN4ksys3res12ASExtensionsD1Ev -0x00000071012f2428,sub_71012F2428,508, -0x00000071012f2624,sub_71012F2624,636, +0x00000071012f2428,sub_71012F2428,508,_ZN4ksys3res12ASExtensions5parseERKNS1_9ParseArgsE +0x00000071012f2624,sub_71012F2624,636,_ZNK4ksys3res12ASExtensions10makeParserERKNS0_13ASParamParser9ParseArgsE 0x00000071012f28a0,sub_71012F28A0,428,_ZNK4ksys3act9ASSetting13getBoneParamsERKN4sead14SafeStringBaseIcEE? -0x00000071012f2a4c,sub_71012F2A4C,80, +0x00000071012f2a4c,sub_71012F2A4C,80,_ZNK4ksys3res12ASExtensions9getParserENS0_13ASParamParser4TypeE 0x00000071012f2a9c,sub_71012F2A9C,252,_ZN4ksys3res9ASSettingC1Ev 0x00000071012f2b98,sub_71012F2B98,360,_ZN4ksys3res9ASSettingD1Ev 0x00000071012f2d00,sub_71012F2D00,8,_ZThn464_N4ksys3res9ASSettingD1Ev diff --git a/lib/agl b/lib/agl index 078f7ddb..e19bb5df 160000 --- a/lib/agl +++ b/lib/agl @@ -1 +1 @@ -Subproject commit 078f7ddbca63a4e20410558f48edd726f7c5ddbc +Subproject commit e19bb5df959a18aac742395ec993a27d0a571688 diff --git a/src/KingSystem/ActorSystem/actASSetting.cpp b/src/KingSystem/ActorSystem/actASSetting.cpp index 0202a85c..7c3d82e2 100644 --- a/src/KingSystem/ActorSystem/actASSetting.cpp +++ b/src/KingSystem/ActorSystem/actASSetting.cpp @@ -16,12 +16,12 @@ void ASSetting::init(const sead::SafeString& config_path) { } // NON_MATCHING: sead::DirectResource to res::ASSetting cast nullptr check; branching for the return -const res::ASSetting::BoneParams* ASSetting::getBoneParams(const sead::SafeString& key) const { +res::ASParamParser* ASSetting::getBoneParams(const sead::SafeString& key) const { auto* res = sead::DynamicCast(mHandle.getResource()); if (!res) return nullptr; - for (const auto& bones : res->getBlenderBones()) { + for (auto& bones : res->getBlenderBones()) { if (key == bones.mKeyName.ref()) return &bones.mBoneParams; } diff --git a/src/KingSystem/ActorSystem/actASSetting.h b/src/KingSystem/ActorSystem/actASSetting.h index 289d68dd..399ad201 100644 --- a/src/KingSystem/ActorSystem/actASSetting.h +++ b/src/KingSystem/ActorSystem/actASSetting.h @@ -16,7 +16,7 @@ class ASSetting { public: void init(const sead::SafeString& config_path); - const res::ASSetting::BoneParams* getBoneParams(const sead::SafeString& key) const; + res::ASParamParser* getBoneParams(const sead::SafeString& key) const; private: res::Handle mHandle; diff --git a/src/KingSystem/Resource/resResourceASResource.cpp b/src/KingSystem/Resource/resResourceASResource.cpp index 0025bfe1..0112f3af 100644 --- a/src/KingSystem/Resource/resResourceASResource.cpp +++ b/src/KingSystem/Resource/resResourceASResource.cpp @@ -1,5 +1,9 @@ #include "KingSystem/Resource/resResourceASResource.h" +#include +#include #include +#include "KingSystem/ActorSystem/actASSetting.h" +#include "KingSystem/Resource/resResourceASSetting.h" namespace ksys::res { @@ -216,7 +220,13 @@ static ASParamParser* dummyASParserFactoryImpl_(sead::Heap*) { return nullptr; } -std::array ASExtensions::sFactories{{ +namespace { +struct Factory { + const char* name; + ASParamParser* (*make)(sead::Heap* heap); +}; + +sead::SafeArray sASFactories{{ {"FrameCtrl", factoryImpl_}, {"TriggerEvents", factoryImpl_}, {"HoldEvents", factoryImpl_}, @@ -227,6 +237,7 @@ std::array ASExtensions::sFactor {"BitIndex", factoryImpl_}, {"BlenderBone", dummyASParserFactoryImpl_}, }}; +} // namespace ASExtensions::~ASExtensions() { for (auto*& parser : mParsers) { @@ -237,4 +248,92 @@ ASExtensions::~ASExtensions() { mParsers.freeBuffer(); } +bool ASExtensions::parse(const ASExtensions::ParseArgs& args) { + const auto Extend = agl::utl::getResParameterList(args.res_list, "Extend"); + if (!Extend) + return true; + + const auto num_extensions = Extend.getResParameterListNum(); + if (num_extensions == 0) + return true; + + if (!mParsers.tryAllocBuffer(num_extensions, args.heap)) + return false; + for (int i = 0, n = mParsers.size(); i < n; ++i) + mParsers(i) = nullptr; + + auto it = mParsers.begin(); + const auto end = mParsers.end(); + + ASParamParser::ParseArgs parse_args{}; + parse_args.list = &mList; + parse_args.heap = args.heap; + + auto res_it = Extend.listBegin(); + const auto res_end = Extend.listEnd(); + + for (; it != end && res_it != res_end; ++it, ++res_it) { + parse_args.res_list = res_it.getList(); + *it = makeParser(parse_args); + + constexpr int bone = int(ASParamParser::Type::BlenderBone); + if (*it == nullptr && parse_args.res_list.getParameterListNameHash() != + agl::utl::ParameterBase::calcHash(sASFactories[bone].name)) { + return false; + } + } + + args.list->addList(&mList, "Extend"); + return true; +} + +ASParamParser* ASExtensions::makeParser(const ASParamParser::ParseArgs& args) const { + const auto is_factory = [&args](int i) { + return args.res_list.getParameterListNameHash() == + agl::utl::ParameterBase::calcHash(sASFactories[i].name); + }; + + std::optional type; + for (int i = 0; i < ASParamParser::NumTypes - 1; ++i) { + if (!is_factory(i)) + continue; + type = i; + break; + } + + if (!type.has_value() && is_factory(int(ASParamParser::Type::BlenderBone))) { + const auto obj = args.res_list.getResParameterObj(0); + if (obj.getNum() > 0) { + const sead::SafeString name = obj.getResParameter(0).getData(); + return act::ASSetting::instance()->getBoneParams(name); + } + } + + if (!type.has_value()) + return nullptr; + + const auto& factory = sASFactories[*type]; + + auto* parser = factory.make(args.heap); + if (!parser) + return nullptr; + + if (!parser->parse(args)) { + delete parser; + return nullptr; + } + + args.list->addList(&parser->getList(), factory.name); + return parser; +} + +ASParamParser* ASExtensions::getParser(ASParamParser::Type type) const { + for (int i = 0, n = mParsers.size(); i < n; ++i) { + auto* parser = mParsers[i]; + if (parser && parser->getType() == type) + return parser; + } + return nullptr; +} + } // namespace ksys::res diff --git a/src/KingSystem/Resource/resResourceASResource.h b/src/KingSystem/Resource/resResourceASResource.h index 0a2ab6bb..fd244cc6 100644 --- a/src/KingSystem/Resource/resResourceASResource.h +++ b/src/KingSystem/Resource/resResourceASResource.h @@ -33,7 +33,7 @@ public: static constexpr int NumTypes = 9; struct ParseArgs { - void* user_data; + agl::utl::ParameterList* list; agl::utl::ResParameterList res_list; sead::Heap* heap; }; @@ -54,19 +54,24 @@ KSYS_CHECK_SIZE_NX150(ASParamParser, 0x58); class ASExtensions { public: + struct ParseArgs { + agl::utl::ResParameterList res_list; + agl::utl::ParameterList* list; + sead::Heap* heap; + }; + ASExtensions() = default; ~ASExtensions(); ASExtensions(const ASExtensions&) = delete; auto operator=(const ASExtensions&) = delete; const sead::Buffer& getParsers() const { return mParsers; } + ASParamParser* getParser(ASParamParser::Type type) const; + + bool parse(const ParseArgs& args); private: - struct Factory { - const char* name; - ASParamParser* (*make)(sead::Heap* heap); - }; - static std::array sFactories; + ASParamParser* makeParser(const ASParamParser::ParseArgs& args) const; agl::utl::ParameterList mList; sead::Buffer mParsers; diff --git a/src/KingSystem/Resource/resResourceASSetting.cpp b/src/KingSystem/Resource/resResourceASSetting.cpp index 2fe40a2a..be0a3865 100644 --- a/src/KingSystem/Resource/resResourceASSetting.cpp +++ b/src/KingSystem/Resource/resResourceASSetting.cpp @@ -59,7 +59,7 @@ bool ASSetting::parse_(u8* data, size_t size, sead::Heap* heap) { it->mList.addList(&it->mBoneParams.getList(), "BoneParam"); const auto list = *res_it; - args.user_data = std::addressof(*it); + args.list = &it->mList; args.res_list = agl::utl::getResParameterList(list, "BoneParam"); if (!it->mBoneParams.parse(args)) return false; diff --git a/src/KingSystem/Resource/resResourceASSetting.h b/src/KingSystem/Resource/resResourceASSetting.h index 069f98ff..9d052bcc 100644 --- a/src/KingSystem/Resource/resResourceASSetting.h +++ b/src/KingSystem/Resource/resResourceASSetting.h @@ -51,6 +51,7 @@ public: bool needsParse() const override { return true; } bool parse_(u8* data, size_t size, sead::Heap* heap) override; + sead::Buffer& getBlenderBones() { return mBlenderBones; } const sead::Buffer& getBlenderBones() const { return mBlenderBones; } private: