From 3d3bcaee1a47825f4736b3d15d745f31207c7892 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Sat, 5 Sep 2020 22:10:51 +0200 Subject: [PATCH] ksys/res: Add ActorLink --- CMakeLists.txt | 4 + data/uking_functions.csv | 44 ++++---- lib/agl | 2 +- lib/sead | 2 +- src/KingSystem/ActorSystem/actTag.h | 30 +++++ .../Resource/resResourceActorLink.cpp | 103 ++++++++++++++++++ .../Resource/resResourceActorLink.h | 74 +++++++++++++ src/KingSystem/Utils/HashUtil.h | 25 +++++ 8 files changed, 260 insertions(+), 24 deletions(-) create mode 100644 src/KingSystem/ActorSystem/actTag.h create mode 100644 src/KingSystem/Resource/resResourceActorLink.cpp create mode 100644 src/KingSystem/Resource/resResourceActorLink.h create mode 100644 src/KingSystem/Utils/HashUtil.h diff --git a/CMakeLists.txt b/CMakeLists.txt index e0a09958..9b11773c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,6 +47,7 @@ add_executable(uking src/KingSystem/ActorSystem/actBaseProcMgr.h src/KingSystem/ActorSystem/actBaseProcUnit.cpp src/KingSystem/ActorSystem/actBaseProcUnit.h + src/KingSystem/ActorSystem/actTag.h src/KingSystem/MessageSystem/mesTransceiver.h @@ -54,6 +55,8 @@ add_executable(uking src/KingSystem/Resource/resEntryFactory.h src/KingSystem/Resource/resResource.cpp src/KingSystem/Resource/resResource.h + src/KingSystem/Resource/resResourceActorLink.cpp + src/KingSystem/Resource/resResourceActorLink.h src/KingSystem/Resource/resResourceDemo.cpp src/KingSystem/Resource/resResourceDemo.h src/KingSystem/Resource/resResourceLod.cpp @@ -67,6 +70,7 @@ add_executable(uking src/KingSystem/Utils/ByamlLocal.h src/KingSystem/Utils/ByamlUtil.cpp src/KingSystem/Utils/Debug.h + src/KingSystem/Utils/HashUtil.h src/KingSystem/Utils/HeapUtil.cpp src/KingSystem/Utils/HeapUtil.h src/KingSystem/Utils/ParamIO.h diff --git a/data/uking_functions.csv b/data/uking_functions.csv index 260cb7a1..3094a57b 100644 --- a/data/uking_functions.csv +++ b/data/uking_functions.csv @@ -88704,28 +88704,28 @@ 0x00000071011661fc,sub_71011661FC,80, 0x000000710116624c,sub_710116624C,76, 0x0000007101166298,sub_7101166298,84, -0x00000071011662ec,Bxml::ctor,2168, -0x0000007101166b64,sub_7101166B64,556, -0x0000007101166d90,nullsub_4611,4, -0x0000007101166d94,nullsub_4612,4, -0x0000007101166d98,Bxml::parse,428, -0x0000007101166f44,ResourceBxml::parse,28, -0x0000007101166f60,sub_7101166F60,124, -0x0000007101166fdc,sub_7101166FDC,124, -0x0000007101167058,Bxml::hasTagByName,164, -0x00000071011670fc,Bxml::hasTag,108, -0x0000007101167168,sub_7101167168,236, -0x0000007101167254,sub_7101167254,224, -0x0000007101167334,sub_7101167334,8, -0x000000710116733c,sub_710116733C,92, -0x0000007101167398,sub_7101167398,8, -0x00000071011673a0,sub_71011673A0,8, -0x00000071011673a8,sub_71011673A8,92, -0x0000007101167404,sub_7101167404,232, -0x00000071011674ec,sub_71011674EC,220, -0x00000071011675c8,sub_71011675C8,8, -0x00000071011675d0,sub_71011675D0,240, -0x00000071011676c0,sub_71011676C0,228, +0x00000071011662ec,Bxml::ctor,2168,_ZN4ksys3res9ActorLinkC1Ev +0x0000007101166b64,sub_7101166B64,556,_ZN4ksys3res9ActorLink5UsersC2Ev +0x0000007101166d90,nullsub_4611,4,_ZN4ksys3res9ActorLink9doCreate_EPhjPN4sead4HeapE +0x0000007101166d94,nullsub_4612,4,_ZThn632_N4ksys3res9ActorLink9doCreate_EPhjPN4sead4HeapE +0x0000007101166d98,Bxml::parse,428,_ZN4ksys3res9ActorLink6parse_EPhmPN4sead4HeapE? +0x0000007101166f44,ResourceBxml::parse,28,_ZThn632_N4ksys3res9ActorLink6parse_EPhmPN4sead4HeapE +0x0000007101166f60,sub_7101166F60,124,_ZN4ksys3res9ActorLink3m5_Ev +0x0000007101166fdc,sub_7101166FDC,124,_ZThn632_N4ksys3res9ActorLink3m5_Ev +0x0000007101167058,Bxml::hasTagByName,164,_ZNK4ksys3res9ActorLink6hasTagEPKc? +0x00000071011670fc,Bxml::hasTag,108,_ZNK4ksys3res9ActorLink6hasTagENS_3act3TagE +0x0000007101167168,sub_7101167168,236,_ZN4ksys3res9ActorLinkD2Ev +0x0000007101167254,sub_7101167254,224,_ZN4ksys3res9ActorLinkD0Ev +0x0000007101167334,sub_7101167334,8,_ZNK4ksys3res9ActorLink27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE? +0x000000710116733c,sub_710116733C,92,_ZNK4ksys3res9ActorLink18getRuntimeTypeInfoEv +0x0000007101167398,sub_7101167398,8,_ZNK4ksys3res9ActorLink10needsParseEv +0x00000071011673a0,sub_71011673A0,8,_ZThn632_NK4ksys3res9ActorLink27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE? +0x00000071011673a8,sub_71011673A8,92,_ZThn632_NK4ksys3res9ActorLink18getRuntimeTypeInfoEv +0x0000007101167404,sub_7101167404,232,_ZThn632_N4ksys3res9ActorLinkD1Ev +0x00000071011674ec,sub_71011674EC,220,_ZThn632_N4ksys3res9ActorLinkD0Ev +0x00000071011675c8,sub_71011675C8,8,_ZThn632_NK4ksys3res9ActorLink10needsParseEv +0x00000071011675d0,sub_71011675D0,240,_ZThn664_N4ksys3res9ActorLinkD1Ev +0x00000071011676c0,sub_71011676C0,228,_ZThn664_N4ksys3res9ActorLinkD0Ev 0x0000007101167918,sub_7101167918,548, 0x0000007101167b3c,sub_7101167B3C,316, 0x0000007101167c78,sub_7101167C78,328, diff --git a/lib/agl b/lib/agl index 292b10a2..27e919f2 160000 --- a/lib/agl +++ b/lib/agl @@ -1 +1 @@ -Subproject commit 292b10a27dac9c59241bd54b87e1772c47ef444e +Subproject commit 27e919f21530a5c7b2186d9c616f9ad590b71496 diff --git a/lib/sead b/lib/sead index b085263d..397b25d7 160000 --- a/lib/sead +++ b/lib/sead @@ -1 +1 @@ -Subproject commit b085263d6999ae37d8442ad1a1e9f5832dbdfc19 +Subproject commit 397b25d7f0c8841972f20a59f6000f1fb5daabfe diff --git a/src/KingSystem/ActorSystem/actTag.h b/src/KingSystem/ActorSystem/actTag.h new file mode 100644 index 00000000..8853b4a6 --- /dev/null +++ b/src/KingSystem/ActorSystem/actTag.h @@ -0,0 +1,30 @@ +#pragma once + +#include +#include +#include "KingSystem/Utils/HashUtil.h" + +namespace ksys::act { + +/// Actor tag. +class Tag { +public: + Tag() = default; + constexpr Tag(u32 hash) : mHash(hash) {} + constexpr Tag(std::string_view name) : mHash(util::calcCrc32(name)) {} + + constexpr bool operator==(Tag other) const { return mHash == other.mHash; } + constexpr bool operator!=(Tag other) const { return mHash != other.mHash; } + constexpr bool operator<(Tag other) const { return mHash < other.mHash; } + constexpr bool operator>(Tag other) const { return mHash > other.mHash; } + constexpr bool operator<=(Tag other) const { return mHash <= other.mHash; } + constexpr bool operator>=(Tag other) const { return mHash >= other.mHash; } + + constexpr operator u32() const { return mHash; } + constexpr u32 getHash() const { return mHash; } + +private: + u32 mHash; +}; + +} // namespace ksys::act diff --git a/src/KingSystem/Resource/resResourceActorLink.cpp b/src/KingSystem/Resource/resResourceActorLink.cpp new file mode 100644 index 00000000..32c3ede5 --- /dev/null +++ b/src/KingSystem/Resource/resResourceActorLink.cpp @@ -0,0 +1,103 @@ +#include "KingSystem/Resource/resResourceActorLink.h" +#include +#include + +namespace ksys::res { + +ActorLink::ActorLink() : ParamIO("xml", 0) { + const auto init_user = [this](auto& param, const char* key, const char* default_ = "Dummy") { + param.init(default_, key, "", &mUsers.obj); + }; + init_user(mUsers.profile, "ProfileUser"); + init_user(mUsers.actor_capture, "ActorCaptureUser"); + init_user(mUsers.as, "ASUser", ""); + init_user(mUsers.model, "ModelUser", ""); + init_user(mUsers.anim, "AnimUser", ""); + init_user(mUsers.ai_program, "AIProgramUser", ""); + init_user(mUsers.gparam, "GParamUser", ""); + init_user(mUsers.damage_param, "DamageParamUser"); + init_user(mUsers.rg_config_list, "RgConfigListUser"); + init_user(mUsers.rg_blend_weight, "RgBlendWeightUser"); + init_user(mUsers.awareness, "AwarenessUser"); + init_user(mUsers.elink, "ElinkUser"); + init_user(mUsers.slink, "SlinkUser"); + init_user(mUsers.xlink, "XlinkUser"); + init_user(mUsers.attention, "AttentionUser"); + init_user(mUsers.physics, "PhysicsUser"); + init_user(mUsers.chemical, "ChemicalUser"); + init_user(mUsers.drop_table, "DropTableUser"); + init_user(mUsers.shop_data, "ShopDataUser"); + init_user(mUsers.recipe, "RecipeUser"); + init_user(mUsers.lod, "LODUser"); + init_user(mUsers.ai_schedule, "AIScheduleUser"); + init_user(mUsers.bone_control, "BoneControlUser"); + init_user(mUsers.life_condition, "LifeConditionUser"); + init_user(mUsers.umii, "UMiiUser"); + init_user(mUsers.animation_info, "AnimationInfo"); + + mActorScale.init(1.0, "ActorScale", "", &mUsers.obj); + mActorNameJpn.init("不正な名前", "ActorNameJpn", "ActorNameJpn", &mUsers.obj); + mPriority.init("", "Priority", "Priority", &mUsers.obj); + + addObj(&mUsers.obj, "LinkTarget"); +} + +bool ActorLink::parse_(u8* data, size_t, sead::Heap* heap) { + if (!data) + return true; + + const agl::utl::ResParameterArchive archive{data}; + const auto root = archive.getRootList(); + + const s32 tags_idx = root.searchObjIndex(agl::utl::ParameterBase::calcHash("Tags")); + // NON_MATCHING: getResParameter (redundant uxtw; i and res increment order) + const auto parse_tags = [&] { + if (tags_idx == -1) + return; + + const auto obj = root.getResParameterObj(tags_idx); + if (!obj.ptr()) + return; + + const auto num_tags = obj.getNum(); + if (num_tags == 0) + return; + + mHeap = heap; + mTags.allocBufferAssert(num_tags, heap); + + for (s32 i = 0; i != num_tags; ++i) { + const char* tag = obj.getResParameter(i).getData(); + mTags[i] = sead::HashCRC32::calcStringHash(tag); + } + + if (num_tags > 1) + mTags.heapSort(0, num_tags - 1); + }; + parse_tags(); + + applyResParameterArchive(agl::utl::ResParameterArchive{data}); + return true; +} + +void ActorLink::m5_() { + if (!mTags.isBufferReady()) + return; + + if (!mHeap) + return; + + sead::ScopedCurrentHeapSetter setter{mHeap}; + mTags.freeBuffer(); +} + +// NON_MATCHING: operands are swapped for an equality comparison in binarySearch +bool ActorLink::hasTag(const char* tag_name) const { + return mTags.size() >= 1 && mTags.binarySearch(sead::HashCRC32::calcStringHash(tag_name)) != -1; +} + +bool ActorLink::hasTag(act::Tag tag) const { + return mTags.size() >= 1 && mTags.binarySearch(tag) != -1; +} + +} // namespace ksys::res diff --git a/src/KingSystem/Resource/resResourceActorLink.h b/src/KingSystem/Resource/resResourceActorLink.h new file mode 100644 index 00000000..0dc0d152 --- /dev/null +++ b/src/KingSystem/Resource/resResourceActorLink.h @@ -0,0 +1,74 @@ +#pragma once + +#include +#include +#include +#include "KingSystem/ActorSystem/actTag.h" +#include "KingSystem/Resource/resResource.h" +#include "KingSystem/Utils/ParamIO.h" +#include "KingSystem/Utils/Types.h" + +namespace ksys::res { + +class ActorLink : public ParamIO, public Resource { + SEAD_RTTI_OVERRIDE(ActorLink, Resource) +public: + struct Users { + agl::utl::Parameter profile; + agl::utl::Parameter actor_capture; + agl::utl::Parameter as; + agl::utl::Parameter model; + agl::utl::Parameter anim; + agl::utl::Parameter ai_program; + agl::utl::Parameter gparam; + agl::utl::Parameter damage_param; + agl::utl::Parameter rg_config_list; + agl::utl::Parameter rg_blend_weight; + agl::utl::Parameter awareness; + agl::utl::Parameter physics; + agl::utl::Parameter chemical; + agl::utl::Parameter attention; + agl::utl::Parameter elink; + agl::utl::Parameter slink; + agl::utl::Parameter xlink; + agl::utl::Parameter drop_table; + agl::utl::Parameter shop_data; + agl::utl::Parameter recipe; + agl::utl::Parameter lod; + agl::utl::Parameter bone_control; + agl::utl::Parameter ai_schedule; + agl::utl::Parameter life_condition; + agl::utl::Parameter umii; + agl::utl::Parameter animation_info; + agl::utl::ParameterObj obj; + }; + + ActorLink(); + + void doCreate_(u8*, u32, sead::Heap*) override {} + bool needsParse() const override { return true; } + + const Users& getUsers() const { return mUsers; } + const sead::SafeString& getActorNameJpn() const { return mActorNameJpn.ref(); } + const sead::SafeString& getPriority() const { return mPriority.ref(); } + f32 getActorScale() const { return mActorScale.ref(); } + + bool hasTag(const char* tag_name) const; + bool hasTag(act::Tag tag) const; + + const sead::Buffer& getTags() const { return mTags; } + +private: + bool parse_(u8* data, size_t size, sead::Heap* heap) override; + void m5_() override; + + Users mUsers; + agl::utl::Parameter mActorNameJpn; + agl::utl::Parameter mPriority; + agl::utl::Parameter mActorScale; + sead::Buffer mTags; + sead::Heap* mHeap = nullptr; +}; +KSYS_CHECK_SIZE_NX150(ActorLink, 0x778); + +} // namespace ksys::res diff --git a/src/KingSystem/Utils/HashUtil.h b/src/KingSystem/Utils/HashUtil.h new file mode 100644 index 00000000..f0828d70 --- /dev/null +++ b/src/KingSystem/Utils/HashUtil.h @@ -0,0 +1,25 @@ +#pragma once + +#include +#include + +namespace ksys::util { + +template +constexpr u32 calcCrc32(const CharType* data, std::size_t size) { + u32 crc = 0xFFFFFFFF; + for (std::size_t i = 0; i < size; ++i) { + crc ^= u8(data[i]); + for (std::size_t j = 0; j < 8; ++j) { + u32 mask = -(crc & 1); + crc = (crc >> 1) ^ (0xEDB88320 & mask); + } + } + return ~crc; +} + +constexpr u32 calcCrc32(std::string_view str) { + return calcCrc32(str.data(), str.size()); +} + +} // namespace ksys::util