diff options
| author | Léo Lam <leo@leolam.fr> | 2020-10-10 16:37:41 +0200 |
|---|---|---|
| committer | Léo Lam <leo@leolam.fr> | 2020-10-11 01:15:56 +0200 |
| commit | fc0d0ddaf7b7bf8a79a86ba0181ecc3b1c4a5b57 (patch) | |
| tree | e1bc7a96f8dbf2f19d4ae0e4c7e3a3eaa0276c9a /src | |
| parent | 689221f4a27048fdd2060a292341517ab20846cc (diff) | |
ksys/res: Implement more ResourceUnit functions
Diffstat (limited to 'src')
| -rw-r--r-- | src/KingSystem/Resource/resCache.cpp | 6 | ||||
| -rw-r--r-- | src/KingSystem/Resource/resControlTask.h | 1 | ||||
| -rw-r--r-- | src/KingSystem/Resource/resResource.cpp | 6 | ||||
| -rw-r--r-- | src/KingSystem/Resource/resResource.h | 4 | ||||
| -rw-r--r-- | src/KingSystem/Resource/resResourceMgrTask.h | 39 | ||||
| -rw-r--r-- | src/KingSystem/Resource/resSystem.h | 4 | ||||
| -rw-r--r-- | src/KingSystem/Resource/resUnit.cpp | 167 | ||||
| -rw-r--r-- | src/KingSystem/Resource/resUnit.h | 44 | ||||
| -rw-r--r-- | src/KingSystem/System/OverlayArena.h | 3 | ||||
| -rw-r--r-- | src/KingSystem/Utils/Thread/Task.h | 1 |
10 files changed, 247 insertions, 28 deletions
diff --git a/src/KingSystem/Resource/resCache.cpp b/src/KingSystem/Resource/resCache.cpp index 55535d65..901668d2 100644 --- a/src/KingSystem/Resource/resCache.cpp +++ b/src/KingSystem/Resource/resCache.cpp @@ -43,7 +43,7 @@ Handle::Status Cache::loadResource(const ControlTaskData& data) { return false; } - if (unit->isStatusFlag1000Set()) { + if (unit->isStatusFlag10000Set()) { unit->removeFromCache(); return false; } @@ -130,10 +130,10 @@ Handle::Status Cache::loadResource(const ControlTaskData& data) { lane_id = 2 * data.mResLoadReq._c + (x ? 1 : 2); } - ResourceUnit::RequestLoadArg load_arg; + ResourceUnit::RequestInitLoadArg load_arg; load_arg.lane_id = lane_id; load_arg.has_handle = data.mResLoadReq._8; - result->requestLoad(load_arg); + result->requestInitLoad(load_arg); return Handle::Status::_7; } diff --git a/src/KingSystem/Resource/resControlTask.h b/src/KingSystem/Resource/resControlTask.h index ddbf2a01..1d69ff1a 100644 --- a/src/KingSystem/Resource/resControlTask.h +++ b/src/KingSystem/Resource/resControlTask.h @@ -43,6 +43,7 @@ class ControlTaskRequest : public util::TaskRequest { SEAD_RTTI_OVERRIDE(ControlTaskRequest, util::TaskRequest) public: ControlTaskRequest() = default; + ControlTaskRequest(bool has_handle) : TaskRequest(has_handle) {} bool mHasResLoadReq = false; ResourceUnit* mPackResUnit = nullptr; diff --git a/src/KingSystem/Resource/resResource.cpp b/src/KingSystem/Resource/resResource.cpp index 713d4edd..777d11e8 100644 --- a/src/KingSystem/Resource/resResource.cpp +++ b/src/KingSystem/Resource/resResource.cpp @@ -16,8 +16,8 @@ void Resource::onDestroy() { onDestroy_(); } -void Resource::parse(Context*, sead::Heap* heap) { - parse_(mRawData, mRawSize, heap); +bool Resource::parse(Context*, sead::Heap* heap) { + return parse_(mRawData, mRawSize, heap); } bool Resource::finalize() { @@ -25,7 +25,7 @@ bool Resource::finalize() { return true; } -bool Resource::finishParsing() { +bool Resource::finishParsing(Context*) { const bool ret = finishParsing_(); mContext = nullptr; return ret; diff --git a/src/KingSystem/Resource/resResource.h b/src/KingSystem/Resource/resResource.h index e5df218c..1944f3c1 100644 --- a/src/KingSystem/Resource/resResource.h +++ b/src/KingSystem/Resource/resResource.h @@ -29,9 +29,9 @@ public: void setContext(Context* context); void onDestroy(); - void parse(Context*, sead::Heap* heap); + bool parse(Context*, sead::Heap* heap); bool finalize(); - bool finishParsing(); + bool finishParsing(Context* context); bool m7(); static constexpr size_t cLoadDataAlignment = 4; diff --git a/src/KingSystem/Resource/resResourceMgrTask.h b/src/KingSystem/Resource/resResourceMgrTask.h index 7778090d..a90c8208 100644 --- a/src/KingSystem/Resource/resResourceMgrTask.h +++ b/src/KingSystem/Resource/resResourceMgrTask.h @@ -71,6 +71,21 @@ KSYS_CHECK_SIZE_NX150(FileDevicePrefix, 0x28); class ResourceMgrTask : public sead::CalculateTask, public sead::hostio::Node { SEAD_RTTI_OVERRIDE(ResourceMgrTask, sead::CalculateTask) public: + enum class LaneId { + _9 = 9, + _10 = 10, + }; + + using ResourceUnitDelegate = sead::Delegate1RFunc<void*, bool>; + using TaskCallback = + sead::Delegate2Func<util::TaskPostRunResult*, const util::TaskPostRunContext&>; + using MemoryTaskDelegate = sead::Delegate1R<ResourceMgrTask, void*, bool>; + + struct ResourceUnitDelegatePair { + ResourceUnitDelegate fn; + TaskCallback cb; + }; + static ResourceMgrTask* instance() { return sInstance; } void prepare() override; @@ -97,6 +112,14 @@ public: sead::BufferedSafeString& new_path, s32 dot_idx, const sead::SafeString& extension); + util::TaskThread* getResourceLoadingThread() const { return mResourceLoadingThread; } + util::TaskThread* getResourceControlThread() const { return mResourceControlThread; } + util::TaskThread* getResourceMemoryThread() const { return mResourceMemoryThread; } + util::TaskThread* getMovableMemoryThread() const { return mMovableMemoryThread; } + + ResourceUnitDelegatePair& getUnitInitLoadFn() { return mUnitInitLoadFn; } + auto& getUnitAdjustHeapFn() { return mUnitAdjustHeapFn; } + private: enum class Flag { @@ -106,20 +129,6 @@ private: ClearAllCachesRequested = 1, }; - enum class LaneId { - _9 = 9, - }; - - using ResourceUnitDelegate = sead::Delegate1RFunc<void*, bool>; - using TaskCallback = - sead::Delegate2Func<util::TaskPostRunResult*, const util::TaskPostRunContext&>; - using MemoryTaskDelegate = sead::Delegate1R<ResourceMgrTask, void*, bool>; - - struct ResourceUnitDelegatePair { - ResourceUnitDelegate fn; - TaskCallback cb; - }; - explicit ResourceMgrTask(const sead::TaskConstructArg& arg); ~ResourceMgrTask(); @@ -168,7 +177,7 @@ private: ResourceUnitDelegatePair mUnitInitLoadFn; ResourceUnitDelegate mUnitPrepareLoadFn; ResourceUnitDelegate mUnitAdjustHeapFn; - ResourceUnitDelegatePair mDelegate2; // TODO: rename + ResourceUnitDelegatePair mUnitUnloadForSyncFn; ResourceUnitDelegatePair mUnitUnloadFn; ResourceUnitDelegatePair mUnitClearCacheForSyncFn; ResourceUnitDelegatePair mUnitClearCacheFn; diff --git a/src/KingSystem/Resource/resSystem.h b/src/KingSystem/Resource/resSystem.h index c22ac378..4ce9a16d 100644 --- a/src/KingSystem/Resource/resSystem.h +++ b/src/KingSystem/Resource/resSystem.h @@ -1,5 +1,7 @@ #pragma once +#include <prim/seadSafeString.h> + namespace ksys::res { // In release builds, the only thing this function does is return 1. @@ -12,6 +14,6 @@ bool returnFalse(); // In release builds, the only thing this function does is return 0. // TODO: figure out what this is used for. Stubbed log function? -bool returnFalse2(); +bool returnFalse2(const sead::SafeString&); } // namespace ksys::res diff --git a/src/KingSystem/Resource/resUnit.cpp b/src/KingSystem/Resource/resUnit.cpp index 1c2f0e1c..a93e5266 100644 --- a/src/KingSystem/Resource/resUnit.cpp +++ b/src/KingSystem/Resource/resUnit.cpp @@ -2,8 +2,10 @@ #include <filedevice/seadArchiveFileDevice.h> #include <resource/seadArchiveRes.h> #include "KingSystem/Resource/resCache.h" +#include "KingSystem/Resource/resControlTask.h" #include "KingSystem/Resource/resEntryFactory.h" #include "KingSystem/Resource/resLoadRequest.h" +#include "KingSystem/Resource/resResourceMgrTask.h" #include "KingSystem/Resource/resSystem.h" namespace ksys::res { @@ -224,4 +226,169 @@ bool ResourceUnit::removeTask3FromQueue() { return true; } +void ResourceUnit::requestInitLoad(const RequestInitLoadArg& arg) { + mStatus = Status::_7; + + util::TaskRequest req; + req.mHasHandle = arg.has_handle; + req.mSynchronous = false; + req.mLaneId = arg.lane_id; + req.mThread = ResourceMgrTask::instance()->getResourceMemoryThread(); + req.mDelegate = &ResourceMgrTask::instance()->getUnitInitLoadFn().fn; + req.mUserData = this; + req.mPostRunCallback = &ResourceMgrTask::instance()->getUnitInitLoadFn().cb; + req.mName = mPath; + mTask1.submitRequest(req); + + if (returnFalse2(sead::SafeString(mPath))) + stubbedLogFunction(); +} + +bool ResourceUnit::waitForResourceAndParse(Context* context) { + const auto adjust_heap_and_dec_ref = [&] { + adjustHeapAndArena(); + if (mStatusFlags.isOn(StatusFlag::_80000)) { + mRefCount.decrement(); + mStatusFlags.reset(StatusFlag::_80000); + ksys::res::stubbedLogFunction(); + } + }; + + if (isParseOk()) + return true; + + if (mCounter.increment() >= 1) { + mEvent.wait(); + if (mStatus != Status::_15 && mStatus != Status::_12) + return true; + ksys::res::stubbedLogFunction(); + return false; + } + + mTask1.wait(); + bool set_status_12 = true; + if (mResource) { + auto* res = sead::DynamicCast<ksys::res::Resource>(mResource); + if (!res || !res->needsParse()) { + mEvent.setSignal(); + return true; + } + + bool finish_parsing = mStatus != Status::_8; + if (!finish_parsing) { + auto* heap = mHeap; + mStatus = Status::_10; + if (context) + res->setContext(context); + + if (res->parse(context, heap)) { + mStatus = Status::_11; + finish_parsing = true; + } else { + adjust_heap_and_dec_ref(); + } + } + + if (finish_parsing) { + mStatus = Status::_13; + if (mResource) { + bool ok = true; + if (auto* ksys_res = sead::DynamicCast<ksys::res::Resource>(mResource)) { + if (context) + ksys_res->setContext(context); + ok = ksys_res->finishParsing(context); + } + mStatus = ok ? Status::_14 : Status::_15; + if (ok) { + adjustHeapAndArena(); + mEvent.setSignal(); + return true; + } + } + adjust_heap_and_dec_ref(); + set_status_12 = false; + } + } + + if (set_status_12) + mStatus = Status::_12; + + mEvent.setSignal(); + + ksys::res::stubbedLogFunction(); + return false; +} + +bool ResourceUnit::waitForTask1() { + mTask1.wait(); + return true; +} + +void ResourceUnit::adjustHeapAndArena() { + if (mStatusFlags.isOn(StatusFlag::HasHeap)) { + mStatusFlags.set(StatusFlag::_8); + return; + } + + if (mStatusFlags.isOn(StatusFlag::_8)) { + auto* arena = mArena1; + + if (mStatusFlags.isOff(StatusFlag::_2)) { + arena->addSize(mHeap ? mHeap->getSize() : 0); + mStatusFlags.set(StatusFlag::_2); + } + + if (mStatusFlags.isOff(StatusFlag::_4) && + mStatusFlags.isOff(StatusFlag::NeedToIncrementRefCount)) { + arena->addSize2(mHeap ? mHeap->getSize() : 0); + mStatusFlags.set(StatusFlag::_4); + return; + } + + } else { + if (mStatusFlags.isOn(StatusFlag::_40000)) { + ControlTaskRequest req{false}; + req.mHasHandle = false; + req.mSynchronous = false; + req.mLaneId = u8(res::ResourceMgrTask::LaneId::_10); + req.mThread = res::ResourceMgrTask::instance()->getResourceMemoryThread(); + req.mDelegate = &res::ResourceMgrTask::instance()->getUnitAdjustHeapFn(); + req.mUserData = this; + req.mName = "HeapAdjust"; + mTask2.submitRequest(req); + return; + } + + auto* arena = mArena1; + + if (mStatusFlags.isOff(StatusFlag::_2)) { + arena->addSize(mHeap ? mHeap->getSize() : 0); + mStatusFlags.set(StatusFlag::_2); + } + + if (mStatusFlags.isOff(StatusFlag::_4) && + mStatusFlags.isOff(StatusFlag::NeedToIncrementRefCount)) { + arena->addSize2(mHeap ? mHeap->getSize() : 0); + mStatusFlags.set(StatusFlag::_4); + return; + } + } +} + +bool ResourceUnit::waitForTask1(const sead::TickSpan& span) { + return mTask1.wait(span); +} + +void ResourceUnit::detachFromHandle_(Handle* handle) { + handle->setUnit(nullptr); +} + +void ResourceUnit::setStatusFlag10000() { + mStatusFlags.set(StatusFlag::_10000); +} + +bool ResourceUnit::isStatusFlag10000Set() const { + return mStatusFlags.isOn(StatusFlag::_10000); +} + } // namespace ksys::res diff --git a/src/KingSystem/Resource/resUnit.h b/src/KingSystem/Resource/resUnit.h index 67a615f2..b819f24c 100644 --- a/src/KingSystem/Resource/resUnit.h +++ b/src/KingSystem/Resource/resUnit.h @@ -25,6 +25,7 @@ class OverlayArena; namespace ksys::res { class Cache; +class Context; class Handle; class LoadRequest; class ResourceUnit; @@ -93,11 +94,11 @@ public: }; KSYS_CHECK_SIZE_NX150(InitArg, 0x50); - struct RequestLoadArg { + struct RequestInitLoadArg { u8 lane_id; bool has_handle; }; - KSYS_CHECK_SIZE_NX150(RequestLoadArg, 0x2); + KSYS_CHECK_SIZE_NX150(RequestInitLoadArg, 0x2); explicit ResourceUnit(const InitArg& arg); ResourceUnit(); @@ -133,9 +134,21 @@ public: bool removeTask3FromQueue(); - void requestLoad(const RequestLoadArg& arg); + void requestInitLoad(const RequestInitLoadArg& arg); + bool waitForResourceAndParse(Context* context); + bool waitForTask1(); + bool waitForTask1(const sead::TickSpan& span); - bool isStatusFlag1000Set() const; + void setStatusFlag10000(); + bool isStatusFlag10000Set() const; + + /// Destroys the underlying resource and reallocates it for defragmentation purposes. + void reallocate(); + + u32 determineFileBufferSize(); + u32 determineFileBufferSize(const sead::SafeString& path, bool flag4, bool flag1, bool flag2); + + void detachFromHandle_(Handle* handle); static size_t getArenaUnitListNodeOffset() { return offsetof(ResourceUnit, mArenaUnitListNode); @@ -165,22 +178,45 @@ private: enum class StatusFlag { HasHeap = 0x1, + _2 = 0x2, + _4 = 0x4, + _8 = 0x8, BufferSizeIsNonZero = 0x10, LoadFromArchive = 0x20, LoadReqField24IsTrue = 0x40, _80 = 0x80, FailedMaybe = 0x100, FileSizeIsZero = 0x200, + _400 = 0x400, FileSizeExceedsAllocSize = 0x800, _1000 = 0x1000, FileOrResInstanceTooLargeForHeap = 0x2000, LoadFailed = 0x4000, NeedToIncrementRefCount = 0x8000, + _10000 = 0x10000, _20000 = 0x20000, _40000 = 0x40000, _80000 = 0x80000, }; + void adjustHeapAndArena(); + + void doLoad(); + void doRetryLoad(); + + void prepareUnload(); + + void initLoad(void* x = nullptr); + void prepareLoad(); + void requestPrepareLoad(util::TaskPostRunResult* result, const util::TaskPostRunContext& ctx); + + void unloadForSync(); + void clearCacheForSync(); + + void unload(); + void clearCache(); + void requestClearCache(util::TaskPostRunResult* result, const util::TaskPostRunContext& ctx); + sead::TypedBitFlag<CacheFlag> mCacheFlags; sead::TypedBitFlag<Flag> mFlags; sead::TypedBitFlag<StatusFlag> mStatusFlags; diff --git a/src/KingSystem/System/OverlayArena.h b/src/KingSystem/System/OverlayArena.h index dfcd9edd..02d4073c 100644 --- a/src/KingSystem/System/OverlayArena.h +++ b/src/KingSystem/System/OverlayArena.h @@ -45,6 +45,9 @@ public: bool init(const InitArg& arg); void destroy(); + void addSize(s32 size); + void addSize2(s32 size); + static constexpr size_t getListNodeOffset() { return offsetof(OverlayArena, mListNode); } private: diff --git a/src/KingSystem/Utils/Thread/Task.h b/src/KingSystem/Utils/Thread/Task.h index 57ff1f51..0df15083 100644 --- a/src/KingSystem/Utils/Thread/Task.h +++ b/src/KingSystem/Utils/Thread/Task.h @@ -74,6 +74,7 @@ class TaskRequest { SEAD_RTTI_BASE(TaskRequest) public: TaskRequest() = default; + explicit TaskRequest(bool has_handle) : mHasHandle(has_handle) {} virtual ~TaskRequest() = default; bool mHasHandle = true; |
