diff --git a/data/uking_functions.csv b/data/uking_functions.csv index dafc9e24..e2693cc7 100644 --- a/data/uking_functions.csv +++ b/data/uking_functions.csv @@ -5049,7 +5049,7 @@ 0x00000071000e6500,AI_Action_DamageTurnByWeakPoint::loadParams,156, 0x00000071000e659c,AI_Action_DamageTurnByWeakPoint::rtti1,288, 0x00000071000e66bc,AI_Action_DamageTurnByWeakPoint::rtti2,92, -0x00000071000e6718,_ZN4sead21FormatFixedSafeStringILi256EEC2EPKcz,224, +0x00000071000e6718,_ZN4sead21FormatFixedSafeStringILi256EEC2EPKcz,224,_ZN4sead21FormatFixedSafeStringILi256EEC2EPKcz 0x00000071000e67f8,j__ZdlPv_42,4, 0x00000071000e67fc,AI_Action_DefeatedHugeEnemyCount::ctor,56, 0x00000071000e6834,AI_Action_DefeatedHugeEnemyCount::dtor,20, @@ -84589,20 +84589,20 @@ 0x0000007100fdf538,sub_7100FDF538,52, 0x0000007100fdf56c,sub_7100FDF56C,92, 0x0000007100fdf5c8,sub_7100FDF5C8,44, -0x0000007100fdf5f4,TempResourceLoader::ctor,148, -0x0000007100fdf688,TempResourceLoader::dtor,44, -0x0000007100fdf6b4,TempResourceLoader::unload,212, -0x0000007100fdf788,TempResourceLoader::setStruct10,16, -0x0000007100fdf798,TempResourceLoader::isStatus1,12, -0x0000007100fdf7a4,TempResourceLoader::hasResourceAndIsParseOk,24, -0x0000007100fdf7bc,TempResourceLoader::callRes2I,24, -0x0000007100fdf7d4,TempResourceLoader::submitLoadReq,412, -0x0000007100fdf970,TempResourceLoader::load,504, -0x0000007100fdfb68,TempResourceLoader::loadSync,844, -0x0000007100fdfeb4,TempResourceLoader::getResource,64, -0x0000007100fdfef4,TempResourceLoader::getResError,8, -0x0000007100fdfefc,TempResourceLoader::getFileDeviceIfHasResource,56, -0x0000007100fdff34,TempResourceLoader::getHeapSize,16, +0x0000007100fdf5f4,TempResourceLoader::ctor,148,_ZN4ksys3res18TempResourceLoaderC1Ev +0x0000007100fdf688,TempResourceLoader::dtor,44,_ZN4ksys3res18TempResourceLoaderD1Ev +0x0000007100fdf6b4,TempResourceLoader::unload,212,_ZN4ksys3res18TempResourceLoader6unloadEv +0x0000007100fdf788,TempResourceLoader::setStruct10,16,_ZN4ksys3res18TempResourceLoader4initERKNS1_7InitArgE +0x0000007100fdf798,TempResourceLoader::isStatus1,12,_ZNK4ksys3res18TempResourceLoader9isLoadingEv +0x0000007100fdf7a4,TempResourceLoader::hasResourceAndIsParseOk,24,_ZNK4ksys3res18TempResourceLoader9isSuccessEv +0x0000007100fdf7bc,TempResourceLoader::callRes2I,24,_ZNK4ksys3res18TempResourceLoader15checkLoadStatusEv +0x0000007100fdf7d4,TempResourceLoader::submitLoadReq,412,_ZN4ksys3res18TempResourceLoader11requestLoadERNS1_7LoadArgE +0x0000007100fdf970,TempResourceLoader::load,504,_ZN4ksys3res18TempResourceLoader25getResourceForLoadRequestEPNS0_7ContextE +0x0000007100fdfb68,TempResourceLoader::loadSync,844,_ZN4ksys3res18TempResourceLoader4loadERNS1_7LoadArgE +0x0000007100fdfeb4,TempResourceLoader::getResource,64,_ZNK4ksys3res18TempResourceLoader11getResourceEv +0x0000007100fdfef4,TempResourceLoader::getResError,8,_ZNK4ksys3res18TempResourceLoader15getHandleStatusEv +0x0000007100fdfefc,TempResourceLoader::getFileDeviceIfHasResource,56,_ZNK4ksys3res18TempResourceLoader19getHandleFileDeviceEv +0x0000007100fdff34,TempResourceLoader::getHeapSize,16,_ZNK4ksys3res18TempResourceLoader15getWorkHeapSizeEv 0x0000007100fdff44,Struct10::ctor,8,_ZN4ksys3res11ArchiveWorkC1Ev 0x0000007100fdff4c,sub_7100FDFF4C,88,_ZN4ksys3res11ArchiveWorkD1Ev 0x0000007100fdffa4,Struct10::initEventAndOverlayArenaS1,260,_ZN4ksys3res11ArchiveWork4initERKNS1_7InitArgE diff --git a/lib/sead b/lib/sead index 2c55e2f0..29da026c 160000 --- a/lib/sead +++ b/lib/sead @@ -1 +1 @@ -Subproject commit 2c55e2f00fd10d58739c3a6efa57cf93c7195995 +Subproject commit 29da026c05155b3432eed35f89818bf474894b2b diff --git a/src/KingSystem/Resource/CMakeLists.txt b/src/KingSystem/Resource/CMakeLists.txt index 715888cf..02d43598 100644 --- a/src/KingSystem/Resource/CMakeLists.txt +++ b/src/KingSystem/Resource/CMakeLists.txt @@ -111,6 +111,8 @@ target_sources(uking PRIVATE resResourceMgrTask.h resSystem.cpp resSystem.h + resTempResourceLoader.cpp + resTempResourceLoader.h resTextureHandleList.cpp resTextureHandleList.h resTextureHandleMgr.cpp 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/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 +#include +#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 +#include +#include +#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 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/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;