From fd2f653b6ff54aa552f89c5b8daf79110d4a0e8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Sat, 5 Dec 2020 01:36:06 +0100 Subject: [PATCH] ksys/act: Start implementing AIClassDef --- data/uking_functions.csv | 14 +-- lib/sead | 2 +- src/KingSystem/ActorSystem/CMakeLists.txt | 2 + src/KingSystem/ActorSystem/actAiClassDef.cpp | 103 +++++++++++++++++++ src/KingSystem/ActorSystem/actAiClassDef.h | 51 +++++++-- 5 files changed, 158 insertions(+), 14 deletions(-) create mode 100644 src/KingSystem/ActorSystem/actAiClassDef.cpp diff --git a/data/uking_functions.csv b/data/uking_functions.csv index 68e716f1..0db3e879 100644 --- a/data/uking_functions.csv +++ b/data/uking_functions.csv @@ -92285,16 +92285,16 @@ 0x00000071011df6a8,sub_71011DF6A8,32, 0x00000071011df6c8,sub_71011DF6C8,96, 0x00000071011df728,sub_71011DF728,68, -0x00000071011df76c,sub_71011DF76C,92, -0x00000071011df7c8,sub_71011DF7C8,100, -0x00000071011df82c,AIClassDef::createInstance,132, -0x00000071011df8b0,sub_71011DF8B0,136, -0x00000071011df938,AIClassDef::init,608, -0x00000071011dfb98,AIClassDef::Data::load,1124, +0x00000071011df76c,sub_71011DF76C,92,_ZN4ksys10AIClassDef18SingletonDisposer_D2Ev +0x00000071011df7c8,sub_71011DF7C8,100,_ZN4ksys10AIClassDef18SingletonDisposer_D0Ev +0x00000071011df82c,AIClassDef::createInstance,132,_ZN4ksys10AIClassDef14createInstanceEPN4sead4HeapE +0x00000071011df8b0,sub_71011DF8B0,136,_ZN4ksys10AIClassDefD1Ev +0x00000071011df938,AIClassDef::init,608,_ZN4ksys10AIClassDef4initERKN4sead14SafeStringBaseIcEEPNS1_4HeapE +0x00000071011dfb98,AIClassDef::Data::load,1124,_ZN4ksys10AIClassDef4Data4loadEPN4sead4HeapE! 0x00000071011dfffc,AIClassDef::getInfo,540, 0x00000071011e0218,ai::doGetClassDef,4284, 0x00000071011e12d4,AIClassDef::getClassDef,320, -0x00000071011e1414,AIClassDef::isSystemQuery,264, +0x00000071011e1414,AIClassDef::isSystemQuery,264,_ZNK4ksys10AIClassDef13isSystemQueryERKN4sead14SafeStringBaseIcEE! 0x00000071011e151c,MassRenderer::ctor,376, 0x00000071011e1694,sub_71011E1694,244, 0x00000071011e1788,sub_71011E1788,380, diff --git a/lib/sead b/lib/sead index dfe17af3..d7bf1a52 160000 --- a/lib/sead +++ b/lib/sead @@ -1 +1 @@ -Subproject commit dfe17af36555e553d9e18f2d7bc81d66d0c1236d +Subproject commit d7bf1a5232dd68886126ae9ca68698a5e07a0193 diff --git a/src/KingSystem/ActorSystem/CMakeLists.txt b/src/KingSystem/ActorSystem/CMakeLists.txt index 2aaea86c..281f81e4 100644 --- a/src/KingSystem/ActorSystem/CMakeLists.txt +++ b/src/KingSystem/ActorSystem/CMakeLists.txt @@ -25,6 +25,8 @@ target_sources(uking PRIVATE actAiAction.h actAiClass.cpp actAiClass.h + actAiClassDef.cpp + actAiClassDef.h actAiParam.cpp actAiParam.h actAiQuery.cpp diff --git a/src/KingSystem/ActorSystem/actAiClassDef.cpp b/src/KingSystem/ActorSystem/actAiClassDef.cpp new file mode 100644 index 00000000..b9b144c9 --- /dev/null +++ b/src/KingSystem/ActorSystem/actAiClassDef.cpp @@ -0,0 +1,103 @@ +#include "KingSystem/ActorSystem/actAiClassDef.h" +#include +#include +#include +#include +#include "KingSystem/Resource/resLoadRequest.h" + +namespace ksys { + +namespace { +const char* str_AIAfter = "AIAfter"; +const char* str_ModelAfter = "ModelAfter"; +const char* str_ChangeDeleteState = "ChangeDeleteState"; +const char* str_StaticInstParams = "StaticInstParams"; +const char* str_DynamicInstParams = "DynamicInstParams"; +const char* str_MapUnitInstParams = "MapUnitInstParams"; +const char* str_AITreeVariables = "AITreeVariables"; +const char* str_AIs = "AIs"; +const char* str_Actions = "Actions"; +const char* str_Behaviors = "Behaviors"; +const char* str_Querys = "Querys"; +} // namespace + +SEAD_SINGLETON_DISPOSER_IMPL(AIClassDef) + +AIClassDef::~AIClassDef() { + freeData(); +} + +void AIClassDef::init(const sead::SafeString& aidef_file_name, sead::Heap* heap) { + res::LoadRequest req; + req.mRequester = "AIClassDef"; + req._22 = true; + sead::FixedSafeString<128> path; + path.format("Actor/AIDef/%s", aidef_file_name.cstr()); + + auto* res = sead::DynamicCast(mResHandle.load(path, &req)); + + freeData(); + mData = new (heap) Data(res->getRawData()); + mData->load(heap); +} + +// NON_MATCHING: not trying to match the heap sort. The rest should be equivalent +bool AIClassDef::Data::load(sead::Heap* heap) { + root_iter.tryGetIterByKey(&iters[s32(AIDefType::AI)], str_AIs); + root_iter.tryGetIterByKey(&iters[s32(AIDefType::Action)], str_Actions); + root_iter.tryGetIterByKey(&iters[s32(AIDefType::Behavior)], str_Behaviors); + root_iter.tryGetIterByKey(&iters[s32(AIDefType::Query)], str_Querys); + + idx_StaticInstParams = root_iter.getKeyIndex(str_StaticInstParams); + idx_DynamicInstParams = root_iter.getKeyIndex(str_DynamicInstParams); + idx_MapUnitInstParams = root_iter.getKeyIndex(str_MapUnitInstParams); + idx_AITreeVariables = root_iter.getKeyIndex(str_AITreeVariables); + idx_Childs = root_iter.getKeyIndex("childs"); + + static_cast(heap->getFreeSize()); + + for (s32 type = 0; type < NumAIDefTypes; ++type) { + if (!iters[type].isValid()) + continue; + + const s32 count = iters[type].getSize(); + if (count <= 0) + continue; + + auto& buffer = defs[type]; + buffer.allocBufferAssert(count, heap); + + for (s32 i = 0; i < count; ++i) { + buffer[i].name_hash = 0; + const char* name = nullptr; + if (iters[type].tryGetIterAndKeyNameByIndex(&buffer[i].iter, &name, i)) + buffer[i].name_hash = sead::HashCRC32::calcStringHash(name); + } + + auto ct = sead::stdIterator(buffer); + std::sort(ct.begin(), ct.end(), + [](const Def& lhs, const Def& rhs) { return lhs.name_hash < rhs.name_hash; }); + } + + return true; +} + +// NON_MATCHING: binary search might be a handwritten loop? +bool AIClassDef::isSystemQuery(const sead::SafeString& query) const { + bool ret = false; + const u32 hash = sead::HashCRC32::calcStringHash(query); + + if (!mData) + return false; + + const s32 idx = mData->defs[s32(AIDefType::Query)].binarySearchC( + [hash](const Data::Def& def) -> s32 { return hash - def.name_hash; }); + + if (idx < 0) + return false; + + mData->defs[s32(AIDefType::Query)][idx].iter.tryGetBoolByKey(&ret, "SystemQuery"); + return ret; +} + +} // namespace ksys diff --git a/src/KingSystem/ActorSystem/actAiClassDef.h b/src/KingSystem/ActorSystem/actAiClassDef.h index d3f3adad..9208ab7c 100644 --- a/src/KingSystem/ActorSystem/actAiClassDef.h +++ b/src/KingSystem/ActorSystem/actAiClassDef.h @@ -1,8 +1,13 @@ #pragma once +#include +#include #include #include #include +#include "KingSystem/Resource/resHandle.h" +#include "KingSystem/Utils/Byaml/Byaml.h" +#include "KingSystem/Utils/SafeDelete.h" #include "KingSystem/Utils/Types.h" namespace ksys { @@ -14,6 +19,8 @@ enum class AIDefType { Query = 3, }; +static constexpr s32 NumAIDefTypes = 4; + enum class AIDefInstParamKind { Static = 0, Dynamic = 1, @@ -56,21 +63,53 @@ struct AIDef { }; KSYS_CHECK_SIZE_NX150(AIDef, 0x650); -// FIXME class AIClassDef { SEAD_SINGLETON_DISPOSER(AIClassDef) + AIClassDef() = default; + ~AIClassDef(); + public: void init(const sead::SafeString& aidef_file_name, sead::Heap* heap); void getDef(AIDef* def, const sead::SafeString& class_name, AIDefInstParamKind param_kind, AIDefType class_type); -private: - class Data; + bool isSystemQuery(const sead::SafeString& query) const; - Data* mData; - // res::Handle mResHandle; +private: + struct Data { + struct Def { + u32 name_hash; + al::ByamlIter iter; + }; + + explicit Data(const u8* root) : root_iter(root) {} + bool load(sead::Heap* heap); + + sead::SafeArray iters; + sead::SafeArray, NumAIDefTypes> defs; + s32 idx_StaticInstParams; + s32 idx_DynamicInstParams; + s32 idx_MapUnitInstParams; + s32 idx_AITreeVariables; + s32 idx_Childs = -1; + al::ByamlIter root_iter; + }; + KSYS_CHECK_SIZE_NX150(Data, 0xa8); + + inline void freeData() { + if (!mData) + return; + + for (auto& defs : mData->defs) + defs.freeBuffer(); + + util::safeDelete(mData); + } + + Data* mData = nullptr; + res::Handle mResHandle; }; -// KSYS_CHECK_SIZE_NX150(AIClassDef, 0x78); +KSYS_CHECK_SIZE_NX150(AIClassDef, 0x78); } // namespace ksys