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/KingSystem/Resource/resUnit.cpp | |
| parent | 689221f4a27048fdd2060a292341517ab20846cc (diff) | |
ksys/res: Implement more ResourceUnit functions
Diffstat (limited to 'src/KingSystem/Resource/resUnit.cpp')
| -rw-r--r-- | src/KingSystem/Resource/resUnit.cpp | 167 |
1 files changed, 167 insertions, 0 deletions
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 |
