diff --git a/include/libultraship/classes.h b/include/libultraship/classes.h index 51341a055..7d444f05c 100644 --- a/include/libultraship/classes.h +++ b/include/libultraship/classes.h @@ -4,7 +4,10 @@ #ifndef _LIBULTRASHIP_CLASSES_H #define _LIBULTRASHIP_CLASSES_H +#include "resource/archive/ArchiveManager.h" #include "resource/archive/Archive.h" +#include "resource/archive/OtrArchive.h" +#include "resource/archive/O2rArchive.h" #include "resource/ResourceManager.h" #include "Context.h" #include "window/Window.h" diff --git a/src/Context.cpp b/src/Context.cpp index d8a90f82b..960a92bbf 100644 --- a/src/Context.cpp +++ b/src/Context.cpp @@ -198,9 +198,11 @@ void Context::InitResourceManager(const std::vector& otrFiles, paths.push_back(mMainPath); paths.push_back(mPatchesPath); - mResourceManager = std::make_shared(paths, validHashes, reservedThreadCount); + mResourceManager = std::make_shared(); + GetResourceManager()->Init(paths, validHashes, reservedThreadCount); } else { - mResourceManager = std::make_shared(otrFiles, validHashes, reservedThreadCount); + mResourceManager = std::make_shared(); + GetResourceManager()->Init(otrFiles, validHashes, reservedThreadCount); } if (!GetResourceManager()->DidLoadSuccessfully()) { diff --git a/src/public/bridge/resourcebridge.cpp b/src/public/bridge/resourcebridge.cpp index a54444ef3..09a85f145 100644 --- a/src/public/bridge/resourcebridge.cpp +++ b/src/public/bridge/resourcebridge.cpp @@ -26,9 +26,9 @@ uint64_t ResourceGetCrcByName(const char* name) { } const char* ResourceGetNameByCrc(uint64_t crc) { - const std::string& hashStr = + const std::string* hashStr = LUS::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->HashToString(crc); - return hashStr == "" ? hashStr.c_str() : nullptr; + return hashStr != nullptr ? hashStr->c_str() : nullptr; } size_t ResourceGetSizeByName(const char* name) { diff --git a/src/resource/ResourceManager.cpp b/src/resource/ResourceManager.cpp index 7740a49bf..e6dd0e11f 100644 --- a/src/resource/ResourceManager.cpp +++ b/src/resource/ResourceManager.cpp @@ -15,10 +15,14 @@ extern bool SFileCheckWildCard(const char* szString, const char* szWildCard); namespace LUS { -ResourceManager::ResourceManager(const std::vector& otrFiles, - const std::unordered_set& validHashes, int32_t reservedThreadCount) { +ResourceManager::ResourceManager() { +} + +void ResourceManager::Init(const std::vector& otrFiles, const std::unordered_set& validHashes, + int32_t reservedThreadCount) { mResourceLoader = std::make_shared(); - mArchiveManager = std::make_shared(otrFiles, validHashes); + mArchiveManager = std::make_shared(); + GetArchiveManager()->Init(otrFiles, validHashes); #if defined(__SWITCH__) || defined(__WIIU__) size_t threadCount = 1; #else diff --git a/src/resource/ResourceManager.h b/src/resource/ResourceManager.h index 1eb8076bc..7b48dd2a9 100644 --- a/src/resource/ResourceManager.h +++ b/src/resource/ResourceManager.h @@ -21,8 +21,9 @@ class ResourceManager { typedef enum class ResourceLoadError { None, NotCached, NotFound } ResourceLoadError; public: - ResourceManager(const std::vector& otrFiles, const std::unordered_set& validHashes, - int32_t reservedThreadCount = 1); + ResourceManager(); + void Init(const std::vector& otrFiles, const std::unordered_set& validHashes, + int32_t reservedThreadCount = 1); ~ResourceManager(); bool DidLoadSuccessfully(); diff --git a/src/resource/archive/Archive.cpp b/src/resource/archive/Archive.cpp index 7b644d113..433a31b7f 100644 --- a/src/resource/archive/Archive.cpp +++ b/src/resource/archive/Archive.cpp @@ -15,7 +15,8 @@ extern bool SFileCheckWildCard(const char* szString, const char* szWildCard); namespace LUS { -Archive::Archive(const std::string& path) : mGameVersion(UNKNOWN_GAME_VERSION), mPath(path), mIsLoaded(false) { +Archive::Archive(const std::string& path) + : mHasGameVersion(false), mGameVersion(UNKNOWN_GAME_VERSION), mPath(path), mIsLoaded(false) { mHashes = std::make_shared>(); } @@ -29,6 +30,7 @@ void Archive::Load() { auto t = LoadFileRaw("version"); bool isGameVersionValid = false; if (t != nullptr && t->IsLoaded) { + mHasGameVersion = true; auto stream = std::make_shared(t->Buffer->data(), t->Buffer->size()); auto reader = std::make_shared(stream); LUS::Endianness endianness = (Endianness)reader->ReadUByte(); @@ -42,7 +44,7 @@ void Archive::Load() { } } - SetLoaded(opened && isGameVersionValid); + SetLoaded(opened && (!mHasGameVersion || isGameVersionValid)); if (!IsLoaded()) { Unload(); @@ -76,6 +78,10 @@ bool Archive::HasFile(uint64_t hash) { return mHashes->count(hash) > 0; } +bool Archive::HasGameVersion() { + return mHasGameVersion; +} + uint32_t Archive::GetGameVersion() { return mGameVersion; } @@ -156,7 +162,9 @@ std::shared_ptr Archive::LoadFile(const std::string& filePath) { } std::shared_ptr Archive::LoadFile(uint64_t hash) { - return LoadFile(Context::GetInstance()->GetResourceManager()->GetArchiveManager()->HashToString(hash)); + const std::string& filePath = + *Context::GetInstance()->GetResourceManager()->GetArchiveManager()->HashToString(hash); + return LoadFile(filePath); } std::shared_ptr Archive::CreateDefaultResourceInitData() { diff --git a/src/resource/archive/Archive.h b/src/resource/archive/Archive.h index 17a53df6a..32991e1bf 100644 --- a/src/resource/archive/Archive.h +++ b/src/resource/archive/Archive.h @@ -29,21 +29,23 @@ class Archive { std::shared_ptr> ListFiles(const std::string& filter); bool HasFile(const std::string& filePath); bool HasFile(uint64_t hash); + bool HasGameVersion(); uint32_t GetGameVersion(); const std::string& GetPath(); bool IsLoaded(); + virtual bool LoadRaw() = 0; + virtual bool UnloadRaw() = 0; + virtual std::shared_ptr LoadFileRaw(const std::string& filePath) = 0; + virtual std::shared_ptr LoadFileRaw(uint64_t hash) = 0; + protected: static std::shared_ptr ReadResourceInitDataBinary(const std::string& filePath, std::shared_ptr headerReader); static std::shared_ptr ReadResourceInitDataXml(const std::string& filePath, std::shared_ptr document); - virtual std::shared_ptr LoadFileRaw(const std::string& filePath) = 0; - virtual std::shared_ptr LoadFileRaw(uint64_t hash) = 0; virtual std::shared_ptr LoadFileMeta(const std::string& filePath) = 0; virtual std::shared_ptr LoadFileMeta(uint64_t hash) = 0; - virtual bool LoadRaw() = 0; - virtual bool UnloadRaw() = 0; void SetLoaded(bool isLoaded); void SetGameVersion(uint32_t gameVersion); @@ -53,6 +55,7 @@ class Archive { static std::shared_ptr CreateDefaultResourceInitData(); bool mIsLoaded; + bool mHasGameVersion; uint32_t mGameVersion; std::string mPath; std::shared_ptr> mHashes; diff --git a/src/resource/archive/ArchiveManager.cpp b/src/resource/archive/ArchiveManager.cpp index 4eedb6800..9bedc0d3f 100644 --- a/src/resource/archive/ArchiveManager.cpp +++ b/src/resource/archive/ArchiveManager.cpp @@ -15,15 +15,16 @@ extern bool SFileCheckWildCard(const char* szString, const char* szWildCard); namespace LUS { -ArchiveManager::ArchiveManager() : ArchiveManager(std::vector()) { +ArchiveManager::ArchiveManager() { } -ArchiveManager::ArchiveManager(const std::vector& archivePaths) : ArchiveManager(archivePaths, {}) { +void ArchiveManager::Init(const std::vector& archivePaths) { + Init(archivePaths, {}); } -ArchiveManager::ArchiveManager(const std::vector& archivePaths, - const std::unordered_set& validGameVersions) - : mValidGameVersions(validGameVersions) { +void ArchiveManager::Init(const std::vector& archivePaths, + const std::unordered_set& validGameVersions) { + mValidGameVersions = validGameVersions; auto archives = GetArchiveListInPaths(archivePaths); for (const auto archive : archives) { AddArchive(archive); @@ -39,6 +40,10 @@ bool ArchiveManager::IsArchiveLoaded() { } std::shared_ptr ArchiveManager::LoadFile(const std::string& filePath) { + if (filePath == "") { + return nullptr; + } + const auto archive = mFileToArchive[CRC64(filePath.c_str())]; if (archive == nullptr) { return nullptr; @@ -56,6 +61,28 @@ std::shared_ptr ArchiveManager::LoadFile(uint64_t hash) { return archive->LoadFile(hash); } +std::shared_ptr ArchiveManager::LoadFileRaw(const std::string& filePath) { + if (filePath == "") { + return nullptr; + } + + const auto archive = mFileToArchive[CRC64(filePath.c_str())]; + if (archive == nullptr) { + return nullptr; + } + + return archive->LoadFileRaw(filePath); +} + +std::shared_ptr ArchiveManager::LoadFileRaw(uint64_t hash) { + const auto archive = mFileToArchive[hash]; + if (archive == nullptr) { + return nullptr; + } + + return archive->LoadFileRaw(hash); +} + bool ArchiveManager::HasFile(const std::string& filePath) { return HasFile(CRC64(filePath.c_str())); } @@ -105,9 +132,9 @@ void ArchiveManager::SetArchives(const std::vector>& ar } } -const std::string& ArchiveManager::HashToString(uint64_t hash) { +const std::string* ArchiveManager::HashToString(uint64_t hash) const { auto it = mHashes.find(hash); - return it != mHashes.end() ? it->second : ""; + return it != mHashes.end() ? &it->second : nullptr; } std::vector ArchiveManager::GetArchiveListInPaths(const std::vector& archivePaths) { @@ -154,6 +181,7 @@ std::shared_ptr ArchiveManager::AddArchive(const std::string& archivePa archive = std::make_shared(archivePath); } + archive->Load(); return AddArchive(archive); } @@ -172,12 +200,12 @@ std::shared_ptr ArchiveManager::AddArchive(std::shared_ptr arc SPDLOG_INFO("Adding Archive {} to Archive Manager", archive->GetPath()); mArchives.push_back(archive); - mGameVersions.push_back(archive->GetGameVersion()); + if (archive->HasGameVersion()) { + mGameVersions.push_back(archive->GetGameVersion()); + } const auto fileList = archive->ListFiles(); - for (size_t i = 0; i < fileList->size(); i++) { - const auto file = fileList->operator[](i); - const auto hash = CRC64(file.c_str()); - mHashes[hash] = file; + for (auto& [hash, filename] : *fileList.get()) { + mHashes[hash] = filename; mFileToArchive[hash] = archive; } return archive; diff --git a/src/resource/archive/ArchiveManager.h b/src/resource/archive/ArchiveManager.h index ff02a1177..1bcdb4503 100644 --- a/src/resource/archive/ArchiveManager.h +++ b/src/resource/archive/ArchiveManager.h @@ -14,13 +14,15 @@ class Archive; class ArchiveManager { public: ArchiveManager(); - ArchiveManager(const std::vector& archivePaths); - ArchiveManager(const std::vector& archivePaths, const std::unordered_set& validGameVersions); + void Init(const std::vector& archivePaths); + void Init(const std::vector& archivePaths, const std::unordered_set& validGameVersions); ~ArchiveManager(); bool IsArchiveLoaded(); std::shared_ptr LoadFile(const std::string& filePath); std::shared_ptr LoadFile(uint64_t hash); + std::shared_ptr LoadFileRaw(const std::string& filePath); + std::shared_ptr LoadFileRaw(uint64_t hash); bool HasFile(const std::string& filePath); bool HasFile(uint64_t hash); std::shared_ptr> ListFiles(const std::string& filter); @@ -28,7 +30,7 @@ class ArchiveManager { std::vector GetGameVersions(); std::vector> GetArchives(); void SetArchives(const std::vector>& archives); - const std::string& HashToString(uint64_t hash); + const std::string* HashToString(uint64_t hash) const; bool IsGameVersionValid(uint32_t gameVersion); protected: diff --git a/src/resource/archive/O2rArchive.h b/src/resource/archive/O2rArchive.h index e233d4ec7..cc00c34d5 100644 --- a/src/resource/archive/O2rArchive.h +++ b/src/resource/archive/O2rArchive.h @@ -18,15 +18,15 @@ class O2rArchive : virtual public Archive { O2rArchive(const std::string& archivePath); ~O2rArchive(); - protected: + bool LoadRaw(); + bool UnloadRaw(); std::shared_ptr LoadFileRaw(const std::string& filePath); std::shared_ptr LoadFileRaw(uint64_t hash); + + protected: std::shared_ptr LoadFileMeta(const std::string& filePath); std::shared_ptr LoadFileMeta(uint64_t hash); - bool LoadRaw(); - bool UnloadRaw(); - private: }; } // namespace LUS diff --git a/src/resource/archive/OtrArchive.cpp b/src/resource/archive/OtrArchive.cpp index 1d4dcb1d4..8f60ede50 100644 --- a/src/resource/archive/OtrArchive.cpp +++ b/src/resource/archive/OtrArchive.cpp @@ -24,10 +24,9 @@ std::shared_ptr OtrArchive::LoadFileRaw(const std::string& filePath) { } auto fileToLoad = std::make_shared(); - fileToLoad->InitData->Path = filePath; DWORD fileSize = SFileGetFileSize(fileHandle, 0); DWORD readBytes; - fileToLoad->Buffer->resize(fileSize); + fileToLoad->Buffer = std::make_shared>(fileSize); bool readFileSuccess = SFileReadFile(fileHandle, fileToLoad->Buffer->data(), fileSize, &readBytes, NULL); if (!readFileSuccess) { @@ -52,7 +51,9 @@ std::shared_ptr OtrArchive::LoadFileRaw(const std::string& filePath) { } std::shared_ptr OtrArchive::LoadFileRaw(uint64_t hash) { - return LoadFileRaw(Context::GetInstance()->GetResourceManager()->GetArchiveManager()->HashToString(hash)); + const std::string& filePath = + *Context::GetInstance()->GetResourceManager()->GetArchiveManager()->HashToString(hash); + return LoadFileRaw(filePath); } std::shared_ptr OtrArchive::LoadFileMeta(const std::string& filePath) { @@ -67,10 +68,10 @@ bool OtrArchive::LoadRaw() { const bool opened = SFileOpenArchive(GetPath().c_str(), 0, MPQ_OPEN_READ_ONLY, &mHandle); if (opened) { SPDLOG_INFO("Opened mpq file \"{}\"", GetPath()); - SFileCloseArchive(mHandle); } else { SPDLOG_ERROR("Failed to load mpq file \"{}\"", GetPath()); mHandle = nullptr; + return false; } // Generate the file list by reading the list file. diff --git a/src/resource/archive/OtrArchive.h b/src/resource/archive/OtrArchive.h index a85793636..4fab6e8c9 100644 --- a/src/resource/archive/OtrArchive.h +++ b/src/resource/archive/OtrArchive.h @@ -24,15 +24,15 @@ class OtrArchive : virtual public Archive { OtrArchive(const std::string& archivePath); ~OtrArchive(); - protected: + bool LoadRaw(); + bool UnloadRaw(); std::shared_ptr LoadFileRaw(const std::string& filePath); std::shared_ptr LoadFileRaw(uint64_t hash); + + protected: std::shared_ptr LoadFileMeta(const std::string& filePath); std::shared_ptr LoadFileMeta(uint64_t hash); - bool LoadRaw(); - bool UnloadRaw(); - private: HANDLE mHandle; }; diff --git a/src/window/gui/GameOverlay.cpp b/src/window/gui/GameOverlay.cpp index 4349a6dc3..5cbe66d03 100644 --- a/src/window/gui/GameOverlay.cpp +++ b/src/window/gui/GameOverlay.cpp @@ -17,7 +17,7 @@ GameOverlay::~GameOverlay() { void GameOverlay::LoadFont(const std::string& name, const std::string& path, float fontSize) { ImGuiIO& io = ImGui::GetIO(); - std::shared_ptr font = Context::GetInstance()->GetResourceManager()->GetArchiveManager()->LoadFile(path); + std::shared_ptr font = Context::GetInstance()->GetResourceManager()->GetArchiveManager()->LoadFileRaw(path); if (font->IsLoaded) { // TODO: Nothing is ever unloading the font or this fontData array. char* fontData = new char[font->Buffer->size()];