diff --git a/data/file_list.yml b/data/file_list.yml index 6d19189f..0fed8fdd 100644 --- a/data/file_list.yml +++ b/data/file_list.yml @@ -295610,7 +295610,7 @@ Project/Resource/ResourceSystem.o: label: - _ZN2al14ResourceSystemC1EPKc - _ZN2al14ResourceSystemC2EPKc - status: NotDecompiled + status: Matching - offset: 0xa7ca30 size: 788 label: _ZN2al14ResourceSystem11addCategoryERKN4sead14SafeStringBaseIcEEiPNS1_4HeapE @@ -295634,27 +295634,27 @@ Project/Resource/ResourceSystem.o: - offset: 0xa7d2c8 size: 472 label: _ZN2al14ResourceSystem14createResourceERKN4sead14SafeStringBaseIcEEPNS0_16ResourceCategoryEPKc - status: NotDecompiled + status: Matching - offset: 0xa7d4a0 size: 688 label: _ZN2al14ResourceSystem14removeCategoryERKN4sead14SafeStringBaseIcEE status: NotDecompiled - offset: 0xa7d750 size: 8 - label: '' - status: NotDecompiled + label: _ZN2al22cleanupResGraphicsFileERKN4sead14SafeStringBaseIcEEPNS_8ResourceE + status: Matching - offset: 0xa7d758 size: 8 label: _ZN2al14ResourceSystem12findResourceERKN4sead14SafeStringBaseIcEE - status: NotDecompiled + status: Matching - offset: 0xa7d760 size: 308 label: _ZN2al14ResourceSystem16findResourceCoreERKN4sead14SafeStringBaseIcEEPNS1_10RingBufferIPNS0_16ResourceCategoryEE8iteratorE - status: NotDecompiled + status: Matching - offset: 0xa7d894 size: 100 label: _ZN2al14ResourceSystem20findOrCreateResourceERKN4sead14SafeStringBaseIcEEPKc - status: NotDecompiled + status: Matching - offset: 0xa7d8f8 size: 416 label: _ZN2al14ResourceSystem20findResourceCategoryERKN4sead14SafeStringBaseIcEE @@ -295666,24 +295666,24 @@ Project/Resource/ResourceSystem.o: - offset: 0xa7dd98 size: 8 label: _ZN2al14ResourceSystem18setCurrentCategoryEPKc - status: NotDecompiled + status: Matching - offset: 0xa7dda0 size: 592 label: _ZNK2al14ResourceSystem25findCategoryNameFromTableERKN4sead14SafeStringBaseIcEE - status: NotDecompiled + status: Matching - offset: 0xa7dff0 size: 232 label: _ZNK2al14ResourceSystem23tryGetTableCategoryIterEPNS_9ByamlIterERKN4sead14SafeStringBaseIcEE - status: NotDecompiled + status: Matching - offset: 0xa7e0d8 size: 632 label: _ZN4sead10StrTreeMapILi156EPN2al8ResourceEE6insertERKNS_14SafeStringBaseIcEERKS3_ - status: NotDecompiled + status: Matching lazy: true - offset: 0xa7e350 size: 308 label: _ZNK2al14ResourceSystem22tryGetGraphicsInfoIterEPNS_9ByamlIterERKN4sead14SafeStringBaseIcEE - status: NotDecompiled + status: Matching - offset: 0xa7e484 size: 20 label: _ZN4sead10StrTreeMapILi156EPN2al8ResourceEE19ForEachConstContextIPFvRNS_14SafeStringBaseIcEES3_EE4callEPNS_11TreeMapNodeIS7_EE @@ -295743,12 +295743,12 @@ Project/Resource/ResourceSystem.o: - offset: 0xa7e924 size: 4 label: _ZN4sead10StrTreeMapILi156EPN2al8ResourceEE4NodeD0Ev - status: NotDecompiled + status: Matching lazy: true - offset: 0xa7e928 size: 32 label: _ZN4sead10StrTreeMapILi156EPN2al8ResourceEE4Node6erase_Ev - status: NotDecompiled + status: Matching lazy: true Project/SaveData/SaveDataDirector.o: '.text': diff --git a/lib/al/Library/Resource/Resource.h b/lib/al/Library/Resource/Resource.h index 40d45475..8f3a76bd 100644 --- a/lib/al/Library/Resource/Resource.h +++ b/lib/al/Library/Resource/Resource.h @@ -41,12 +41,16 @@ public: bool tryCreateResGraphicsFile(const sead::SafeString& filePath, nn::g3d::ResFile* resFile); void cleanupResGraphicsFile(); + sead::ArchiveRes* getFileArchive() const { return mArchive; } + sead::ArchiveFileDevice* getFileDevice() const { return mDevice; } const char* getPath() const { return mPath.cstr(); } ActorInitResourceData* getResData() const { return mData; } + void setActorInitResourceData(ActorInitResourceData* data) { mData = data; } + nn::g3d::ResFile* getResFile() const { return mResFile; } private: diff --git a/lib/al/Project/Resource/ResourceSystem.cpp b/lib/al/Project/Resource/ResourceSystem.cpp new file mode 100644 index 00000000..0e4524a5 --- /dev/null +++ b/lib/al/Project/Resource/ResourceSystem.cpp @@ -0,0 +1,192 @@ +#include "Project/Resource/ResourceSystem.h" + +#include +#include + +#include "Library/Base/Macros.h" +#include "Library/Base/StringUtil.h" +#include "Library/File/FileUtil.h" +#include "Library/LiveActor/ActorInitResourceData.h" +#include "Library/LiveActor/ActorResourceFunction.h" +#include "Library/Resource/Resource.h" +#include "Library/Yaml/ByamlIter.h" + +namespace al { + +ResourceSystem::ResourceSystem(const char* name) { + addCategory("リソースシステム", 1, sead::HeapMgr::instance()->getCurrentHeap()); + + const char* resourceName = "SystemData/ResourceSystem"; + if (name) + resourceName = name; + + if (isExistArchive(resourceName)) { + Resource* resource = + findOrCreateResourceCategory(resourceName, "リソースシステム", nullptr); + if (resource) + mResourceCategoryTable = new ByamlIter(resource->getByml("ResourceCategoryTable")); + } +} + +ALWAYS_INLINE void ResourceSystem::createResourceCore(Resource* resource) { + StringTmp<256> fileName = StringTmp<256>("%s.bfres", resource->getArchiveName()); + + if (!resource->isExistFile(fileName)) + return; + + ByamlIter iter; + nn::g3d::ResFile* resFile = nullptr; + if (tryGetActorInitFileIter(&iter, resource, "InitModel", nullptr)) { + const char* textureArc = nullptr; + iter.tryGetStringByKey(&textureArc, "TextureArc"); + + if (textureArc) { + StringTmp<256> filePath = StringTmp<256>("ObjectData/%s", textureArc); + resFile = findOrCreateResource(filePath, nullptr)->getResFile(); + } + } + resource->tryCreateResGraphicsFile(fileName, resFile); + resource->setActorInitResourceData(new ActorInitResourceData(resource)); +} + +Resource* ResourceSystem::createResource(const sead::SafeString& name, ResourceCategory* category, + const char* ext) { + sead::ScopedCurrentHeapSetter setter(category->heap); + + Resource* resource = nullptr; + resource = ext ? new Resource(name, loadArchiveWithExt(name, ext)) : new Resource(name); + category->treeMap.insert(name, resource); + + createResourceCore(resource); + + return resource->getFileArchive() ? resource : nullptr; +} + +void cleanupResGraphicsFile(const sead::SafeString& key, Resource* resource) { + resource->cleanupResGraphicsFile(); +} + +Resource* ResourceSystem::findResource(const sead::SafeString& categoryName) { + return findResourceCore(categoryName, nullptr); +} + +Resource* ResourceSystem::findResourceCore(const sead::SafeString& name, + sead::RingBuffer::iterator* outIter) { + for (auto iter = mCategories.begin(); iter != mCategories.end(); ++iter) { + auto* node = (*iter)->treeMap.find(name); + if (!node) + continue; + if (outIter) + *outIter = iter; + return node->value(); + } + + return nullptr; +} + +Resource* ResourceSystem::findOrCreateResource(const sead::SafeString& categoryName, + const char* name) { + Resource* resource = findResource(categoryName); + if (resource) + return resource; + + return createResource(categoryName, findResourceCategory(categoryName), name); +} + +void ResourceSystem::setCurrentCategory(const char* name) { + mCurrentCategoryName = name; +} + +const char* ResourceSystem::findCategoryNameFromTable(const sead::SafeString& name) const { + if (!mResourceCategoryTable) + return nullptr; + + for (s32 i = 0; i < mResourceCategoryTable->getSize(); i++) { + ByamlIter categoryIter; + if (!mResourceCategoryTable->tryGetIterByIndex(&categoryIter, i)) + continue; + + const char* categoryName = nullptr; + if (!categoryIter.tryGetStringByKey(&categoryName, "Category")) + continue; + + ByamlIter arcsIter; + categoryIter.tryGetIterByKey(&arcsIter, "Arcs"); + + bool isLocalized = false; + categoryIter.tryGetBoolByKey(&isLocalized, "Localized"); + + for (s32 j = 0; j < arcsIter.getSize(); j++) { + ByamlIter subArcIter; + arcsIter.tryGetIterByIndex(&subArcIter, j); + + const char* arcName = nullptr; + if (!subArcIter.tryGetStringByKey(&arcName, "Name")) + continue; + + sead::FixedSafeString<0x80> localizedName; + if (isLocalized) { + if (isEqualString(name, "TrialRating")) + makeLocalizedArchivePathByCountryCode(&localizedName, name); + else + makeLocalizedArchivePath(&localizedName, arcName); + arcName = localizedName.cstr(); + } + + if (isEqualString(arcName, name.cstr())) + return categoryName; + } + } + + return nullptr; +} + +bool ResourceSystem::tryGetTableCategoryIter(ByamlIter* iter, const sead::SafeString& name) const { + if (!mResourceCategoryTable) + return false; + + for (s32 i = 0; i < mResourceCategoryTable->getSize(); i++) { + ByamlIter categoryIter; + if (!mResourceCategoryTable->tryGetIterByIndex(&categoryIter, i)) + continue; + + const char* categoryName = nullptr; + if (!categoryIter.tryGetStringByKey(&categoryName, "Category")) + continue; + + if (isEqualString(categoryName, name.cstr()) && + mResourceCategoryTable->tryGetIterByIndex(iter, i)) { + return true; + } + } + + return false; +} + +bool ResourceSystem::tryGetGraphicsInfoIter(ByamlIter* iter, const sead::SafeString& name) const { + if (!mResourceCategoryTable) + return false; + + for (s32 i = 0; i < mResourceCategoryTable->getSize(); i++) { + ByamlIter categoryIter; + if (!mResourceCategoryTable->tryGetIterByIndex(&categoryIter, i)) + continue; + + ByamlIter graphicsInfoIter; + if (!categoryIter.tryGetIterByKey(&graphicsInfoIter, "GraphicsInfo")) + continue; + + for (s32 j = 0; j < graphicsInfoIter.getSize(); j++) { + graphicsInfoIter.tryGetIterByIndex(iter, j); + + const char* arcName = nullptr; + iter->tryGetStringByKey(&arcName, "Arc"); + if (isEqualString(name, arcName)) + return true; + } + } + + return false; +} + +} // namespace al diff --git a/lib/al/Project/Resource/ResourceSystem.h b/lib/al/Project/Resource/ResourceSystem.h index 5b0bd6d4..6c4de535 100644 --- a/lib/al/Project/Resource/ResourceSystem.h +++ b/lib/al/Project/Resource/ResourceSystem.h @@ -1,9 +1,13 @@ #pragma once #include -#include +#include #include +namespace sead { +class Heap; +} // namespace sead + namespace al { class Resource; class ByamlIter; @@ -11,28 +15,42 @@ class SeadAudioPlayer; class ResourceSystem { public: - struct ResourceCategory; + struct ResourceCategory { + ResourceCategory(const sead::SafeString& categoryName, sead::Heap* categoryHeap) { + name = categoryName; + heap = categoryHeap; + } - ResourceSystem(const char*); + sead::FixedSafeString<0x80> name; + sead::Heap* heap; + sead::StrTreeMap<156, Resource*> treeMap; + }; - const sead::SafeString& addCategory(const sead::SafeString&, s32, sead::Heap*); - Resource* findOrCreateResourceCategory(const sead::SafeString&, const sead::SafeString&, - const char*); - s64 findResourceCategoryIter(const sead::SafeString&); - bool isEmptyCategoryResource(const sead::SafeString&); - void createCategoryResourceAll(const sead::SafeString&); - Resource* createResource(const sead::SafeString&, ResourceCategory*, const char*); - void removeCategory(const sead::SafeString&); - Resource* findResource(const sead::SafeString&); - Resource* findResourceCore(const sead::SafeString&, - sead::RingBuffer::iterator*); - Resource* findOrCreateResource(const sead::SafeString&, const char*); - ResourceCategory* findResourceCategory(const sead::SafeString&); - void loadCategoryArchiveAll(const sead::SafeString&); - void setCurrentCategory(const char*); - const char* findCategoryNameFromTable(const sead::SafeString&) const; - bool tryGetTableCategoryIter(ByamlIter*, const sead::SafeString&) const; - bool tryGetGraphicsInfoIter(ByamlIter*, const sead::SafeString&) const; + static_assert(sizeof(ResourceCategory) == 0xc0); + + ResourceSystem(const char* name); + + ResourceCategory* addCategory(const sead::SafeString& name, s32 id, sead::Heap* heap); + Resource* findOrCreateResourceCategory(const sead::SafeString& name, + const sead::SafeString& category, const char* ext); + sead::RingBuffer::iterator + findResourceCategoryIter(const sead::SafeString& name); + bool isEmptyCategoryResource(const sead::SafeString& name); + void createCategoryResourceAll(const sead::SafeString& name); + inline void createResourceCore(Resource* resource); + Resource* createResource(const sead::SafeString& name, ResourceCategory* category, + const char* ext); + void removeCategory(const sead::SafeString& name); + Resource* findResource(const sead::SafeString& name); + Resource* findResourceCore(const sead::SafeString& name, + sead::RingBuffer::iterator* outIter); + Resource* findOrCreateResource(const sead::SafeString& categoryName, const char* name); + ResourceCategory* findResourceCategory(const sead::SafeString& name); + void loadCategoryArchiveAll(const sead::SafeString& name); + void setCurrentCategory(const char* name); + const char* findCategoryNameFromTable(const sead::SafeString& name) const; + bool tryGetTableCategoryIter(ByamlIter* iter, const sead::SafeString& name) const; + bool tryGetGraphicsInfoIter(ByamlIter* iter, const sead::SafeString& name) const; void resetCurrentCategoryName() { mCurrentCategoryName = nullptr; } @@ -42,11 +60,12 @@ public: } private: - char filler[0xb0]; - const char* mCurrentCategoryName; + sead::FixedRingBuffer mCategories; + ByamlIter* mResourceCategoryTable = nullptr; + const char* mCurrentCategoryName = nullptr; // TODO: proper names for these two - SeadAudioPlayer* mAudioPlayerA; - SeadAudioPlayer* mAudioPlayerB; + SeadAudioPlayer* mAudioPlayerA = nullptr; + SeadAudioPlayer* mAudioPlayerB = nullptr; }; static_assert(sizeof(ResourceSystem) == 0xc8);