aboutsummaryrefslogtreecommitdiff
path: root/src/core/loader/deconstructed_rom_directory.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/loader/deconstructed_rom_directory.cpp')
-rw-r--r--src/core/loader/deconstructed_rom_directory.cpp53
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;
}