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/KingSystem/Resource/resInfoContainer.cpp | |
| parent | 99de7fa00931d1d7c75a0c51d6fd38c09f60b160 (diff) | |
ksys/res: Implement some ResourceMgrTask prerequisites
Diffstat (limited to 'src/KingSystem/Resource/resInfoContainer.cpp')
| -rw-r--r-- | src/KingSystem/Resource/resInfoContainer.cpp | 113 |
1 files changed, 113 insertions, 0 deletions
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 |
