summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLéo Lam <leo@leolam.fr>2020-10-04 15:39:04 +0200
committerLéo Lam <leo@leolam.fr>2020-10-08 00:09:53 +0200
commit76655d85a90ca1cede47a45b4faa3e6e767b99a3 (patch)
tree15d04cd8e0e130435f11d561c7c4131ee44f674f /src
parent99de7fa00931d1d7c75a0c51d6fd38c09f60b160 (diff)
ksys/res: Implement some ResourceMgrTask prerequisites
Diffstat (limited to 'src')
-rw-r--r--src/KingSystem/Resource/CMakeLists.txt7
-rw-r--r--src/KingSystem/Resource/resCounter.cpp40
-rw-r--r--src/KingSystem/Resource/resCounter.h54
-rw-r--r--src/KingSystem/Resource/resInfoContainer.cpp113
-rw-r--r--src/KingSystem/Resource/resInfoContainer.h48
-rw-r--r--src/KingSystem/Resource/resResourceMgrTask.h6
-rw-r--r--src/KingSystem/Resource/resSystem.cpp17
-rw-r--r--src/KingSystem/Resource/resSystem.h4
-rw-r--r--src/KingSystem/Resource/resUnitPool.cpp33
-rw-r--r--src/KingSystem/Resource/resUnitPool.h33
10 files changed, 354 insertions, 1 deletions
diff --git a/src/KingSystem/Resource/CMakeLists.txt b/src/KingSystem/Resource/CMakeLists.txt
index 09ec38ef..bd9b5c16 100644
--- a/src/KingSystem/Resource/CMakeLists.txt
+++ b/src/KingSystem/Resource/CMakeLists.txt
@@ -88,12 +88,16 @@ target_sources(uking PRIVATE
resCacheCriticalSection.h
resControlTask.cpp
resControlTask.h
+ resCounter.cpp
+ resCounter.h
resCurrentResNameMgr.cpp
resCurrentResNameMgr.h
resEntryFactory.cpp
resEntryFactory.h
resHandle.cpp
resHandle.h
+ resInfoContainer.cpp
+ resInfoContainer.h
resLoadRequest.cpp
resLoadRequest.h
resMemoryTask.cpp
@@ -102,11 +106,14 @@ target_sources(uking PRIVATE
resOffsetReadFileDevice.h
resResourceMgrTask.cpp
resResourceMgrTask.h
+ resSystem.cpp
resSystem.h
resTaskRequest.cpp
resTaskRequest.h
resUnit.cpp
resUnit.h
+ resUnitPool.cpp
+ resUnitPool.h
resResource.cpp
resResource.h
diff --git a/src/KingSystem/Resource/resCounter.cpp b/src/KingSystem/Resource/resCounter.cpp
new file mode 100644
index 00000000..20fc787a
--- /dev/null
+++ b/src/KingSystem/Resource/resCounter.cpp
@@ -0,0 +1,40 @@
+#include "KingSystem/Resource/resCounter.h"
+
+namespace ksys::res {
+
+CounterBase::CounterBase() = default;
+
+CounterBase::~CounterBase() = default;
+
+bool CounterBase::setData(const CounterBase::Data& data) {
+ return doSetData_(data);
+}
+
+void CounterBase::incrementRef() {
+ mRefCount.increment();
+}
+
+void CounterBase::decrementRef() {
+ if (mRefCount)
+ mRefCount.decrement();
+}
+
+void CounterBase::setFlag() {
+ mFlag = true;
+}
+
+void CounterBase::reset() {
+ [[maybe_unused]] const auto count = mRefCount;
+ mFlag = false;
+}
+
+bool CounterBase::isFlagSet() const {
+ return mFlag;
+}
+
+bool Counter::doSetData_(const CounterBase::Data& data) {
+ mData = data.mData;
+ return true;
+}
+
+} // namespace ksys::res
diff --git a/src/KingSystem/Resource/resCounter.h b/src/KingSystem/Resource/resCounter.h
new file mode 100644
index 00000000..74b1913f
--- /dev/null
+++ b/src/KingSystem/Resource/resCounter.h
@@ -0,0 +1,54 @@
+#pragma once
+
+#include <basis/seadTypes.h>
+#include <prim/seadRuntimeTypeInfo.h>
+#include <thread/seadAtomic.h>
+#include "KingSystem/Utils/Types.h"
+
+namespace ksys::res {
+
+class CounterBase {
+public:
+ class DataBase {
+ SEAD_RTTI_BASE(DataBase)
+ };
+
+ class Data : public DataBase {
+ SEAD_RTTI_OVERRIDE(Data, DataBase)
+ public:
+ explicit Data(void* data) : mData(data) {}
+ virtual ~Data() = default;
+ void* mData;
+ };
+
+ CounterBase();
+ virtual ~CounterBase();
+
+ bool setData(const Data& data);
+
+ void incrementRef();
+ void decrementRef();
+
+ void setFlag();
+ void reset();
+ bool isFlagSet() const;
+
+private:
+ virtual bool doSetData_(const Data& data) = 0;
+
+ bool mFlag = true;
+ sead::Atomic<s32> mRefCount;
+};
+
+class Counter : public CounterBase {
+public:
+ Counter() = default;
+ ~Counter() override = default;
+
+private:
+ bool doSetData_(const Data& data) override;
+
+ void* mData = nullptr;
+};
+
+} // namespace ksys::res
diff --git a/src/KingSystem/Resource/resInfoContainer.cpp b/src/KingSystem/Resource/resInfoContainer.cpp
new file mode 100644
index 00000000..f1669f80
--- /dev/null
+++ b/src/KingSystem/Resource/resInfoContainer.cpp
@@ -0,0 +1,113 @@
+#include "KingSystem/Resource/resInfoContainer.h"
+#include <codec/seadHashCRC32.h>
+#include <prim/seadBitUtil.h>
+#include "KingSystem/Resource/resLoadRequest.h"
+#include "KingSystem/Resource/resResource.h"
+#include "KingSystem/Resource/resSystem.h"
+
+namespace ksys::res {
+
+ResourceInfoContainer::ResourceInfoContainer() = default;
+
+ResourceInfoContainer::~ResourceInfoContainer() = default;
+
+// NON_MATCHING: LoadRequest field write order
+bool ResourceInfoContainer::loadResourceSizeTable() {
+ const auto load_res = [&] {
+ LoadRequest req;
+ req._68 = nullptr;
+ req.mArena = nullptr;
+ req.mPackHandle = nullptr;
+ req._22 = false;
+ req._20 = false;
+ req._21 = false;
+ req._26 = false;
+ req.mFileDevice = nullptr;
+ req.mLoadCompressed = true;
+ req._24 = false;
+ req._8 = true;
+ req.mLoadDataAlignment = 8;
+ req.mBufferSize = 0;
+ req.mEntryFactory = nullptr;
+ req.mAocFileDevice = nullptr;
+ req._34 = 0;
+ req.mRequester = "ResourceInfoContainer";
+ req.mPath = "System/Resource/ResourceSizeTable.product.rsizetable";
+ req._c = 1;
+ return sead::DynamicCast<Resource>(mRstbHandle.load(req.mPath, req));
+ };
+
+ const Resource* resource = load_res();
+ if (!resource)
+ return false;
+
+ const u8* data = resource->getRawData();
+
+ if (data[0] == 'R' && data[1] == 'S' && data[2] == 'T' && data[3] == 'B') {
+ stubbedLogFunction();
+ const auto num_entries = sead::BitUtil::bitCastPtr<s32>(data, 0x4);
+ const auto num_string_entries = sead::BitUtil::bitCastPtr<s32>(data, 0x8);
+
+ auto* entries_data =
+ reinterpret_cast<const ResEntry*>(reinterpret_cast<const u8*>(data) + 0xc);
+
+ if (num_entries >= 1) {
+ mEntries = {num_entries, entries_data};
+ entries_data += num_entries;
+ }
+
+ if (num_string_entries >= 1) {
+ mStringEntries = {num_string_entries,
+ reinterpret_cast<const ResStringEntry*>(entries_data)};
+ // Log each conflict.
+ for (s32 i = 0; i < num_string_entries; ++i)
+ stubbedLogFunction();
+ }
+ } else {
+ // Assume that there is no string table.
+ stubbedLogFunction();
+ if (resource->getRawSize() != 0) {
+ const u32 num_entries = resource->getRawSize() / sizeof(ResEntry);
+ mEntries.setBuffer(num_entries,
+ reinterpret_cast<const ResEntry*>(resource->getRawData()));
+ }
+ }
+
+ stubbedLogFunction();
+ stubbedLogFunction();
+ stubbedLogFunction();
+ return true;
+}
+
+// NON_MATCHING: missing mStringEntries(string_entry_idx).res_size > 0 check
+u32 ResourceInfoContainer::getResourceSize(const sead::SafeString& name) {
+ const u32 name_hash = sead::HashCRC32::calcStringHash(name.cstr());
+
+ const s32 entry_idx = mEntries.binarySearch({name_hash, 0}, ResEntry::compareT);
+ if (entry_idx >= 1 && mEntries(entry_idx).res_size > 0)
+ return mEntries(entry_idx).res_size;
+
+ const s32 string_entry_idx = mStringEntries.binarySearchC(
+ [&](const ResStringEntry& entry) { return entry.compare(name); });
+ if (string_entry_idx >= 1 && mStringEntries(string_entry_idx).res_size > 0)
+ return mStringEntries(string_entry_idx).res_size;
+
+ return 0;
+}
+
+namespace {
+[[gnu::noinline]] bool stringLessThan(const sead::SafeString& a, const sead::SafeString& b) {
+ return a < b;
+}
+} // namespace
+
+[[gnu::noinline]] s32
+ResourceInfoContainer::ResStringEntry::compare(const sead::SafeString& name) const {
+ if (res_name > name)
+ return 1;
+ if (stringLessThan(res_name, name))
+ return -1;
+ return 0;
+}
+
+} // namespace ksys::res
diff --git a/src/KingSystem/Resource/resInfoContainer.h b/src/KingSystem/Resource/resInfoContainer.h
new file mode 100644
index 00000000..096e43fc
--- /dev/null
+++ b/src/KingSystem/Resource/resInfoContainer.h
@@ -0,0 +1,48 @@
+#pragma once
+
+#include <basis/seadTypes.h>
+#include <container/seadBuffer.h>
+#include <prim/seadSafeString.h>
+#include "KingSystem/Resource/resHandle.h"
+#include "KingSystem/Utils/Types.h"
+
+namespace ksys::res {
+
+class ResourceInfoContainer {
+public:
+ ResourceInfoContainer();
+ virtual ~ResourceInfoContainer();
+
+ bool loadResourceSizeTable();
+ u32 getResourceSize(const sead::SafeString& name);
+
+private:
+ struct ResEntry {
+ static s32 compareT(const ResEntry* lhs, const ResEntry* rhs) {
+ if (*lhs > *rhs)
+ return 1;
+ if (*lhs < *rhs)
+ return -1;
+ return 0;
+ }
+
+ bool operator<(const ResEntry& other) const { return res_name_hash < other.res_name_hash; }
+ bool operator>(const ResEntry& other) const { return res_name_hash > other.res_name_hash; }
+ u32 res_name_hash;
+ s32 res_size;
+ };
+
+ struct ResStringEntry {
+ s32 compare(const sead::SafeString& name) const;
+
+ char res_name[128];
+ s32 res_size;
+ };
+
+ Handle mRstbHandle;
+ sead::Buffer<const ResEntry> mEntries;
+ sead::Buffer<const ResStringEntry> mStringEntries;
+};
+KSYS_CHECK_SIZE_NX150(ResourceInfoContainer, 0x78);
+
+} // namespace ksys::res
diff --git a/src/KingSystem/Resource/resResourceMgrTask.h b/src/KingSystem/Resource/resResourceMgrTask.h
index 08051522..7a7524d9 100644
--- a/src/KingSystem/Resource/resResourceMgrTask.h
+++ b/src/KingSystem/Resource/resResourceMgrTask.h
@@ -1,5 +1,7 @@
#pragma once
+#include <framework/seadCalculateTask.h>
+#include <hostio/seadHostIONode.h>
#include "KingSystem/Resource/resUnit.h"
namespace sead {
@@ -17,7 +19,7 @@ class TaskThread;
namespace ksys::res {
// FIXME: very, very incomplete.
-class ResourceMgrTask {
+class ResourceMgrTask : public sead::CalculateTask, public sead::hostio::Node {
public:
static ResourceMgrTask* instance() { return sInstance; }
@@ -46,5 +48,7 @@ public:
private:
static ResourceMgrTask* sInstance;
};
+KSYS_CHECK_SIZE_NX150(sead::TaskBase, 0xd0);
+KSYS_CHECK_SIZE_NX150(sead::MethodTreeNode, 0x98);
} // namespace ksys::res
diff --git a/src/KingSystem/Resource/resSystem.cpp b/src/KingSystem/Resource/resSystem.cpp
new file mode 100644
index 00000000..be87826c
--- /dev/null
+++ b/src/KingSystem/Resource/resSystem.cpp
@@ -0,0 +1,17 @@
+#include "KingSystem/Resource/resSystem.h"
+
+namespace ksys::res {
+
+bool stubbedLogFunction() {
+ return true;
+}
+
+bool returnFalse() {
+ return false;
+}
+
+bool returnFalse2() {
+ return false;
+}
+
+} // namespace ksys::res
diff --git a/src/KingSystem/Resource/resSystem.h b/src/KingSystem/Resource/resSystem.h
index 4c27f2b4..c22ac378 100644
--- a/src/KingSystem/Resource/resSystem.h
+++ b/src/KingSystem/Resource/resSystem.h
@@ -10,4 +10,8 @@ bool stubbedLogFunction();
// TODO: figure out what this is used for. Stubbed log function?
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();
+
} // namespace ksys::res
diff --git a/src/KingSystem/Resource/resUnitPool.cpp b/src/KingSystem/Resource/resUnitPool.cpp
new file mode 100644
index 00000000..fd235159
--- /dev/null
+++ b/src/KingSystem/Resource/resUnitPool.cpp
@@ -0,0 +1,33 @@
+#include "KingSystem/Resource/resUnitPool.h"
+
+namespace ksys::res {
+
+ResourceUnitPool::ResourceUnitPool() = default;
+
+ResourceUnitPool::~ResourceUnitPool() = default;
+
+bool ResourceUnitPool::init() {
+ for (s32 i = 0; i < UnitCapacity; ++i)
+ mRingBuffer.pushBack(&mUnits[i]);
+ return true;
+}
+
+ResourceUnit* ResourceUnitPool::tryAlloc() {
+ if (mRingBuffer.empty())
+ return nullptr;
+ return mRingBuffer.popFront();
+}
+
+ResourceUnit* ResourceUnitPool::alloc() {
+ return mRingBuffer.popFront();
+}
+
+void ResourceUnitPool::free(ResourceUnit* unit) {
+ mRingBuffer.pushBack(unit);
+}
+
+void ResourceUnitPool::freeForSync(ResourceUnit* unit) {
+ free(unit);
+}
+
+} // namespace ksys::res
diff --git a/src/KingSystem/Resource/resUnitPool.h b/src/KingSystem/Resource/resUnitPool.h
new file mode 100644
index 00000000..35e515ef
--- /dev/null
+++ b/src/KingSystem/Resource/resUnitPool.h
@@ -0,0 +1,33 @@
+#pragma once
+
+#include <container/seadRingBuffer.h>
+#include "KingSystem/Resource/resUnit.h"
+#include "KingSystem/Utils/Types.h"
+
+namespace ksys::res {
+
+class ResourceUnitPool {
+public:
+ ResourceUnitPool();
+ virtual ~ResourceUnitPool();
+
+ ResourceUnitPool(const ResourceUnitPool&) = delete;
+ ResourceUnitPool& operator=(const ResourceUnitPool&) = delete;
+
+ bool init();
+
+ ResourceUnit* tryAlloc();
+ ResourceUnit* alloc();
+
+ void free(ResourceUnit* unit);
+ void freeForSync(ResourceUnit* unit);
+
+private:
+ static constexpr s32 UnitCapacity = 9000;
+
+ ResourceUnit mUnits[UnitCapacity];
+ sead::FixedRingBuffer<ResourceUnit*, UnitCapacity> mRingBuffer;
+};
+KSYS_CHECK_SIZE_NX150(ResourceUnitPool, 0x9c01a0);
+
+} // namespace ksys::res