diff options
| author | Léo Lam <leo@leolam.fr> | 2020-10-04 15:39:04 +0200 |
|---|---|---|
| committer | Léo Lam <leo@leolam.fr> | 2020-10-08 00:09:53 +0200 |
| commit | 76655d85a90ca1cede47a45b4faa3e6e767b99a3 (patch) | |
| tree | 15d04cd8e0e130435f11d561c7c4131ee44f674f /src | |
| parent | 99de7fa00931d1d7c75a0c51d6fd38c09f60b160 (diff) | |
ksys/res: Implement some ResourceMgrTask prerequisites
Diffstat (limited to 'src')
| -rw-r--r-- | src/KingSystem/Resource/CMakeLists.txt | 7 | ||||
| -rw-r--r-- | src/KingSystem/Resource/resCounter.cpp | 40 | ||||
| -rw-r--r-- | src/KingSystem/Resource/resCounter.h | 54 | ||||
| -rw-r--r-- | src/KingSystem/Resource/resInfoContainer.cpp | 113 | ||||
| -rw-r--r-- | src/KingSystem/Resource/resInfoContainer.h | 48 | ||||
| -rw-r--r-- | src/KingSystem/Resource/resResourceMgrTask.h | 6 | ||||
| -rw-r--r-- | src/KingSystem/Resource/resSystem.cpp | 17 | ||||
| -rw-r--r-- | src/KingSystem/Resource/resSystem.h | 4 | ||||
| -rw-r--r-- | src/KingSystem/Resource/resUnitPool.cpp | 33 | ||||
| -rw-r--r-- | src/KingSystem/Resource/resUnitPool.h | 33 |
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 |
