summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authornotyourav <65437533+notyourav@users.noreply.github.com>2020-11-16 15:49:02 -0800
committerGitHub <noreply@github.com>2020-11-16 15:49:02 -0800
commitd4f80d7cf97641742dd56cabc0b1d503cfdf7b0d (patch)
tree05b09142b74869f74779a00deff410019b8dcaac /src
parent8205744abcae5784138629038976f2449269a81f (diff)
parentb0498a15bf6f1782f1429ffbd0b03c187f61d7c9 (diff)
Merge branch 'master' into placement
Diffstat (limited to 'src')
-rw-r--r--src/KingSystem/ActorSystem/CMakeLists.txt5
-rw-r--r--src/KingSystem/ActorSystem/actActorParam.cpp8
-rw-r--r--src/KingSystem/ActorSystem/actActorParam.h22
-rw-r--r--src/KingSystem/ActorSystem/actActorParamMgr.cpp754
-rw-r--r--src/KingSystem/ActorSystem/actActorParamMgr.h54
-rw-r--r--src/KingSystem/ActorSystem/actActorTemplate.cpp2
-rw-r--r--src/KingSystem/ActorSystem/actAttention.cpp9
-rw-r--r--src/KingSystem/ActorSystem/actAttention.h70
-rw-r--r--src/KingSystem/ActorSystem/actInfoData.cpp296
-rw-r--r--src/KingSystem/ActorSystem/actInfoData.h135
-rw-r--r--src/KingSystem/Ecosystem/ecoLevelSensor.cpp2
-rw-r--r--src/KingSystem/GameData/gdtManager.h2
-rw-r--r--src/KingSystem/Map/mapMubinIter.h2
-rw-r--r--src/KingSystem/Resource/CMakeLists.txt32
-rw-r--r--src/KingSystem/Resource/resHandle.h1
-rw-r--r--src/KingSystem/Resource/resModelResourceDivide.cpp7
-rw-r--r--src/KingSystem/Resource/resModelResourceDivide.h30
-rw-r--r--src/KingSystem/Resource/resResource.h2
-rw-r--r--src/KingSystem/Resource/resResourceAISchedule.cpp1
-rw-r--r--src/KingSystem/Resource/resResourceAISchedule.h13
-rw-r--r--src/KingSystem/Resource/resResourceAS.cpp1
-rw-r--r--src/KingSystem/Resource/resResourceAS.h42
-rw-r--r--src/KingSystem/Resource/resResourceASList.cpp7
-rw-r--r--src/KingSystem/Resource/resResourceASList.h89
-rw-r--r--src/KingSystem/Resource/resResourceActorLink.h88
-rw-r--r--src/KingSystem/Resource/resResourceAnimInfo.cpp1
-rw-r--r--src/KingSystem/Resource/resResourceAnimInfo.h13
-rw-r--r--src/KingSystem/Resource/resResourceAttClient.cpp7
-rw-r--r--src/KingSystem/Resource/resResourceAttClient.h45
-rw-r--r--src/KingSystem/Resource/resResourceAttClientList.cpp1
-rw-r--r--src/KingSystem/Resource/resResourceAttClientList.h54
-rw-r--r--src/KingSystem/Resource/resResourceBoneControl.cpp1
-rw-r--r--src/KingSystem/Resource/resResourceBoneControl.h13
-rw-r--r--src/KingSystem/Resource/resResourceChemical.cpp1
-rw-r--r--src/KingSystem/Resource/resResourceChemical.h13
-rw-r--r--src/KingSystem/Resource/resResourceGameData.cpp2
-rw-r--r--src/KingSystem/Resource/resResourceGameSaveData.cpp2
-rw-r--r--src/KingSystem/Resource/resResourceMgrTask.cpp8
-rw-r--r--src/KingSystem/Resource/resResourceMgrTask.h5
-rw-r--r--src/KingSystem/Resource/resResourceModelList.cpp7
-rw-r--r--src/KingSystem/Resource/resResourceModelList.h114
-rw-r--r--src/KingSystem/Resource/resResourcePhysics.cpp1
-rw-r--r--src/KingSystem/Resource/resResourcePhysics.h13
-rw-r--r--src/KingSystem/Resource/resResourceRagdollBlendWeight.cpp1
-rw-r--r--src/KingSystem/Resource/resResourceRagdollBlendWeight.h13
-rw-r--r--src/KingSystem/Resource/resResourceRagdollConfig.cpp1
-rw-r--r--src/KingSystem/Resource/resResourceRagdollConfig.h13
-rw-r--r--src/KingSystem/Resource/resResourceRagdollConfigList.cpp1
-rw-r--r--src/KingSystem/Resource/resResourceRagdollConfigList.h65
-rw-r--r--src/KingSystem/Resource/resResourceUMii.cpp15
-rw-r--r--src/KingSystem/Resource/resResourceUMii.h27
-rw-r--r--src/KingSystem/Resource/resSystem.cpp9
-rw-r--r--src/KingSystem/Resource/resSystem.h4
-rw-r--r--src/KingSystem/Resource/resTempResourceLoader.cpp220
-rw-r--r--src/KingSystem/Resource/resTempResourceLoader.h87
-rw-r--r--src/KingSystem/Resource/resTextureHandleMgr.h3
-rw-r--r--src/KingSystem/Resource/resUnit.h2
-rw-r--r--src/KingSystem/Utils/Byaml.cpp1
-rw-r--r--src/KingSystem/Utils/Byaml/Byaml.cpp402
-rw-r--r--src/KingSystem/Utils/Byaml/Byaml.h (renamed from src/KingSystem/Utils/Byaml.h)158
-rw-r--r--src/KingSystem/Utils/Byaml/ByamlArrayIter.cpp29
-rw-r--r--src/KingSystem/Utils/Byaml/ByamlArrayIter.h28
-rw-r--r--src/KingSystem/Utils/Byaml/ByamlData.cpp7
-rw-r--r--src/KingSystem/Utils/Byaml/ByamlData.h45
-rw-r--r--src/KingSystem/Utils/Byaml/ByamlHashIter.cpp110
-rw-r--r--src/KingSystem/Utils/Byaml/ByamlHashIter.h38
-rw-r--r--src/KingSystem/Utils/Byaml/ByamlLocal.cpp3
-rw-r--r--src/KingSystem/Utils/Byaml/ByamlLocal.h38
-rw-r--r--src/KingSystem/Utils/Byaml/ByamlStringTableIter.cpp50
-rw-r--r--src/KingSystem/Utils/Byaml/ByamlStringTableIter.h27
-rw-r--r--src/KingSystem/Utils/Byaml/ByamlUtil.cpp (renamed from src/KingSystem/Utils/ByamlUtil.cpp)2
-rw-r--r--src/KingSystem/Utils/ByamlLocal.cpp1
-rw-r--r--src/KingSystem/Utils/ByamlLocal.h16
-rw-r--r--src/KingSystem/Utils/CMakeLists.txt19
-rw-r--r--src/KingSystem/Utils/ParamIO.h5
75 files changed, 3244 insertions, 171 deletions
diff --git a/src/KingSystem/ActorSystem/CMakeLists.txt b/src/KingSystem/ActorSystem/CMakeLists.txt
index d80bb38d..05aff8cd 100644
--- a/src/KingSystem/ActorSystem/CMakeLists.txt
+++ b/src/KingSystem/ActorSystem/CMakeLists.txt
@@ -22,6 +22,8 @@ target_sources(uking PRIVATE
actAiClass.h
actAiParam.cpp
actAiParam.h
+ actAttention.cpp
+ actAttention.h
actBaseProc.cpp
actBaseProc.h
actBaseProcHandle.cpp
@@ -40,7 +42,10 @@ target_sources(uking PRIVATE
actBaseProcUnit.h
actDebug.cpp
actDebug.h
+ actInfoData.cpp
+ actInfoData.h
actInstParamPack.cpp
actInstParamPack.h
+ actLifeRecoveryInfo.h
actTag.h
)
diff --git a/src/KingSystem/ActorSystem/actActorParam.cpp b/src/KingSystem/ActorSystem/actActorParam.cpp
index b358375a..dbe2096e 100644
--- a/src/KingSystem/ActorSystem/actActorParam.cpp
+++ b/src/KingSystem/ActorSystem/actActorParam.cpp
@@ -3,7 +3,7 @@
#include <prim/seadScopedLock.h>
#include "KingSystem/ActorSystem/actActorParamMgr.h"
#include "KingSystem/ActorSystem/actActorTemplate.h"
-#include "KingSystem/Utils/Byaml.h"
+#include "KingSystem/Utils/Byaml/Byaml.h"
namespace ksys::act {
@@ -49,8 +49,8 @@ void ActorParam::deleteResHandles() {
handles.freeBuffer();
}
-bool ActorParam::isDummyParam(res::ActorLink::Users::User user) const {
- return mRes.mActorLink->getUsers().getUserName(user) == "Dummy";
+bool ActorParam::isDummyParam(res::ActorLink::User user) const {
+ return sead::SafeString(mRes.mActorLink->getUserName(user)) == "Dummy";
}
void ActorParam::allocResHandles(sead::Heap* heap, u32 buffer_idx, s32 count) {
@@ -154,4 +154,6 @@ void ActorParam::setProfileAndPriority(const char* profile, const char* priority
}
}
+void ActorParam::onLoadFinished(ActorParamMgr*) {}
+
} // namespace ksys::act
diff --git a/src/KingSystem/ActorSystem/actActorParam.h b/src/KingSystem/ActorSystem/actActorParam.h
index 88f563ec..1186e244 100644
--- a/src/KingSystem/ActorSystem/actActorParam.h
+++ b/src/KingSystem/ActorSystem/actActorParam.h
@@ -40,6 +40,8 @@ class UMii;
namespace act {
+class ActorParamMgr;
+
// FIXME: incomplete
class ActorParam : public sead::hostio::Node {
public:
@@ -69,7 +71,15 @@ public:
LifeCondition = 22,
UMii = 23,
AnimationInfo = 24,
+ AS = 25,
+ AttClient = 26,
+ RagdollConfig = 27,
};
+ static constexpr s32 NumResourceTypes = 28;
+
+ static constexpr bool isValidType(ResourceType type) {
+ return type <= ResourceType::AnimationInfo;
+ }
union Resources {
struct {
@@ -112,7 +122,7 @@ public:
Priority getPriority() const { return mPriority; }
const Resources& getRes() const { return mRes; }
- bool isDummyParam(res::ActorLink::Users::User user) const;
+ bool isDummyParam(res::ActorLink::User user) const;
static void resetDummyResources();
@@ -141,7 +151,15 @@ private:
bool setPriority(const sead::SafeString& priority);
void setProfileAndPriority(const char* profile, const char* priority);
- u16 _8 = 0;
+ void setResourceIfValidType(ResourceType type, ParamIO* param_io) {
+ if (isValidType(type))
+ setResource(type, param_io);
+ }
+
+ void onLoadFinished(ActorParamMgr* mgr);
+
+ u8 _8 = 0;
+ u8 _9 = 0;
u8 _a = 0;
sead::FixedSafeString<64> mActorName;
sead::SafeString mProfile;
diff --git a/src/KingSystem/ActorSystem/actActorParamMgr.cpp b/src/KingSystem/ActorSystem/actActorParamMgr.cpp
index 82fa697e..e75eb43f 100644
--- a/src/KingSystem/ActorSystem/actActorParamMgr.cpp
+++ b/src/KingSystem/ActorSystem/actActorParamMgr.cpp
@@ -3,18 +3,75 @@
#include "KingSystem/ActorSystem/actASSetting.h"
#include "KingSystem/ActorSystem/actActorParam.h"
#include "KingSystem/Resource/resLoadRequest.h"
+#include "KingSystem/Resource/resResourceAIProgram.h"
+#include "KingSystem/Resource/resResourceAISchedule.h"
+#include "KingSystem/Resource/resResourceAS.h"
+#include "KingSystem/Resource/resResourceASList.h"
+#include "KingSystem/Resource/resResourceActorLink.h"
+#include "KingSystem/Resource/resResourceAnimInfo.h"
+#include "KingSystem/Resource/resResourceArchive.h"
+#include "KingSystem/Resource/resResourceAttClient.h"
+#include "KingSystem/Resource/resResourceAttClientList.h"
+#include "KingSystem/Resource/resResourceAwareness.h"
+#include "KingSystem/Resource/resResourceBoneControl.h"
+#include "KingSystem/Resource/resResourceChemical.h"
+#include "KingSystem/Resource/resResourceDamageParam.h"
+#include "KingSystem/Resource/resResourceDrop.h"
#include "KingSystem/Resource/resResourceGParamList.h"
+#include "KingSystem/Resource/resResourceLifeCondition.h"
+#include "KingSystem/Resource/resResourceLod.h"
+#include "KingSystem/Resource/resResourceMgrTask.h"
+#include "KingSystem/Resource/resResourceModelList.h"
+#include "KingSystem/Resource/resResourcePhysics.h"
+#include "KingSystem/Resource/resResourceRagdollBlendWeight.h"
+#include "KingSystem/Resource/resResourceRagdollConfig.h"
+#include "KingSystem/Resource/resResourceRagdollConfigList.h"
+#include "KingSystem/Resource/resResourceRecipe.h"
+#include "KingSystem/Resource/resResourceShop.h"
+#include "KingSystem/Resource/resResourceUMii.h"
+#include "KingSystem/Resource/resSystem.h"
+#include "KingSystem/Resource/resTempResourceLoader.h"
+#include "KingSystem/Utils/Debug.h"
+#include "KingSystem/Utils/ParamIO.h"
namespace ksys::act {
SEAD_SINGLETON_DISPOSER_IMPL(ActorParamMgr)
+using Type = ActorParam::ResourceType;
+using User = res::ActorLink::User;
+
ActorParamMgr::ActorParamMgr() = default;
ActorParamMgr::~ActorParamMgr() {
ASSetting::deleteInstance();
}
+bool ActorParamMgr::checkPath(const sead::SafeString& path) const {
+ return res::returnFalse3(path);
+}
+
+ActorParam* ActorParamMgr::allocParam(const char* actor_name, bool* allocated_new) {
+ auto lock = sead::makeScopedLock(mCS);
+
+ ActorParam* free_param = nullptr;
+ auto* param = getParam(actor_name, &free_param);
+
+ if (!param) {
+ param = free_param;
+ if (free_param)
+ free_param->mRes = {};
+ else
+ param = &mParams[NumParams - 1];
+
+ param->mActorName = actor_name;
+ *allocated_new = true;
+ }
+
+ param->incrementRef();
+ return param;
+}
+
// NON_MATCHING: addressing mode
ActorParam* ActorParamMgr::getParam(const char* actor_name, ActorParam** out_free_param) const {
auto lock = sead::makeScopedLock(mCS);
@@ -30,33 +87,13 @@ ActorParam* ActorParamMgr::getParam(const char* actor_name, ActorParam** out_fre
return nullptr;
}
-ActorParam* ActorParamMgr::loadParam(const char* actor_name, res::Handle* handle, void* x,
+ActorParam* ActorParamMgr::loadParam(const char* actor_name, res::Handle* pack_handle, void* x,
u32 load_req_c) {
- ActorParam* param;
- bool existing = false;
-
- {
- auto lock = sead::makeScopedLock(mCS);
-
- ActorParam* free_param = nullptr;
- param = getParam(actor_name, &free_param);
+ bool allocated_new = false;
+ ActorParam* param = allocParam(actor_name, &allocated_new);
- if (param) {
- existing = true;
- } else {
- param = free_param;
- if (free_param)
- free_param->mRes = {};
- else
- param = &mParams[NumParams - 1];
-
- param->mActorName = actor_name;
- }
- param->incrementRef();
- }
-
- if (!existing) {
- loadFiles(param, mTmpActorParamMgrHeap, handle, x, load_req_c);
+ if (allocated_new) {
+ loadFiles(param, mTmpActorParamMgrHeap, pack_handle, x, load_req_c);
param->setEventSignal();
} else {
param->waitForEvent();
@@ -65,8 +102,40 @@ ActorParam* ActorParamMgr::loadParam(const char* actor_name, res::Handle* handle
return param;
}
-bool ActorParamMgr::loadActorPack(res::Handle* handle, const sead::SafeString& actor_name,
- u32 load_req_c) {
+void ActorParamMgr::loadFiles(ActorParam* param, sead::Heap* heap, res::Handle* pack_handle,
+ void* x, u32 load_req_c) {
+ param->deleteResHandles();
+ param->allocResHandles(heap, 0, ActorParam::NumResourceTypes + 1);
+ param->mActiveBufferIdx = 0;
+
+ const auto* link =
+ loadFile<res::ActorLink>(param, Type::ActorLink, "Actor/ActorLink", "xml",
+ param->getActorName().cstr(), pack_handle, x, load_req_c);
+
+ if (link)
+ param->setProfileAndPriority(link->getUserName(User::Profile), link->getPriority().cstr());
+
+ const auto* actor_link = param->getRes().mActorLink;
+ if (!actor_link)
+ return;
+
+ param->mActiveBufferIdx = 0;
+
+ loadFile<res::ModelList>(param, Type::ModelList, "Actor/ModelList", "modellist",
+ actor_link->getUserName(User::Model), pack_handle, x, load_req_c);
+
+ loadFile<res::UMii>(param, Type::UMii, "Actor/UMii", "umii",
+ actor_link->getUserName(User::UMii), pack_handle, x, load_req_c);
+
+ loadFile<res::ASList>(param, Type::ASList, "Actor/ASList", "aslist",
+ actor_link->getUserName(res::ActorLink::User::AS), pack_handle, x,
+ load_req_c);
+
+ loadFilesStep2(param, heap, pack_handle, x, load_req_c);
+}
+
+bool ActorParamMgr::requestLoadActorPack(res::Handle* handle, const sead::SafeString& actor_name,
+ u32 load_req_c) {
sead::FixedSafeString<128> path;
res::LoadRequest req;
@@ -81,9 +150,638 @@ bool ActorParamMgr::loadActorPack(res::Handle* handle, const sead::SafeString& a
return handle->requestLoad(path, &req);
}
+ActorParam* ActorParamMgr::loadParamAsync(const char* actor_name, res::Handle* pack_handle,
+ bool* allocated_new, void* x, u32 load_req_c) {
+ auto* param = allocParam(actor_name, allocated_new);
+ if (!*allocated_new)
+ return param;
+
+ param->deleteResHandles();
+ param->allocResHandles(mTmpActorParamMgrHeap, 0, ActorParam::NumResourceTypes + 1);
+ param->mActiveBufferIdx = 0;
+
+ loadFileAsync<res::ActorLink>(param, Type::ActorLink, "Actor/ActorLink", "xml",
+ param->getActorName().cstr(), pack_handle, x, load_req_c);
+ return param;
+}
+
+template <typename T>
+bool ActorParamMgr::loadFileAsync(ActorParam* param, ActorParam::ResourceType type,
+ const sead::SafeString& dir_name,
+ const sead::SafeString& extension, const sead::SafeString& name,
+ res::Handle* pack_handle, void* x, u32 load_req_c) {
+ auto* handle = param->allocHandle();
+
+ if (name != "Dummy" && !name.isEmpty()) {
+ sead::FixedSafeString<128> path;
+ res::LoadRequest req;
+ prepareLoadFromActorPack(&path, &req, x, dir_name, extension, name, pack_handle, load_req_c,
+ param->getActorName());
+ return handle->requestLoad(path, &req);
+ }
+
+ if (ActorParam::isValidType(type)) {
+ auto* res = sead::DynamicCast<T>(mDummyResources[u32(type)].getResource());
+ param->setResource(type, res);
+ }
+
+ return true;
+}
+
+// NON_MATCHING: different address calculation for static_cast<ParamIO*>(res)->getPath()
+template <typename T>
+T* ActorParamMgr::handleAsyncFileLoad(ActorParam* param, s32* idx, ActorParam::ResourceType type,
+ void*) {
+ const s32 current_idx = *idx;
+ auto& handle = param->mHandles[param->mActiveBufferIdx][current_idx];
+ *idx = current_idx + 1;
+
+ if (ActorParam::isValidType(type)) {
+ if (auto* res = static_cast<T*>(param->getRes().mArray[u32(type)]))
+ return res;
+ }
+
+ if (handle.isFlag8Set())
+ return sead::DynamicCast<T>(handle.getResource());
+
+ if (!handle.isReadyOrNeedsParse())
+ return nullptr;
+
+ handle.parseResource(nullptr);
+
+ if (handle.checkLoadStatus() && type != Type::EventFlow)
+ param->_a = 1;
+
+ auto* res = sead::DynamicCast<T>(handle.getResource());
+ if (res) {
+ auto* unit = handle.getUnit();
+ if (unit)
+ static_cast<ParamIO*>(res)->getPath().copy(unit->getPath());
+ } else {
+ res = sead::DynamicCast<T>(mDummyResources[s32(type)].getResource());
+ }
+
+ if (ActorParam::isValidType(type) && res)
+ param->setResource(type, res);
+
+ return res;
+}
+
+bool ActorParamMgr::finishLoadingActorLink(ActorParam* param, void* x) {
+ s32 idx = 0;
+ if (!handleAsyncFileLoad<res::ActorLink>(param, &idx, Type::ActorLink, x))
+ return param->_a != 0;
+
+ const auto* link = param->getRes().mActorLink;
+ if (!link)
+ return true;
+
+ param->setProfileAndPriority(link->getUsers().getProfile(), link->getPriority().cstr());
+ return true;
+}
+
+void ActorParamMgr::loadParamAsyncStep2(ActorParam* param, res::Handle* pack_handle, void* x,
+ u32 load_req_c) {
+ const auto* link = param->getRes().mActorLink;
+
+ loadFileAsync<res::ModelList>(param, Type::ModelList, "Actor/ModelList", "modellist",
+ link->getUsers().getModel(), pack_handle, x, load_req_c);
+
+ loadFileAsync<res::UMii>(param, Type::UMii, "Actor/UMii", "umii", link->getUsers().getUMii(),
+ pack_handle, x, load_req_c);
+
+ loadFileAsync<res::ASList>(param, Type::ASList, "Actor/ASList", "aslist",
+ link->getUsers().getAS(), pack_handle, x, load_req_c);
+
+ loadFileAsync<res::AttClientList>(param, Type::AttClientList, "Actor/AttClientList", "atcllist",
+ link->getUserName(User::Attention), pack_handle, x,
+ load_req_c);
+
+ loadFileAsync<res::RagdollConfigList>(param, Type::RagdollConfigList, "Actor/RagdollConfigList",
+ "rgconfiglist", link->getUserName(User::RgConfigList),
+ pack_handle, x, load_req_c);
+
+ loadFileAsync<res::AIProgram>(param, Type::AIProgram, "Actor/AIProgram", "aiprog",
+ link->getUsers().getAIProgram(), pack_handle, x, load_req_c);
+
+ loadFileAsync<res::GParamList>(param, Type::GParamList, "Actor/GeneralParamList", "gparamlist",
+ link->getUsers().getGParam(), pack_handle, x, load_req_c);
+
+ loadFileAsync<res::Physics>(param, Type::Physics, "Actor/Physics", "physics",
+ link->getUsers().getPhysics(), pack_handle, x, load_req_c);
+
+ loadFileAsync<res::Chemical>(param, Type::Chemical, "Actor/Chemical", "chemical",
+ link->getUsers().getChemical(), pack_handle, x, load_req_c);
+
+ loadFileAsync<res::DamageParam>(param, Type::DamageParam, "Actor/DamageParam", "dmgparam",
+ link->getUsers().getDamageParam(), pack_handle, x, load_req_c);
+
+ loadFileAsync<res::RagdollBlendWeight>(
+ param, Type::RagdollBlendWeight, "Actor/RagdollBlendWeight", "rgbw",
+ link->getUsers().getRgBlendWeight(), pack_handle, x, load_req_c);
+
+ loadFileAsync<res::Awareness>(param, Type::Awareness, "Actor/Awareness", "awareness",
+ link->getUsers().getAwareness(), pack_handle, x, load_req_c);
+
+ loadFileAsync<res::Drop>(param, Type::DropTable, "Actor/DropTable", "drop",
+ link->getUsers().getDropTable(), pack_handle, x, load_req_c);
+
+ loadFileAsync<res::Shop>(param, Type::ShopData, "Actor/ShopData", "shop",
+ link->getUsers().getShopData(), pack_handle, x, load_req_c);
+
+ loadFileAsync<res::Recipe>(param, Type::Recipe, "Actor/Recipe", "recipe",
+ link->getUsers().getRecipe(), pack_handle, x, load_req_c);
+
+ loadFileAsync<res::Lod>(param, Type::Lod, "Actor/LOD", "lod", link->getUsers().getLOD(),
+ pack_handle, x, load_req_c);
+
+ loadFileAsync<res::AISchedule>(param, Type::AISchedule, "Actor/AISchedule", "aischedule",
+ link->getUsers().getAISchedule(), pack_handle, x, load_req_c);
+
+ loadFileAsync<res::BoneControl>(param, Type::BoneControl, "Actor/BoneControl", "bonectrl",
+ link->getUsers().getBoneControl(), pack_handle, x, load_req_c);
+
+ loadFileAsync<res::LifeCondition>(param, Type::LifeCondition, "Actor/LifeCondition",
+ "lifecondition", link->getUsers().getLifeCondition(),
+ pack_handle, x, load_req_c);
+
+ loadFileAsync<res::AnimInfo>(param, Type::AnimationInfo, "Actor/AnimationInfo", "animinfo",
+ link->getUsers().getAnimationInfo(), pack_handle, x, load_req_c);
+}
+
+bool ActorParamMgr::finishLoadingStep2(ActorParam* param, void* x) {
+ s32 idx = 1;
+
+ if (!handleAsyncFileLoad<res::ModelList>(param, &idx, Type::ModelList, x))
+ return false;
+
+ if (!handleAsyncFileLoad<res::UMii>(param, &idx, Type::UMii, x))
+ return false;
+
+ if (!handleAsyncFileLoad<res::ASList>(param, &idx, Type::ASList, x))
+ return false;
+
+ if (!handleAsyncFileLoad<res::AttClientList>(param, &idx, Type::AttClientList, x))
+ return false;
+
+ if (!handleAsyncFileLoad<res::RagdollConfigList>(param, &idx, Type::RagdollConfigList, x))
+ return false;
+
+ if (!handleAsyncFileLoad<res::AIProgram>(param, &idx, Type::AIProgram, x))
+ return false;
+
+ if (!handleAsyncFileLoad<res::GParamList>(param, &idx, Type::GParamList, x))
+ return false;
+
+ if (!handleAsyncFileLoad<res::Physics>(param, &idx, Type::Physics, x))
+ return false;
+
+ if (!handleAsyncFileLoad<res::Chemical>(param, &idx, Type::Chemical, x))
+ return false;
+
+ if (!handleAsyncFileLoad<res::DamageParam>(param, &idx, Type::DamageParam, x))
+ return false;
+
+ if (!handleAsyncFileLoad<res::RagdollBlendWeight>(param, &idx, Type::RagdollBlendWeight, x))
+ return false;
+
+ if (!handleAsyncFileLoad<res::Awareness>(param, &idx, Type::Awareness, x))
+ return false;
+
+ if (!handleAsyncFileLoad<res::Drop>(param, &idx, Type::DropTable, x))
+ return false;
+
+ if (!handleAsyncFileLoad<res::Shop>(param, &idx, Type::ShopData, x))
+ return false;
+
+ if (!handleAsyncFileLoad<res::Recipe>(param, &idx, Type::Recipe, x))
+ return false;
+
+ if (!handleAsyncFileLoad<res::Lod>(param, &idx, Type::Lod, x))
+ return false;
+
+ if (!handleAsyncFileLoad<res::AISchedule>(param, &idx, Type::AISchedule, x))
+ return false;
+
+ if (!handleAsyncFileLoad<res::BoneControl>(param, &idx, Type::BoneControl, x))
+ return false;
+
+ if (!handleAsyncFileLoad<res::LifeCondition>(param, &idx, Type::LifeCondition, x))
+ return false;
+
+ if (!handleAsyncFileLoad<res::AnimInfo>(param, &idx, Type::AnimationInfo, x))
+ return false;
+
+ return true;
+}
+
+void ActorParamMgr::loadExtraResAsync(ActorParam* param, res::Handle* pack_handle, void* x,
+ u32 load_req_c) {
+ const auto* aslist = param->getRes().mASList;
+ const auto* atcllist = param->getRes().mAttClientList;
+ const auto* rgconfiglist = param->getRes().mRagdollConfigList;
+
+ const auto num_as = aslist ? aslist->getASDefines().size() : 0;
+ const auto num_att = atcllist ? atcllist->getClients().size() : 0;
+ const auto num_rg = rgconfiglist ? rgconfiglist->getImpulseParams().size() : 0;
+
+ param->allocResHandles(mTmpActorParamMgrHeap, 1, num_as + num_att + num_rg);
+ param->mActiveBufferIdx = 1;
+
+ if (aslist) {
+ for (s32 i = 0; i < num_as; ++i) {
+ loadFileAsync<res::AS>(param, Type::AS, "Actor/AS", "as",
+ aslist->getASDefines()[i].getFileName(), pack_handle, x,
+ load_req_c);
+ }
+ }
+
+ if (atcllist) {
+ for (s32 i = 0; i < num_att; ++i) {
+ loadFileAsync<res::AttClient>(param, Type::AttClient, "Actor/AttClient", "atcl",
+ atcllist->getClients()[i].getFileName(), pack_handle, x,
+ load_req_c);
+ }
+ }
+
+ if (rgconfiglist) {
+ for (s32 i = 0; i < num_rg; ++i) {
+ loadFileAsync<res::RagdollConfig>(
+ param, Type::RagdollConfig, "Actor/RagdollConfig", "rgconfig",
+ rgconfiglist->getImpulseParams()[i].getFileName(), pack_handle, x, load_req_c);
+ }
+ }
+}
+
+bool ActorParamMgr::finishLoadingExtraRes(ActorParam* param, void* x) {
+ s32 idx = 0;
+
+ auto* aslist = param->getRes().mASList;
+ if (aslist) {
+ for (s32 i = 0, n = aslist->getASDefines().size(); i < n; ++i) {
+ const sead::SafeString file_name = aslist->getASDefines()[i].getFileName();
+ if (file_name == "Dummy" || file_name.isEmpty()) {
+ auto* as = sead::DynamicCast<res::AS>(mDummyResources[u32(Type::AS)].getResource());
+ as->setIndex(u32(Type::AS));
+ aslist->addAS_(i, as);
+ ++idx;
+ } else {
+ const res::Handle& handle = param->mHandles[1][idx];
+ if (handle.isFlag8Set()) {
+ ++idx;
+ continue;
+ }
+
+ auto* as = handleAsyncFileLoad<res::AS>(param, &idx, Type::AS, x);
+ if (!as)
+ return false;
+
+ as->setIndex(u32(Type::AS));
+ aslist->addAS_(i, as);
+ }
+ }
+ }
+
+ auto* atcllist = param->getRes().mAttClientList;
+ if (atcllist) {
+ for (s32 i = 0, n = atcllist->getClients().size(); i < n; ++i) {
+ const sead::SafeString file_name = atcllist->getClients()[i].getFileName();
+ if (file_name == "Dummy" || file_name.isEmpty()) {
+ auto* res = sead::DynamicCast<res::AttClient>(
+ mDummyResources[u32(Type::AttClient)].getResource());
+ /// @bug This should be Type::AttClient. Copy paste error?
+ res->setIndex(u32(Type::AS));
+ atcllist->addClient_(i, res);
+ ++idx;
+ } else {
+ const res::Handle& handle = param->mHandles[1][idx];
+ if (handle.isFlag8Set()) {
+ ++idx;
+ continue;
+ }
+
+ auto* res = handleAsyncFileLoad<res::AttClient>(param, &idx, Type::AttClient, x);
+ if (!res)
+ return false;
+
+ res->setIndex(u32(Type::AttClient));
+ atcllist->addClient_(i, res);
+ }
+ }
+ }
+
+ auto* rgconfiglist = param->getRes().mRagdollConfigList;
+ if (rgconfiglist) {
+ for (s32 i = 0, n = rgconfiglist->getImpulseParams().size(); i < n; ++i) {
+ const sead::SafeString file_name = rgconfiglist->getImpulseParams()[i].getFileName();
+ if (file_name == "Dummy" || file_name.isEmpty()) {
+ auto* res = sead::DynamicCast<res::RagdollConfig>(
+ mDummyResources[u32(Type::RagdollConfig)].getResource());
+ res->setIndex(u32(Type::RagdollConfig));
+ rgconfiglist->addImpulseParamConfig_(i, res);
+ ++idx;
+ } else {
+ const res::Handle& handle = param->mHandles[1][idx];
+ if (handle.isFlag8Set()) {
+ ++idx;
+ continue;
+ }
+
+ auto* res =
+ handleAsyncFileLoad<res::RagdollConfig>(param, &idx, Type::RagdollConfig, x);
+ if (!res)
+ return false;
+
+ res->setIndex(u32(Type::RagdollConfig));
+ rgconfiglist->addImpulseParamConfig_(i, res);
+ }
+ }
+ }
+
+ param->_9 = 0;
+ param->onLoadFinished(this);
+ param->setEventSignal();
+ return true;
+}
+
+void ActorParamMgr::allocExtraResHandles(ActorParam* param, sead::Heap* heap) const {
+ s32 num_extra_handles = 0;
+
+ auto* aslist = param->getRes().mASList;
+ auto* atcllist = param->getRes().mAttClientList;
+ auto* rgconfiglist = param->getRes().mRagdollConfigList;
+
+ if (aslist)
+ num_extra_handles += aslist->getASDefines().size();
+
+ if (atcllist)
+ num_extra_handles += atcllist->getClients().size();
+
+ if (rgconfiglist)
+ num_extra_handles += rgconfiglist->getImpulseParams().size();
+
+ param->allocResHandles(heap, 1, num_extra_handles);
+}
+
+void ActorParamMgr::loadFilesStep2(ActorParam* param, sead::Heap* heap, res::Handle* pack_handle,
+ void* x, u32 load_req_c) {
+ const auto* link = param->getRes().mActorLink;
+ param->mActiveBufferIdx = 0;
+
+ loadFile<res::AttClientList>(param, Type::AttClientList, "Actor/AttClientList", "atcllist",
+ link->getUserName(User::Attention), pack_handle, x, load_req_c);
+
+ loadFile<res::RagdollConfigList>(param, Type::RagdollConfigList, "Actor/RagdollConfigList",
+ "rgconfiglist", link->getUserName(User::RgConfigList),
+ pack_handle, x, load_req_c);
+
+ // Start loading the extra ActorParam files.
+ allocExtraResHandles(param, heap);
+ param->mActiveBufferIdx = 1;
+
+ if (auto* aslist = param->getRes().mASList) {
+ for (s32 i = 0; i < aslist->getASDefines().size(); ++i) {
+ auto* as = loadFile<res::AS>(param, Type::AS, "Actor/AS", "as",
+ aslist->getASDefines()[i].getFileName(), pack_handle, x,
+ load_req_c);
+ if (as) {
+ as->setIndex(u32(Type::AS));
+ aslist->addAS_(i, as);
+ }
+ }
+ }
+
+ if (auto* list = param->getRes().mAttClientList) {
+ for (s32 i = 0; i < list->getClients().size(); ++i) {
+ auto* client = loadFile<res::AttClient>(param, Type::AttClient, "Actor/AttClient",
+ "atcl", list->getClients()[i].getFileName(),
+ pack_handle, x, load_req_c);
+ if (client) {
+ client->setIndex(u32(Type::AttClient));
+ list->addClient_(i, client);
+ }
+ }
+ }
+
+ if (auto* list = param->getRes().mRagdollConfigList) {
+ for (s32 i = 0; i < list->getImpulseParams().size(); ++i) {
+ auto* config = loadFile<res::RagdollConfig>(
+ param, Type::RagdollConfig, "Actor/RagdollConfig", "rgconfig",
+ list->getImpulseParams()[i].getFileName(), pack_handle, x, load_req_c);
+ if (config) {
+ config->setIndex(u32(Type::RagdollConfig));
+ list->addImpulseParamConfig_(i, config);
+ }
+ }
+ }
+
+ // We have now finished loading the extra ActorParam files.
+ // Go back to using the main resource handle buffer.
+ param->mActiveBufferIdx = 0;
+
+ loadFile<res::AIProgram>(param, Type::AIProgram, "Actor/AIProgram", "aiprog",
+ link->getUsers().getAIProgram(), pack_handle, x, load_req_c);
+
+ loadFile<res::GParamList>(param, Type::GParamList, "Actor/GeneralParamList", "gparamlist",
+ link->getUsers().getGParam(), pack_handle, x, load_req_c);
+
+ loadFile<res::Physics>(param, Type::Physics, "Actor/Physics", "physics",
+ link->getUsers().getPhysics(), pack_handle, x, load_req_c);
+
+ loadFile<res::Chemical>(param, Type::Chemical, "Actor/Chemical", "chemical",
+ link->getUsers().getChemical(), pack_handle, x, load_req_c);
+
+ loadFile<res::DamageParam>(param, Type::DamageParam, "Actor/DamageParam", "dmgparam",
+ link->getUsers().getDamageParam(), pack_handle, x, load_req_c);
+
+ loadFile<res::RagdollBlendWeight>(param, Type::RagdollBlendWeight, "Actor/RagdollBlendWeight",
+ "rgbw", link->getUsers().getRgBlendWeight(), pack_handle, x,
+ load_req_c);
+
+ loadFile<res::Awareness>(param, Type::Awareness, "Actor/Awareness", "awareness",
+ link->getUsers().getAwareness(), pack_handle, x, load_req_c);
+
+ loadFile<res::Drop>(param, Type::DropTable, "Actor/DropTable", "drop",
+ link->getUsers().getDropTable(), pack_handle, x, load_req_c);
+
+ loadFile<res::Shop>(param, Type::ShopData, "Actor/ShopData", "shop",
+ link->getUsers().getShopData(), pack_handle, x, load_req_c);
+
+ loadFile<res::Recipe>(param, Type::Recipe, "Actor/Recipe", "recipe",
+ link->getUsers().getRecipe(), pack_handle, x, load_req_c);
+
+ loadFile<res::Lod>(param, Type::Lod, "Actor/LOD", "lod", link->getUsers().getLOD(), pack_handle,
+ x, load_req_c);
+
+ loadFile<res::AISchedule>(param, Type::AISchedule, "Actor/AISchedule", "aischedule",
+ link->getUsers().getAISchedule(), pack_handle, x, load_req_c);
+
+ loadFile<res::BoneControl>(param, Type::BoneControl, "Actor/BoneControl", "bonectrl",
+ link->getUsers().getBoneControl(), pack_handle, x, load_req_c);
+
+ loadFile<res::LifeCondition>(param, Type::LifeCondition, "Actor/LifeCondition", "lifecondition",
+ link->getUsers().getLifeCondition(), pack_handle, x, load_req_c);
+
+ loadFile<res::AnimInfo>(param, Type::AnimationInfo, "Actor/AnimationInfo", "animinfo",
+ link->getUsers().getAnimationInfo(), pack_handle, x, load_req_c);
+
+ param->_9 = 0;
+ param->onLoadFinished(this);
+}
+
+void ActorParamMgr::unloadParam(ActorParam* param) {
+ auto lock = sead::makeScopedLock(mCS);
+ param->decrementRef();
+}
+
+bool ActorParamMgr::prepareLoadFromActorPack(sead::BufferedSafeString* path, res::LoadRequest* req,
+ void*, const sead::SafeString& dir_name,
+ const sead::SafeString& extension,
+ const sead::SafeString& file_name,
+ res::Handle* pack_handle, u32 load_req_c,
+ const sead::SafeString& requester) {
+ path->format("%s/%s.b%s", dir_name.cstr(), file_name.cstr(), extension.cstr());
+
+ bool in_pack = false;
+ if (pack_handle && pack_handle->isSuccess()) {
+ auto* pack = static_cast<sead::ArchiveRes*>(pack_handle->getResourceUnchecked());
+ in_pack = pack->getFile(*path) != nullptr;
+ }
+
+ const bool cond1 = res::returnFalse3(*path);
+ const bool is_host_path = res::isHostPath(*path);
+ if (!in_pack && !cond1 && !is_host_path && path->include("bxml")) {
+ sead::FormatFixedSafeString<256> message("↓↓↓\nファイルパス : %s\n↑↑↑\n", path->cstr());
+ util::PrintDebug(message);
+ }
+
+ const bool ret = res::returnFalse3(*path);
+ if (!ret && pack_handle && pack_handle->isSuccess()) {
+ req->mPackHandle = pack_handle;
+ req->_24 = false;
+ }
+
+ req->_c = load_req_c;
+ req->mRequester = requester;
+ req->_8 = true;
+ return ret;
+}
+
+res::Archive* ActorParamMgr::loadActorPack(res::Handle* handle, const sead::SafeString& actor_name,
+ u32 load_req_c) {
+ sead::FixedSafeString<128> path;
+ res::TempResourceLoader::LoadArg arg;
+ arg.retry_on_failure = true;
+ arg.use_handle = true;
+
+ if (mFlags.isOn(Flag::_5))
+ return nullptr;
+
+ path.format("Actor/Pack/%s.bactorpack", actor_name.cstr());
+ arg.load_req.mRequester = actor_name;
+ arg.load_req._c = load_req_c;
+ arg.load_req._8 = true;
+ arg.load_req._28 = false;
+ arg.load_req.mPath = path;
+
+ res::TempResourceLoader loader;
+ {
+ res::TempResourceLoader::InitArg init_arg{};
+ res::ResourceMgrTask::instance()->initTempResourceLoader(&loader, init_arg);
+ }
+ loader.load(arg);
+
+ res::SimpleLoadRequest req;
+ req.mRequester = "tap::ActorParamMgr";
+ req.mPath = path;
+ req._c = 2;
+ return sead::DynamicCast<res::Archive>(handle->load(path, &req));
+}
+
+template <typename T>
+T* ActorParamMgr::loadFile(ActorParam* param, ActorParam::ResourceType type, const char* dir_name_c,
+ const char* extension_c, const char* name_c, res::Handle* pack_handle,
+ void* x, u32 load_req_c) {
+ const sead::SafeString name = name_c;
+ const sead::SafeString extension = extension_c;
+ sead::FixedSafeString<128> path;
+
+ T* res = nullptr;
+
+ if (name != "Dummy" && !name.isEmpty()) {
+ auto* temp_handle = param->allocHandle();
+ const sead::SafeString* actor_name;
+ path.format("%s/%s.b%s", dir_name_c, name_c, extension_c);
+ {
+ res::SimpleLoadRequest req;
+ req._8 = true;
+ actor_name = &param->getActorName();
+ req.mRequester = *actor_name;
+ req.mPath = path;
+ req._c = 2;
+ res = sead::DynamicCast<T>(temp_handle->load(path, &req));
+ }
+
+ // If loading the resource from the RomFS has failed, try to load it from the actor pack.
+ if (!res) {
+ if (!pack_handle->isSuccess())
+ loadActorPack(pack_handle, *actor_name, load_req_c);
+
+ res::LoadRequest req;
+ prepareLoadFromActorPack(&path, &req, x, dir_name_c, extension_c, name_c, pack_handle,
+ load_req_c, *actor_name);
+ res = sead::DynamicCast<T>(temp_handle->load(path, &req));
+
+ if (!res) {
+ static_cast<void>(temp_handle->isSuccess());
+ // Try again without the pack.
+ if (req.mPackHandle) {
+ req.mPackHandle = nullptr;
+ req._24 = false;
+ res = sead::DynamicCast<T>(temp_handle->load(path, &req));
+ if (!res)
+ static_cast<void>(temp_handle->isSuccess());
+ }
+ }
+ }
+
+ if (!res)
+ param->freeLastHandle();
+ else if (type == ActorParam::ResourceType::EventFlow)
+ temp_handle->requestUnload2();
+
+ } else {
+ path.format("%s/%s.b%s", dir_name_c, name_c, extension_c);
+ res = sead::DynamicCast<T>(mDummyResources[s32(type)].getResource());
+ }
+
+ if (res) {
+ if (type == ActorParam::ResourceType::EventFlow)
+ return res;
+
+ static_cast<ParamIO*>(res)->getPath().copy(path);
+ param->setResourceIfValidType(type, res);
+ return res;
+ }
+
+ if (extension != "fevfl")
+ param->_a = 1;
+
+ // Fall back to using the dummy resource.
+ res = sead::DynamicCast<T>(mDummyResources[s32(type)].getResource());
+ sead::FixedSafeString<128> dummy_path;
+ dummy_path.format("%s/Dummy.b%s", dir_name_c, extension_c);
+ if (res) {
+ static_cast<ParamIO*>(res)->getPath().copy(dummy_path);
+ param->setResourceIfValidType(type, res);
+ }
+
+ return res;
+}
+
res::GParamList* ActorParamMgr::getDummyGParamList() const {
return static_cast<res::GParamList*>(
- mResHandles[u32(ActorParam::ResourceType::GParamList)].getResourceUnchecked());
+ mDummyResources[u32(ActorParam::ResourceType::GParamList)].getResourceUnchecked());
}
} // namespace ksys::act
diff --git a/src/KingSystem/ActorSystem/actActorParamMgr.h b/src/KingSystem/ActorSystem/actActorParamMgr.h
index accb3457..461ca4a6 100644
--- a/src/KingSystem/ActorSystem/actActorParamMgr.h
+++ b/src/KingSystem/ActorSystem/actActorParamMgr.h
@@ -6,6 +6,7 @@
#include <prim/seadSafeString.h>
#include <prim/seadTypedBitFlag.h>
#include <thread/seadCriticalSection.h>
+#include "KingSystem/ActorSystem/actActorParam.h"
#include "KingSystem/Resource/resHandle.h"
#include "KingSystem/System/DebugMessage.h"
#include "KingSystem/System/KingEditor.h"
@@ -14,13 +15,13 @@
namespace ksys {
namespace res {
+class Archive;
class GParamList;
+class LoadRequest;
} // namespace res
namespace act {
-class ActorParam;
-
// FIXME: incomplete
class ActorParamMgr final : public sead::hostio::Node, public KingEditorComponent {
SEAD_SINGLETON_DISPOSER(ActorParamMgr)
@@ -35,11 +36,23 @@ public:
sead::Heap* getDebugHeap() const { return mDebugHeap; }
sead::Heap* getTmpActorParamMgrHeap() const { return mTmpActorParamMgrHeap; }
+ bool checkPath(const sead::SafeString& path) const;
+
void init(sead::Heap* heap, sead::Heap* debug_heap);
+ ActorParam* allocParam(const char* actor_name, bool* allocated_new);
ActorParam* getParam(const char* actor_name, ActorParam** out_free_param) const;
- ActorParam* loadParam(const char* actor_name, res::Handle* handle, void* x, u32 load_req_c);
-
+ ActorParam* loadParam(const char* actor_name, res::Handle* pack_handle, void* x,
+ u32 load_req_c);
+ void unloadParam(ActorParam* param);
+
+ ActorParam* loadParamAsync(const char* actor_name, res::Handle* pack_handle,
+ bool* allocated_new, void* x, u32 load_req_c);
+ bool finishLoadingActorLink(ActorParam* param, void* x);
+ void loadParamAsyncStep2(ActorParam* param, res::Handle* pack_handle, void* x, u32 load_req_c);
+ bool finishLoadingStep2(ActorParam* param, void* x);
+ void loadExtraResAsync(ActorParam* param, res::Handle* pack_handle, void* x, u32 load_req_c);
+ bool finishLoadingExtraRes(ActorParam* param, void* x);
res::GParamList* getDummyGParamList() const;
private:
@@ -50,9 +63,36 @@ private:
_5 = _1 | _4,
};
- void loadFiles(ActorParam* param, sead::Heap* heap, res::Handle* handle, void* x,
+ void loadFiles(ActorParam* param, sead::Heap* heap, res::Handle* pack_handle, void* x,
u32 load_req_c);
- bool loadActorPack(res::Handle* handle, const sead::SafeString& actor_name, u32 load_req_c);
+ bool requestLoadActorPack(res::Handle* handle, const sead::SafeString& actor_name,
+ u32 load_req_c);
+ bool prepareLoadFromActorPack(sead::BufferedSafeString* path, res::LoadRequest* req, void* x,
+ const sead::SafeString& dir_name,
+ const sead::SafeString& extension,
+ const sead::SafeString& file_name, res::Handle* pack_handle,
+ u32 load_req_c, const sead::SafeString& requester);
+ res::Archive* loadActorPack(res::Handle* handle, const sead::SafeString& actor_name,
+ u32 load_req_c);
+
+ template <typename T>
+ T* loadFile(ActorParam* param, ActorParam::ResourceType type, const char* dir_name_c,
+ const char* extension_c, const char* name_c, res::Handle* pack_handle, void* x,
+ u32 load_req_c);
+
+ template <typename T>
+ bool loadFileAsync(ActorParam* param, ActorParam::ResourceType type,
+ const sead::SafeString& dir_name, const sead::SafeString& extension,
+ const sead::SafeString& name, res::Handle* pack_handle, void* x,
+ u32 load_req_c);
+
+ template <typename T>
+ T* handleAsyncFileLoad(ActorParam* param, s32* idx, ActorParam::ResourceType type, void* x);
+
+ void loadFilesStep2(ActorParam* param, sead::Heap* heap, res::Handle* pack_handle, void* x,
+ u32 load_req_c);
+
+ void allocExtraResHandles(ActorParam* param, sead::Heap* heap) const;
static constexpr s32 NumParams = 0x400;
@@ -63,7 +103,7 @@ private:
void* _e8 = nullptr;
sead::Heap* mDebugHeap = nullptr;
sead::Heap* mTmpActorParamMgrHeap = nullptr;
- sead::SafeArray<res::Handle, 28> mResHandles;
+ sead::SafeArray<res::Handle, ActorParam::NumResourceTypes> mDummyResources;
mutable sead::CriticalSection mCS;
};
KSYS_CHECK_SIZE_NX150(ActorParamMgr, 0xa00);
diff --git a/src/KingSystem/ActorSystem/actActorTemplate.cpp b/src/KingSystem/ActorSystem/actActorTemplate.cpp
index 0daf5dae..f4b16526 100644
--- a/src/KingSystem/ActorSystem/actActorTemplate.cpp
+++ b/src/KingSystem/ActorSystem/actActorTemplate.cpp
@@ -1,6 +1,6 @@
#include "KingSystem/ActorSystem/actActorTemplate.h"
#include "KingSystem/ActorSystem/actActorParamMgr.h"
-#include "KingSystem/Utils/Byaml.h"
+#include "KingSystem/Utils/Byaml/Byaml.h"
#include "KingSystem/Utils/SafeDelete.h"
namespace ksys::act {
diff --git a/src/KingSystem/ActorSystem/actAttention.cpp b/src/KingSystem/ActorSystem/actAttention.cpp
new file mode 100644
index 00000000..001c72f2
--- /dev/null
+++ b/src/KingSystem/ActorSystem/actAttention.cpp
@@ -0,0 +1,9 @@
+#include "KingSystem/ActorSystem/actAttention.h"
+
+namespace ksys::act {
+
+SEAD_ENUM_IMPL(AttActionType)
+
+SEAD_ENUM_IMPL(AttPriorityType)
+
+} // namespace ksys::act
diff --git a/src/KingSystem/ActorSystem/actAttention.h b/src/KingSystem/ActorSystem/actAttention.h
new file mode 100644
index 00000000..bf7ed816
--- /dev/null
+++ b/src/KingSystem/ActorSystem/actAttention.h
@@ -0,0 +1,70 @@
+#pragma once
+
+#include <prim/seadEnum.h>
+
+namespace ksys::act {
+
+enum class AttType {
+ Action = 0,
+ Lock = 1,
+ SwordSearch = 2,
+ Attack = 3,
+ Appeal = 4,
+ JumpRide = 5,
+ NameBalloon = 6,
+ LookOnly = 7,
+ Invalid = 8,
+};
+
+// Make sure to update AttActionType if this is changed
+enum class AttActionCode {
+ None = 0x1800000,
+ Talk,
+ Listen,
+ Awake,
+ Grab,
+ Open,
+ Pick,
+ Catch,
+ CheckCatch,
+ CatchWeapon,
+ Skin,
+ Sleep,
+ Sit,
+ Lumber,
+ Pushpull,
+ Read,
+ Check,
+ Boot,
+ BootPStop,
+ Leave,
+ Remind,
+ Buy,
+ Ride,
+ Wakeboard,
+ WakeboardRide,
+ RideRito,
+ RideZora,
+ Cook,
+ KillTime,
+ Display,
+ DisplayBow,
+ DisplayShield,
+ PickUp,
+ Pray,
+ PullOut,
+ Waterfall,
+ CommandWait,
+ CommandCome,
+ Thrust,
+ Put,
+ PickToEvent,
+ Dummy,
+};
+
+// clang-format off
+SEAD_ENUM(AttActionType, None,Talk,Listen,Awake,Grab,Open,Pick,Catch,CheckCatch,CatchWeapon,Skin,Sleep,Sit,Lumber,Pushpull,Read,Check,Boot,BootPStop,Leave,Remind,Buy,Ride,Wakeboard,WakeboardRide,RideRito,RideZora,Cook,KillTime,Display,DisplayBow,DisplayShield,PickUp,Pray,PullOut,Waterfall,CommandWait,CommandCome,Thrust,Put,PickToEvent,Dummy)
+SEAD_ENUM(AttPriorityType, Default,Enemy,Npc,Obj,ObjLow,ObjMiddle,ObjHigh,Bullet)
+// clang-format on
+
+} // namespace ksys::act
diff --git a/src/KingSystem/ActorSystem/actInfoData.cpp b/src/KingSystem/ActorSystem/actInfoData.cpp
new file mode 100644
index 00000000..54499e40
--- /dev/null
+++ b/src/KingSystem/ActorSystem/actInfoData.cpp
@@ -0,0 +1,296 @@
+#include "KingSystem/ActorSystem/actInfoData.h"
+#include <codec/seadHashCRC32.h>
+#include <math/seadMathNumbers.h>
+#include "KingSystem/Utils/Byaml/Byaml.h"
+#include "KingSystem/Utils/Byaml/ByamlArrayIter.h"
+#include "KingSystem/Utils/Byaml/ByamlData.h"
+#include "KingSystem/Utils/Byaml/ByamlHashIter.h"
+
+namespace ksys::act {
+
+SEAD_SINGLETON_DISPOSER_IMPL(InfoData)
+
+InfoData::~InfoData() {
+ if (mHashesIter)
+ delete mHashesIter;
+
+ if (mActorsIter)
+ delete mActorsIter;
+
+ if (mRootIter)
+ delete mRootIter;
+
+ mRootIter = nullptr;
+ mHashesIter = nullptr;
+ mActorsIter = nullptr;
+ mHashesBytes = nullptr;
+ mHashes = nullptr;
+ mActorsBytes = nullptr;
+ mActorOffsets = nullptr;
+}
+
+void InfoData::init(u8* data, sead::Heap* heap, sead::Heap* debug_heap) {
+ mRootIter = new (heap) al::ByamlIter(data);
+ mHashesIter = new (heap) al::ByamlIter();
+ mActorsIter = new (heap) al::ByamlIter();
+
+ if (debug_heap) {
+ mDebugEntries = new (debug_heap) DebugEntry[NumDebugEntries];
+ for (s32 i = 0; i != NumDebugEntries; ++i)
+ mDebugEntries[i].used = false;
+ } else {
+ mDebugEntries = nullptr;
+ }
+
+ if (mRootIter->tryGetIterByKey(mHashesIter, "Hashes")) {
+ mHashesBytes = mHashesIter->getData();
+ mHashes = al::ByamlArrayIter(mHashesIter->getRootNode()).getDataTable();
+ }
+
+ if (mRootIter->tryGetIterByKey(mActorsIter, "Actors")) {
+ mActorsBytes = mActorsIter->getData();
+ mActorOffsets = al::ByamlArrayIter(mActorsIter->getRootNode()).getDataTable();
+ }
+
+ mNumActors = mActorsIter->getSize();
+ _88 = 0;
+ mDebugHeap = debug_heap;
+ mTagsIdx = mRootIter->getKeyIndex("tags");
+ mProfileIdx = mRootIter->getKeyIndex("profile");
+ mInvalidWeathersIdx = mRootIter->getKeyIndex("invalidWeathers");
+ mInvalidTimesIdx = mRootIter->getKeyIndex("invalidTimes");
+ mNameIdx = mRootIter->getKeyIndex("name");
+ mSystemSameGroupActorNameIdx = mRootIter->getKeyIndex("systemSameGroupActorName");
+}
+
+bool InfoData::getActorIter(al::ByamlIter* iter, const char* actor, bool x) const {
+ const u32 hash = sead::HashCRC32::calcStringHash(actor);
+
+ // Perform a binary search.
+ s32 a = 0;
+ s32 b = mNumActors;
+ while (a < b) {
+ const s32 idx = (a + b) / 2;
+ const u32 hash_i = mHashes[idx];
+
+ if (hash_i == hash) {
+ *iter = al::ByamlIter(mActorsBytes, mActorsBytes + mActorOffsets[idx]);
+ return true;
+ }
+
+ if (hash_i >= hash)
+ b = idx;
+ else
+ a = idx + 1;
+ }
+
+ if (x)
+ static_cast<void>(logFailure(actor));
+
+ return false;
+}
+
+void InfoData::getRecipeInfo(const char* actor, InfoData::RecipeInfo& info) const {
+ al::ByamlIter iter;
+ if (getActorIter(&iter, actor)) {
+ info.num_items = iter.getIntByKey("normal0StuffNum");
+
+ info.items[0].name = iter.getStringByKey("normal0ItemName01");
+ info.items[0].num = iter.getIntByKey("normal0ItemNum01");
+
+ info.items[1].name = iter.getStringByKey("normal0ItemName02");
+ info.items[1].num = iter.getIntByKey("normal0ItemNum02");
+
+ info.items[2].name = iter.getStringByKey("normal0ItemName03");
+ info.items[2].num = iter.getIntByKey("normal0ItemNum03");
+
+ } else {
+ info.num_items = 0;
+
+ info.items[0].name = sead::SafeString::cEmptyString;
+ info.items[0].num = 0;
+
+ info.items[1].name = sead::SafeString::cEmptyString;
+ info.items[1].num = 0;
+
+ info.items[2].name = sead::SafeString::cEmptyString;
+ info.items[2].num = 0;
+ }
+}
+
+s32 InfoData::getIntByKey(const al::ByamlIter& iter, const char* key, s32 default_) {
+ s32 value;
+ return iter.tryGetIntByKey(&value, key) ? value : default_;
+}
+
+const char* InfoData::getStringByKey(const al::ByamlIter& iter, const char* key,
+ const sead::SafeString& default_) {
+ const char* value;
+ return iter.tryGetStringByKey(&value, key) ? value : default_.cstr();
+}
+
+[[gnu::noinline]] static InfoData::Locator::Type
+getLocatorTypeFromStr(const sead::SafeString& type) {
+ static constexpr const char* types[] = {"Trunk", "Branch", "GlowStone",
+ "OnTree", "MagnePos", "StopTimerPos"};
+ for (s32 i = 0; i < s32(std::size(types)); ++i) {
+ if (type == types[i])
+ return InfoData::Locator::Type(i);
+ }
+ return InfoData::Locator::Type::Invalid;
+}
+
+void InfoData::getLocators(const char* actor, Locators& info) const {
+ info.num = 0;
+
+ al::ByamlIter iter;
+ if (!getActorIter(&iter, actor))
+ return;
+
+ al::ByamlIter iter_locators;
+ if (!iter.tryGetIterByKey(&iter_locators, "locators"))
+ return;
+
+ info.num = iter_locators.getSize();
+ for (s32 i = 0; i < info.num; ++i) {
+ al::ByamlIter it;
+ if (!iter_locators.tryGetIterByIndex(&it, i))
+ continue;
+
+ const char* type_str{};
+ auto& locator = info.locators[i];
+
+ it.tryGetFloatByKey(&locator.pos.x, "pos_x");
+ it.tryGetFloatByKey(&locator.pos.y, "pos_y");
+ it.tryGetFloatByKey(&locator.pos.z, "pos_z");
+
+ it.tryGetFloatByKey(&locator.rot.x, "rot_x");
+ it.tryGetFloatByKey(&locator.rot.y, "rot_y");
+ it.tryGetFloatByKey(&locator.rot.z, "rot_z");
+
+ it.tryGetStringByKey(&type_str, "type");
+ locator.type = type_str ? getLocatorTypeFromStr(type_str) : Locator::Type::Invalid;
+
+ locator.rot *= 2 * sead::numbers::pi / 360.0;
+ }
+}
+
+void InfoData::getHomeAreas(const char* actor, HomeAreas& info) const {
+ info.names.fill("");
+
+ al::ByamlIter iter;
+ if (!getActorIter(&iter, actor))
+ return;
+
+ al::ByamlIter home_area;
+ if (!iter.tryGetIterByKey(&home_area, "homeArea"))
+ return;
+
+ for (s32 i = 0, n = home_area.getSize(); i < info.names.size() && i < n; ++i) {
+ al::ByamlIter it;
+ if (home_area.tryGetIterByIndex(&it, i))
+ it.tryGetStringByKey(&info.names[i], "name");
+ }
+}
+
+const char* InfoData::getSameGroupActorName(const char* actor) const {
+ al::ByamlIter iter;
+ return [&] {
+ if (getActorIter(&iter, actor, false)) {
+ al::ByamlHashIter hash_iter{iter.getRootNode()};
+ al::ByamlData data;
+ if (hash_iter.getDataByKey(&data, mSystemSameGroupActorNameIdx)) {
+ const char* name;
+ if (iter.tryConvertString(&name, &data))
+ return name;
+ }
+ }
+ return sead::SafeString::cEmptyString.cstr();
+ }();
+}
+
+const char* InfoData::getString(const char* actor, const char* key,
+ const sead::SafeString& default_, bool x) const {
+ al::ByamlIter iter;
+ if (!getActorIter(&iter, actor, x))
+ return default_.cstr();
+
+ return getStringByKey(iter, key, default_);
+}
+
+const char* InfoData::getSLinkUser(const char* actor) const {
+ al::ByamlIter iter;
+ if (!getActorIter(&iter, actor))
+ return "Dummy";
+
+ return getStringByKey(iter, "slink", "Dummy");
+}
+
+bool InfoData::getSLinkAndELinkUsers(const char* actor, const char** elink,
+ const char** slink) const {
+ al::ByamlIter iter;
+ if (getActorIter(&iter, actor)) {
+ *elink = getStringByKey(iter, "elink", "Dummy");
+ *slink = getStringByKey(iter, "slink", "Dummy");
+ return true;
+ }
+ *elink = "Dummy";
+ *slink = "Dummy";
+ return false;
+}
+
+const char* InfoData::getXLinkUser(const char* actor) const {
+ return getString(actor, "xlink", "Dummy");
+}
+
+bool InfoData::getActorProfile(const char** profile, const char* actor) const {
+ al::ByamlIter iter;
+ if (getActorIter(&iter, actor)) {
+ al::ByamlHashIter hash_iter{iter.getRootNode()};
+ al::ByamlData data;
+ if (hash_iter.getDataByKey(&data, mProfileIdx))
+ return iter.tryConvertString(profile, &data);
+ }
+ *profile = "Dummy";
+ return false;
+}
+
+s32 InfoData::getInt(const char* actor, const char* key, s32 default_, bool x) const {
+ al::ByamlIter iter;
+ if (!getActorIter(&iter, actor, x))
+ return default_;
+
+ return getIntByKey(iter, key, default_);
+}
+
+f32 InfoData::getFloat(const char* actor, const char* key, f32 default_, bool x) const {
+ al::ByamlIter iter;
+ if (!getActorIter(&iter, actor, x))
+ return default_;
+
+ return getFloatByKey(iter, key, default_);
+}
+
+bool InfoData::getBool(const char* actor, const char* key, bool default_, bool x) const {
+ al::ByamlIter iter;
+ if (!getActorIter(&iter, actor, x))
+ return default_;
+
+ return getBoolByKey(iter, key, default_);
+}
+
+f32 InfoData::getFloatByKey(const al::ByamlIter& iter, const char* key, f32 default_) {
+ f32 value;
+ return iter.tryGetFloatByKey(&value, key) ? value : default_;
+}
+
+bool InfoData::getBoolByKey(const al::ByamlIter& iter, const char* key, bool default_) {
+ bool value;
+ return iter.tryGetBoolByKey(&value, key) ? value != 0 : default_;
+}
+
+f32 InfoData::getScale(const char* actor) const {
+ return getFloat(actor, "actorScale", 1.0);
+}
+
+} // namespace ksys::act
diff --git a/src/KingSystem/ActorSystem/actInfoData.h b/src/KingSystem/ActorSystem/actInfoData.h
new file mode 100644
index 00000000..56a84e6f
--- /dev/null
+++ b/src/KingSystem/ActorSystem/actInfoData.h
@@ -0,0 +1,135 @@
+#pragma once
+
+#include <basis/seadTypes.h>
+#include <container/seadSafeArray.h>
+#include <gfx/seadColor.h>
+#include <heap/seadDisposer.h>
+#include <math/seadVector.h>
+#include <prim/seadSafeString.h>
+#include "KingSystem/Utils/Types.h"
+
+namespace al {
+class ByamlIter;
+}
+
+namespace ksys::act {
+
+class InfoData {
+ SEAD_SINGLETON_DISPOSER(InfoData)
+ InfoData() = default;
+ virtual ~InfoData();
+
+public:
+ struct ModelInfo {
+ sead::Vector3f baseScale;
+ sead::Color4f addColor;
+ sead::Color4f mulColor;
+ const char* bfres;
+ const char* mainModel;
+ };
+ KSYS_CHECK_SIZE_NX150(ModelInfo, 0x40);
+
+ struct RecipeInfo {
+ struct Item {
+ sead::FixedSafeString<64> name;
+ s32 num;
+ };
+
+ s32 num_items;
+ Item items[3];
+ };
+ KSYS_CHECK_SIZE_NX150(RecipeInfo, 0x128);
+
+ struct Locator {
+ enum class Type {
+ Invalid = -1,
+ Trunk = 0,
+ Branch = 1,
+ GlowStone = 2,
+ OnTree = 3,
+ MagnePos = 4,
+ StopTimerPos = 5,
+ };
+
+ Type type;
+ sead::Vector3f pos;
+ sead::Vector3f rot;
+ };
+ KSYS_CHECK_SIZE_NX150(Locator, 0x1c);
+
+ struct Locators {
+ s32 num;
+ sead::SafeArray<Locator, 8> locators;
+ };
+ KSYS_CHECK_SIZE_NX150(Locators, 0xe4);
+
+ struct HomeAreas {
+ sead::SafeArray<const char*, 3> names;
+ };
+ KSYS_CHECK_SIZE_NX150(HomeAreas, 0x18);
+
+ void init(u8* data, sead::Heap* heap, sead::Heap* debug_heap);
+
+ void getModelInfo(const char* actor, ModelInfo& info) const;
+ bool getActorIter(al::ByamlIter* iter, const char* actor, bool x = true) const;
+ bool logFailure(const sead::SafeString& actor_name) const;
+ void getRecipeInfo(const char* actor, RecipeInfo& info) const;
+ void getLocators(const char* actor, Locators& info) const;
+ void getHomeAreas(const char* actor, HomeAreas& info) const;
+ // TODO: invalid time function
+ // TODO: tag functions
+ const char* getSameGroupActorName(const char* actor) const;
+ // TODO: more functions
+ const char* getSLinkUser(const char* actor) const;
+ bool getSLinkAndELinkUsers(const char* actor, const char** elink, const char** slink) const;
+ const char* getXLinkUser(const char* actor) const;
+ bool getActorProfile(const char** profile, const char* actor) const;
+ // TODO: more functions
+ f32 getScale(const char* actor) const;
+
+ const char* getString(const char* actor, const char* key, const sead::SafeString& default_,
+ bool x = true) const;
+ s32 getInt(const char* actor, const char* key, s32 default_ = 0, bool x = true) const;
+ f32 getFloat(const char* actor, const char* key, f32 default_ = 0, bool x = true) const;
+ bool getBool(const char* actor, const char* key, bool default_ = false, bool x = true) const;
+
+ static s32 getIntByKey(const al::ByamlIter& iter, const char* key, s32 default_ = 0);
+ static f32 getFloatByKey(const al::ByamlIter& iter, const char* key, f32 default_ = 0);
+ static bool getBoolByKey(const al::ByamlIter& iter, const char* key, bool default_ = false);
+ static const char* getStringByKey(const al::ByamlIter& iter, const char* key,
+ const sead::SafeString& default_);
+
+private:
+ struct DebugEntry {
+ sead::FixedSafeString<64> str;
+ bool used;
+ };
+ KSYS_CHECK_SIZE_NX150(DebugEntry, 0x60);
+
+ al::ByamlIter* mRootIter{};
+ al::ByamlIter* mHashesIter{};
+ al::ByamlIter* mActorsIter{};
+
+ const u8* mHashesBytes{};
+ const u32* mHashes{};
+
+ const u8* mActorsBytes{};
+ const u32* mActorOffsets{};
+
+ s32 mTagsIdx = -1;
+ s32 mInvalidWeathersIdx = -1;
+ s32 mInvalidTimesIdx = -1;
+ s32 mSystemSameGroupActorNameIdx = -1;
+ s32 mNameIdx = -1;
+ s32 mProfileIdx = -1;
+
+ s32 mNumActors = 0;
+ DebugEntry* mDebugEntries{};
+ u32 _88 = 0;
+ sead::Heap* mDebugHeap{};
+
+ static constexpr s32 NumDebugEntries = 512;
+};
+KSYS_CHECK_SIZE_NX150(InfoData, 0x98);
+
+} // namespace ksys::act
diff --git a/src/KingSystem/Ecosystem/ecoLevelSensor.cpp b/src/KingSystem/Ecosystem/ecoLevelSensor.cpp
index 42676953..f7db37fd 100644
--- a/src/KingSystem/Ecosystem/ecoLevelSensor.cpp
+++ b/src/KingSystem/Ecosystem/ecoLevelSensor.cpp
@@ -1,5 +1,5 @@
#include "KingSystem/Ecosystem/ecoLevelSensor.h"
-#include "KingSystem/Utils/Byaml.h"
+#include "KingSystem/Utils/Byaml/Byaml.h"
namespace ksys::eco {
diff --git a/src/KingSystem/GameData/gdtManager.h b/src/KingSystem/GameData/gdtManager.h
index 8208414b..7dca62ce 100644
--- a/src/KingSystem/GameData/gdtManager.h
+++ b/src/KingSystem/GameData/gdtManager.h
@@ -12,7 +12,7 @@
#include "KingSystem/GameData/gdtTriggerParam.h"
#include "KingSystem/Resource/resHandle.h"
#include "KingSystem/System/KingEditor.h"
-#include "KingSystem/Utils/Byaml.h"
+#include "KingSystem/Utils/Byaml/Byaml.h"
#include "KingSystem/Utils/Types.h"
namespace sead {
diff --git a/src/KingSystem/Map/mapMubinIter.h b/src/KingSystem/Map/mapMubinIter.h
index cf9f7243..fc7c8606 100644
--- a/src/KingSystem/Map/mapMubinIter.h
+++ b/src/KingSystem/Map/mapMubinIter.h
@@ -2,7 +2,7 @@
#include <prim/seadSafeString.h>
#include "KingSystem/Map/mapTypes.h"
-#include "KingSystem/Utils/Byaml.h"
+#include "KingSystem/Utils/Byaml/Byaml.h"
namespace ksys::map {
diff --git a/src/KingSystem/Resource/CMakeLists.txt b/src/KingSystem/Resource/CMakeLists.txt
index 715888cf..e2e23994 100644
--- a/src/KingSystem/Resource/CMakeLists.txt
+++ b/src/KingSystem/Resource/CMakeLists.txt
@@ -105,12 +105,16 @@ target_sources(uking PRIVATE
resLoadRequest.h
resMemoryTask.cpp
resMemoryTask.h
+ resModelResourceDivide.cpp
+ resModelResourceDivide.h
resOffsetReadFileDevice.cpp
resOffsetReadFileDevice.h
resResourceMgrTask.cpp
resResourceMgrTask.h
resSystem.cpp
resSystem.h
+ resTempResourceLoader.cpp
+ resTempResourceLoader.h
resTextureHandleList.cpp
resTextureHandleList.h
resTextureHandleMgr.cpp
@@ -128,10 +132,26 @@ target_sources(uking PRIVATE
resResourceActorLink.h
resResourceAIProgram.cpp
resResourceAIProgram.h
+ resResourceAISchedule.cpp
+ resResourceAISchedule.h
+ resResourceAnimInfo.cpp
+ resResourceAnimInfo.h
+ resResourceAS.cpp
+ resResourceAS.h
+ resResourceASList.cpp
+ resResourceASList.h
+ resResourceAttClient.cpp
+ resResourceAttClient.h
+ resResourceAttClientList.cpp
+ resResourceAttClientList.h
resResourceArchive.cpp
resResourceArchive.h
resResourceAwareness.cpp
resResourceAwareness.h
+ resResourceBoneControl.cpp
+ resResourceBoneControl.h
+ resResourceChemical.cpp
+ resResourceChemical.h
resResourceDamageParam.cpp
resResourceDamageParam.h
resResourceDemo.cpp
@@ -148,8 +168,20 @@ target_sources(uking PRIVATE
resResourceLifeCondition.h
resResourceLod.cpp
resResourceLod.h
+ resResourceModelList.cpp
+ resResourceModelList.h
+ resResourcePhysics.cpp
+ resResourcePhysics.h
+ resResourceRagdollBlendWeight.cpp
+ resResourceRagdollBlendWeight.h
+ resResourceRagdollConfig.cpp
+ resResourceRagdollConfig.h
+ resResourceRagdollConfigList.cpp
+ resResourceRagdollConfigList.h
resResourceRecipe.cpp
resResourceRecipe.h
resResourceShop.cpp
resResourceShop.h
+ resResourceUMii.cpp
+ resResourceUMii.h
)
diff --git a/src/KingSystem/Resource/resHandle.h b/src/KingSystem/Resource/resHandle.h
index 32993f0d..e97ff259 100644
--- a/src/KingSystem/Resource/resHandle.h
+++ b/src/KingSystem/Resource/resHandle.h
@@ -73,6 +73,7 @@ public:
sead::SafeString makeEmptyString();
+ ResourceUnit* getUnit() const { return mUnit; }
void setUnit(ResourceUnit* unit) { mUnit = unit; }
bool isLinked() const { return mListNode.isLinked(); }
diff --git a/src/KingSystem/Resource/resModelResourceDivide.cpp b/src/KingSystem/Resource/resModelResourceDivide.cpp
new file mode 100644
index 00000000..772fac7f
--- /dev/null
+++ b/src/KingSystem/Resource/resModelResourceDivide.cpp
@@ -0,0 +1,7 @@
+#include "KingSystem/Resource/resModelResourceDivide.h"
+
+namespace ksys::res {
+
+SEAD_SINGLETON_DISPOSER_IMPL(ModelResourceDivide)
+
+} // namespace ksys::res
diff --git a/src/KingSystem/Resource/resModelResourceDivide.h b/src/KingSystem/Resource/resModelResourceDivide.h
new file mode 100644
index 00000000..1e7b9576
--- /dev/null
+++ b/src/KingSystem/Resource/resModelResourceDivide.h
@@ -0,0 +1,30 @@
+#pragma once
+
+#include <heap/seadDisposer.h>
+#include <prim/seadSafeString.h>
+#include "KingSystem/Resource/resHandle.h"
+
+namespace al {
+class ByamlIter;
+}
+
+namespace ksys::res {
+
+class ModelResourceDivide {
+ SEAD_SINGLETON_DISPOSER(ModelResourceDivide)
+ ModelResourceDivide() = default;
+ virtual ~ModelResourceDivide();
+
+public:
+ void init(sead::Heap* heap);
+
+ const char* getModelResource(const sead::SafeString& model_name,
+ const sead::SafeString& fmdb_name) const;
+
+private:
+ al::ByamlIter* mIter{};
+ Handle mHandle;
+};
+KSYS_CHECK_SIZE_NX150(ModelResourceDivide, 0x80);
+
+} // namespace ksys::res
diff --git a/src/KingSystem/Resource/resResource.h b/src/KingSystem/Resource/resResource.h
index d8613219..675fe739 100644
--- a/src/KingSystem/Resource/resResource.h
+++ b/src/KingSystem/Resource/resResource.h
@@ -21,7 +21,7 @@ public:
Resource();
~Resource() override;
- void doCreate_(u8* buffer, u32 bufferSize, sead::Heap* heap) override;
+ void doCreate_(u8* buffer, u32 buffer_size, sead::Heap* heap) override;
virtual bool needsParse() const { return false; }
virtual bool m2_() { return true; }
diff --git a/src/KingSystem/Resource/resResourceAISchedule.cpp b/src/KingSystem/Resource/resResourceAISchedule.cpp
new file mode 100644
index 00000000..99e09384
--- /dev/null
+++ b/src/KingSystem/Resource/resResourceAISchedule.cpp
@@ -0,0 +1 @@
+#include "KingSystem/Resource/resResourceAISchedule.h"
diff --git a/src/KingSystem/Resource/resResourceAISchedule.h b/src/KingSystem/Resource/resResourceAISchedule.h
new file mode 100644
index 00000000..2d1ceb29
--- /dev/null
+++ b/src/KingSystem/Resource/resResourceAISchedule.h
@@ -0,0 +1,13 @@
+#pragma once
+
+#include "KingSystem/Resource/resResource.h"
+#include "KingSystem/Utils/ParamIO.h"
+
+namespace ksys::res {
+
+// TODO
+class AISchedule : public ParamIO, public Resource {
+ SEAD_RTTI_OVERRIDE(AISchedule, Resource)
+};
+
+} // namespace ksys::res
diff --git a/src/KingSystem/Resource/resResourceAS.cpp b/src/KingSystem/Resource/resResourceAS.cpp
new file mode 100644
index 00000000..e4d0dbdc
--- /dev/null
+++ b/src/KingSystem/Resource/resResourceAS.cpp
@@ -0,0 +1 @@
+#include "KingSystem/Resource/resResourceAS.h"
diff --git a/src/KingSystem/Resource/resResourceAS.h b/src/KingSystem/Resource/resResourceAS.h
new file mode 100644
index 00000000..76f2af2d
--- /dev/null
+++ b/src/KingSystem/Resource/resResourceAS.h
@@ -0,0 +1,42 @@
+#pragma once
+
+#include <agl/Utils/aglParameter.h>
+#include <agl/Utils/aglParameterList.h>
+#include <agl/Utils/aglParameterObj.h>
+#include <container/seadBuffer.h>
+#include "KingSystem/Resource/resResource.h"
+#include "KingSystem/Utils/ParamIO.h"
+#include "KingSystem/Utils/Types.h"
+
+namespace ksys::res {
+
+class AS : public ParamIO, public Resource {
+ SEAD_RTTI_OVERRIDE(AS, Resource)
+public:
+ struct Element {};
+
+ AS();
+
+ void doCreate_(u8*, u32, sead::Heap*) override {}
+ bool needsParse() const override { return true; }
+ bool parse_(u8* data, size_t size, sead::Heap* heap) override;
+ void finalize_() override;
+
+private:
+ sead::Buffer<Element*> mElements;
+ agl::utl::ParameterList mElementsList;
+
+ agl::utl::ParameterObj mCommonParams;
+ agl::utl::Parameter<f32> mRandomRateMin;
+ agl::utl::Parameter<f32> mRandomRateMax;
+ agl::utl::Parameter<bool> mForbidPartialDemoAS;
+ agl::utl::Parameter<bool> mUseIK;
+ u8 _3b8{};
+ u8 _3b9{};
+ u8 _3ba{};
+ u8 _3bb{};
+ sead::Heap* mHeap{};
+};
+KSYS_CHECK_SIZE_NX150(AS, 0x3c8);
+
+} // namespace ksys::res
diff --git a/src/KingSystem/Resource/resResourceASList.cpp b/src/KingSystem/Resource/resResourceASList.cpp
new file mode 100644
index 00000000..31880bbf
--- /dev/null
+++ b/src/KingSystem/Resource/resResourceASList.cpp
@@ -0,0 +1,7 @@
+#include "KingSystem/Resource/resResourceASList.h"
+
+namespace ksys::res {
+
+ASList::ASList() : ParamIO("aslist", 0) {}
+
+} // namespace ksys::res
diff --git a/src/KingSystem/Resource/resResourceASList.h b/src/KingSystem/Resource/resResourceASList.h
new file mode 100644
index 00000000..34795aa4
--- /dev/null
+++ b/src/KingSystem/Resource/resResourceASList.h
@@ -0,0 +1,89 @@
+#pragma once
+
+#include <agl/Utils/aglParameter.h>
+#include <agl/Utils/aglParameterList.h>
+#include <agl/Utils/aglParameterObj.h>
+#include <container/seadBuffer.h>
+#include <prim/seadStorageFor.h>
+#include "KingSystem/Resource/resResource.h"
+#include "KingSystem/Utils/ParamIO.h"
+
+namespace ksys::res {
+
+class AS;
+
+class ASList : public ParamIO, public Resource {
+ SEAD_RTTI_OVERRIDE(ASList, Resource)
+public:
+ struct ASDefine {
+ const char* getFileName() const { return file_name.ref().cstr(); }
+
+ agl::utl::Parameter<sead::SafeString> name;
+ agl::utl::Parameter<sead::SafeString> file_name;
+ agl::utl::ParameterObj obj;
+ AS* as;
+ };
+ KSYS_CHECK_SIZE_NX150(ASDefine, 0x88);
+
+ struct CFDefine {
+ agl::utl::Parameter<sead::SafeString> name;
+ agl::utl::ParameterObj pre_obj;
+ sead::Buffer<void*> posts;
+ agl::utl::ParameterList posts_list;
+ sead::Buffer<void*> excepts;
+ agl::utl::ParameterObj obj;
+ agl::utl::ParameterList excepts_list;
+ };
+ KSYS_CHECK_SIZE_NX150(CFDefine, 0x138);
+
+ struct AddRes {
+ agl::utl::Parameter<sead::SafeString> _0;
+ agl::utl::Parameter<sead::SafeString> _28;
+ agl::utl::Parameter<bool> _50;
+ agl::utl::ParameterObj obj;
+ };
+ KSYS_CHECK_SIZE_NX150(AddRes, 0xa0);
+
+ struct Common {
+ agl::utl::Parameter<f32> rate_all;
+ agl::utl::ParameterObj obj;
+ };
+ KSYS_CHECK_SIZE_NX150(Common, 0x50);
+
+ struct Buffers {
+ Buffers() { _0 = 0; }
+
+ s32 _0;
+ sead::Buffer<ASDefine> as_defines;
+ sead::Buffer<CFDefine> cf_defines;
+ sead::Buffer<AddRes> add_reses;
+ };
+
+ ASList();
+ ~ASList() override;
+
+ void doCreate_(u8* buffer, u32 buffer_size, sead::Heap* heap) override;
+ bool needsParse() const override { return true; }
+ bool parse_(u8* data, size_t size, sead::Heap* heap) override;
+
+ const sead::Buffer<ASDefine>& getASDefines() const { return mBuffers.as_defines; }
+ const sead::Buffer<CFDefine>& getCFDefines() const { return mBuffers.cf_defines; }
+ const sead::Buffer<AddRes>& getAddReses() const { return mBuffers.add_reses; }
+ const Common& getCommon() const { return mCommon.ref(); }
+
+ void addAS_(s32 index, AS* as);
+
+protected:
+ bool finishParsing_() override;
+ bool m7_() override;
+
+private:
+ Buffers mBuffers;
+ agl::utl::ParameterList mCFDefinesList;
+ agl::utl::ParameterList mASDefinesList;
+ agl::utl::ParameterList mAddResesList;
+ sead::StorageFor<Common> mCommon{sead::ZeroInitializeTag{}};
+};
+KSYS_CHECK_SIZE_NX150(ASList, 0x410);
+
+} // namespace ksys::res
diff --git a/src/KingSystem/Resource/resResourceActorLink.h b/src/KingSystem/Resource/resResourceActorLink.h
index 7463e1c2..7230d68f 100644
--- a/src/KingSystem/Resource/resResourceActorLink.h
+++ b/src/KingSystem/Resource/resResourceActorLink.h
@@ -13,41 +13,68 @@ namespace ksys::res {
class ActorLink : public ParamIO, public Resource {
SEAD_RTTI_OVERRIDE(ActorLink, Resource)
public:
- struct Users {
- enum class User {
- Profile = 0,
- ActorCapture = 1,
- AS = 2,
- Model = 3,
- Anim = 4,
- AIProgram = 5,
- GParam = 6,
- DamageParam = 7,
- RgConfigList = 8,
- RgBlendWeight = 9,
- Awareness = 10,
- Physics = 11,
- Chemical = 12,
- Attention = 13,
- ELink = 14,
- SLink = 15,
- XLink = 16,
- DropTable = 17,
- ShopData = 18,
- Recipe = 19,
- LOD = 20,
- BoneControl = 21,
- AISchedule = 22,
- LifeCondition = 23,
- UMii = 24,
- AnimationInfo = 25,
- };
+ enum class User {
+ Profile = 0,
+ ActorCapture = 1,
+ AS = 2,
+ Model = 3,
+ Anim = 4,
+ AIProgram = 5,
+ GParam = 6,
+ DamageParam = 7,
+ RgConfigList = 8,
+ RgBlendWeight = 9,
+ Awareness = 10,
+ Physics = 11,
+ Chemical = 12,
+ Attention = 13,
+ ELink = 14,
+ SLink = 15,
+ XLink = 16,
+ DropTable = 17,
+ ShopData = 18,
+ Recipe = 19,
+ LOD = 20,
+ BoneControl = 21,
+ AISchedule = 22,
+ LifeCondition = 23,
+ UMii = 24,
+ AnimationInfo = 25,
+ };
+ struct Users {
const agl::utl::Parameter<sead::SafeString>& getUser(User user) const {
return *(&profile + u32(user));
}
- sead::SafeString getUserName(User user) const { return getUser(user).ref().cstr(); }
+ const char* getUserName(User user) const { return getUser(user).ref().cstr(); }
+
+ const char* getProfile() const { return profile.ref().cstr(); }
+ const char* getActorCapture() const { return actor_capture.ref().cstr(); }
+ const char* getAS() const { return as.ref().cstr(); }
+ const char* getModel() const { return model.ref().cstr(); }
+ const char* getAnim() const { return anim.ref().cstr(); }
+ const char* getAIProgram() const { return ai_program.ref().cstr(); }
+ const char* getGParam() const { return gparam.ref().cstr(); }
+ const char* getDamageParam() const { return damage_param.ref().cstr(); }
+ const char* getRgConfigList() const { return rg_config_list.ref().cstr(); }
+ const char* getRgBlendWeight() const { return rg_blend_weight.ref().cstr(); }
+ const char* getAwareness() const { return awareness.ref().cstr(); }
+ const char* getPhysics() const { return physics.ref().cstr(); }
+ const char* getChemical() const { return chemical.ref().cstr(); }
+ const char* getAttention() const { return attention.ref().cstr(); }
+ const char* getELink() const { return elink.ref().cstr(); }
+ const char* getSLink() const { return slink.ref().cstr(); }
+ const char* getXLink() const { return xlink.ref().cstr(); }
+ const char* getDropTable() const { return drop_table.ref().cstr(); }
+ const char* getShopData() const { return shop_data.ref().cstr(); }
+ const char* getRecipe() const { return recipe.ref().cstr(); }
+ const char* getLOD() const { return lod.ref().cstr(); }
+ const char* getBoneControl() const { return bone_control.ref().cstr(); }
+ const char* getAISchedule() const { return ai_schedule.ref().cstr(); }
+ const char* getLifeCondition() const { return life_condition.ref().cstr(); }
+ const char* getUMii() const { return umii.ref().cstr(); }
+ const char* getAnimationInfo() const { return animation_info.ref().cstr(); }
agl::utl::Parameter<sead::SafeString> profile;
agl::utl::Parameter<sead::SafeString> actor_capture;
@@ -84,6 +111,7 @@ public:
bool needsParse() const override { return true; }
const Users& getUsers() const { return mUsers; }
+ const char* getUserName(User user) const { return getUsers().getUserName(user); }
const sead::SafeString& getActorNameJpn() const { return mActorNameJpn.ref(); }
const sead::SafeString& getPriority() const { return mPriority.ref(); }
f32 getActorScale() const { return mActorScale.ref(); }
diff --git a/src/KingSystem/Resource/resResourceAnimInfo.cpp b/src/KingSystem/Resource/resResourceAnimInfo.cpp
new file mode 100644
index 00000000..b70e4e2d
--- /dev/null
+++ b/src/KingSystem/Resource/resResourceAnimInfo.cpp
@@ -0,0 +1 @@
+#include "KingSystem/Resource/resResourceAnimInfo.h"
diff --git a/src/KingSystem/Resource/resResourceAnimInfo.h b/src/KingSystem/Resource/resResourceAnimInfo.h
new file mode 100644
index 00000000..d25f9203
--- /dev/null
+++ b/src/KingSystem/Resource/resResourceAnimInfo.h
@@ -0,0 +1,13 @@
+#pragma once
+
+#include "KingSystem/Resource/resResource.h"
+#include "KingSystem/Utils/ParamIO.h"
+
+namespace ksys::res {
+
+// TODO
+class AnimInfo : public ParamIO, public Resource {
+ SEAD_RTTI_OVERRIDE(AnimInfo, Resource)
+};
+
+} // namespace ksys::res
diff --git a/src/KingSystem/Resource/resResourceAttClient.cpp b/src/KingSystem/Resource/resResourceAttClient.cpp
new file mode 100644
index 00000000..2bbe4f26
--- /dev/null
+++ b/src/KingSystem/Resource/resResourceAttClient.cpp
@@ -0,0 +1,7 @@
+#include "KingSystem/Resource/resResourceAttClient.h"
+
+namespace ksys::res {
+
+AttClient::AttClient() : ParamIO("atcl", 0) {}
+
+} // namespace ksys::res
diff --git a/src/KingSystem/Resource/resResourceAttClient.h b/src/KingSystem/Resource/resResourceAttClient.h
new file mode 100644
index 00000000..808b8c81
--- /dev/null
+++ b/src/KingSystem/Resource/resResourceAttClient.h
@@ -0,0 +1,45 @@
+#pragma once
+
+#include <agl/Utils/aglParameter.h>
+#include <agl/Utils/aglParameterObj.h>
+#include <container/seadBuffer.h>
+#include <prim/seadSafeString.h>
+#include "KingSystem/ActorSystem/actAttention.h"
+#include "KingSystem/Resource/resResource.h"
+#include "KingSystem/Utils/ParamIO.h"
+#include "KingSystem/Utils/Types.h"
+
+namespace ksys::res {
+
+class AttClient : public ParamIO, public Resource {
+ SEAD_RTTI_OVERRIDE(AttClient, Resource)
+public:
+ struct Check {};
+
+ AttClient();
+ ~AttClient() override;
+
+ act::AttType getAttType() const { return mAttType; }
+ act::AttActionCode getActionCode() const { return mActionCode; }
+ act::AttPriorityType getPriorityType() const { return mPriorityType; }
+ const sead::SafeString& getPriorityTypeStr() const { return mPriorityTypeStr; }
+ const sead::Buffer<Check*>& getChecks() const { return mChecks; }
+
+ void doCreate_(u8*, u32, sead::Heap*) override {}
+ bool needsParse() const override { return true; }
+ bool parse_(u8* data, size_t size, sead::Heap* heap) override;
+
+private:
+ act::AttType mAttType = act::AttType::Action;
+ act::AttActionCode mActionCode = act::AttActionCode::None;
+ act::AttPriorityType mPriorityType = act::AttPriorityType::Default;
+ sead::FixedSafeString<32> mPriorityTypeStr;
+ agl::utl::ParameterObj mAttClientParamsObj;
+ agl::utl::Parameter<sead::FixedSafeString<32>> mAttTypeParam;
+ agl::utl::Parameter<sead::FixedSafeString<32>> mActionTypeParam;
+ agl::utl::Parameter<sead::FixedSafeString<32>> mPriorityTypeParam;
+ sead::Buffer<Check*> mChecks;
+};
+KSYS_CHECK_SIZE_NX150(AttClient, 0x428);
+
+} // namespace ksys::res
diff --git a/src/KingSystem/Resource/resResourceAttClientList.cpp b/src/KingSystem/Resource/resResourceAttClientList.cpp
new file mode 100644
index 00000000..c764ef74
--- /dev/null
+++ b/src/KingSystem/Resource/resResourceAttClientList.cpp
@@ -0,0 +1 @@
+#include "KingSystem/Resource/resResourceAttClientList.h"
diff --git a/src/KingSystem/Resource/resResourceAttClientList.h b/src/KingSystem/Resource/resResourceAttClientList.h
new file mode 100644
index 00000000..aaf85966
--- /dev/null
+++ b/src/KingSystem/Resource/resResourceAttClientList.h
@@ -0,0 +1,54 @@
+#pragma once
+
+#include <agl/Utils/aglParameter.h>
+#include <agl/Utils/aglParameterList.h>
+#include <agl/Utils/aglParameterObj.h>
+#include <container/seadBuffer.h>
+#include "KingSystem/Resource/resResource.h"
+#include "KingSystem/Utils/ParamIO.h"
+#include "KingSystem/Utils/Types.h"
+
+namespace ksys::res {
+
+class AttClient;
+
+class AttClientList : public ParamIO, public Resource {
+ SEAD_RTTI_OVERRIDE(AttClientList, Resource)
+public:
+ struct AttPos {
+ agl::utl::Parameter<sead::SafeString> _0;
+ agl::utl::Parameter<sead::Vector3f> _28;
+ agl::utl::Parameter<sead::Vector3f> _50;
+ agl::utl::Parameter<bool> _78;
+ };
+ KSYS_CHECK_SIZE_NX150(AttPos, 0x98);
+
+ struct Client {
+ const char* getFileName() const { return file_name.ref().cstr(); }
+
+ agl::utl::Parameter<sead::SafeString> name;
+ agl::utl::Parameter<sead::SafeString> file_name;
+ agl::utl::Parameter<bool> is_valid;
+ agl::utl::ParameterObj obj;
+ AttClient* client;
+ };
+ KSYS_CHECK_SIZE_NX150(Client, 0xa8);
+
+ AttClientList() : ParamIO("atcllist", 0) {}
+
+ const AttPos& getAttPos() const { return mAttPos; }
+ bool isForceEdit() const { return mForceEdit.ref(); }
+ const sead::Buffer<Client>& getClients() const { return mClients; }
+
+ void addClient_(s32 index, AttClient* client) { mClients[index].client = client; }
+
+private:
+ agl::utl::ParameterList mAttClientsList;
+ agl::utl::ParameterObj mAttPosObj;
+ AttPos mAttPos;
+ agl::utl::Parameter<bool> mForceEdit;
+ sead::Buffer<Client> mClients;
+};
+KSYS_CHECK_SIZE_NX150(AttClientList, 0x3f0);
+
+} // namespace ksys::res
diff --git a/src/KingSystem/Resource/resResourceBoneControl.cpp b/src/KingSystem/Resource/resResourceBoneControl.cpp
new file mode 100644
index 00000000..b8d7521d
--- /dev/null
+++ b/src/KingSystem/Resource/resResourceBoneControl.cpp
@@ -0,0 +1 @@
+#include "KingSystem/Resource/resResourceBoneControl.h"
diff --git a/src/KingSystem/Resource/resResourceBoneControl.h b/src/KingSystem/Resource/resResourceBoneControl.h
new file mode 100644
index 00000000..9adedd57
--- /dev/null
+++ b/src/KingSystem/Resource/resResourceBoneControl.h
@@ -0,0 +1,13 @@
+#pragma once
+
+#include "KingSystem/Resource/resResource.h"
+#include "KingSystem/Utils/ParamIO.h"
+
+namespace ksys::res {
+
+// TODO
+class BoneControl : public ParamIO, public Resource {
+ SEAD_RTTI_OVERRIDE(BoneControl, Resource)
+};
+
+} // namespace ksys::res
diff --git a/src/KingSystem/Resource/resResourceChemical.cpp b/src/KingSystem/Resource/resResourceChemical.cpp
new file mode 100644
index 00000000..fa7bd256
--- /dev/null
+++ b/src/KingSystem/Resource/resResourceChemical.cpp
@@ -0,0 +1 @@
+#include "KingSystem/Resource/resResourceChemical.h"
diff --git a/src/KingSystem/Resource/resResourceChemical.h b/src/KingSystem/Resource/resResourceChemical.h
new file mode 100644
index 00000000..bb9ffe9b
--- /dev/null
+++ b/src/KingSystem/Resource/resResourceChemical.h
@@ -0,0 +1,13 @@
+#pragma once
+
+#include "KingSystem/Resource/resResource.h"
+#include "KingSystem/Utils/ParamIO.h"
+
+namespace ksys::res {
+
+// TODO
+class Chemical : public ParamIO, public Resource {
+ SEAD_RTTI_OVERRIDE(Chemical, Resource)
+};
+
+} // namespace ksys::res
diff --git a/src/KingSystem/Resource/resResourceGameData.cpp b/src/KingSystem/Resource/resResourceGameData.cpp
index 7020a57d..cc315128 100644
--- a/src/KingSystem/Resource/resResourceGameData.cpp
+++ b/src/KingSystem/Resource/resResourceGameData.cpp
@@ -1,7 +1,7 @@
#include "KingSystem/Resource/resResourceGameData.h"
#include <type_traits>
#include "KingSystem/GameData/gdtManager.h"
-#include "KingSystem/Utils/Byaml.h"
+#include "KingSystem/Utils/Byaml/Byaml.h"
#include "KingSystem/Utils/HeapUtil.h"
namespace ksys::res {
diff --git a/src/KingSystem/Resource/resResourceGameSaveData.cpp b/src/KingSystem/Resource/resResourceGameSaveData.cpp
index 108239f2..b832fb27 100644
--- a/src/KingSystem/Resource/resResourceGameSaveData.cpp
+++ b/src/KingSystem/Resource/resResourceGameSaveData.cpp
@@ -3,7 +3,7 @@
#include <codec/seadHashCRC32.h>
#include <prim/seadContainerIterator.h>
#include "KingSystem/GameData/gdtManager.h"
-#include "KingSystem/Utils/Byaml.h"
+#include "KingSystem/Utils/Byaml/Byaml.h"
namespace ksys::res {
diff --git a/src/KingSystem/Resource/resResourceMgrTask.cpp b/src/KingSystem/Resource/resResourceMgrTask.cpp
index 5b5d39ed..b883c84a 100644
--- a/src/KingSystem/Resource/resResourceMgrTask.cpp
+++ b/src/KingSystem/Resource/resResourceMgrTask.cpp
@@ -373,7 +373,7 @@ bool ResourceMgrTask::canUseSdCard() const {
return false;
}
-bool ResourceMgrTask::returnFalse() const {
+bool ResourceMgrTask::isHostPath(const sead::SafeString&) const {
return false;
}
@@ -634,6 +634,12 @@ bool ResourceMgrTask::isCompactionStopped() const {
return mCompactionCounter == 0;
}
+bool ResourceMgrTask::initTempResourceLoader(TempResourceLoader* loader,
+ TempResourceLoader::InitArg& arg) {
+ arg.work = mTexHandleMgr->getArchiveWork();
+ return loader->init(arg);
+}
+
bool ResourceMgrTask::returnTrue1() {
return true;
}
diff --git a/src/KingSystem/Resource/resResourceMgrTask.h b/src/KingSystem/Resource/resResourceMgrTask.h
index df1117e9..d8c1d042 100644
--- a/src/KingSystem/Resource/resResourceMgrTask.h
+++ b/src/KingSystem/Resource/resResourceMgrTask.h
@@ -21,6 +21,7 @@
#include "KingSystem/Resource/resControlTask.h"
#include "KingSystem/Resource/resCounter.h"
#include "KingSystem/Resource/resInfoContainer.h"
+#include "KingSystem/Resource/resTempResourceLoader.h"
#include "KingSystem/Resource/resUnit.h"
#include "KingSystem/Resource/resUnitPool.h"
#include "KingSystem/System/OverlayArena.h"
@@ -162,7 +163,7 @@ public:
sead::DirectResource* load(const DirectLoadArg& arg);
bool canUseSdCard() const;
- bool returnFalse() const;
+ bool isHostPath(const sead::SafeString& path) const;
bool dropSFromExtensionIfNeeded(const sead::SafeString& path,
sead::BufferedSafeString& new_path, s32 dot_idx,
@@ -213,6 +214,8 @@ public:
void setCompactionStopped(bool stopped);
bool isCompactionStopped() const;
+ bool initTempResourceLoader(TempResourceLoader* loader, TempResourceLoader::InitArg& arg);
+
bool returnTrue1();
void clearCacheWithFileExtension(const sead::SafeString& extension);
diff --git a/src/KingSystem/Resource/resResourceModelList.cpp b/src/KingSystem/Resource/resResourceModelList.cpp
new file mode 100644
index 00000000..b5d6ed03
--- /dev/null
+++ b/src/KingSystem/Resource/resResourceModelList.cpp
@@ -0,0 +1,7 @@
+#include "KingSystem/Resource/resResourceModelList.h"
+
+namespace ksys::res {
+
+ModelList::ModelList() : ParamIO("modellist", 0) {}
+
+} // namespace ksys::res
diff --git a/src/KingSystem/Resource/resResourceModelList.h b/src/KingSystem/Resource/resResourceModelList.h
new file mode 100644
index 00000000..58038559
--- /dev/null
+++ b/src/KingSystem/Resource/resResourceModelList.h
@@ -0,0 +1,114 @@
+#pragma once
+
+#include <agl/Utils/aglParameter.h>
+#include <agl/Utils/aglParameterObj.h>
+#include <container/seadBuffer.h>
+#include <prim/seadStorageFor.h>
+#include "KingSystem/Resource/resResource.h"
+#include "KingSystem/Utils/ParamIO.h"
+
+namespace ksys::res {
+
+// FIXME: incomplete
+class ModelList : public ParamIO, public Resource {
+ SEAD_RTTI_OVERRIDE(ModelList, Resource)
+public:
+ struct ControllerInfo {
+ agl::utl::Parameter<sead::Color4f> _2b0;
+ agl::utl::Parameter<sead::Color4f> _2d8;
+ agl::utl::ParameterObj mControllerInfo;
+ agl::utl::Parameter<sead::Vector3f> mBaseScale;
+ agl::utl::Parameter<sead::SafeString> _358;
+ agl::utl::Parameter<s32> _380;
+ agl::utl::Parameter<sead::SafeString> _3a0;
+ agl::utl::Parameter<s32> _3c8;
+ agl::utl::Parameter<sead::SafeString> _3e8;
+ };
+ KSYS_CHECK_SIZE_NX150(ControllerInfo, 0x160);
+
+ struct Attention {
+ agl::utl::Parameter<bool> _0;
+ agl::utl::Parameter<sead::SafeString> _20;
+ agl::utl::Parameter<sead::Vector3f> _48;
+ agl::utl::Parameter<f32> _70;
+ agl::utl::Parameter<f32> _90;
+ agl::utl::Parameter<sead::SafeString> _b0;
+ agl::utl::Parameter<sead::Vector3f> _d8;
+ agl::utl::Parameter<sead::SafeString> _100;
+ agl::utl::Parameter<sead::Vector3f> _128;
+ agl::utl::Parameter<sead::SafeString> _150;
+ agl::utl::Parameter<sead::Vector3f> _178;
+ agl::utl::Parameter<sead::SafeString> _1a0;
+ agl::utl::Parameter<sead::Vector3f> _1c8;
+ agl::utl::Parameter<f32> _1f0;
+ agl::utl::Parameter<sead::SafeString> _210;
+ agl::utl::Parameter<sead::Vector3f> _238;
+ agl::utl::Parameter<bool> _260;
+ agl::utl::Parameter<sead::SafeString> _280;
+ agl::utl::Parameter<sead::Vector3f> _2a8;
+ agl::utl::ParameterObj _2d0;
+ };
+ KSYS_CHECK_SIZE_NX150(Attention, 0x300);
+
+ struct Unit {
+ agl::utl::Parameter<sead::SafeString> unit_name;
+ agl::utl::Parameter<sead::SafeString> bind_bone;
+ agl::utl::ParameterObj obj;
+ };
+ KSYS_CHECK_SIZE_NX150(Unit, 0x80);
+
+ struct ModelData {
+ agl::utl::Parameter<sead::SafeString> folder;
+ agl::utl::ParameterObj base_obj;
+ sead::Buffer<Unit> units;
+ agl::utl::ParameterList unit_list;
+ agl::utl::ParameterList list;
+ };
+ KSYS_CHECK_SIZE_NX150(ModelData, 0xf8);
+
+ // Misspelling of "partical", which is a misspelling of "particle"?
+ struct Partial {
+ agl::utl::Parameter<sead::SafeString> bone;
+ agl::utl::Parameter<s32> bind_flag;
+ agl::utl::Parameter<bool> recursible;
+ agl::utl::ParameterObj obj;
+ };
+ KSYS_CHECK_SIZE_NX150(Partial, 0x98);
+
+ struct AnmTarget {
+ agl::utl::Parameter<s32> num_as_slot;
+ agl::utl::Parameter<bool> is_partical_enable;
+ agl::utl::Parameter<s32> target_type;
+ agl::utl::ParameterObj base_obj;
+ sead::Buffer<Partial> partials;
+ agl::utl::ParameterList partial_list;
+ agl::utl::ParameterList list;
+ };
+ KSYS_CHECK_SIZE_NX150(AnmTarget, 0x130);
+
+ ModelList();
+ ~ModelList() override;
+
+ void doCreate_(u8* buffer, u32 buffer_size, sead::Heap* heap) override;
+ bool needsParse() const override { return true; }
+ bool parse_(u8* data, size_t size, sead::Heap* heap) override;
+
+ const ControllerInfo& getControllerInfo() const { return mControllerInfo.ref(); }
+ const Attention& getAttention() const { return mAttention.ref(); }
+ const sead::Buffer<ModelData>& getModelData() const { return mModelData; }
+ const sead::Buffer<AnmTarget>& getAnmTargets() const { return mAnmTargets; }
+ bool is7C8() const { return _7c8; }
+
+private:
+ sead::StorageFor<ControllerInfo> mControllerInfo{sead::ZeroInitializeTag{}};
+ sead::StorageFor<Attention> mAttention{sead::ZeroInitializeTag{}};
+ u8* mRawData{};
+ sead::Buffer<ModelData> mModelData;
+ agl::utl::ParameterList mModelDataList;
+ sead::Buffer<AnmTarget> mAnmTargets;
+ agl::utl::ParameterList mAnmTargetList;
+ bool _7c8 = false;
+};
+KSYS_CHECK_SIZE_NX150(ModelList, 0x7d0);
+
+} // namespace ksys::res
diff --git a/src/KingSystem/Resource/resResourcePhysics.cpp b/src/KingSystem/Resource/resResourcePhysics.cpp
new file mode 100644
index 00000000..89054e81
--- /dev/null
+++ b/src/KingSystem/Resource/resResourcePhysics.cpp
@@ -0,0 +1 @@
+#include "KingSystem/Resource/resResourcePhysics.h"
diff --git a/src/KingSystem/Resource/resResourcePhysics.h b/src/KingSystem/Resource/resResourcePhysics.h
new file mode 100644
index 00000000..fb95e0c1
--- /dev/null
+++ b/src/KingSystem/Resource/resResourcePhysics.h
@@ -0,0 +1,13 @@
+#pragma once
+
+#include "KingSystem/Resource/resResource.h"
+#include "KingSystem/Utils/ParamIO.h"
+
+namespace ksys::res {
+
+// TODO
+class Physics : public ParamIO, public Resource {
+ SEAD_RTTI_OVERRIDE(Physics, Resource)
+};
+
+} // namespace ksys::res
diff --git a/src/KingSystem/Resource/resResourceRagdollBlendWeight.cpp b/src/KingSystem/Resource/resResourceRagdollBlendWeight.cpp
new file mode 100644
index 00000000..f0b511a8
--- /dev/null
+++ b/src/KingSystem/Resource/resResourceRagdollBlendWeight.cpp
@@ -0,0 +1 @@
+#include "KingSystem/Resource/resResourceRagdollBlendWeight.h"
diff --git a/src/KingSystem/Resource/resResourceRagdollBlendWeight.h b/src/KingSystem/Resource/resResourceRagdollBlendWeight.h
new file mode 100644
index 00000000..fbc76b92
--- /dev/null
+++ b/src/KingSystem/Resource/resResourceRagdollBlendWeight.h
@@ -0,0 +1,13 @@
+#pragma once
+
+#include "KingSystem/Resource/resResource.h"
+#include "KingSystem/Utils/ParamIO.h"
+
+namespace ksys::res {
+
+// TODO
+class RagdollBlendWeight : public ParamIO, public Resource {
+ SEAD_RTTI_OVERRIDE(RagdollBlendWeight, Resource)
+};
+
+} // namespace ksys::res
diff --git a/src/KingSystem/Resource/resResourceRagdollConfig.cpp b/src/KingSystem/Resource/resResourceRagdollConfig.cpp
new file mode 100644
index 00000000..e5c27c33
--- /dev/null
+++ b/src/KingSystem/Resource/resResourceRagdollConfig.cpp
@@ -0,0 +1 @@
+#include "KingSystem/Resource/resResourceRagdollConfig.h"
diff --git a/src/KingSystem/Resource/resResourceRagdollConfig.h b/src/KingSystem/Resource/resResourceRagdollConfig.h
new file mode 100644
index 00000000..d9768b22
--- /dev/null
+++ b/src/KingSystem/Resource/resResourceRagdollConfig.h
@@ -0,0 +1,13 @@
+#pragma once
+
+#include "KingSystem/Resource/resResource.h"
+#include "KingSystem/Utils/ParamIO.h"
+
+namespace ksys::res {
+
+// TODO
+class RagdollConfig : public ParamIO, public Resource {
+ SEAD_RTTI_OVERRIDE(RagdollConfig, Resource)
+};
+
+} // namespace ksys::res
diff --git a/src/KingSystem/Resource/resResourceRagdollConfigList.cpp b/src/KingSystem/Resource/resResourceRagdollConfigList.cpp
new file mode 100644
index 00000000..218c20b8
--- /dev/null
+++ b/src/KingSystem/Resource/resResourceRagdollConfigList.cpp
@@ -0,0 +1 @@
+#include "KingSystem/Resource/resResourceRagdollConfigList.h"
diff --git a/src/KingSystem/Resource/resResourceRagdollConfigList.h b/src/KingSystem/Resource/resResourceRagdollConfigList.h
new file mode 100644
index 00000000..f5975628
--- /dev/null
+++ b/src/KingSystem/Resource/resResourceRagdollConfigList.h
@@ -0,0 +1,65 @@
+#pragma once
+
+#include <agl/Utils/aglParameter.h>
+#include <agl/Utils/aglParameterList.h>
+#include <agl/Utils/aglParameterObj.h>
+#include <container/seadBuffer.h>
+#include "KingSystem/Resource/resResource.h"
+#include "KingSystem/Utils/ParamIO.h"
+#include "KingSystem/Utils/Types.h"
+
+namespace ksys::res {
+
+class RagdollConfig;
+
+class RagdollConfigList : public ParamIO, public Resource {
+ SEAD_RTTI_OVERRIDE(RagdollConfigList, Resource)
+public:
+ struct ImpulseParam {
+ const char* getFileName() const { return file_name.ref().cstr(); }
+
+ agl::utl::Parameter<sead::SafeString> file_name;
+ agl::utl::ParameterObj obj;
+ RagdollConfig* config;
+ };
+ KSYS_CHECK_SIZE_NX150(ImpulseParam, 0x60);
+
+ struct BodyParam : agl::utl::ParameterObj {
+ agl::utl::Parameter<sead::SafeString> rigid_name;
+ agl::utl::Parameter<f32> friction_scale;
+ agl::utl::Parameter<f32> buoyancy_scale;
+ };
+ KSYS_CHECK_SIZE_NX150(BodyParam, 0x98);
+
+ RagdollConfigList();
+ ~RagdollConfigList() override;
+
+ void doCreate_(u8*, u32, sead::Heap*) override {}
+ bool needsParse() const override { return true; }
+ bool parse_(u8* data, size_t size, sead::Heap* heap) override;
+ bool finishParsing_() override;
+ bool m7_() override;
+
+ const sead::Buffer<ImpulseParam>& getImpulseParams() const { return mImpulseParams; }
+ f32 getUpperLimitHeight() const { return mUpperLimitHeight.ref(); }
+ f32 getLowerLimitHeight() const { return mLowerLimitHeight.ref(); }
+ const sead::Buffer<BodyParam>& getBodyParams() const { return mBodyParams; }
+
+ void addImpulseParamConfig_(s32 index, RagdollConfig* config) {
+ mImpulseParams[index].config = config;
+ }
+
+private:
+ agl::utl::ParameterList mImpulseParamList;
+ sead::Buffer<ImpulseParam> mImpulseParams;
+
+ agl::utl::ParameterObj mCommonData;
+ agl::utl::Parameter<f32> mUpperLimitHeight;
+ agl::utl::Parameter<f32> mLowerLimitHeight;
+
+ agl::utl::ParameterList mBodyParamList;
+ sead::Buffer<BodyParam> mBodyParams;
+};
+KSYS_CHECK_SIZE_NX150(RagdollConfigList, 0x3d0);
+
+} // namespace ksys::res
diff --git a/src/KingSystem/Resource/resResourceUMii.cpp b/src/KingSystem/Resource/resResourceUMii.cpp
new file mode 100644
index 00000000..cefadea6
--- /dev/null
+++ b/src/KingSystem/Resource/resResourceUMii.cpp
@@ -0,0 +1,15 @@
+#include "KingSystem/Resource/resResourceUMii.h"
+
+namespace ksys::res {
+
+UMii::UMii() : ParamIO("umii", 0) {}
+
+UMii::~UMii() = default;
+
+bool UMii::parse_(u8* data, size_t, sead::Heap*) {
+ agl::utl::ResParameterArchive archive{data + mAllocSize};
+ mData = archive.ptr();
+ return true;
+}
+
+} // namespace ksys::res
diff --git a/src/KingSystem/Resource/resResourceUMii.h b/src/KingSystem/Resource/resResourceUMii.h
new file mode 100644
index 00000000..1191c76e
--- /dev/null
+++ b/src/KingSystem/Resource/resResourceUMii.h
@@ -0,0 +1,27 @@
+#pragma once
+
+#include "KingSystem/Resource/resResource.h"
+#include "KingSystem/Utils/ParamIO.h"
+#include "KingSystem/Utils/Types.h"
+
+namespace ksys::res {
+
+class UMii : public ParamIO, public Resource {
+ SEAD_RTTI_OVERRIDE(UMii, Resource)
+public:
+ UMii();
+ ~UMii() override;
+
+ agl::utl::ResParameterArchiveData* getData() const { return mData; }
+
+ bool needsParse() const override { return true; }
+ bool m2_() override { return mData != nullptr; }
+ void doCreate_(u8*, u32, sead::Heap*) override {}
+ bool parse_(u8* data, size_t size, sead::Heap* heap) override;
+
+private:
+ agl::utl::ResParameterArchiveData* mData{};
+};
+KSYS_CHECK_SIZE_NX150(UMii, 0x2b8);
+
+} // namespace ksys::res
diff --git a/src/KingSystem/Resource/resSystem.cpp b/src/KingSystem/Resource/resSystem.cpp
index 71713a1c..f4238ad1 100644
--- a/src/KingSystem/Resource/resSystem.cpp
+++ b/src/KingSystem/Resource/resSystem.cpp
@@ -1,4 +1,5 @@
#include "KingSystem/Resource/resSystem.h"
+#include "KingSystem/Resource/resResourceMgrTask.h"
namespace ksys::res {
@@ -6,6 +7,10 @@ bool stubbedLogFunction() {
return true;
}
+bool isHostPath(const sead::SafeString& path) {
+ return ResourceMgrTask::instance()->isHostPath(path);
+}
+
bool returnFalse() {
return false;
}
@@ -14,6 +19,10 @@ bool returnFalse2(const sead::SafeString&) {
return false;
}
+bool returnFalse3(const sead::SafeString&) {
+ return false;
+}
+
s32 getDefaultAlignment() {
return 8;
}
diff --git a/src/KingSystem/Resource/resSystem.h b/src/KingSystem/Resource/resSystem.h
index b617d323..4d44d20f 100644
--- a/src/KingSystem/Resource/resSystem.h
+++ b/src/KingSystem/Resource/resSystem.h
@@ -9,6 +9,8 @@ class EntryFactoryBase;
void registerEntryFactory(EntryFactoryBase* factory, const sead::SafeString& name);
void unregisterEntryFactory(EntryFactoryBase* factory);
+bool isHostPath(const sead::SafeString& path);
+
// In release builds, the only thing this function does is return 1.
// TODO: figure out what this is used for. Stubbed log function?
bool stubbedLogFunction();
@@ -21,6 +23,8 @@ bool returnFalse();
// TODO: figure out what this is used for. Stubbed log function?
bool returnFalse2(const sead::SafeString&);
+bool returnFalse3(const sead::SafeString& path);
+
s32 getDefaultAlignment();
} // namespace ksys::res
diff --git a/src/KingSystem/Resource/resTempResourceLoader.cpp b/src/KingSystem/Resource/resTempResourceLoader.cpp
new file mode 100644
index 00000000..704c7e30
--- /dev/null
+++ b/src/KingSystem/Resource/resTempResourceLoader.cpp
@@ -0,0 +1,220 @@
+#include "KingSystem/Resource/resTempResourceLoader.h"
+#include <resource/seadResource.h>
+#include <thread/seadThread.h>
+#include "KingSystem/Resource/resArchiveWork.h"
+#include "KingSystem/Resource/resResourceMgrTask.h"
+#include "KingSystem/Resource/resSystem.h"
+#include "KingSystem/Resource/resUnit.h"
+#include "KingSystem/Utils/Debug.h"
+#include "KingSystem/Utils/Thread/TaskThread.h"
+
+namespace ksys::res {
+
+TempResourceLoader::TempResourceLoader() = default;
+
+TempResourceLoader::~TempResourceLoader() {
+ unload();
+}
+
+void TempResourceLoader::unload() {
+ const auto* unit = mHandle.getUnit();
+ const auto& path = unit ? unit->getPath() : sead::SafeString::cEmptyString;
+ sead::FormatFixedSafeString<256> message("(TempResourceLoader) アンロードします。: %s\n",
+ path.cstr());
+ util::PrintDebug(message);
+
+ if (mFlags.isOn(Flag::IsRetryingLoad)) {
+ stubbedLogFunction();
+ mFlags.reset(Flag::IsRetryingLoad);
+ } else if (returnFalse()) {
+ stubbedLogFunction();
+ }
+
+ mFlags.reset(Flag::Loading);
+ mHandle.requestUnload();
+
+ if (mResource) {
+ ResourceMgrTask::instance()->unloadSeadResource(mResource);
+ mResource = nullptr;
+ }
+
+ if (mWork)
+ mWork->setEvent();
+}
+
+bool TempResourceLoader::init(const InitArg& arg) {
+ mWork = arg.work;
+ return true;
+}
+
+bool TempResourceLoader::isLoading() const {
+ return mFlags.isOn(Flag::Loading);
+}
+
+bool TempResourceLoader::isSuccess() const {
+ return !isLoading() && mHandle.isSuccess();
+}
+
+bool TempResourceLoader::checkLoadStatus() const {
+ return !isLoading() && mHandle.checkLoadStatus();
+}
+
+void TempResourceLoader::requestLoad(LoadArg& arg) {
+ if (!arg.use_handle)
+ return;
+
+ updateFlagsBeforeLoadingStarts();
+ mPath = arg.load_req.mPath;
+ mLoadArg = arg;
+ mLoadArg.load_req.mPath = mPath;
+ arg.load_req.mArena = mWork->getArena();
+ mHandle.requestLoad(arg.load_req.mPath, &arg.load_req);
+ if (returnFalse())
+ stubbedLogFunction();
+}
+
+sead::DirectResource* TempResourceLoader::getResourceForLoadRequest(Context* context) {
+ if (!mLoadArg.use_handle || !mHandle.isFlag2Set() || mHandle.isFlag8Set() ||
+ !mHandle.isReadyOrNeedsParse()) {
+ return nullptr;
+ }
+
+ mHandle.parseResource(context);
+
+ if (!mHandle.isSuccess()) {
+ if (mHandle.getStatus() != Handle::Status::_3) {
+ mFlags.reset(Flag::Loading);
+ sead::FormatFixedSafeString<256> message(
+ "(TempResourceLoader) メモリ不足以外のエラーでした。: %s(%d)\n",
+ mLoadArg.load_req.mPath.cstr(), s32(mHandle.getStatus()));
+ util::PrintDebug(message);
+ resetRetryFlag();
+ return nullptr;
+ }
+
+ if (!mLoadArg.retry_on_failure) {
+ mFlags.reset(Flag::Loading);
+ sead::FormatFixedSafeString<256> message(
+ "(TempResourceLoader) ロード失敗しました。: %s\n", mLoadArg.load_req.mPath.cstr());
+ util::PrintDebug(message);
+ resetRetryFlag();
+ return nullptr;
+ }
+
+ setRetryFlag();
+ mLoadArg.load_req.mArena = mWork->getArena();
+ mHandle.requestLoad(mLoadArg.load_req.mPath, &mLoadArg.load_req);
+ return nullptr;
+ }
+
+ mFlags.reset(Flag::Loading);
+ sead::FormatFixedSafeString<256> message("(TempResourceLoader) ロードに成功しました。: %s\n",
+ mLoadArg.load_req.mPath.cstr());
+ util::PrintDebug(message);
+ resetRetryFlag();
+ return mHandle.getResource();
+}
+
+sead::DirectResource* TempResourceLoader::load(TempResourceLoader::LoadArg& arg) {
+ updateFlagsBeforeLoadingStarts();
+
+ const auto* current_thread = sead::ThreadMgr::instance()->getCurrentThread();
+ bool is_on_res_thread = false;
+ is_on_res_thread |= current_thread == ResourceMgrTask::instance()->getResourceMemoryThread();
+ is_on_res_thread |= current_thread == ResourceMgrTask::instance()->getResourceLoadingThread();
+ if (is_on_res_thread)
+ arg.use_handle = false;
+
+ while (true) {
+ if (returnFalse())
+ stubbedLogFunction();
+
+ bool use_handle = arg.use_handle;
+ auto* arena = mWork->getArena();
+ if (use_handle) {
+ arg.load_req.mArena = arena;
+ mHandle.load(arg.load_req.mPath, &arg.load_req);
+
+ if (mHandle.isSuccess())
+ break;
+
+ if (mHandle.getStatus() != Handle::Status::_3) {
+ mFlags.reset(Flag::Loading);
+ sead::FormatFixedSafeString<256> message(
+ "(TempResourceLoader) メモリ不足以外のエラーでした。: %s(%d)\n",
+ arg.load_req.mPath.cstr(), s32(mHandle.getStatus()));
+ util::PrintDebug(message);
+ resetRetryFlag();
+ return nullptr;
+ }
+ } else {
+ ResourceMgrTask::DirectLoadArg load_arg{};
+ load_arg.heap = arena->getHeap();
+ load_arg.req._21 = false;
+ load_arg.req._22 = true;
+ load_arg.req.mPath = arg.load_req.mPath;
+ load_arg.req.mAocFileDevice = arg.load_req.mAocFileDevice;
+ load_arg.req.mLoadDataAlignment = arg.load_req.mLoadDataAlignment;
+ load_arg.req.mEntryFactory = arg.load_req.mEntryFactory;
+ load_arg.req._20 = false;
+ load_arg.req.mRequester = "TempResourceLoader";
+
+ if (arena->getHeap()->isLockEnabled())
+ arena->getHeap()->getCriticalSection().lock();
+
+ mResource = ResourceMgrTask::instance()->load(load_arg);
+
+ if (arena->getHeap()->isLockEnabled())
+ arena->getHeap()->getCriticalSection().unlock();
+
+ if (mResource) {
+ mFlags.reset(Flag::Loading);
+ return mResource;
+ }
+ }
+
+ if (!arg.retry_on_failure) {
+ mFlags.reset(Flag::Loading);
+ sead::FormatFixedSafeString<256> message(
+ "(TempResourceLoader) ロード失敗しました。: %s\n", arg.load_req.mPath.cstr());
+ util::PrintDebug(message);
+ resetRetryFlag();
+ return nullptr;
+ }
+
+ setRetryFlag();
+ if (!mWork->waitForEvent(arg.ms_between_attempts)) {
+ mFlags.reset(Flag::Loading);
+ return nullptr;
+ }
+ }
+
+ mFlags.reset(Flag::Loading);
+ sead::FormatFixedSafeString<256> message("(TempResourceLoader) ロードに成功しました。: %s\n",
+ arg.load_req.mPath.cstr());
+ util::PrintDebug(message);
+ resetRetryFlag();
+ return mHandle.getResource();
+}
+
+sead::DirectResource* TempResourceLoader::getResource() const {
+ if (mHandle.getResource())
+ return mHandle.getResource();
+ return mResource;
+}
+
+Handle::Status TempResourceLoader::getHandleStatus() const {
+ return mHandle.getStatus();
+}
+
+sead::FileDevice* TempResourceLoader::getHandleFileDevice() const {
+ if (mHandle.isSuccess())
+ return mHandle.getUnit()->getLoadArg().device;
+ return nullptr;
+}
+
+u32 TempResourceLoader::getWorkHeapSize() const {
+ return mWork ? mWork->getHeapSize() : 0;
+}
+
+} // namespace ksys::res
diff --git a/src/KingSystem/Resource/resTempResourceLoader.h b/src/KingSystem/Resource/resTempResourceLoader.h
new file mode 100644
index 00000000..69e42ce1
--- /dev/null
+++ b/src/KingSystem/Resource/resTempResourceLoader.h
@@ -0,0 +1,87 @@
+#pragma once
+
+#include <basis/seadTypes.h>
+#include <prim/seadSafeString.h>
+#include <prim/seadTypedBitFlag.h>
+#include "KingSystem/Resource/resHandle.h"
+#include "KingSystem/Resource/resLoadRequest.h"
+#include "KingSystem/Resource/resSystem.h"
+#include "KingSystem/Utils/Types.h"
+
+namespace sead {
+class DirectResource;
+}
+
+namespace ksys::res {
+
+class ArchiveWork;
+
+class TempResourceLoader {
+public:
+ struct InitArg {
+ ArchiveWork* work;
+ };
+
+ struct LoadArg {
+ bool retry_on_failure = true;
+ bool use_handle = true;
+ u32 ms_between_attempts = 0;
+ LoadRequest load_req;
+ };
+
+ TempResourceLoader();
+ ~TempResourceLoader();
+
+ void unload();
+ bool init(const InitArg& arg);
+ bool isLoading() const;
+ bool isSuccess() const;
+ bool checkLoadStatus() const;
+ void requestLoad(LoadArg& arg);
+ sead::DirectResource* getResourceForLoadRequest(Context* context);
+ sead::DirectResource* load(LoadArg& arg);
+ sead::DirectResource* getResource() const;
+ Handle::Status getHandleStatus() const;
+ sead::FileDevice* getHandleFileDevice() const;
+ u32 getWorkHeapSize() const;
+
+private:
+ enum class Flag : u8 {
+ Loading = 1,
+ IsRetryingLoad = 2,
+ };
+
+ void setRetryFlag() {
+ if (mFlags.isOff(Flag::IsRetryingLoad)) {
+ stubbedLogFunction();
+ mFlags.set(Flag::IsRetryingLoad);
+ } else if (returnFalse()) {
+ stubbedLogFunction();
+ }
+ }
+
+ void resetRetryFlag() {
+ if (mFlags.isOn(Flag::IsRetryingLoad)) {
+ stubbedLogFunction();
+ mFlags.reset(Flag::IsRetryingLoad);
+ } else if (returnFalse()) {
+ stubbedLogFunction();
+ }
+ }
+
+ void updateFlagsBeforeLoadingStarts() {
+ mFlags.reset(Flag::Loading);
+ mFlags.reset(Flag::IsRetryingLoad);
+ mFlags.set(Flag::Loading);
+ }
+
+ sead::TypedBitFlag<Flag> mFlags;
+ sead::DirectResource* mResource{};
+ ArchiveWork* mWork{};
+ Handle mHandle;
+ LoadArg mLoadArg;
+ sead::FixedSafeString<128> mPath;
+};
+KSYS_CHECK_SIZE_NX150(TempResourceLoader, 0x188);
+
+} // namespace ksys::res
diff --git a/src/KingSystem/Resource/resTextureHandleMgr.h b/src/KingSystem/Resource/resTextureHandleMgr.h
index 7e90d537..b9fd7701 100644
--- a/src/KingSystem/Resource/resTextureHandleMgr.h
+++ b/src/KingSystem/Resource/resTextureHandleMgr.h
@@ -2,11 +2,14 @@
namespace ksys::res {
+class ArchiveWork;
+
// TODO: very incomplete
class TextureHandleMgr {
public:
virtual ~TextureHandleMgr();
+ ArchiveWork* getArchiveWork() const;
void clearAllCache();
};
diff --git a/src/KingSystem/Resource/resUnit.h b/src/KingSystem/Resource/resUnit.h
index 8cbfa907..61a5b544 100644
--- a/src/KingSystem/Resource/resUnit.h
+++ b/src/KingSystem/Resource/resUnit.h
@@ -94,6 +94,8 @@ public:
void attachHandle(Handle* handle);
+ const sead::SafeString& getPath() const { return mPath; }
+ const sead::ResourceMgr::LoadArg& getLoadArg() const { return mLoadArg; }
s32 getRefCount() const;
Status getStatus() const;
diff --git a/src/KingSystem/Utils/Byaml.cpp b/src/KingSystem/Utils/Byaml.cpp
deleted file mode 100644
index 23d82bb9..00000000
--- a/src/KingSystem/Utils/Byaml.cpp
+++ /dev/null
@@ -1 +0,0 @@
-#include "KingSystem/Utils/Byaml.h"
diff --git a/src/KingSystem/Utils/Byaml/Byaml.cpp b/src/KingSystem/Utils/Byaml/Byaml.cpp
new file mode 100644
index 00000000..2fe0dac1
--- /dev/null
+++ b/src/KingSystem/Utils/Byaml/Byaml.cpp
@@ -0,0 +1,402 @@
+#include "KingSystem/Utils/Byaml/Byaml.h"
+#include <math/seadMathCalcCommon.h>
+#include <prim/seadMemUtil.h>
+#include "KingSystem/Utils/Byaml/ByamlArrayIter.h"
+#include "KingSystem/Utils/Byaml/ByamlData.h"
+#include "KingSystem/Utils/Byaml/ByamlHashIter.h"
+#include "KingSystem/Utils/Byaml/ByamlLocal.h"
+#include "KingSystem/Utils/Byaml/ByamlStringTableIter.h"
+
+namespace al {
+
+ByamlIter::ByamlIter() : mData(nullptr), mRootNode(nullptr) {}
+
+ByamlIter::ByamlIter(const u8* data) {
+ mData = data;
+ mRootNode = nullptr;
+ if (mData) {
+ if (ByamlLocalUtil::verifiByaml(mData)) {
+ const ByamlHeader* header = reinterpret_cast<const ByamlHeader*>(mData);
+ u32 data_root_offset = header->getDataOffset();
+ if (data_root_offset) {
+ mRootNode = &mData[data_root_offset];
+ }
+ } else {
+ mData = nullptr;
+ mRootNode = nullptr;
+ }
+ }
+}
+
+ByamlIter::ByamlIter(const u8* data, const u8* root_node) : mData(data), mRootNode(root_node) {}
+
+ByamlIter::ByamlIter(const ByamlIter& other) : mData(other.mData), mRootNode(other.mRootNode) {}
+
+ByamlIter& ByamlIter::operator=(const ByamlIter& rhs) {
+ if (this != &rhs) {
+ // This is formally undefined behavior because ByamlIter is not trivially copyable
+ // (since it has non-trivial copy constructors and copy assignment operators)
+ // but those are effectively trivial so this will work in practice.
+ // This is what Nintendo did and it is required for matching.
+ sead::MemUtil::copy(this, &rhs, sizeof(*this));
+ }
+ return *this;
+}
+
+bool ByamlIter::isValid() const {
+ return mData != nullptr;
+}
+
+bool ByamlIter::isTypeHash() const {
+ const ByamlContainerHeader* node = reinterpret_cast<const ByamlContainerHeader*>(mRootNode);
+ return node && node->getType() == ByamlType::Hash;
+}
+
+bool ByamlIter::isTypeArray() const {
+ const ByamlContainerHeader* node = reinterpret_cast<const ByamlContainerHeader*>(mRootNode);
+ return node && node->getType() == ByamlType::Array;
+}
+
+bool ByamlIter::isTypeContainer() const {
+ return isTypeArray() || isTypeHash();
+}
+
+bool ByamlIter::isExistKey(const char* key) const {
+ if (!mRootNode) {
+ return false;
+ }
+
+ if (!isTypeHash()) {
+ return false;
+ }
+
+ const s32 index = getKeyIndex(key);
+ if (index < 0) {
+ return 0;
+ }
+
+ ByamlHashIter node_hash(mRootNode);
+ return node_hash.findPair(index);
+}
+
+s32 ByamlIter::getKeyIndex(const char* key) const {
+ const ByamlStringTableIter table = ByamlLocalUtil::getHashKeyTableIter(mData);
+ return table.findStringIndex(key);
+}
+
+s32 ByamlIter::getSize() const {
+ if (!mRootNode) {
+ return 0;
+ }
+
+ if (isTypeContainer()) {
+ return ByamlLocalUtil::getContainerSize(mRootNode);
+ }
+
+ return 0;
+}
+
+ByamlIter ByamlIter::getIterByIndex(s32 index) const {
+ ByamlData data;
+ if (!getByamlDataByIndex(&data, index)) {
+ return ByamlIter();
+ }
+
+ return getIterFromData(data);
+}
+
+ByamlIter ByamlIter::getIterByKey(const char* key) const {
+ ByamlData data;
+ if (!getByamlDataByKey(&data, key)) {
+ return ByamlIter();
+ }
+
+ return getIterFromData(data);
+}
+
+ByamlIter ByamlIter::getIterFromData(const ByamlData& data) const {
+ if (data.getType() == ByamlType::Hash || data.getType() == ByamlType::Array) {
+ return ByamlIter(mData, &mData[data.getValue()]);
+ }
+
+ if (data.getType() == ByamlType::Null) {
+ return ByamlIter(mData, nullptr);
+ }
+
+ return ByamlIter();
+}
+
+bool ByamlIter::getByamlDataByIndex(ByamlData* data, s32 index) const {
+ if (isTypeArray()) {
+ ByamlArrayIter array_node(mRootNode);
+ return array_node.getDataByIndex(data, index);
+ } else if (isTypeHash()) {
+ ByamlHashIter hash_node(mRootNode);
+ return hash_node.getDataByIndex(data, index);
+ }
+
+ return false;
+}
+
+bool ByamlIter::getByamlDataByKey(ByamlData* data, const char* key) const {
+ if (!isTypeHash()) {
+ return false;
+ }
+
+ auto* header = reinterpret_cast<const al::ByamlHeader*>(mData);
+ const s32 offset = header->getHashKeyTableOffset();
+ if (!offset) {
+ return false;
+ }
+ const ByamlStringTableIter table = ByamlStringTableIter(&mData[offset]);
+
+ ByamlHashIter hash_node(mRootNode);
+ const s32 size = hash_node.getSize();
+ if (size < 1) {
+ return false;
+ }
+
+ // Binary Search
+ const ByamlHashPair* pair;
+ s32 start = 0;
+ s32 end = size;
+ s32 index;
+ while (true) {
+ if (start >= end) {
+ return false;
+ }
+
+ index = (start + end) / 2;
+ pair = hash_node.getPairByIndex(index);
+ const char* str = table.getString(pair->getKey());
+ s32 result = std::strcmp(key, str);
+ if (result == 0)
+ break;
+ if (result > 0)
+ start = index + 1;
+ else if (result < 0)
+ end = index;
+ }
+
+ data->set(pair);
+
+ return true;
+}
+
+bool ByamlIter::getByamlDataAndKeyNameByIndex(ByamlData* data, const char** key, s32 index) const {
+ if (!isTypeHash()) {
+ return false;
+ }
+
+ const ByamlHashIter hash_iter(mRootNode);
+ const ByamlHashPair* pair = hash_iter.getPairByIndex(index);
+ if (!pair) {
+ return false;
+ }
+
+ if (data) {
+ data->set(pair);
+ }
+
+ ByamlStringTableIter table_iter = ByamlLocalUtil::getHashKeyTableIter(mData);
+ *key = table_iter.getString(pair->getKey());
+ return true;
+}
+
+bool ByamlIter::getKeyName(const char** key, s32 index) const {
+ if (!mRootNode) {
+ return false;
+ }
+
+ if (!isTypeHash()) {
+ return false;
+ }
+
+ ByamlHashIter hash_node(mRootNode);
+ const ByamlHashPair* pair = hash_node.getPairByIndex(index);
+ if (!pair) {
+ return false;
+ }
+
+ const ByamlStringTableIter hash_table = ByamlLocalUtil::getHashKeyTableIter(mData);
+ *key = hash_table.getString(pair->getKey());
+
+ return true;
+}
+
+bool ByamlIter::tryGetIterByIndex(ByamlIter* iter, s32 index) const {
+ *iter = getIterByIndex(index);
+ return iter->isValid();
+}
+
+bool ByamlIter::tryGetIterByKey(ByamlIter* iter, const char* key) const {
+ *iter = getIterByKey(key);
+ return iter->isValid();
+}
+
+bool ByamlIter::tryGetIterAndKeyNameByIndex(ByamlIter* iter, const char** key, s32 index) const {
+ ByamlData data;
+ if (!getByamlDataAndKeyNameByIndex(&data, key, index)) {
+ *key = nullptr;
+ return tryGetIterByIndex(iter, index);
+ }
+
+ *iter = getIterFromData(data);
+ return true;
+}
+
+bool ByamlIter::tryGetStringByIndex(const char** value, s32 index) const {
+ ByamlData data;
+ if (!getByamlDataByIndex(&data, index)) {
+ return false;
+ }
+
+ return tryConvertString(value, &data);
+}
+
+bool ByamlIter::tryGetStringByKey(const char** value, const char* key) const {
+ ByamlData data;
+ if (!getByamlDataByKey(&data, key)) {
+ return false;
+ }
+
+ return tryConvertString(value, &data);
+}
+
+bool ByamlIter::tryConvertString(const char** value, const ByamlData* data) const {
+ if (data->getType() != ByamlType::String) {
+ return false;
+ }
+
+ const auto string_table = ByamlLocalUtil::getStringTableIter(mData);
+ *value = string_table.getString(data->getValue());
+
+ return true;
+}
+
+bool ByamlIter::tryGetIntByIndex(s32* value, s32 index) const {
+ ByamlData data;
+ if (!getByamlDataByIndex(&data, index)) {
+ return false;
+ }
+
+ return tryConvertInt(value, &data);
+}
+
+bool ByamlIter::tryGetIntByKey(s32* value, const char* key) const {
+ ByamlData data;
+ if (!getByamlDataByKey(&data, key)) {
+ return false;
+ }
+
+ return tryConvertInt(value, &data);
+}
+
+bool ByamlIter::tryConvertInt(s32* value, const ByamlData* data) const {
+ if (data->getType() != ByamlType::Int) {
+ return false;
+ }
+
+ *value = data->getValue();
+ return true;
+}
+
+bool ByamlIter::tryGetUIntByIndex(u32* value, s32 index) const {
+ ByamlData data;
+ if (!getByamlDataByIndex(&data, index)) {
+ return false;
+ }
+
+ return tryConvertUInt(value, &data);
+}
+
+bool ByamlIter::tryGetUIntByKey(u32* value, const char* key) const {
+ ByamlData data;
+ if (!getByamlDataByKey(&data, key)) {
+ return false;
+ }
+
+ return tryConvertUInt(value, &data);
+}
+
+bool ByamlIter::tryConvertUInt(u32* value, const ByamlData* data) const {
+ if (data->getType() == ByamlType::Int) {
+ s32 signed_value = data->getValue<s32>();
+ if (signed_value < 0) {
+ *value = 0;
+ return false;
+ } else {
+ *value = signed_value;
+ return true;
+ }
+ } else if (data->getType() == ByamlType::UInt) {
+ *value = data->getValue();
+ return true;
+ }
+
+ return false;
+}
+
+bool ByamlIter::tryGetFloatByIndex(f32* value, s32 index) const {
+ ByamlData data;
+ if (!getByamlDataByIndex(&data, index)) {
+ return false;
+ }
+
+ return tryConvertFloat(value, &data);
+}
+
+bool ByamlIter::tryGetFloatByKey(f32* value, const char* key) const {
+ ByamlData data;
+ if (!getByamlDataByKey(&data, key)) {
+ return false;
+ }
+
+ return tryConvertFloat(value, &data);
+}
+
+bool ByamlIter::tryConvertFloat(f32* value, const ByamlData* data) const {
+ if (data->getType() != ByamlType::Float) {
+ return false;
+ }
+
+ *value = data->getValue<f32>();
+ return true;
+}
+
+bool ByamlIter::tryGetBoolByIndex(bool* value, s32 index) const {
+ ByamlData data;
+ if (!getByamlDataByIndex(&data, index)) {
+ return false;
+ }
+
+ return tryConvertBool(value, &data);
+}
+
+bool ByamlIter::tryGetBoolByKey(bool* value, const char* key) const {
+ ByamlData data;
+ if (!getByamlDataByKey(&data, key)) {
+ return false;
+ }
+
+ return tryConvertBool(value, &data);
+}
+
+bool ByamlIter::tryConvertBool(bool* value, const ByamlData* data) const {
+ if (data->getType() != ByamlType::Bool) {
+ return false;
+ }
+
+ *value = data->getValue() != 0;
+ return true;
+}
+
+bool ByamlIter::isEqualData(const ByamlIter& other) const {
+ if (!mData || !other.mData) {
+ return false;
+ }
+
+ return mData == other.mData && mRootNode == other.mRootNode;
+}
+
+} // namespace al
diff --git a/src/KingSystem/Utils/Byaml.h b/src/KingSystem/Utils/Byaml/Byaml.h
index 5c600627..c13500d7 100644
--- a/src/KingSystem/Utils/Byaml.h
+++ b/src/KingSystem/Utils/Byaml/Byaml.h
@@ -4,12 +4,14 @@
#include <basis/seadTypes.h>
#include <math/seadVector.h>
+#include <prim/seadEndian.h>
#include <prim/seadSizedEnum.h>
#include "KingSystem/Utils/Types.h"
namespace al {
struct ByamlData;
+struct ByamlHashPair;
enum class ByamlType {
Invalid = 0,
@@ -41,6 +43,9 @@ public:
ByamlIter& operator=(const ByamlIter& rhs);
+ const u8* getData() const { return mData; }
+ const u8* getRootNode() const { return mRootNode; }
+
bool isValid() const;
bool isTypeHash() const;
bool isTypeArray() const;
@@ -51,11 +56,13 @@ public:
s32 getSize() const;
- void getByamlDataByIndex(ByamlData* data, s32 index) const;
- bool getByamlDataByKey(ByamlData* data, const char* key) const;
- bool getByamlDataByKeyIndex(ByamlData* data, s32 index) const;
ByamlIter getIterByIndex(s32 index) const;
ByamlIter getIterByKey(const char* key) const;
+ ByamlIter getIterFromData(const ByamlData& data) const;
+ bool getByamlDataByIndex(ByamlData* data, s32 index) const;
+ bool getByamlDataByKey(ByamlData* data, const char* key) const;
+ bool getByamlDataAndKeyNameByIndex(ByamlData* data, const char** key, s32 index) const;
+
bool getKeyName(const char** key, s32 index) const;
bool tryGetIterByIndex(ByamlIter* iter, s32 index) const;
@@ -68,6 +75,7 @@ public:
bool tryGetIntByIndex(s32* value, s32 index) const;
bool tryGetIntByKey(s32* value, const char* key) const;
+ bool tryConvertInt(s32* value, const ByamlData* data) const;
bool tryGetUIntByIndex(u32* value, s32 index) const;
bool tryGetUIntByKey(u32* value, const char* key) const;
@@ -75,61 +83,96 @@ public:
bool tryGetFloatByIndex(f32* value, s32 index) const;
bool tryGetFloatByKey(f32* value, const char* key) const;
+ bool tryConvertFloat(f32* value, const ByamlData* data) const;
bool tryGetBoolByIndex(bool* value, s32 index) const;
bool tryGetBoolByKey(bool* value, const char* key) const;
+ bool tryConvertBool(bool* value, const ByamlData* data) const;
bool isEqualData(const ByamlIter& other) const;
+ const char* getStringByIndex(s32 index) const {
+ const char* value;
+ if (!tryGetStringByIndex(&value, index))
+ return "";
+ return value;
+ }
+
+ const char* getStringByKey(const char* key) const {
+ const char* value;
+ if (!tryGetStringByKey(&value, key))
+ return "";
+ return value;
+ }
+
+ s32 getIntByIndex(s32 index) const {
+ s32 value;
+ if (!tryGetIntByIndex(&value, index))
+ return {};
+ return value;
+ }
+
+ s32 getIntByKey(const char* key) const {
+ s32 value;
+ if (!tryGetIntByKey(&value, key))
+ return {};
+ return value;
+ }
+
+ u32 getUIntByIndex(s32 index) const {
+ u32 value;
+ if (!tryGetUIntByIndex(&value, index))
+ return {};
+ return value;
+ }
+
+ u32 getUIntByKey(const char* key) const {
+ u32 value;
+ if (!tryGetUIntByKey(&value, key))
+ return {};
+ return value;
+ }
+
+ f32 getFloatByIndex(s32 index) const {
+ f32 value;
+ if (!tryGetFloatByIndex(&value, index))
+ return {};
+ return value;
+ }
+
+ f32 getFloatByKey(const char* key) const {
+ f32 value;
+ if (!tryGetFloatByKey(&value, key))
+ return {};
+ return value;
+ }
+
+ bool getBoolByIndex(s32 index) const {
+ bool value;
+ if (!tryGetBoolByIndex(&value, index))
+ return {};
+ return value;
+ }
+
+ bool getBoolByKey(const char* key) const {
+ bool value;
+ if (!tryGetBoolByKey(&value, key))
+ return {};
+ return value;
+ }
+
private:
const u8* mData = nullptr;
const u8* mRootNode = nullptr;
};
-class ByamlStringTableIter {
-public:
- explicit ByamlStringTableIter(const u8* data) : mData(data) {}
-
- const char* getString(s32 index) const;
- s32 findStringIndex(const char* string) const;
-
-private:
- const u8* mData;
-};
-
-class ByamlArrayIter {
-public:
- explicit ByamlArrayIter(const u8* data);
-
- const u8* getDataTable() const;
- bool getDataByIndex(ByamlData* data, s32 index);
-
-private:
- const u8* mData;
-};
-
-class ByamlHashIter {
-public:
- explicit ByamlHashIter(const u8* data);
-
- s32 getSize() const;
- const u8* getPairTable() const;
- bool getDataByIndex(ByamlData* data, s32 index) const;
- bool getDataByKey(ByamlData* data, s32 key_index) const;
- const u8* findPair(s32 key_index) const;
- const u8* getPairByIndex(s32 index) const;
-
-private:
- const u8* mData;
-};
-
struct ByamlHeader {
u16 getTag() const;
bool isInvertHeader() const;
- u16 getVersion() const;
- u16 getHashKeyTableOffset() const;
- u16 getStringTableOffset() const;
- u16 getDataOffset() const;
+ u16 getVersion() const { return version; };
+ u32 getHashKeyTableOffset() const { return hash_key_table_offset; };
+ u32 getStringTableOffset() const { return string_table_offset; };
+ u32 getDataOffset() const { return data_offset; };
u16 magic;
u16 version;
@@ -140,32 +183,15 @@ struct ByamlHeader {
KSYS_CHECK_SIZE_NX150(ByamlHeader, 0x10);
struct ByamlContainerHeader {
- ByamlType getType() const;
- u32 getCount(bool byteswap) const;
+ ByamlType getType() const {
+ // Type is only the first byte
+ return ByamlType(*reinterpret_cast<const u8*>(&type_and_size));
+ }
+ u32 getCount() const { return type_and_size >> 8; };
u32 type_and_size;
};
-struct ByamlHashPair {
- u32 getKey(bool byteswap) const;
- ByamlType getType() const;
- u32 getValue(bool byteswap) const;
-
- u32 name_and_type;
- u32 value;
-};
-
-struct ByamlData {
- u32 getValue() const { return value; }
- ByamlType getType() const { return type; }
-
- void set(const ByamlHashPair* pair, bool byteswap);
- void set(u8, u32, bool byteswap);
-
- u32 value = 0;
- sead::SizedEnum<ByamlType, u8> type = ByamlType::Invalid;
-};
-
bool tryGetByamlS32(s32* value, const ByamlIter& iter, const char* key);
bool tryGetByamlU32(u32* value, const ByamlIter& iter, const char* key);
bool tryGetByamlF32(f32* value, const ByamlIter& iter, const char* key);
diff --git a/src/KingSystem/Utils/Byaml/ByamlArrayIter.cpp b/src/KingSystem/Utils/Byaml/ByamlArrayIter.cpp
new file mode 100644
index 00000000..fe5db205
--- /dev/null
+++ b/src/KingSystem/Utils/Byaml/ByamlArrayIter.cpp
@@ -0,0 +1,29 @@
+#include "KingSystem/Utils/Byaml/ByamlArrayIter.h"
+#include "KingSystem/Utils/Byaml/Byaml.h"
+#include "KingSystem/Utils/Byaml/ByamlData.h"
+#include "KingSystem/Utils/Byaml/ByamlLocal.h"
+
+namespace al {
+ByamlArrayIter::ByamlArrayIter(const u8* data) {
+ mData = data;
+}
+
+const u32* ByamlArrayIter::getDataTable() const {
+ return reinterpret_cast<const u32*>(&mData[TypeTableOffset + getDataOffset()]);
+}
+
+bool ByamlArrayIter::getDataByIndex(ByamlData* data, s32 index) {
+ if (index < 0) {
+ return false;
+ }
+
+ if (index >= ByamlLocalUtil::getContainerSize(mData)) {
+ return false;
+ }
+
+ data->setType(ByamlType(mData[TypeTableOffset + index]));
+ data->setValue(getDataTable()[index]);
+
+ return true;
+}
+} // namespace al \ No newline at end of file
diff --git a/src/KingSystem/Utils/Byaml/ByamlArrayIter.h b/src/KingSystem/Utils/Byaml/ByamlArrayIter.h
new file mode 100644
index 00000000..a29cefc1
--- /dev/null
+++ b/src/KingSystem/Utils/Byaml/ByamlArrayIter.h
@@ -0,0 +1,28 @@
+#pragma once
+
+#include <basis/seadTypes.h>
+#include <math/seadMathCalcCommon.h>
+#include "KingSystem/Utils/Byaml/Byaml.h"
+#include "KingSystem/Utils/Byaml/ByamlLocal.h"
+
+namespace al {
+
+class ByamlArrayIter {
+public:
+ explicit ByamlArrayIter(const u8* data);
+
+ const u32* getDataTable() const;
+ bool getDataByIndex(ByamlData* data, s32 index);
+
+private:
+ s32 getDataOffset() const {
+ const s32 size = ByamlLocalUtil::getContainerSize(mData);
+ return sead::Mathu::roundUp(size, 4);
+ }
+
+ static constexpr s32 TypeTableOffset = 4;
+
+ const u8* mData;
+};
+
+} // namespace al
diff --git a/src/KingSystem/Utils/Byaml/ByamlData.cpp b/src/KingSystem/Utils/Byaml/ByamlData.cpp
new file mode 100644
index 00000000..2aff5f96
--- /dev/null
+++ b/src/KingSystem/Utils/Byaml/ByamlData.cpp
@@ -0,0 +1,7 @@
+#include "KingSystem/Utils/Byaml/ByamlData.h"
+#include "KingSystem/Utils/Byaml/Byaml.h"
+
+namespace al {
+ByamlData::ByamlData() = default;
+
+} // namespace al \ No newline at end of file
diff --git a/src/KingSystem/Utils/Byaml/ByamlData.h b/src/KingSystem/Utils/Byaml/ByamlData.h
new file mode 100644
index 00000000..ed41dc82
--- /dev/null
+++ b/src/KingSystem/Utils/Byaml/ByamlData.h
@@ -0,0 +1,45 @@
+#pragma once
+
+#include <basis/seadTypes.h>
+#include "KingSystem/Utils/Byaml/Byaml.h"
+#include "KingSystem/Utils/Byaml/ByamlHashIter.h"
+
+namespace al {
+
+struct ByamlData {
+ ByamlData();
+
+ template <typename T = u32>
+ T getValue() const {
+ return *reinterpret_cast<const T*>(&mValue);
+ }
+ ByamlType getType() const { return mType; }
+
+ void set(const ByamlHashPair* pair) {
+ mType = pair->getType();
+ mValue = pair->getValue();
+ }
+ template <typename T = u32>
+ void set(const ByamlType& type, const T& value) {
+ mType = type;
+ mValue = *reinterpret_cast<const u32*>(&value);
+ }
+
+ void setType(const ByamlType& type) { mType = type; }
+
+ template <typename T = u32>
+ void setValue(const T& value) {
+ mValue = *reinterpret_cast<const u32*>(&value);
+ }
+
+ void clear() {
+ mValue = 0;
+ mType = ByamlType::Invalid;
+ }
+
+private:
+ u32 mValue = 0;
+ sead::SizedEnum<ByamlType, u8> mType = ByamlType::Invalid;
+};
+
+} // namespace al
diff --git a/src/KingSystem/Utils/Byaml/ByamlHashIter.cpp b/src/KingSystem/Utils/Byaml/ByamlHashIter.cpp
new file mode 100644
index 00000000..edce10ee
--- /dev/null
+++ b/src/KingSystem/Utils/Byaml/ByamlHashIter.cpp
@@ -0,0 +1,110 @@
+#include "KingSystem/Utils/Byaml/ByamlHashIter.h"
+#include "KingSystem/Utils/Byaml/Byaml.h"
+#include "KingSystem/Utils/Byaml/ByamlData.h"
+#include "KingSystem/Utils/Byaml/ByamlLocal.h"
+
+namespace al {
+
+ByamlHashIter::ByamlHashIter(const u8* data) {
+ mData = data;
+}
+
+s32 ByamlHashIter::getSize() const {
+ if (!mData) {
+ return 0;
+ }
+
+ return ByamlLocalUtil::getContainerSize(mData);
+}
+
+const ByamlHashPair* ByamlHashIter::getPairTable() const {
+ if (!mData) {
+ return nullptr;
+ }
+
+ return reinterpret_cast<const ByamlHashPair*>(&mData[mTableOffset]);
+}
+
+bool ByamlHashIter::getDataByIndex(ByamlData* data, s32 index) const {
+ if (!mData) {
+ return false;
+ }
+
+ if (ByamlLocalUtil::getContainerSize(mData) == 0) {
+ return false;
+ }
+
+ const ByamlHashPair* pair_table = getPairTable();
+ const ByamlHashPair* pair = &pair_table[index];
+ if (!pair) // This seems wrong, this can never be null?
+ {
+ return false;
+ }
+
+ data->set(pair);
+
+ return true;
+}
+
+bool ByamlHashIter::getDataByKey(ByamlData* data, s32 key_index) const {
+ if (getSize() == 0) {
+ return false;
+ }
+
+ const ByamlHashPair* pair = findPair(key_index);
+ if (!pair) {
+ return false;
+ }
+
+ data->set(pair);
+ return true;
+}
+
+const ByamlHashPair* ByamlHashIter::findPair(s32 key_index) const {
+ const ByamlHashPair* pair_table = getPairTable();
+ if (!pair_table) {
+ return nullptr;
+ }
+
+ if (ByamlLocalUtil::getContainerSize(mData) == 0) {
+ return nullptr;
+ }
+
+ // Binary Search
+ s32 start = 0;
+ s32 end = getSize();
+ s32 index;
+ const ByamlHashPair* pair;
+ while (true) {
+ if (start >= end) {
+ return nullptr;
+ }
+
+ index = (start + end) / 2;
+ pair = &pair_table[index];
+ s32 result = key_index - pair->getKey();
+ if (result == 0)
+ break;
+ if (result > 0)
+ start = index + 1;
+ else if (result < 0)
+ end = index;
+ }
+
+ return pair;
+}
+
+const ByamlHashPair* ByamlHashIter::getPairByIndex(s32 index) const {
+ if (index < 0) {
+ return nullptr;
+ }
+
+ if (getSize() <= index) {
+ return nullptr;
+ }
+
+ const ByamlHashPair* pair_table = getPairTable();
+ return pair_table + index;
+}
+
+} // namespace al
diff --git a/src/KingSystem/Utils/Byaml/ByamlHashIter.h b/src/KingSystem/Utils/Byaml/ByamlHashIter.h
new file mode 100644
index 00000000..2ad55877
--- /dev/null
+++ b/src/KingSystem/Utils/Byaml/ByamlHashIter.h
@@ -0,0 +1,38 @@
+#pragma once
+
+#include <basis/seadTypes.h>
+#include "KingSystem/Utils/Byaml/Byaml.h"
+#include "prim/seadEndian.h"
+
+namespace al {
+
+struct ByamlData;
+struct ByamlHashPair;
+
+class ByamlHashIter {
+public:
+ explicit ByamlHashIter(const u8* data);
+
+ s32 getSize() const;
+ const ByamlHashPair* getPairTable() const;
+ bool getDataByIndex(ByamlData* data, s32 index) const;
+ bool getDataByKey(ByamlData* data, s32 key_index) const;
+ const ByamlHashPair* findPair(s32 key_index) const;
+ const ByamlHashPair* getPairByIndex(s32 index) const;
+
+private:
+ const u8* mData;
+
+ static constexpr s32 mTableOffset = 4;
+};
+
+struct ByamlHashPair {
+ u32 getKey() const { return mKeyAndType & 0xFFFFFF; }
+ ByamlType getType() const { return ByamlType(mKeyAndType >> 24); }
+ u32 getValue() const { return mValue; }
+
+ u32 mKeyAndType;
+ u32 mValue;
+};
+
+} // namespace al
diff --git a/src/KingSystem/Utils/Byaml/ByamlLocal.cpp b/src/KingSystem/Utils/Byaml/ByamlLocal.cpp
new file mode 100644
index 00000000..321fc879
--- /dev/null
+++ b/src/KingSystem/Utils/Byaml/ByamlLocal.cpp
@@ -0,0 +1,3 @@
+#include "KingSystem/Utils/Byaml/ByamlLocal.h"
+
+namespace al::ByamlLocalUtil {} // namespace al::ByamlLocalUtil \ No newline at end of file
diff --git a/src/KingSystem/Utils/Byaml/ByamlLocal.h b/src/KingSystem/Utils/Byaml/ByamlLocal.h
new file mode 100644
index 00000000..faf51cac
--- /dev/null
+++ b/src/KingSystem/Utils/Byaml/ByamlLocal.h
@@ -0,0 +1,38 @@
+#pragma once
+
+#include "KingSystem/Utils/Byaml/Byaml.h"
+#include "KingSystem/Utils/Byaml/ByamlStringTableIter.h"
+
+#include <basis/seadTypes.h>
+
+namespace al::ByamlLocalUtil {
+
+inline ByamlStringTableIter getHashKeyTableIter(const u8* data) {
+ auto* header = reinterpret_cast<const al::ByamlHeader*>(data);
+ const u8* ptr = &data[header->getHashKeyTableOffset()];
+ return ByamlStringTableIter(ptr);
+}
+
+inline ByamlStringTableIter getStringTableIter(const u8* data) {
+ auto* header = reinterpret_cast<const al::ByamlHeader*>(data);
+ const u8* ptr = &data[header->getStringTableOffset()];
+ return ByamlStringTableIter(ptr);
+}
+
+inline s32 getContainerSize(const u8* data) {
+ auto* node = reinterpret_cast<const al::ByamlContainerHeader*>(data);
+ return node->getCount();
+}
+
+inline al::ByamlType getType(const u8* data) {
+ auto* node = reinterpret_cast<const al::ByamlContainerHeader*>(data);
+ return node->getType();
+}
+
+const char* getDataTypeString(s32 type);
+
+bool verifiByaml(const u8* data);
+bool verifiByamlHeader(const u8* data);
+bool verifiByamlStringTable(const u8* data);
+
+} // namespace al::ByamlLocalUtil
diff --git a/src/KingSystem/Utils/Byaml/ByamlStringTableIter.cpp b/src/KingSystem/Utils/Byaml/ByamlStringTableIter.cpp
new file mode 100644
index 00000000..f55e69c8
--- /dev/null
+++ b/src/KingSystem/Utils/Byaml/ByamlStringTableIter.cpp
@@ -0,0 +1,50 @@
+#include "KingSystem/Utils/Byaml/ByamlStringTableIter.h"
+#include "KingSystem/Utils/Byaml/Byaml.h"
+#include "KingSystem/Utils/Byaml/ByamlLocal.h"
+
+namespace al {
+
+ByamlStringTableIter::ByamlStringTableIter(const u8* data) {
+ mData = data;
+}
+
+ByamlStringTableIter::ByamlStringTableIter(const ByamlStringTableIter& other) {
+ mData = other.mData;
+}
+
+const char* ByamlStringTableIter::getString(s32 index) const {
+ const u32* string_offset_array = getStringOffsetArray();
+ return reinterpret_cast<const char*>(&mData[string_offset_array[index]]);
+}
+
+s32 ByamlStringTableIter::findStringIndex(const char* string) const {
+ const u32* string_offset_array = getStringOffsetArray();
+ u32 table_size = ByamlLocalUtil::getContainerSize(mData);
+ if (table_size == 0) {
+ return -1;
+ }
+
+ // Binary Search
+ s32 start = 0;
+ s32 end = table_size;
+ s32 index;
+ while (true) {
+ if (start >= end) {
+ return -1;
+ }
+
+ index = (start + end) / 2;
+ const char* str = reinterpret_cast<const char*>(&mData[string_offset_array[index]]);
+ s32 result = std::strcmp(string, str);
+ if (result == 0)
+ break;
+ if (result > 0)
+ start = index + 1;
+ else if (result < 0)
+ end = index;
+ }
+
+ return index;
+}
+
+} // namespace al
diff --git a/src/KingSystem/Utils/Byaml/ByamlStringTableIter.h b/src/KingSystem/Utils/Byaml/ByamlStringTableIter.h
new file mode 100644
index 00000000..5e397ab4
--- /dev/null
+++ b/src/KingSystem/Utils/Byaml/ByamlStringTableIter.h
@@ -0,0 +1,27 @@
+#pragma once
+
+#include <basis/seadTypes.h>
+
+namespace al {
+
+class ByamlStringTableIter {
+public:
+ explicit ByamlStringTableIter(const u8* data);
+ ByamlStringTableIter(const ByamlStringTableIter& other);
+
+ const char* getString(s32 index) const;
+ s32 findStringIndex(const char* string) const;
+
+ bool isValid() const { return mData != nullptr; }
+
+ const u32* getStringOffsetArray() const {
+ return reinterpret_cast<const u32*>(&mData[TableOffset]);
+ }
+
+private:
+ const u8* mData;
+
+ static constexpr u32 TableOffset = 4u;
+};
+
+} // namespace al \ No newline at end of file
diff --git a/src/KingSystem/Utils/ByamlUtil.cpp b/src/KingSystem/Utils/Byaml/ByamlUtil.cpp
index 6c46fff5..ef0df072 100644
--- a/src/KingSystem/Utils/ByamlUtil.cpp
+++ b/src/KingSystem/Utils/Byaml/ByamlUtil.cpp
@@ -1,4 +1,4 @@
-#include "KingSystem/Utils/Byaml.h"
+#include "KingSystem/Utils/Byaml/Byaml.h"
namespace al {
diff --git a/src/KingSystem/Utils/ByamlLocal.cpp b/src/KingSystem/Utils/ByamlLocal.cpp
deleted file mode 100644
index e981e804..00000000
--- a/src/KingSystem/Utils/ByamlLocal.cpp
+++ /dev/null
@@ -1 +0,0 @@
-#include "KingSystem/Utils/ByamlLocal.h"
diff --git a/src/KingSystem/Utils/ByamlLocal.h b/src/KingSystem/Utils/ByamlLocal.h
deleted file mode 100644
index f10c68b8..00000000
--- a/src/KingSystem/Utils/ByamlLocal.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#pragma once
-
-#include <basis/seadTypes.h>
-
-namespace alByamlLocalUtil {
-
-const char* getDataTypeString(s32 type);
-
-const u8* getHashKeyTable(const u8* data);
-const u8* getStringTable(const u8* data);
-
-bool verifiByaml(const u8* data);
-bool verifiByamlHeader(const u8* data);
-bool verifiByamlStringTable(const u8* data);
-
-} // namespace alByamlLocalUtil
diff --git a/src/KingSystem/Utils/CMakeLists.txt b/src/KingSystem/Utils/CMakeLists.txt
index 1fa59cff..45b8ecdd 100644
--- a/src/KingSystem/Utils/CMakeLists.txt
+++ b/src/KingSystem/Utils/CMakeLists.txt
@@ -21,11 +21,20 @@ target_sources(uking PRIVATE
Thread/TaskThread.cpp
Thread/TaskThread.h
- Byaml.cpp
- Byaml.h
- ByamlLocal.cpp
- ByamlLocal.h
- ByamlUtil.cpp
+ Byaml/Byaml.cpp
+ Byaml/Byaml.h
+ Byaml/ByamlArrayIter.cpp
+ Byaml/ByamlArrayIter.h
+ Byaml/ByamlData.cpp
+ Byaml/ByamlData.h
+ Byaml/ByamlStringTableIter.cpp
+ Byaml/ByamlStringTableIter.h
+ Byaml/ByamlHashIter.cpp
+ Byaml/ByamlHashIter.h
+ Byaml/ByamlLocal.cpp
+ Byaml/ByamlLocal.h
+ Byaml/ByamlUtil.cpp
+
Debug.h
FixedString.h
HashUtil.h
diff --git a/src/KingSystem/Utils/ParamIO.h b/src/KingSystem/Utils/ParamIO.h
index 58f14e55..820cdc76 100644
--- a/src/KingSystem/Utils/ParamIO.h
+++ b/src/KingSystem/Utils/ParamIO.h
@@ -16,12 +16,13 @@ public:
bool applyResourceUpdate(const char* data, const char* data1);
u32 getIdx() const { return mIdx; }
- const sead::SafeString& getId() const { return mId; }
+ sead::BufferedSafeString& getPath() { return mPath; }
+ const sead::BufferedSafeString& getPath() const { return mPath; }
void setIndex(u32 idx) { mIdx = idx; }
protected:
u32 mIdx = 0x1c;
- sead::FixedSafeString<128> mId;
+ sead::FixedSafeString<128> mPath;
};
KSYS_CHECK_SIZE_NX150(ParamIO, 0x278);