diff options
Diffstat (limited to 'src/core/loader/deconstructed_rom_directory.cpp')
| -rw-r--r-- | src/core/loader/deconstructed_rom_directory.cpp | 53 |
1 files changed, 26 insertions, 27 deletions
diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp index 94dd3395ba..463a8c8930 100644 --- a/src/core/loader/deconstructed_rom_directory.cpp +++ b/src/core/loader/deconstructed_rom_directory.cpp @@ -8,6 +8,8 @@ #include <cctype> #include <chrono> #include <cstring> +#include <map> +#include <memory> #include <mutex> #include <string_view> #include "common/logging.h" @@ -92,31 +94,24 @@ FileSys::VirtualFile FindLooseRomFS(const FileSys::VirtualDir& exefs_dir) { } if (const auto parent = exefs_dir->GetParentDirectory()) { if (const auto romfs_dir = parent->GetSubdirectory("romfs")) { - // Keep no ownership here: launch preparation hands its image to the real loader. + // Building it walks every file and keeps an object for each (title 1: 206k files, ~150 + // MiB), so loaders of the same directory share one build while any of them holds it. static std::mutex cache_mutex; - static std::string cached_path; - static std::weak_ptr<FileSys::VfsFile> cached_romfs; - const auto path = romfs_dir->GetFullPath(); - { - std::scoped_lock lock{cache_mutex}; - if (cached_path == path) { - if (auto cached = cached_romfs.lock()) { - return cached; - } - } + static std::map<std::string, std::weak_ptr<FileSys::VfsFile>> cache; + std::scoped_lock lk{cache_mutex}; + auto& cached = cache[romfs_dir->GetFullPath()]; + if (auto built = cached.lock()) { + return built; } + LOG_INFO(Loader, "Using RomFS directory next to the ExeFS"); const auto started = std::chrono::steady_clock::now(); - LOG_INFO(Loader, "Building loose RomFS directory image"); - auto image = FileSys::CreateRomFS(romfs_dir); + auto built = FileSys::CreateRomFS(romfs_dir); LOG_INFO(Loader, "Loose RomFS image ready: elapsed_ms={}", std::chrono::duration_cast<std::chrono::milliseconds>( - std::chrono::steady_clock::now() - started).count()); - { - std::scoped_lock lock{cache_mutex}; - cached_path = path; - cached_romfs = image; - } - return image; + std::chrono::steady_clock::now() - started) + .count()); + cached = built; + return built; } } return nullptr; @@ -258,6 +253,7 @@ AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(FileSys name = control->GetApplicationName(); } + romfs_exefs_dir = file_dir; if (const auto title_dir = file_dir->GetParentDirectory()) { romfs_version = RomFSProductVersion(title_dir->GetSubdirectory("romfs")); } @@ -269,13 +265,17 @@ AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory( , dir(std::move(directory)) , override_update(override_update_) { + romfs_exefs_dir = dir; } -void AppLoader_DeconstructedRomDirectory::EnsureRomFS() { - if (!romfs_initialized) { - romfs = FindLooseRomFS(dir ? dir : file->GetContainingDirectory()); - romfs_initialized = true; +// Loaders made only for metadata (the game list, title lookups) never need the RomFS, and several +// of them were alive with a whole copy each. +const FileSys::VirtualFile& AppLoader_DeconstructedRomDirectory::LooseRomFS() { + if (!romfs_resolved) { + romfs_resolved = true; + romfs = FindLooseRomFS(romfs_exefs_dir); } + return romfs; } FileType AppLoader_DeconstructedRomDirectory::IdentifyType(const FileSys::VirtualFile& dir_file) { @@ -336,7 +336,7 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect // Loose-ExeFS loads bypass the NCA/NSP loaders, which are the ones that normally apply // LayeredFS to the RomFS; apply it here so mods in user/load/<titleid>/ work too. - if (romfs != nullptr) { + if (LooseRomFS() != nullptr) { const FileSys::PatchManager patch_manager(metadata.GetTitleID(), system.GetFileSystemController(), system.GetContentProvider()); @@ -446,8 +446,7 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect } ResultStatus AppLoader_DeconstructedRomDirectory::ReadRomFS(FileSys::VirtualFile& out_dir) { - EnsureRomFS(); - if (romfs == nullptr) { + if (LooseRomFS() == nullptr) { return ResultStatus::ErrorNoRomFS; } |
