From 655dc01a06a89cc2a3ac81ddd21be6cd8c784130 Mon Sep 17 00:00:00 2001 From: Phillip Stephens Date: Thu, 21 Nov 2019 07:37:08 -0800 Subject: [PATCH] Add support for override paks --- Runtime/CPakFile.cpp | 3 +- Runtime/CPakFile.hpp | 12 ++++---- Runtime/CResLoader.cpp | 67 +++++++++++++++++++++++++++++++++--------- Runtime/CResLoader.hpp | 7 +++-- Runtime/MP1/MP1.cpp | 8 +++++ Runtime/MP1/MP1.hpp | 2 ++ 6 files changed, 77 insertions(+), 22 deletions(-) diff --git a/Runtime/CPakFile.cpp b/Runtime/CPakFile.cpp index 5e8ad3b3b..cf94b9ead 100644 --- a/Runtime/CPakFile.cpp +++ b/Runtime/CPakFile.cpp @@ -3,13 +3,14 @@ namespace urde { static logvisor::Module Log("urde::CPakFile"); -CPakFile::CPakFile(std::string_view filename, bool buildDepList, bool worldPak) : CDvdFile(filename) { +CPakFile::CPakFile(std::string_view filename, bool buildDepList, bool worldPak, bool override) : CDvdFile(filename) { if (!CDvdFile::operator bool()) Log.report(logvisor::Fatal, fmt("{}: Unable to open"), GetPath()); x28_24_buildDepList = buildDepList; //x28_24_buildDepList = true; // Always do this so URDE can rapidly pre-warm shaders x28_26_worldPak = worldPak; x28_27_stashedInARAM = false; + m_override = override; } CPakFile::~CPakFile() { diff --git a/Runtime/CPakFile.hpp b/Runtime/CPakFile.hpp index 0ed918f83..d978d7fc6 100644 --- a/Runtime/CPakFile.hpp +++ b/Runtime/CPakFile.hpp @@ -38,10 +38,11 @@ public: private: union { struct { - bool x28_24_buildDepList; - bool x28_25_aramFile; - bool x28_26_worldPak; - bool x28_27_stashedInARAM; + bool x28_24_buildDepList : 1; + bool x28_25_aramFile : 1; + bool x28_26_worldPak : 1; + bool x28_27_stashedInARAM : 1; + bool m_override : 1; }; u32 _dummy = 0; }; @@ -67,7 +68,7 @@ private: void Warmup(); public: - CPakFile(std::string_view filename, bool buildDepList, bool worldPak); + CPakFile(std::string_view filename, bool buildDepList, bool worldPak, bool override=false); ~CPakFile(); const std::vector>& GetNameList() const { return x54_nameList; } const std::vector& GetDepList() const { return x64_depList; } @@ -76,6 +77,7 @@ public: const SResInfo* GetResInfoForLoadDirectionless(CAssetId id) const; const SResInfo* GetResInfo(CAssetId id) const; bool IsWorldPak() const { return x28_26_worldPak; } + bool IsOverridePak() const { return m_override; } u32 GetFakeStaticSize() const { return 0; } void AsyncIdle(); CAssetId GetMLVLId() const { return m_mlvlId; } diff --git a/Runtime/CResLoader.cpp b/Runtime/CResLoader.cpp index df607e59f..d7af1d62a 100644 --- a/Runtime/CResLoader.cpp +++ b/Runtime/CResLoader.cpp @@ -16,16 +16,16 @@ const std::vector* CResLoader::GetTagListForFile(std::string_view name return nullptr; } -void CResLoader::AddPakFileAsync(std::string_view name, bool buildDepList, bool worldPak) { +void CResLoader::AddPakFileAsync(std::string_view name, bool buildDepList, bool worldPak, bool override) { const std::string namePak = std::string(name).append(".upak"); if (CDvdFile::FileExists(namePak)) { - x30_pakLoadingList.emplace_back(std::make_unique(namePak, buildDepList, worldPak)); + x30_pakLoadingList.emplace_back(std::make_unique(namePak, buildDepList, worldPak, override)); ++x44_pakLoadingCount; } } -void CResLoader::AddPakFile(std::string_view name, bool samusPak, bool worldPak) { - AddPakFileAsync(name, samusPak, worldPak); +void CResLoader::AddPakFile(std::string_view name, bool samusPak, bool worldPak, bool override) { + AddPakFileAsync(name, samusPak, worldPak, override); WaitForPakFileLoadingComplete(); } @@ -116,17 +116,30 @@ std::unique_ptr CResLoader::LoadNewResourcePartSync(const urde::SObjectTag void CResLoader::GetTagListForFile(const char* pakName, std::vector& out) const { std::string path = std::string(pakName) + ".upak"; - for (const std::unique_ptr& file : x18_pakLoadedList) { - if (CStringExtras::CompareCaseInsensitive(file->GetPath(), path)) { - auto& depList = file->GetDepList(); - out.reserve(depList.size()); - for (const auto& dep : depList) { - auto resInfo = file->GetResInfo(dep); - out.emplace_back(resInfo->GetType(), dep); - } + + for (const std::unique_ptr& file : m_overridePakList) { + if (_GetTagListForFile(out, path, file)) return; - } } + + for (const std::unique_ptr& file : x18_pakLoadedList) { + if (_GetTagListForFile(out, path, file)) + return; + } +} + +bool CResLoader::_GetTagListForFile(std::vector& out, const std::string& path, + const std::unique_ptr& file) const { + if (CStringExtras::CompareCaseInsensitive(file->GetPath(), path)) { + auto& depList = file->GetDepList(); + out.reserve(depList.size()); + for (const auto& dep : depList) { + auto resInfo = file->GetResInfo(dep); + out.emplace_back(resInfo->GetType(), dep); + } + return true; + } + return false; } bool CResLoader::GetResourceCompression(const SObjectTag& tag) const { @@ -150,6 +163,10 @@ FourCC CResLoader::GetResourceTypeById(CAssetId id) const { } const SObjectTag* CResLoader::GetResourceIdByName(std::string_view name) const { + for (const std::unique_ptr& file : m_overridePakList) + if (const SObjectTag* id = file->GetResIdByName(name)) + return id; + for (const std::unique_ptr& file : x18_pakLoadedList) if (const SObjectTag* id = file->GetResIdByName(name)) return id; @@ -175,6 +192,12 @@ bool CResLoader::FindResource(CAssetId id) const { if (x4c_cachedResId == id) return true; + for (auto it = m_overridePakList.begin(); it != m_overridePakList.end(); ++it) { + if (CacheFromPak(**it, id)) { + return true; + } + } + if (x48_curPak != x18_pakLoadedList.end()) if (CacheFromPak(**x48_curPak, id)) return true; @@ -191,6 +214,12 @@ bool CResLoader::FindResource(CAssetId id) const { } CPakFile* CResLoader::FindResourceForLoad(CAssetId id) { + for (auto it = m_overridePakList.begin(); it != m_overridePakList.end(); ++it) { + if (CacheFromPakForLoad(**it, id)) { + return &**it; + } + } + if (x48_curPak != x18_pakLoadedList.end()) if (CacheFromPakForLoad(**x48_curPak, id)) return &**x48_curPak; @@ -237,7 +266,10 @@ bool CResLoader::CacheFromPak(const CPakFile& file, CAssetId id) const { } void CResLoader::MoveToCorrectLoadedList(std::unique_ptr&& file) { - x18_pakLoadedList.push_back(std::move(file)); + if (file->IsOverridePak()) + m_overridePakList.push_back(std::move(file)); + else + x18_pakLoadedList.push_back(std::move(file)); } std::vector> CResLoader::GetResourceIdToNameList() const { @@ -249,6 +281,13 @@ std::vector> CResLoader::GetResourceIdToNameL } void CResLoader::EnumerateResources(const std::function& lambda) const { + for (auto it = m_overridePakList.begin(); it != m_overridePakList.end(); ++it) { + for (const CAssetId& id : (*it)->GetDepList()) { + SObjectTag fcc(GetResourceTypeById(id), id); + if (!lambda(fcc)) + return; + } + } for (auto it = x18_pakLoadedList.begin(); it != x18_pakLoadedList.end(); ++it) { for (const CAssetId& id : (*it)->GetDepList()) { SObjectTag fcc(GetResourceTypeById(id), id); diff --git a/Runtime/CResLoader.hpp b/Runtime/CResLoader.hpp index e9edf7b32..71386f4e9 100644 --- a/Runtime/CResLoader.hpp +++ b/Runtime/CResLoader.hpp @@ -19,17 +19,20 @@ class CResLoader { // std::list> x0_aramList; std::list> x18_pakLoadedList; std::list> x30_pakLoadingList; + std::list> m_overridePakList; // URDE Addition, Trilogy has a similar mechanism, need to verify behavior against it u32 x44_pakLoadingCount = 0; std::list>::iterator x48_curPak; mutable CAssetId x4c_cachedResId; mutable const CPakFile::SResInfo* x50_cachedResInfo = nullptr; bool x54_forwardSeek = false; + bool _GetTagListForFile(std::vector& out, const std::string& path, + const std::unique_ptr& file) const; public: CResLoader(); const std::vector* GetTagListForFile(std::string_view name) const; - void AddPakFileAsync(std::string_view name, bool buildDepList, bool worldPak); - void AddPakFile(std::string_view name, bool samusPak, bool worldPak); + void AddPakFileAsync(std::string_view name, bool buildDepList, bool worldPak, bool override=false); + void AddPakFile(std::string_view name, bool samusPak, bool worldPak, bool override=false); void WaitForPakFileLoadingComplete(); std::unique_ptr LoadNewResourcePartSync(const SObjectTag& tag, u32 length, u32 offset, void* extBuf); void LoadMemResourceSync(const SObjectTag& tag, std::unique_ptr& bufOut, int* sizeOut); diff --git a/Runtime/MP1/MP1.cpp b/Runtime/MP1/MP1.cpp index de05a85b5..ecd555a07 100644 --- a/Runtime/MP1/MP1.cpp +++ b/Runtime/MP1/MP1.cpp @@ -337,6 +337,13 @@ void CMain::AddWorldPaks() { loader->WaitForPakFileLoadingComplete(); } +void CMain::AddOverridePaks() { + if (CResLoader* loader = g_ResFactory->GetResLoader()) { + loader->AddPakFileAsync("URDE", false, false, true); + loader->WaitForPakFileLoadingComplete(); + } +} + void CMain::ResetGameState() { CPersistentOptions sysOpts = g_GameState->SystemOptions(); CGameOptions gameOpts = g_GameState->GameOptions(); @@ -687,6 +694,7 @@ void CMain::Init(const hecl::Runtime::FileStoreManager& storeMgr, hecl::CVarMana hecl::SConsoleCommand::ECommandFlags::Normal); InitializeSubsystems(); + AddOverridePaks(); x128_globalObjects.PostInitialize(); x70_tweaks.RegisterTweaks(m_cvarMgr); x70_tweaks.RegisterResourceTweaks(m_cvarMgr); diff --git a/Runtime/MP1/MP1.hpp b/Runtime/MP1/MP1.hpp index f45977c3e..939c090ff 100644 --- a/Runtime/MP1/MP1.hpp +++ b/Runtime/MP1/MP1.hpp @@ -102,6 +102,7 @@ public: CScriptMazeNode::LoadMazeSeeds(); } + void ResetGameState() { x134_gameState = std::make_unique(); g_GameState = x134_gameState.get(); @@ -256,6 +257,7 @@ public: boo::IGraphicsCommandQueue* cmdQ, const boo::ObjToken& spareTex); void RegisterResourceTweaks(); void AddWorldPaks(); + void AddOverridePaks(); void ResetGameState(); void StreamNewGameState(CBitStreamReader&, u32 idx); void RefreshGameState();