From b1926813b720b1f8088db62160cb60430b0b11f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Fri, 25 Sep 2020 17:49:07 +0200 Subject: [PATCH] ksys/res: Start adding ResourceUnit and Cache --- data/uking_functions.csv | 72 +++--- lib/sead | 2 +- src/KingSystem/Resource/CMakeLists.txt | 9 +- src/KingSystem/Resource/resCache.cpp | 25 ++ src/KingSystem/Resource/resCache.h | 31 +++ .../Resource/resCacheCriticalSection.cpp | 9 + .../Resource/resCacheCriticalSection.h | 9 + src/KingSystem/Resource/resHandle.h | 13 ++ src/KingSystem/Resource/resLoadRequest.h | 2 +- src/KingSystem/Resource/resUnit.cpp | 221 ++++++++++++++++++ src/KingSystem/Resource/resUnit.h | 191 +++++++++++++++ src/KingSystem/System/OverlayArena.cpp | 6 +- src/KingSystem/Utils/CMakeLists.txt | 1 + src/KingSystem/Utils/InitTimeInfo.h | 23 ++ src/KingSystem/Utils/StrTreeMap.h | 1 + src/KingSystem/Utils/Thread/Task.h | 1 + 16 files changed, 573 insertions(+), 43 deletions(-) create mode 100644 src/KingSystem/Resource/resCache.cpp create mode 100644 src/KingSystem/Resource/resCache.h create mode 100644 src/KingSystem/Resource/resCacheCriticalSection.cpp create mode 100644 src/KingSystem/Resource/resCacheCriticalSection.h create mode 100644 src/KingSystem/Resource/resUnit.cpp create mode 100644 src/KingSystem/Resource/resUnit.h create mode 100644 src/KingSystem/Utils/InitTimeInfo.h diff --git a/data/uking_functions.csv b/data/uking_functions.csv index 576e566d..823d5b32 100644 --- a/data/uking_functions.csv +++ b/data/uking_functions.csv @@ -90833,13 +90833,13 @@ 0x0000007101202f40,ResourceLoadArg3::dtorDelete,4,_ZN4ksys3res23SimplePackedLoadRequestD0Ev 0x0000007101202f44,sub_7101202F44,140,_ZNK4sead15RuntimeTypeInfo6DeriveIN4ksys3res12ILoadRequestEE9isDerivedEPKNS0_9InterfaceE 0x0000007101202fd0,sub_7101202FD0,32, -0x0000007101202ff0,Struct18::ctor,32, -0x0000007101203010,nullsub_4696,4, -0x0000007101203014,j__ZdlPv_1236,4, -0x0000007101203018,nullsub_4697,4, -0x000000710120301c,Struct18::getBinder,288, +0x0000007101202ff0,Struct18::ctor,32,_ZN4ksys3res5CacheC1Ev +0x0000007101203010,nullsub_4696,4,_ZN4ksys3res5CacheD2Ev +0x0000007101203014,j__ZdlPv_1236,4,_ZN4ksys3res5CacheD0Ev +0x0000007101203018,nullsub_4697,4,_ZN4ksys3res5Cache4initEv +0x000000710120301c,Struct18::getBinder,288,_ZNK4ksys3res5Cache8findUnitERKNS_4util13StrTreeMapKeyE 0x000000710120313c,Struct18::doLoadOnThread,1008, -0x000000710120352c,Struct18::eraseResFromCache,108, +0x000000710120352c,Struct18::eraseResFromCache,108,_ZN4ksys3res5Cache9eraseUnitEPNS0_12ResourceUnitE 0x0000007101203598,sub_7101203598,100, 0x0000007101203694,nullsub_4698,4, 0x0000007101203698,res::lockResourceCacheCS,12, @@ -90851,7 +90851,7 @@ 0x00000071012037c4,sub_71012037C4,116, 0x0000007101203838,sub_7101203838,48, 0x0000007101203868,sub_7101203868,92, -0x00000071012038c4,sub_71012038C4,76, +0x00000071012038c4,sub_71012038C4,76,_GLOBAL__sub_I_resCacheCriticalSection.cpp 0x0000007101203910,nullsub_5571,4, 0x0000007101203914,sub_7101203914,228, 0x00000071012039f8,res::ResourceMgrTask::setInstance,32, @@ -90995,31 +90995,31 @@ 0x000000710120d070,sub_710120D070,92, 0x000000710120d0cc,j__ZdlPv_1241,4, 0x000000710120d0d0,sub_710120D0D0,140, -0x000000710120d15c,ResourceBinder::ctor,664, -0x000000710120d3f4,ResourceBinder::initAndSetFlags,1408, -0x000000710120d974,ResourceBinder::ctor2,400, -0x000000710120db04,ResourceBinder::dtor,128, -0x000000710120db84,ResourceBinder::unloadArchiveResAndRes2,24, -0x000000710120db9c,sub_710120DB9C,20, -0x000000710120dbb0,ResourceBinder::dtorDelete,136, -0x000000710120dc38,ResourceBinder::j,40, -0x000000710120dc60,ResourceBinder::getFieldBC,8, -0x000000710120dc68,ResourceBinder::getError,8, -0x000000710120dc70,ResourceBinder::updateErrorFromMap,36, -0x000000710120dc94,ResourceBinder::event1Field40IsOne,16, -0x000000710120dca4,ResourceBinder::errorIsZero,16, -0x000000710120dcb4,ResourceBinder::needsPrepareLoad,80, -0x000000710120dd04,ResourceBinder::errorIsOne,16, -0x000000710120dddc,ResourceBinder::errorMinus9Stuff,44, -0x000000710120de08,ResourceBinder::isParseOk,228, -0x000000710120deec,ResourceBinder::getStatusByteRightShift7Stuff,12, -0x000000710120def8,ResourceBinder::b,32, -0x000000710120df18,ResourceBinder::getHeapSize,24, -0x000000710120df30,ResourceBinder::getHeap,8, -0x000000710120df38,ResourceBinder::isBitSetOnField8,12, -0x000000710120df44,ResourceBinder::field8Stuff,56, -0x000000710120df7c,ResourceBinder::c,24, -0x000000710120df94,ResourceBinder::eps3CallP,28, +0x000000710120d15c,ResourceBinder::ctor,664,_ZN4ksys3res12ResourceUnitC1ERKNS1_7InitArgE +0x000000710120d3f4,ResourceBinder::initAndSetFlags,1408,_ZN4ksys3res12ResourceUnit4initERKNS1_7InitArgE +0x000000710120d974,ResourceBinder::ctor2,400,_ZN4ksys3res12ResourceUnitC1Ev +0x000000710120db04,ResourceBinder::dtor,128,_ZN4ksys3res12ResourceUnitD1Ev +0x000000710120db84,ResourceBinder::unloadArchiveResAndRes2,24,_ZN4ksys3res12ResourceUnit16unloadArchiveResEv +0x000000710120db9c,sub_710120DB9C,20,_ZN4ksys3res19ResourceUnitMapNodeD2Ev +0x000000710120dbb0,ResourceBinder::dtorDelete,136,_ZN4ksys3res12ResourceUnitD0Ev +0x000000710120dc38,ResourceBinder::j,40,_ZN4ksys3res12ResourceUnit12attachHandleEPNS0_6HandleE +0x000000710120dc60,ResourceBinder::getFieldBC,8,_ZNK4ksys3res12ResourceUnit11getRefCountEv +0x000000710120dc68,ResourceBinder::getError,8,_ZNK4ksys3res12ResourceUnit9getStatusEv +0x000000710120dc70,ResourceBinder::updateErrorFromMap,36,_ZN4ksys3res12ResourceUnit12updateStatusEv? +0x000000710120dc94,ResourceBinder::event1Field40IsOne,16,_ZNK4ksys3res12ResourceUnit16isTask1NotQueuedEv +0x000000710120dca4,ResourceBinder::errorIsZero,16,_ZNK4ksys3res12ResourceUnit9isStatus0Ev +0x000000710120dcb4,ResourceBinder::needsPrepareLoad,80,_ZNK4ksys3res12ResourceUnit22isTask1ActiveOrStatus7Ev +0x000000710120dd04,ResourceBinder::errorIsOne,16,_ZNK4ksys3res12ResourceUnit9isStatus1Ev +0x000000710120dddc,ResourceBinder::errorMinus9Stuff,44,_ZNK4ksys3res12ResourceUnit15isStatus9_12_15Ev +0x000000710120de08,ResourceBinder::isParseOk,228,_ZNK4ksys3res12ResourceUnit9isParseOkEv? +0x000000710120deec,ResourceBinder::getStatusByteRightShift7Stuff,12,_ZNK4ksys3res12ResourceUnit19isStatusFlag8000SetEv +0x000000710120def8,ResourceBinder::b,32,_ZNK4ksys3res12ResourceUnit21isLinkedToResourceMgrEv +0x000000710120df18,ResourceBinder::getHeapSize,24,_ZNK4ksys3res12ResourceUnit11getHeapSizeEv +0x000000710120df30,ResourceBinder::getHeap,8,_ZNK4ksys3res12ResourceUnit7getHeapEv +0x000000710120df38,ResourceBinder::isBitSetOnField8,12,_ZNK4ksys3res12ResourceUnit15isLinkedToCacheEv +0x000000710120df44,ResourceBinder::field8Stuff,56,_ZN4ksys3res12ResourceUnit18setIsLinkedToCacheEb +0x000000710120df7c,ResourceBinder::c,24,_ZN4ksys3res12ResourceUnit15removeFromCacheEv +0x000000710120df94,ResourceBinder::eps3CallP,28,_ZN4ksys3res12ResourceUnit20removeTask3FromQueueEv 0x000000710120dfb0,ResourceBinder::requestReadFilePathAndPrepareLoadOnResMemThread,204, 0x000000710120e07c,ResourceBinder::waitForResourceAndParse,792, 0x000000710120e394,ResourceBinder::waitForEvent1,28, @@ -91040,10 +91040,10 @@ 0x0000007101211e78,ResourceBinder::h,120, 0x00000071012127a0,ResourceBinder::clearCacheUnloadDestroyDev,976, 0x0000007101212d74,res::clearCacheAndDeleteUnit,456, -0x0000007101212ff8,ResourceBinder::rtti1,112, -0x0000007101213068,ResourceBinder::rtti2,92, -0x00000071012130c4,j__ZdlPv_1242,4, -0x00000071012130c8,sub_71012130C8,8, +0x0000007101212ff8,ResourceBinder::rtti1,112,_ZNK4ksys3res12ResourceUnit27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE +0x0000007101213068,ResourceBinder::rtti2,92,_ZNK4ksys3res12ResourceUnit18getRuntimeTypeInfoEv +0x00000071012130c4,j__ZdlPv_1242,4,_ZN4ksys3res19ResourceUnitMapNodeD0Ev +0x00000071012130c8,sub_71012130C8,8,_ZN4ksys3res19ResourceUnitMapNode6erase_Ev 0x00000071012130d0,sub_71012130D0,116, 0x0000007101213144,isResourceMgrOom,16, 0x0000007101213154,res::registerEntryFactory,32, diff --git a/lib/sead b/lib/sead index bb63f3f5..eab3d9e0 160000 --- a/lib/sead +++ b/lib/sead @@ -1 +1 @@ -Subproject commit bb63f3f5d6fc1d68e543cf76a7920006eff70910 +Subproject commit eab3d9e09fcf11b1ef052bc1cd1b339fb4fe387b diff --git a/src/KingSystem/Resource/CMakeLists.txt b/src/KingSystem/Resource/CMakeLists.txt index 75aaab56..46218270 100644 --- a/src/KingSystem/Resource/CMakeLists.txt +++ b/src/KingSystem/Resource/CMakeLists.txt @@ -82,6 +82,10 @@ target_sources(uking PRIVATE GeneralParamList/resGParamListObjectZora.h GeneralParamList/resGParamListTraits.h + resCache.cpp + resCache.h + resCacheCriticalSection.cpp + resCacheCriticalSection.h resCurrentResNameMgr.cpp resCurrentResNameMgr.h resEntryFactory.cpp @@ -92,6 +96,9 @@ target_sources(uking PRIVATE resLoadRequest.h resOffsetReadFileDevice.cpp resOffsetReadFileDevice.h + resSystem.h + resUnit.cpp + resUnit.h resResource.cpp resResource.h @@ -111,6 +118,4 @@ target_sources(uking PRIVATE resResourceLod.h resResourceRecipe.cpp resResourceRecipe.h - - resSystem.h ) diff --git a/src/KingSystem/Resource/resCache.cpp b/src/KingSystem/Resource/resCache.cpp new file mode 100644 index 00000000..4f7abb62 --- /dev/null +++ b/src/KingSystem/Resource/resCache.cpp @@ -0,0 +1,25 @@ +#include "KingSystem/Resource/resCache.h" +#include +#include "KingSystem/Resource/resCacheCriticalSection.h" + +namespace ksys::res { + +Cache::Cache() = default; + +void Cache::init() {} + +ResourceUnit* Cache::findUnit(const util::StrTreeMapNode::KeyType& key) const { + auto lock = sead::makeScopedLock(gCacheCriticalSection); + ResourceUnitMapNode* node = mMap.find(key); + return node ? node->getUnit() : nullptr; +} + +void Cache::eraseUnit(ResourceUnit* unit) { + auto lock = sead::makeScopedLock(gCacheCriticalSection); + if (unit->isLinkedToCache()) { + mMap.erase(unit->getCacheKey()); + unit->setIsLinkedToCache(false); + } +} + +} // namespace ksys::res diff --git a/src/KingSystem/Resource/resCache.h b/src/KingSystem/Resource/resCache.h new file mode 100644 index 00000000..a0a2da91 --- /dev/null +++ b/src/KingSystem/Resource/resCache.h @@ -0,0 +1,31 @@ +#pragma once + +#include +#include "KingSystem/Resource/resUnit.h" +#include "KingSystem/Utils/StrTreeMap.h" +#include "KingSystem/Utils/Types.h" + +namespace ksys::res { + +struct LoadContext; + +class Cache : public sead::hostio::Node { +public: + Cache(); + virtual ~Cache() = default; + + void init(); + + ResourceUnit* findUnit(const ResourceUnitMapNode::KeyType& key) const; + void eraseUnit(ResourceUnit* unit); + + // FIXME: return type + s32 loadResource(const LoadContext& context); + +private: + [[maybe_unused]] u8 _8 = 2; + util::StrTreeMap mMap; +}; +KSYS_CHECK_SIZE_NX150(Cache, 0x18); + +} // namespace ksys::res diff --git a/src/KingSystem/Resource/resCacheCriticalSection.cpp b/src/KingSystem/Resource/resCacheCriticalSection.cpp new file mode 100644 index 00000000..eb2a12db --- /dev/null +++ b/src/KingSystem/Resource/resCacheCriticalSection.cpp @@ -0,0 +1,9 @@ +#include "KingSystem/Resource/resCacheCriticalSection.h" +#include "KingSystem/Utils/InitTimeInfo.h" + +namespace ksys::res { + +[[maybe_unused]] static util::InitTimeInfo sInitTimeInfo; +sead::CriticalSection gCacheCriticalSection; + +} // namespace ksys::res diff --git a/src/KingSystem/Resource/resCacheCriticalSection.h b/src/KingSystem/Resource/resCacheCriticalSection.h new file mode 100644 index 00000000..339a34be --- /dev/null +++ b/src/KingSystem/Resource/resCacheCriticalSection.h @@ -0,0 +1,9 @@ +#pragma once + +#include + +namespace ksys::res { + +extern sead::CriticalSection gCacheCriticalSection; + +} // namespace ksys::res diff --git a/src/KingSystem/Resource/resHandle.h b/src/KingSystem/Resource/resHandle.h index 186cb4ab..f31dcb67 100644 --- a/src/KingSystem/Resource/resHandle.h +++ b/src/KingSystem/Resource/resHandle.h @@ -1,12 +1,18 @@ #pragma once #include +#include #include #include "KingSystem/Utils/Thread/ManagedTaskHandle.h" #include "KingSystem/Utils/Types.h" +namespace sead { +class DirectResource; +} + namespace ksys::res { +class ILoadRequest; class ResourceUnit; // FIXME: incomplete @@ -22,6 +28,13 @@ public: Status getStatus() const; + sead::DirectResource* load(const sead::SafeString& path, const ILoadRequest& request, + Status* out_status = nullptr); + + void unload(); + + void setUnit(ResourceUnit* unit) { mUnit = unit; } + private: enum class Flag : u8 { _1 = 0x1, diff --git a/src/KingSystem/Resource/resLoadRequest.h b/src/KingSystem/Resource/resLoadRequest.h index e72d6ab6..e7384aa0 100644 --- a/src/KingSystem/Resource/resLoadRequest.h +++ b/src/KingSystem/Resource/resLoadRequest.h @@ -46,7 +46,7 @@ public: bool _27 = true; bool _28 = true; s32 mLoadDataAlignment = 0; - u32 mAllocSize = 0; + u32 mBufferSize = 0; u32 _34 = 0; sead::FileDevice* mFileDevice = nullptr; EntryFactoryBase* mEntryFactory = nullptr; diff --git a/src/KingSystem/Resource/resUnit.cpp b/src/KingSystem/Resource/resUnit.cpp new file mode 100644 index 00000000..8ddc4f34 --- /dev/null +++ b/src/KingSystem/Resource/resUnit.cpp @@ -0,0 +1,221 @@ +#include "KingSystem/Resource/resUnit.h" +#include +#include +#include "KingSystem/Resource/resCache.h" +#include "KingSystem/Resource/resEntryFactory.h" +#include "KingSystem/Resource/resLoadRequest.h" +#include "KingSystem/Resource/resSystem.h" + +namespace ksys::res { + +ResourceUnit::ResourceUnit(const InitArg& arg) + : mArena(arg.arena), mLoadReqArena(arg.load_req->mArena), mLoadReqField68(arg.load_req->_68), + mCache(arg.cache), mFileDevice(arg.load_req->mFileDevice), + mLoadReqAllocSize(arg.load_req->_34), mAllocSize(arg.alloc_size), mPath(arg.path), + mHeap(arg.heap) { + init(arg); +} + +ResourceUnit::ResourceUnit() = default; + +bool ResourceUnit::init(const ResourceUnit::InitArg& arg) { + mCacheFlags.makeAllZero(); + mFlags.makeAllZero(); + mStatusFlags.makeAllZero(); + mStatus = Status::_0; + mArena = arg.arena; + mArena1 = nullptr; + mArena2 = nullptr; + mLoadReqArena = arg.load_req->mArena; + mArchiveRes = nullptr; + mResource = nullptr; + mLoadReqField68 = arg.load_req->_68; + mCache = arg.cache; + mFileDevice = arg.load_req->mFileDevice; + mLoadReqAllocSize = arg.load_req->_34; + mAllocSize = arg.alloc_size; + mInfoAllocSize = 0; + mRefCount.storeNonAtomic(0); + mCounter.storeNonAtomic(0); + mEvent.resetSignal(); + mLoadArg = {}; + mPath = arg.path; + mHeap = arg.heap; + + if (arg.load_req->mPackHandle) { + SimplePackedLoadRequest request; + request._8 = true; + request.mRequester = "ResourceUnit"; + request._c = 2; + request.mPack = arg.load_req->mPackHandle; + mArchiveRes = sead::DynamicCast(mArchiveResHandle.load("", request)); + } + + mMapNode.key().setKey(mPath); + + mLoadArg.path = mPath; + mLoadArg.instance_heap = nullptr; + mLoadArg.instance_alignment = sizeof(void*); + mLoadArg.load_data_heap = nullptr; + mLoadArg.load_data_alignment = arg.load_req->mLoadDataAlignment; + mLoadArg.load_data_buffer = nullptr; + mLoadArg.load_data_buffer_size = arg.load_req->mBufferSize; + mLoadArg.factory = arg.load_req->mEntryFactory; + mLoadArg.device = arg.load_req->mAocFileDevice; + mLoadArg.assert_on_alloc_fail = false; + + bool load_from_archive; + if (sead::IsDerivedFrom(mLoadArg.device)) + load_from_archive = true; + else + load_from_archive = arg.load_req->mPackHandle != nullptr; + + mStatusFlags.change(StatusFlag::BufferSizeIsNonZero, arg.load_req->mBufferSize != 0); + mStatusFlags.change(StatusFlag::LoadFromArchive, load_from_archive); + mStatusFlags.change(StatusFlag::LoadReqField24IsTrue, arg.load_req->_24); + + mFlags.change(Flag::_1, arg.set_flag_1); + mFlags.change(Flag::_2, arg.set_flag_2); + mFlags.change(Flag::_4, arg.set_flag_4); + + mStatusFlags.change(StatusFlag::_20000, arg.load_req_field_26 && !arg.load_req_field_28); + mStatusFlags.change(StatusFlag::_40000, arg.load_req->_27); + mStatusFlags.change(StatusFlag::HasHeap, arg.heap != nullptr); + mStatusFlags.change(StatusFlag::_80000, arg.load_req_field_28); + + if (arg.handle) { + arg.handle->setUnit(this); + mRefCount.increment(); + mStatusFlags.reset(StatusFlag::NeedToIncrementRefCount); + } + + { + util::TaskDelegateSetter setter; + mTask1.setDelegate(setter); + } + + { + util::TaskDelegateSetter setter; + mTask2.setDelegate(setter); + } + + if (mStatusFlags.isOn(StatusFlag::_80000)) { + mRefCount.increment(); + mStatusFlags.reset(StatusFlag::NeedToIncrementRefCount); + stubbedLogFunction(); + } + + return true; +} + +ResourceUnit::~ResourceUnit() { + unloadArchiveRes(); +} + +void ResourceUnit::unloadArchiveRes() { + if (mArchiveRes) { + mArchiveRes = nullptr; + mArchiveResHandle.unload(); + } +} + +void ResourceUnit::attachHandle(Handle* handle) { + handle->setUnit(this); + mRefCount.increment(); + mStatusFlags.reset(StatusFlag::NeedToIncrementRefCount); +} + +s32 ResourceUnit::getRefCount() const { + return mRefCount; +} + +ResourceUnit::Status ResourceUnit::getStatus() const { + return mStatus; +} + +// NON_MATCHING: ldr + sxtw -> ldrsw +void ResourceUnit::updateStatus() { + static const Status sMap[] = {Status::_8, Status::_11, Status::_11, Status::_14, Status::_14}; + if (Status::_2 <= mStatus && mStatus <= Status::_6) + mStatus = sMap[s32(mStatus)]; +} + +bool ResourceUnit::isTask1NotQueued() const { + return mTask1.getStatus() == util::Task::Status::RemovedFromQueue; +} + +bool ResourceUnit::isStatus0() const { + return mStatus == Status::_0; +} + +bool ResourceUnit::isTask1ActiveOrStatus7() const { + if (!mTask1.isInactive()) + return true; + if (isTask1NotQueued()) + return false; + return mStatus == Status::_7; +} + +bool ResourceUnit::isStatus1() const { + return mStatus == Status::_1; +} + +bool ResourceUnit::isStatus9_12_15() const { + return mStatus == Status::_9 || mStatus == Status::_12 || mStatus == Status::_15; +} + +// NON_MATCHING: branching for the second if +bool ResourceUnit::isParseOk() const { + auto* ksys_res = sead::DynamicCast(mResource); + + if (mStatus == Status::_14) + return true; + + if (mStatus == Status::_8 && !ksys_res) + return mResource != nullptr; + + if (mStatus == Status::_8 && ksys_res) + return !ksys_res->needsParse(); + + return false; +} + +bool ResourceUnit::isStatusFlag8000Set() const { + return mStatusFlags.isOn(StatusFlag::NeedToIncrementRefCount); +} + +bool ResourceUnit::isLinkedToResourceMgr() const { + return mResMgrUnitListNode.isLinked(); +} + +size_t ResourceUnit::getHeapSize() const { + return mHeap ? mHeap->getSize() : 0; +} + +sead::Heap* ResourceUnit::getHeap() const { + return mHeap; +} + +bool ResourceUnit::isLinkedToCache() const { + return mCacheFlags.isOn(CacheFlag::IsLinkedToCache); +} + +void ResourceUnit::setIsLinkedToCache(bool linked) { + mCacheFlags.change(CacheFlag::IsLinkedToCache, linked); + if (returnFalse()) + stubbedLogFunction(); +} + +void ResourceUnit::removeFromCache() { + if (mCache) + mCache->eraseUnit(this); + else + stubbedLogFunction(); +} + +bool ResourceUnit::removeTask3FromQueue() { + mTask3.removeFromQueue(); + return true; +} + +} // namespace ksys::res diff --git a/src/KingSystem/Resource/resUnit.h b/src/KingSystem/Resource/resUnit.h new file mode 100644 index 00000000..4f81f919 --- /dev/null +++ b/src/KingSystem/Resource/resUnit.h @@ -0,0 +1,191 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include "KingSystem/Resource/resHandle.h" +#include "KingSystem/Utils/Thread/Event.h" +#include "KingSystem/Utils/Thread/Task.h" +#include "KingSystem/Utils/Types.h" + +namespace sead { +class ArchiveRes; +class DirectResource; +class FileDevice; +} // namespace sead + +namespace ksys::res { + +class Cache; +class Handle; +class LoadRequest; +class OverlayArena; +class ResourceUnit; + +class ResourceUnitMapNode : public util::StrTreeMapNode { +public: + explicit ResourceUnitMapNode(ResourceUnit* unit) : mUnit(unit) {} + ~ResourceUnitMapNode() override { ; } + void erase_() override { util::StrTreeMapNode::erase_(); } + + ResourceUnit* getUnit() const { return mUnit; } + util::StrTreeMapKey& key() { return mKey; } + const util::StrTreeMapKey& key() const { return mKey; } + +private: + ResourceUnit* mUnit = nullptr; +}; + +class ResourceUnit : public sead::hostio::Node { + SEAD_RTTI_BASE(ResourceUnit) +public: + enum class Status { + _0 = 0, + _1 = 1, + _2 = 2, + _3 = 3, + _4 = 4, + _5 = 5, + _6 = 6, + _7 = 7, + _8 = 8, + _9 = 9, + _10 = 10, + _11 = 11, + _12 = 12, + _13 = 13, + _14 = 14, + _15 = 15, + }; + + struct InitArg { + bool set_flag_1; + bool set_flag_2; + bool set_flag_4; + sead::Atomic load_req_field_26; + sead::Atomic load_req_field_28; + Handle* handle; + Cache* cache; + void* _18; + sead::Heap* heap; + LoadRequest* load_req; + OverlayArena* arena; + u32 alloc_size; + sead::SafeString path; + }; + KSYS_CHECK_SIZE_NX150(InitArg, 0x50); + + explicit ResourceUnit(const InitArg& arg); + ResourceUnit(); + virtual ~ResourceUnit(); + + bool init(const InitArg& arg); + + void unloadArchiveRes(); + + void attachHandle(Handle* handle); + + s32 getRefCount() const; + + Status getStatus() const; + void updateStatus(); + + bool isTask1NotQueued() const; + bool isStatus0() const; + bool isTask1ActiveOrStatus7() const; + bool isStatus1() const; + bool isStatus9_12_15() const; + bool isParseOk() const; + bool isStatusFlag8000Set() const; + bool isLinkedToResourceMgr() const; + size_t getHeapSize() const; + sead::Heap* getHeap() const; + + bool isLinkedToCache() const; + void setIsLinkedToCache(bool linked); + const auto& getCacheKey() const { return mMapNode.key(); } + void removeFromCache(); + + bool removeTask3FromQueue(); + + static size_t getArenaUnitListNodeOffset() { + return offsetof(ResourceUnit, mArenaUnitListNode); + } + + static size_t getArenaUnitListNode2Offset() { + return offsetof(ResourceUnit, mArenaUnitListNode2); + } + + static size_t getResMgrUnitListNodeOffset() { + return offsetof(ResourceUnit, mResMgrUnitListNode); + } + +private: + friend class Handle; + + enum class CacheFlag : u8 { + IsLinkedToCache = 0x1, + }; + + enum class Flag : u8 { + _1 = 0x1, + _2 = 0x2, + _4 = 0x4, + }; + + enum class StatusFlag { + HasHeap = 0x1, + BufferSizeIsNonZero = 0x10, + LoadFromArchive = 0x20, + LoadReqField24IsTrue = 0x40, + FailedMaybe = 0x100, + FileSizeIsZero = 0x200, + FileSizeExceedsAllocSize = 0x800, + _1000 = 0x1000, + FileOrResInstanceTooLargeForHeap = 0x2000, + LoadFailed = 0x4000, + NeedToIncrementRefCount = 0x8000, + _20000 = 0x20000, + _40000 = 0x40000, + _80000 = 0x80000, + }; + + sead::TypedBitFlag mCacheFlags; + sead::TypedBitFlag mFlags; + sead::TypedBitFlag mStatusFlags; + Status mStatus = Status::_0; + OverlayArena* mArena = nullptr; + OverlayArena* mArena1 = nullptr; + OverlayArena* mArena2 = nullptr; + OverlayArena* mLoadReqArena = nullptr; + sead::DirectResource* mResource = nullptr; + Handle mArchiveResHandle; + sead::ArchiveRes* mArchiveRes = nullptr; + void* mLoadReqField68 = nullptr; + Cache* mCache = nullptr; + sead::FileDevice* mFileDevice = nullptr; + u32 mLoadReqAllocSize = 0; + u32 mAllocSize = 0; + u32 mInfoAllocSize = 0; + sead::Atomic mRefCount; + sead::ListNode mArenaUnitListNode; + sead::ListNode mArenaUnitListNode2; + sead::ListNode mResMgrUnitListNode; + util::Task mTask1; + util::Task mTask2; + util::Task mTask3; + ResourceUnitMapNode mMapNode{this}; + sead::Atomic mCounter; + util::Event mEvent{nullptr, + sead::IDisposer::HeapNullOption::DoNotAppendDisposerIfNoHeapSpecified, true}; + sead::ResourceMgr::LoadArg mLoadArg; + sead::FixedSafeString<128> mPath; + sead::Heap* mHeap = nullptr; +}; +KSYS_CHECK_SIZE_NX150(ResourceUnit, 0x468); + +} // namespace ksys::res diff --git a/src/KingSystem/System/OverlayArena.cpp b/src/KingSystem/System/OverlayArena.cpp index 3e612cbf..718480ea 100644 --- a/src/KingSystem/System/OverlayArena.cpp +++ b/src/KingSystem/System/OverlayArena.cpp @@ -2,13 +2,13 @@ #include #include "KingSystem/Resource/resResourceMgrTask.h" #include "KingSystem/Resource/resSystem.h" +#include "KingSystem/Resource/resUnit.h" namespace ksys { OverlayArena::OverlayArena() { - // FIXME: these should use offsetof() - mUnits.initOffset(0xc0); - mOffsetList2.initOffset(0xd0); + mUnits.initOffset(res::ResourceUnit::getArenaUnitListNodeOffset()); + mOffsetList2.initOffset(res::ResourceUnit::getArenaUnitListNode2Offset()); } OverlayArena::~OverlayArena() { diff --git a/src/KingSystem/Utils/CMakeLists.txt b/src/KingSystem/Utils/CMakeLists.txt index f19cee86..544422c5 100644 --- a/src/KingSystem/Utils/CMakeLists.txt +++ b/src/KingSystem/Utils/CMakeLists.txt @@ -30,6 +30,7 @@ target_sources(uking PRIVATE HashUtil.h HeapUtil.cpp HeapUtil.h + InitTimeInfo.h ParamIO.h StrTreeMap.h Types.h diff --git a/src/KingSystem/Utils/InitTimeInfo.h b/src/KingSystem/Utils/InitTimeInfo.h new file mode 100644 index 00000000..022334c7 --- /dev/null +++ b/src/KingSystem/Utils/InitTimeInfo.h @@ -0,0 +1,23 @@ +#pragma once + +#include