summaryrefslogtreecommitdiff
path: root/src/KingSystem/Resource/resUnit.cpp
diff options
context:
space:
mode:
authorLéo Lam <leo@leolam.fr>2020-10-10 16:37:41 +0200
committerLéo Lam <leo@leolam.fr>2020-10-11 01:15:56 +0200
commitfc0d0ddaf7b7bf8a79a86ba0181ecc3b1c4a5b57 (patch)
treee1bc7a96f8dbf2f19d4ae0e4c7e3a3eaa0276c9a /src/KingSystem/Resource/resUnit.cpp
parent689221f4a27048fdd2060a292341517ab20846cc (diff)
ksys/res: Implement more ResourceUnit functions
Diffstat (limited to 'src/KingSystem/Resource/resUnit.cpp')
-rw-r--r--src/KingSystem/Resource/resUnit.cpp167
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