From fdc35b8257db94a51031bb868a495daa947c912e Mon Sep 17 00:00:00 2001 From: GRAnimated Date: Mon, 7 Apr 2025 22:46:44 -0400 Subject: [PATCH] WIP E3ResourceLoader --- data/odyssey_functions.csv | 34 ++--- src/Sequence/E3ResourceLoader.cpp | 210 ++++++++++++++++++++++++++++++ src/Sequence/E3ResourceLoader.h | 37 ++++++ 3 files changed, 264 insertions(+), 17 deletions(-) create mode 100644 src/Sequence/E3ResourceLoader.cpp create mode 100644 src/Sequence/E3ResourceLoader.h diff --git a/data/odyssey_functions.csv b/data/odyssey_functions.csv index e0f28ccb..7cb50428 100644 --- a/data/odyssey_functions.csv +++ b/data/odyssey_functions.csv @@ -32397,23 +32397,23 @@ Address,Quality,Size,Name 0x000000710050a328,U,000008, 0x000000710050a330,U,000008, 0x000000710050a338,U,000008, -0x000000710050a340,U,000276,_ZN16E3ResourceLoaderC2Ev -0x000000710050a454,U,000452,_ZN16E3ResourceLoader21loadHomeStageResourceEv -0x000000710050a618,U,000348,_ZN16E3ResourceLoader17loadWorldResourceEv -0x000000710050a774,U,000332,_ZN16E3ResourceLoaderD2Ev -0x000000710050a8c0,U,000012,_ZN16E3ResourceLoader23cancelLoadWorldResourceEv -0x000000710050a8cc,U,000036,_ZN16E3ResourceLoaderD0Ev -0x000000710050a8f0,U,000104,_ZN16E3ResourceLoader33requestLoadWorldHomeStageResourceEv -0x000000710050a958,U,000008,_ZNK16E3ResourceLoader31isEndLoadWorldHomeStageResourceEv -0x000000710050a960,U,000112,_ZN16E3ResourceLoader24requestLoadWorldResourceEi -0x000000710050a9d0,U,000060,_ZNK16E3ResourceLoader12isEndLoadAnyEv -0x000000710050aa0c,U,000396,_ZN16E3ResourceLoader15tryCreateExHeapEi -0x000000710050ab98,U,000180,_ZN16E3ResourceLoader23tryDestroyWorldResourceEPN4sead4HeapE -0x000000710050ac4c,U,000004,_ZNK16E3ResourceLoader13printHeapInfoEv -0x000000710050ac50,U,000360,_ZN16E3ResourceLoader28loadHomeStageResourceByWorldEPKcPN4sead4HeapEii -0x000000710050adb8,U,000028,_ZNK2al10FunctorV0MIP16E3ResourceLoaderMS1_FvvEEclEv -0x000000710050add4,U,000076,_ZNK2al10FunctorV0MIP16E3ResourceLoaderMS1_FvvEE5cloneEv -0x000000710050ae20,U,000004,_ZN2al10FunctorV0MIP16E3ResourceLoaderMS1_FvvEED0Ev +0x000000710050a340,M,000276,_ZN16E3ResourceLoaderC2Ev +0x000000710050a454,O,000452,_ZN16E3ResourceLoader21loadHomeStageResourceEv +0x000000710050a618,O,000348,_ZN16E3ResourceLoader17loadWorldResourceEv +0x000000710050a774,M,000332,_ZN16E3ResourceLoaderD2Ev +0x000000710050a8c0,O,000012,_ZN16E3ResourceLoader23cancelLoadWorldResourceEv +0x000000710050a8cc,M,000036,_ZN16E3ResourceLoaderD0Ev +0x000000710050a8f0,O,000104,_ZN16E3ResourceLoader33requestLoadWorldHomeStageResourceEv +0x000000710050a958,O,000008,_ZNK16E3ResourceLoader31isEndLoadWorldHomeStageResourceEv +0x000000710050a960,O,000112,_ZN16E3ResourceLoader24requestLoadWorldResourceEi +0x000000710050a9d0,O,000060,_ZNK16E3ResourceLoader12isEndLoadAnyEv +0x000000710050aa0c,M,000396,_ZN16E3ResourceLoader15tryCreateExHeapEi +0x000000710050ab98,O,000180,_ZN16E3ResourceLoader23tryDestroyWorldResourceEPN4sead4HeapE +0x000000710050ac4c,O,000004,_ZNK16E3ResourceLoader13printHeapInfoEv +0x000000710050ac50,M,000360,_ZN16E3ResourceLoader28loadHomeStageResourceByWorldEPKcPN4sead4HeapEii +0x000000710050adb8,O,000028,_ZNK2al10FunctorV0MIP16E3ResourceLoaderMS1_FvvEEclEv +0x000000710050add4,O,000076,_ZNK2al10FunctorV0MIP16E3ResourceLoaderMS1_FvvEE5cloneEv +0x000000710050ae20,O,000004,_ZN2al10FunctorV0MIP16E3ResourceLoaderMS1_FvvEED0Ev 0x000000710050ae24,U,000032, 0x000000710050ae44,U,000312,_ZN10E3SequenceC2EPKc 0x000000710050af7c,U,000316,_ZN10E3SequenceD2Ev diff --git a/src/Sequence/E3ResourceLoader.cpp b/src/Sequence/E3ResourceLoader.cpp new file mode 100644 index 00000000..028b56a0 --- /dev/null +++ b/src/Sequence/E3ResourceLoader.cpp @@ -0,0 +1,210 @@ +#include "Sequence/E3ResourceLoader.h" +#include "Library/Base/StringUtil.h" +#include "Library/File/FileUtil.h" +#include "Library/Memory/HeapUtil.h" +#include "Library/Resource/ResourceHolder.h" +#include "Library/Thread/AsyncFunctorThread.h" +#include "Library/Yaml/ByamlIter.h" +#include "Library/Yaml/ByamlUtil.h" +#include "System/GameDataFunction.h" +#include "heap/seadFrameHeap.h" + +s32 cPriority = 22; +s32 cCoreId = 16; + +E3ResourceLoader::E3ResourceLoader() { + using E3ResourceLoaderFunctor = al::FunctorV0M; + + mLoadHomeStageResourceThread = new al::AsyncFunctorThread( + "LoadHomeStageResourceThread", + E3ResourceLoaderFunctor(this, &E3ResourceLoader::loadHomeStageResource), cPriority, + 0x100000, 0); + + mWorldResourceThread = new al::AsyncFunctorThread( + "WolrdResourceThread", E3ResourceLoaderFunctor(this, &E3ResourceLoader::loadWorldResource), + cPriority, 0x100000, 0); + + al::createWorldResourceHeap(false); + mWorldResourceHeap = al::getWorldResourceHeap(); +} + +E3ResourceLoader::~E3ResourceLoader() {} + +void E3ResourceLoader::loadHomeStageResource() { + if (!_30) { + al::createCategoryResourceAll("プレイヤーモデル"); + al::addResourceCategory("E3常駐", 0x400, mWorldResourceHeap); + al::createCategoryResourceAll("E3常駐"); + _30 = true; + } + if (mWorldExResource) { + al::removeResourceCategory("ワールド常駐"); + mWorldExResource->destroy(); + mWorldExResource = nullptr; + } + if (!mSandWorldHomeStageResource) { + sead::FrameHeap* heap = + sead::FrameHeap::create(0x11800000, "SandWorldHomeStageResource", mWorldResourceHeap, 8, + sead::Heap::cHeapDirection_Forward, false); + mSandWorldHomeStageResource = heap; + al::addResourceCategory("砂ワールドホーム", 0x400, heap); + s32 worldIndexSand = GameDataFunction::getWorldIndexSand(); + loadHomeStageResourceByWorld("砂ワールドホーム", mWorldResourceHeap, worldIndexSand, 8); + } + if (!mCityWorldHomeStageResource) { + sead::FrameHeap* heap = + sead::FrameHeap::create(0x12200000, "CityWorldHomeStageResource", mWorldResourceHeap, 8, + sead::Heap::cHeapDirection_Reverse, false); + mCityWorldHomeStageResource = heap; + al::addResourceCategory("都市ワールドホーム", 0x400, heap); + s32 worldIndexCity = GameDataFunction::getWorldIndexCity(); + loadHomeStageResourceByWorld("都市ワールドホーム", heap, worldIndexCity, 12); + } +} + +void E3ResourceLoader::loadWorldResource() { + al::setCurrentCategoryNameDefault(); + + u8* byml = (al::tryGetBymlFromArcName("SystemData/WorldList", "WorldResource")); + + al::ByamlIter byamlIter = al::ByamlIter(byml); + al::ByamlIter worldIter; + al::getByamlIterByIndex(&worldIter, byamlIter, _3c); + al::ByamlIter worldResourceIter; + al::getByamlIterByKey(&worldResourceIter, worldIter, "WorldResource"); + + s32 size = worldResourceIter.getSize(); + + for (s32 i = 0; i < size; i++) { + al::ByamlIter v8; + worldResourceIter.tryGetIterByIndex(&v8, i); + const char* name = nullptr; + const char* ext = nullptr; + v8.tryGetStringByKey(&name, "Name"); + v8.tryGetStringByKey(&ext, "Ext"); + + if (!al::findResource(name)) + al::findOrCreateResource(name, ext); + if (mHasLoadedWorldResource) + return; + } + _39 = true; +} + +void E3ResourceLoader::cancelLoadWorldResource() { + mHasLoadedWorldResource = true; +} + +bool E3ResourceLoader::requestLoadWorldHomeStageResource() { + if (mSandWorldHomeStageResource && mCityWorldHomeStageResource && + isEndLoadWorldHomeStageResource()) + return false; + if (isEndLoadWorldHomeStageResource()) { + mHasLoadedWorldResource = false; + _39 = false; + _3c = -1; + al::clearFileLoaderEntry(); + mLoadHomeStageResourceThread->start(); + return true; + } + return false; +} + +bool E3ResourceLoader::isEndLoadWorldHomeStageResource() const { + return mLoadHomeStageResourceThread->isDone(); +} + +bool E3ResourceLoader::requestLoadWorldResource(s32 id) { + if (_3c == id && _39) + return false; + if (isEndLoadAny()) { + mHasLoadedWorldResource = false; + al::clearFileLoaderEntry(); + _39 = false; + _3c = id; + mWorldResourceThread->start(); + return true; + } + return false; +} + +bool E3ResourceLoader::isEndLoadAny() const { + return mWorldResourceThread->isDone() && isEndLoadWorldHomeStageResource(); +} + +void E3ResourceLoader::tryCreateExHeap(s32 worldId) { + if (mWorldExResource) + return; + + if (GameDataFunction::getWorldIndexSand() == worldId) { + if (mCityWorldHomeStageResource) { + if (mSandWorldHomeStageResource == mCityWorldHomeStageResource) { + al::removeResourceCategory("砂ワールドホーム"); + mSandWorldHomeStageResource->destroy(); + mSandWorldHomeStageResource = nullptr; + } + al::removeResourceCategory("都市ワールドホーム"); + mCityWorldHomeStageResource->destroy(); + mCityWorldHomeStageResource = nullptr; + } + } else { + if (GameDataFunction::getWorldIndexCity() == worldId) { + if (mSandWorldHomeStageResource) { + al::removeResourceCategory("砂ワールドホーム"); + mSandWorldHomeStageResource->destroy(); + mSandWorldHomeStageResource = nullptr; + } + } + } + + sead::FrameHeap* newHeap = sead::FrameHeap::create(0, "WorldExResource", mWorldResourceHeap, 8, + sead::Heap::cHeapDirection_Forward, false); + mWorldExResource = newHeap; + al::addResourceCategory("ワールド常駐", 0x400, newHeap); +} + +void E3ResourceLoader::tryDestroyWorldResource(sead::Heap* heap) { + if (!heap) + return; + + if (mSandWorldHomeStageResource == heap) { + al::removeResourceCategory("砂ワールドホーム"); + mSandWorldHomeStageResource->destroy(); + mSandWorldHomeStageResource = nullptr; + } + + if (mCityWorldHomeStageResource == heap) { + al::removeResourceCategory("都市ワールドホーム"); + mCityWorldHomeStageResource->destroy(); + mCityWorldHomeStageResource = nullptr; + } +} + +void E3ResourceLoader::printHeapInfo() const {} + +void E3ResourceLoader::loadHomeStageResourceByWorld(const char* worldName, sead::Heap*, s32 id, + s32 scenarioid) { + al::ByamlIter byamlIter = (al::tryGetBymlFromArcName("SystemData/WorldList", "WorldResource")); + al::ByamlIter worldIter; + al::getByamlIterByIndex(&worldIter, byamlIter, id); + al::ByamlIter worldResourceIter; + al::StringTmp<32> scenarioId{"Scenario%d", scenarioid}; + + if (!al::tryGetByamlIterByKey(&worldResourceIter, worldIter, scenarioId.cstr())) + return; + + al::setCurrentCategoryName(worldName); + s32 size = worldResourceIter.getSize(); + for (s32 i = 0; i < size; i++) { + al::ByamlIter v8; + worldResourceIter.tryGetIterByIndex(&v8, i); + const char* name = nullptr; + const char* ext = nullptr; + v8.tryGetStringByKey(&name, "Name"); + v8.tryGetStringByKey(&ext, "Ext"); + + al::findOrCreateResource(name, ext); + if (mHasLoadedWorldResource) + return; + } +} diff --git a/src/Sequence/E3ResourceLoader.h b/src/Sequence/E3ResourceLoader.h new file mode 100644 index 00000000..8104be91 --- /dev/null +++ b/src/Sequence/E3ResourceLoader.h @@ -0,0 +1,37 @@ +#pragma once + +#include + +namespace al { +class AsyncFunctorThread; +} + +class E3ResourceLoader { +public: + E3ResourceLoader(); + virtual ~E3ResourceLoader(); + + void loadHomeStageResource(); + void loadWorldResource(); + void cancelLoadWorldResource(); + bool requestLoadWorldHomeStageResource(); + bool isEndLoadWorldHomeStageResource() const; + bool requestLoadWorldResource(s32); + bool isEndLoadAny() const; + void tryCreateExHeap(s32); + void tryDestroyWorldResource(sead::Heap*); + void printHeapInfo() const; + void loadHomeStageResourceByWorld(const char*, sead::Heap*, s32, s32); + +private: + al::AsyncFunctorThread* mLoadHomeStageResourceThread = nullptr; + al::AsyncFunctorThread* mWorldResourceThread = nullptr; + sead::Heap* mWorldResourceHeap = nullptr; + sead::FrameHeap* mSandWorldHomeStageResource = nullptr; + sead::FrameHeap* mCityWorldHomeStageResource = nullptr; + sead::FrameHeap* mWorldExResource = nullptr; + bool mHasLoadedWorldResource = false; + bool _39 = false; + bool _30 = false; + s32 _3c = -1; +};