summaryrefslogtreecommitdiff
path: root/src/KingSystem/Resource/resTempResourceLoader.cpp
diff options
context:
space:
mode:
authorLéo Lam <leo@leolam.fr>2020-11-12 00:28:15 +0100
committerLéo Lam <leo@leolam.fr>2020-11-12 12:38:47 +0100
commit13d1f0d0be4eb8e71277b3fae8860153d868dd5a (patch)
tree787f84d07f986153f2a728eaca2112246bbdde01 /src/KingSystem/Resource/resTempResourceLoader.cpp
parent2f80f2b58106b1641300b44660d3d6e94d6fc895 (diff)
ksys/res: Add TempResourceLoader
Diffstat (limited to 'src/KingSystem/Resource/resTempResourceLoader.cpp')
-rw-r--r--src/KingSystem/Resource/resTempResourceLoader.cpp220
1 files changed, 220 insertions, 0 deletions
diff --git a/src/KingSystem/Resource/resTempResourceLoader.cpp b/src/KingSystem/Resource/resTempResourceLoader.cpp
new file mode 100644
index 00000000..704c7e30
--- /dev/null
+++ b/src/KingSystem/Resource/resTempResourceLoader.cpp
@@ -0,0 +1,220 @@
+#include "KingSystem/Resource/resTempResourceLoader.h"
+#include <resource/seadResource.h>
+#include <thread/seadThread.h>
+#include "KingSystem/Resource/resArchiveWork.h"
+#include "KingSystem/Resource/resResourceMgrTask.h"
+#include "KingSystem/Resource/resSystem.h"
+#include "KingSystem/Resource/resUnit.h"
+#include "KingSystem/Utils/Debug.h"
+#include "KingSystem/Utils/Thread/TaskThread.h"
+
+namespace ksys::res {
+
+TempResourceLoader::TempResourceLoader() = default;
+
+TempResourceLoader::~TempResourceLoader() {
+ unload();
+}
+
+void TempResourceLoader::unload() {
+ const auto* unit = mHandle.getUnit();
+ const auto& path = unit ? unit->getPath() : sead::SafeString::cEmptyString;
+ sead::FormatFixedSafeString<256> message("(TempResourceLoader) アンロードします。: %s\n",
+ path.cstr());
+ util::PrintDebug(message);
+
+ if (mFlags.isOn(Flag::IsRetryingLoad)) {
+ stubbedLogFunction();
+ mFlags.reset(Flag::IsRetryingLoad);
+ } else if (returnFalse()) {
+ stubbedLogFunction();
+ }
+
+ mFlags.reset(Flag::Loading);
+ mHandle.requestUnload();
+
+ if (mResource) {
+ ResourceMgrTask::instance()->unloadSeadResource(mResource);
+ mResource = nullptr;
+ }
+
+ if (mWork)
+ mWork->setEvent();
+}
+
+bool TempResourceLoader::init(const InitArg& arg) {
+ mWork = arg.work;
+ return true;
+}
+
+bool TempResourceLoader::isLoading() const {
+ return mFlags.isOn(Flag::Loading);
+}
+
+bool TempResourceLoader::isSuccess() const {
+ return !isLoading() && mHandle.isSuccess();
+}
+
+bool TempResourceLoader::checkLoadStatus() const {
+ return !isLoading() && mHandle.checkLoadStatus();
+}
+
+void TempResourceLoader::requestLoad(LoadArg& arg) {
+ if (!arg.use_handle)
+ return;
+
+ updateFlagsBeforeLoadingStarts();
+ mPath = arg.load_req.mPath;
+ mLoadArg = arg;
+ mLoadArg.load_req.mPath = mPath;
+ arg.load_req.mArena = mWork->getArena();
+ mHandle.requestLoad(arg.load_req.mPath, &arg.load_req);
+ if (returnFalse())
+ stubbedLogFunction();
+}
+
+sead::DirectResource* TempResourceLoader::getResourceForLoadRequest(Context* context) {
+ if (!mLoadArg.use_handle || !mHandle.isFlag2Set() || mHandle.isFlag8Set() ||
+ !mHandle.isReadyOrNeedsParse()) {
+ return nullptr;
+ }
+
+ mHandle.parseResource(context);
+
+ if (!mHandle.isSuccess()) {
+ if (mHandle.getStatus() != Handle::Status::_3) {
+ mFlags.reset(Flag::Loading);
+ sead::FormatFixedSafeString<256> message(
+ "(TempResourceLoader) メモリ不足以外のエラーでした。: %s(%d)\n",
+ mLoadArg.load_req.mPath.cstr(), s32(mHandle.getStatus()));
+ util::PrintDebug(message);
+ resetRetryFlag();
+ return nullptr;
+ }
+
+ if (!mLoadArg.retry_on_failure) {
+ mFlags.reset(Flag::Loading);
+ sead::FormatFixedSafeString<256> message(
+ "(TempResourceLoader) ロード失敗しました。: %s\n", mLoadArg.load_req.mPath.cstr());
+ util::PrintDebug(message);
+ resetRetryFlag();
+ return nullptr;
+ }
+
+ setRetryFlag();
+ mLoadArg.load_req.mArena = mWork->getArena();
+ mHandle.requestLoad(mLoadArg.load_req.mPath, &mLoadArg.load_req);
+ return nullptr;
+ }
+
+ mFlags.reset(Flag::Loading);
+ sead::FormatFixedSafeString<256> message("(TempResourceLoader) ロードに成功しました。: %s\n",
+ mLoadArg.load_req.mPath.cstr());
+ util::PrintDebug(message);
+ resetRetryFlag();
+ return mHandle.getResource();
+}
+
+sead::DirectResource* TempResourceLoader::load(TempResourceLoader::LoadArg& arg) {
+ updateFlagsBeforeLoadingStarts();
+
+ const auto* current_thread = sead::ThreadMgr::instance()->getCurrentThread();
+ bool is_on_res_thread = false;
+ is_on_res_thread |= current_thread == ResourceMgrTask::instance()->getResourceMemoryThread();
+ is_on_res_thread |= current_thread == ResourceMgrTask::instance()->getResourceLoadingThread();
+ if (is_on_res_thread)
+ arg.use_handle = false;
+
+ while (true) {
+ if (returnFalse())
+ stubbedLogFunction();
+
+ bool use_handle = arg.use_handle;
+ auto* arena = mWork->getArena();
+ if (use_handle) {
+ arg.load_req.mArena = arena;
+ mHandle.load(arg.load_req.mPath, &arg.load_req);
+
+ if (mHandle.isSuccess())
+ break;
+
+ if (mHandle.getStatus() != Handle::Status::_3) {
+ mFlags.reset(Flag::Loading);
+ sead::FormatFixedSafeString<256> message(
+ "(TempResourceLoader) メモリ不足以外のエラーでした。: %s(%d)\n",
+ arg.load_req.mPath.cstr(), s32(mHandle.getStatus()));
+ util::PrintDebug(message);
+ resetRetryFlag();
+ return nullptr;
+ }
+ } else {
+ ResourceMgrTask::DirectLoadArg load_arg{};
+ load_arg.heap = arena->getHeap();
+ load_arg.req._21 = false;
+ load_arg.req._22 = true;
+ load_arg.req.mPath = arg.load_req.mPath;
+ load_arg.req.mAocFileDevice = arg.load_req.mAocFileDevice;
+ load_arg.req.mLoadDataAlignment = arg.load_req.mLoadDataAlignment;
+ load_arg.req.mEntryFactory = arg.load_req.mEntryFactory;
+ load_arg.req._20 = false;
+ load_arg.req.mRequester = "TempResourceLoader";
+
+ if (arena->getHeap()->isLockEnabled())
+ arena->getHeap()->getCriticalSection().lock();
+
+ mResource = ResourceMgrTask::instance()->load(load_arg);
+
+ if (arena->getHeap()->isLockEnabled())
+ arena->getHeap()->getCriticalSection().unlock();
+
+ if (mResource) {
+ mFlags.reset(Flag::Loading);
+ return mResource;
+ }
+ }
+
+ if (!arg.retry_on_failure) {
+ mFlags.reset(Flag::Loading);
+ sead::FormatFixedSafeString<256> message(
+ "(TempResourceLoader) ロード失敗しました。: %s\n", arg.load_req.mPath.cstr());
+ util::PrintDebug(message);
+ resetRetryFlag();
+ return nullptr;
+ }
+
+ setRetryFlag();
+ if (!mWork->waitForEvent(arg.ms_between_attempts)) {
+ mFlags.reset(Flag::Loading);
+ return nullptr;
+ }
+ }
+
+ mFlags.reset(Flag::Loading);
+ sead::FormatFixedSafeString<256> message("(TempResourceLoader) ロードに成功しました。: %s\n",
+ arg.load_req.mPath.cstr());
+ util::PrintDebug(message);
+ resetRetryFlag();
+ return mHandle.getResource();
+}
+
+sead::DirectResource* TempResourceLoader::getResource() const {
+ if (mHandle.getResource())
+ return mHandle.getResource();
+ return mResource;
+}
+
+Handle::Status TempResourceLoader::getHandleStatus() const {
+ return mHandle.getStatus();
+}
+
+sead::FileDevice* TempResourceLoader::getHandleFileDevice() const {
+ if (mHandle.isSuccess())
+ return mHandle.getUnit()->getLoadArg().device;
+ return nullptr;
+}
+
+u32 TempResourceLoader::getWorkHeapSize() const {
+ return mWork ? mWork->getHeapSize() : 0;
+}
+
+} // namespace ksys::res