summaryrefslogtreecommitdiff
path: root/src
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
parent689221f4a27048fdd2060a292341517ab20846cc (diff)
ksys/res: Implement more ResourceUnit functions
Diffstat (limited to 'src')
-rw-r--r--src/KingSystem/Resource/resCache.cpp6
-rw-r--r--src/KingSystem/Resource/resControlTask.h1
-rw-r--r--src/KingSystem/Resource/resResource.cpp6
-rw-r--r--src/KingSystem/Resource/resResource.h4
-rw-r--r--src/KingSystem/Resource/resResourceMgrTask.h39
-rw-r--r--src/KingSystem/Resource/resSystem.h4
-rw-r--r--src/KingSystem/Resource/resUnit.cpp167
-rw-r--r--src/KingSystem/Resource/resUnit.h44
-rw-r--r--src/KingSystem/System/OverlayArena.h3
-rw-r--r--src/KingSystem/Utils/Thread/Task.h1
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;