summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/core.cpp6
-rw-r--r--src/core/file_sys/patch_manager.cpp81
-rw-r--r--src/core/file_sys/patch_manager.h13
-rw-r--r--src/core/file_sys/romfs_factory.cpp6
-rw-r--r--src/core/hle/service/acc/acc.cpp6
-rw-r--r--src/core/hle/service/am/am.cpp14
-rw-r--r--src/core/hle/service/aoc/aoc_u.cpp3
-rw-r--r--src/core/hle/service/filesystem/filesystem.cpp7
-rw-r--r--src/core/hle/service/filesystem/fsp_srv.cpp8
-rw-r--r--src/core/hle/service/filesystem/fsp_srv.h7
-rw-r--r--src/core/hle/service/ns/ns.cpp24
-rw-r--r--src/core/hle/service/ns/ns.h28
-rw-r--r--src/core/loader/deconstructed_rom_directory.cpp6
-rw-r--r--src/core/loader/loader.cpp27
-rw-r--r--src/core/loader/loader.h9
-rw-r--r--src/core/loader/nso.cpp2
-rw-r--r--src/core/loader/nsp.cpp19
-rw-r--r--src/core/loader/nsp.h13
-rw-r--r--src/core/loader/xci.cpp16
-rw-r--r--src/core/loader/xci.h13
-rw-r--r--src/core/telemetry_session.cpp9
-rw-r--r--src/core/telemetry_session.h18
-rw-r--r--src/yuzu/configuration/configure_per_game.cpp7
-rw-r--r--src/yuzu/configuration/configure_per_game_addons.cpp6
-rw-r--r--src/yuzu/game_list_worker.cpp36
-rw-r--r--src/yuzu/main.cpp32
26 files changed, 259 insertions, 157 deletions
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 242796008..9253e05b7 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -210,7 +210,7 @@ struct System::Impl {
210 210
211 ResultStatus Load(System& system, Frontend::EmuWindow& emu_window, 211 ResultStatus Load(System& system, Frontend::EmuWindow& emu_window,
212 const std::string& filepath) { 212 const std::string& filepath) {
213 app_loader = Loader::GetLoader(GetGameFileFromPath(virtual_filesystem, filepath)); 213 app_loader = Loader::GetLoader(system, GetGameFileFromPath(virtual_filesystem, filepath));
214 if (!app_loader) { 214 if (!app_loader) {
215 LOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath); 215 LOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath);
216 return ResultStatus::ErrorGetLoader; 216 return ResultStatus::ErrorGetLoader;
@@ -224,7 +224,7 @@ struct System::Impl {
224 return init_result; 224 return init_result;
225 } 225 }
226 226
227 telemetry_session->AddInitialInfo(*app_loader); 227 telemetry_session->AddInitialInfo(*app_loader, fs_controller, *content_provider);
228 auto main_process = 228 auto main_process =
229 Kernel::Process::Create(system, "main", Kernel::Process::ProcessType::Userland); 229 Kernel::Process::Create(system, "main", Kernel::Process::ProcessType::Userland);
230 const auto [load_result, load_parameters] = app_loader->Load(*main_process, system); 230 const auto [load_result, load_parameters] = app_loader->Load(*main_process, system);
@@ -338,7 +338,7 @@ struct System::Impl {
338 Service::Glue::ApplicationLaunchProperty launch{}; 338 Service::Glue::ApplicationLaunchProperty launch{};
339 launch.title_id = process.GetTitleID(); 339 launch.title_id = process.GetTitleID();
340 340
341 FileSys::PatchManager pm{launch.title_id}; 341 FileSys::PatchManager pm{launch.title_id, fs_controller, *content_provider};
342 launch.version = pm.GetGameVersion().value_or(0); 342 launch.version = pm.GetGameVersion().value_or(0);
343 343
344 // TODO(DarkLordZach): When FSController/Game Card Support is added, if 344 // TODO(DarkLordZach): When FSController/Game Card Support is added, if
diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp
index 807b05821..e9d1607d0 100644
--- a/src/core/file_sys/patch_manager.cpp
+++ b/src/core/file_sys/patch_manager.cpp
@@ -112,7 +112,10 @@ bool IsDirValidAndNonEmpty(const VirtualDir& dir) {
112} 112}
113} // Anonymous namespace 113} // Anonymous namespace
114 114
115PatchManager::PatchManager(u64 title_id) : title_id(title_id) {} 115PatchManager::PatchManager(u64 title_id_,
116 const Service::FileSystem::FileSystemController& fs_controller_,
117 const ContentProvider& content_provider_)
118 : title_id{title_id_}, fs_controller{fs_controller_}, content_provider{content_provider_} {}
116 119
117PatchManager::~PatchManager() = default; 120PatchManager::~PatchManager() = default;
118 121
@@ -128,34 +131,30 @@ VirtualDir PatchManager::PatchExeFS(VirtualDir exefs) const {
128 131
129 if (Settings::values.dump_exefs) { 132 if (Settings::values.dump_exefs) {
130 LOG_INFO(Loader, "Dumping ExeFS for title_id={:016X}", title_id); 133 LOG_INFO(Loader, "Dumping ExeFS for title_id={:016X}", title_id);
131 const auto dump_dir = 134 const auto dump_dir = fs_controller.GetModificationDumpRoot(title_id);
132 Core::System::GetInstance().GetFileSystemController().GetModificationDumpRoot(title_id);
133 if (dump_dir != nullptr) { 135 if (dump_dir != nullptr) {
134 const auto exefs_dir = GetOrCreateDirectoryRelative(dump_dir, "/exefs"); 136 const auto exefs_dir = GetOrCreateDirectoryRelative(dump_dir, "/exefs");
135 VfsRawCopyD(exefs, exefs_dir); 137 VfsRawCopyD(exefs, exefs_dir);
136 } 138 }
137 } 139 }
138 140
139 const auto& installed = Core::System::GetInstance().GetContentProvider();
140
141 const auto& disabled = Settings::values.disabled_addons[title_id]; 141 const auto& disabled = Settings::values.disabled_addons[title_id];
142 const auto update_disabled = 142 const auto update_disabled =
143 std::find(disabled.cbegin(), disabled.cend(), "Update") != disabled.cend(); 143 std::find(disabled.cbegin(), disabled.cend(), "Update") != disabled.cend();
144 144
145 // Game Updates 145 // Game Updates
146 const auto update_tid = GetUpdateTitleID(title_id); 146 const auto update_tid = GetUpdateTitleID(title_id);
147 const auto update = installed.GetEntry(update_tid, ContentRecordType::Program); 147 const auto update = content_provider.GetEntry(update_tid, ContentRecordType::Program);
148 148
149 if (!update_disabled && update != nullptr && update->GetExeFS() != nullptr && 149 if (!update_disabled && update != nullptr && update->GetExeFS() != nullptr &&
150 update->GetStatus() == Loader::ResultStatus::ErrorMissingBKTRBaseRomFS) { 150 update->GetStatus() == Loader::ResultStatus::ErrorMissingBKTRBaseRomFS) {
151 LOG_INFO(Loader, " ExeFS: Update ({}) applied successfully", 151 LOG_INFO(Loader, " ExeFS: Update ({}) applied successfully",
152 FormatTitleVersion(installed.GetEntryVersion(update_tid).value_or(0))); 152 FormatTitleVersion(content_provider.GetEntryVersion(update_tid).value_or(0)));
153 exefs = update->GetExeFS(); 153 exefs = update->GetExeFS();
154 } 154 }
155 155
156 // LayeredExeFS 156 // LayeredExeFS
157 const auto load_dir = 157 const auto load_dir = fs_controller.GetModificationLoadRoot(title_id);
158 Core::System::GetInstance().GetFileSystemController().GetModificationLoadRoot(title_id);
159 if (load_dir != nullptr && load_dir->GetSize() > 0) { 158 if (load_dir != nullptr && load_dir->GetSize() > 0) {
160 auto patch_dirs = load_dir->GetSubdirectories(); 159 auto patch_dirs = load_dir->GetSubdirectories();
161 std::sort( 160 std::sort(
@@ -241,8 +240,7 @@ std::vector<u8> PatchManager::PatchNSO(const std::vector<u8>& nso, const std::st
241 if (Settings::values.dump_nso) { 240 if (Settings::values.dump_nso) {
242 LOG_INFO(Loader, "Dumping NSO for name={}, build_id={}, title_id={:016X}", name, build_id, 241 LOG_INFO(Loader, "Dumping NSO for name={}, build_id={}, title_id={:016X}", name, build_id,
243 title_id); 242 title_id);
244 const auto dump_dir = 243 const auto dump_dir = fs_controller.GetModificationDumpRoot(title_id);
245 Core::System::GetInstance().GetFileSystemController().GetModificationDumpRoot(title_id);
246 if (dump_dir != nullptr) { 244 if (dump_dir != nullptr) {
247 const auto nso_dir = GetOrCreateDirectoryRelative(dump_dir, "/nso"); 245 const auto nso_dir = GetOrCreateDirectoryRelative(dump_dir, "/nso");
248 const auto file = nso_dir->CreateFile(fmt::format("{}-{}.nso", name, build_id)); 246 const auto file = nso_dir->CreateFile(fmt::format("{}-{}.nso", name, build_id));
@@ -254,8 +252,7 @@ std::vector<u8> PatchManager::PatchNSO(const std::vector<u8>& nso, const std::st
254 252
255 LOG_INFO(Loader, "Patching NSO for name={}, build_id={}", name, build_id); 253 LOG_INFO(Loader, "Patching NSO for name={}, build_id={}", name, build_id);
256 254
257 const auto load_dir = 255 const auto load_dir = fs_controller.GetModificationLoadRoot(title_id);
258 Core::System::GetInstance().GetFileSystemController().GetModificationLoadRoot(title_id);
259 if (load_dir == nullptr) { 256 if (load_dir == nullptr) {
260 LOG_ERROR(Loader, "Cannot load mods for invalid title_id={:016X}", title_id); 257 LOG_ERROR(Loader, "Cannot load mods for invalid title_id={:016X}", title_id);
261 return nso; 258 return nso;
@@ -298,8 +295,7 @@ bool PatchManager::HasNSOPatch(const BuildID& build_id_) const {
298 295
299 LOG_INFO(Loader, "Querying NSO patch existence for build_id={}", build_id); 296 LOG_INFO(Loader, "Querying NSO patch existence for build_id={}", build_id);
300 297
301 const auto load_dir = 298 const auto load_dir = fs_controller.GetModificationLoadRoot(title_id);
302 Core::System::GetInstance().GetFileSystemController().GetModificationLoadRoot(title_id);
303 if (load_dir == nullptr) { 299 if (load_dir == nullptr) {
304 LOG_ERROR(Loader, "Cannot load mods for invalid title_id={:016X}", title_id); 300 LOG_ERROR(Loader, "Cannot load mods for invalid title_id={:016X}", title_id);
305 return false; 301 return false;
@@ -313,8 +309,8 @@ bool PatchManager::HasNSOPatch(const BuildID& build_id_) const {
313} 309}
314 310
315std::vector<Core::Memory::CheatEntry> PatchManager::CreateCheatList( 311std::vector<Core::Memory::CheatEntry> PatchManager::CreateCheatList(
316 const Core::System& system, const BuildID& build_id_) const { 312 const BuildID& build_id_) const {
317 const auto load_dir = system.GetFileSystemController().GetModificationLoadRoot(title_id); 313 const auto load_dir = fs_controller.GetModificationLoadRoot(title_id);
318 if (load_dir == nullptr) { 314 if (load_dir == nullptr) {
319 LOG_ERROR(Loader, "Cannot load mods for invalid title_id={:016X}", title_id); 315 LOG_ERROR(Loader, "Cannot load mods for invalid title_id={:016X}", title_id);
320 return {}; 316 return {};
@@ -347,9 +343,9 @@ std::vector<Core::Memory::CheatEntry> PatchManager::CreateCheatList(
347 return out; 343 return out;
348} 344}
349 345
350static void ApplyLayeredFS(VirtualFile& romfs, u64 title_id, ContentRecordType type) { 346static void ApplyLayeredFS(VirtualFile& romfs, u64 title_id, ContentRecordType type,
351 const auto load_dir = 347 const Service::FileSystem::FileSystemController& fs_controller) {
352 Core::System::GetInstance().GetFileSystemController().GetModificationLoadRoot(title_id); 348 const auto load_dir = fs_controller.GetModificationLoadRoot(title_id);
353 if ((type != ContentRecordType::Program && type != ContentRecordType::Data) || 349 if ((type != ContentRecordType::Program && type != ContentRecordType::Data) ||
354 load_dir == nullptr || load_dir->GetSize() <= 0) { 350 load_dir == nullptr || load_dir->GetSize() <= 0) {
355 return; 351 return;
@@ -411,19 +407,19 @@ VirtualFile PatchManager::PatchRomFS(VirtualFile romfs, u64 ivfc_offset, Content
411 const auto log_string = fmt::format("Patching RomFS for title_id={:016X}, type={:02X}", 407 const auto log_string = fmt::format("Patching RomFS for title_id={:016X}, type={:02X}",
412 title_id, static_cast<u8>(type)); 408 title_id, static_cast<u8>(type));
413 409
414 if (type == ContentRecordType::Program || type == ContentRecordType::Data) 410 if (type == ContentRecordType::Program || type == ContentRecordType::Data) {
415 LOG_INFO(Loader, "{}", log_string); 411 LOG_INFO(Loader, "{}", log_string);
416 else 412 } else {
417 LOG_DEBUG(Loader, "{}", log_string); 413 LOG_DEBUG(Loader, "{}", log_string);
414 }
418 415
419 if (romfs == nullptr) 416 if (romfs == nullptr) {
420 return romfs; 417 return romfs;
421 418 }
422 const auto& installed = Core::System::GetInstance().GetContentProvider();
423 419
424 // Game Updates 420 // Game Updates
425 const auto update_tid = GetUpdateTitleID(title_id); 421 const auto update_tid = GetUpdateTitleID(title_id);
426 const auto update = installed.GetEntryRaw(update_tid, type); 422 const auto update = content_provider.GetEntryRaw(update_tid, type);
427 423
428 const auto& disabled = Settings::values.disabled_addons[title_id]; 424 const auto& disabled = Settings::values.disabled_addons[title_id];
429 const auto update_disabled = 425 const auto update_disabled =
@@ -434,7 +430,7 @@ VirtualFile PatchManager::PatchRomFS(VirtualFile romfs, u64 ivfc_offset, Content
434 if (new_nca->GetStatus() == Loader::ResultStatus::Success && 430 if (new_nca->GetStatus() == Loader::ResultStatus::Success &&
435 new_nca->GetRomFS() != nullptr) { 431 new_nca->GetRomFS() != nullptr) {
436 LOG_INFO(Loader, " RomFS: Update ({}) applied successfully", 432 LOG_INFO(Loader, " RomFS: Update ({}) applied successfully",
437 FormatTitleVersion(installed.GetEntryVersion(update_tid).value_or(0))); 433 FormatTitleVersion(content_provider.GetEntryVersion(update_tid).value_or(0)));
438 romfs = new_nca->GetRomFS(); 434 romfs = new_nca->GetRomFS();
439 } 435 }
440 } else if (!update_disabled && update_raw != nullptr) { 436 } else if (!update_disabled && update_raw != nullptr) {
@@ -447,7 +443,7 @@ VirtualFile PatchManager::PatchRomFS(VirtualFile romfs, u64 ivfc_offset, Content
447 } 443 }
448 444
449 // LayeredFS 445 // LayeredFS
450 ApplyLayeredFS(romfs, title_id, type); 446 ApplyLayeredFS(romfs, title_id, type, fs_controller);
451 447
452 return romfs; 448 return romfs;
453} 449}
@@ -458,12 +454,11 @@ PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile u
458 } 454 }
459 455
460 std::map<std::string, std::string, std::less<>> out; 456 std::map<std::string, std::string, std::less<>> out;
461 const auto& installed = Core::System::GetInstance().GetContentProvider();
462 const auto& disabled = Settings::values.disabled_addons[title_id]; 457 const auto& disabled = Settings::values.disabled_addons[title_id];
463 458
464 // Game Updates 459 // Game Updates
465 const auto update_tid = GetUpdateTitleID(title_id); 460 const auto update_tid = GetUpdateTitleID(title_id);
466 PatchManager update{update_tid}; 461 PatchManager update{update_tid, fs_controller, content_provider};
467 const auto metadata = update.GetControlMetadata(); 462 const auto metadata = update.GetControlMetadata();
468 const auto& nacp = metadata.first; 463 const auto& nacp = metadata.first;
469 464
@@ -474,8 +469,8 @@ PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile u
474 if (nacp != nullptr) { 469 if (nacp != nullptr) {
475 out.insert_or_assign(update_label, nacp->GetVersionString()); 470 out.insert_or_assign(update_label, nacp->GetVersionString());
476 } else { 471 } else {
477 if (installed.HasEntry(update_tid, ContentRecordType::Program)) { 472 if (content_provider.HasEntry(update_tid, ContentRecordType::Program)) {
478 const auto meta_ver = installed.GetEntryVersion(update_tid); 473 const auto meta_ver = content_provider.GetEntryVersion(update_tid);
479 if (meta_ver.value_or(0) == 0) { 474 if (meta_ver.value_or(0) == 0) {
480 out.insert_or_assign(update_label, ""); 475 out.insert_or_assign(update_label, "");
481 } else { 476 } else {
@@ -487,8 +482,7 @@ PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile u
487 } 482 }
488 483
489 // General Mods (LayeredFS and IPS) 484 // General Mods (LayeredFS and IPS)
490 const auto mod_dir = 485 const auto mod_dir = fs_controller.GetModificationLoadRoot(title_id);
491 Core::System::GetInstance().GetFileSystemController().GetModificationLoadRoot(title_id);
492 if (mod_dir != nullptr && mod_dir->GetSize() > 0) { 486 if (mod_dir != nullptr && mod_dir->GetSize() > 0) {
493 for (const auto& mod : mod_dir->GetSubdirectories()) { 487 for (const auto& mod : mod_dir->GetSubdirectories()) {
494 std::string types; 488 std::string types;
@@ -532,13 +526,15 @@ PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile u
532 } 526 }
533 527
534 // DLC 528 // DLC
535 const auto dlc_entries = installed.ListEntriesFilter(TitleType::AOC, ContentRecordType::Data); 529 const auto dlc_entries =
530 content_provider.ListEntriesFilter(TitleType::AOC, ContentRecordType::Data);
536 std::vector<ContentProviderEntry> dlc_match; 531 std::vector<ContentProviderEntry> dlc_match;
537 dlc_match.reserve(dlc_entries.size()); 532 dlc_match.reserve(dlc_entries.size());
538 std::copy_if(dlc_entries.begin(), dlc_entries.end(), std::back_inserter(dlc_match), 533 std::copy_if(dlc_entries.begin(), dlc_entries.end(), std::back_inserter(dlc_match),
539 [this, &installed](const ContentProviderEntry& entry) { 534 [this](const ContentProviderEntry& entry) {
540 return (entry.title_id & DLC_BASE_TITLE_ID_MASK) == title_id && 535 return (entry.title_id & DLC_BASE_TITLE_ID_MASK) == title_id &&
541 installed.GetEntry(entry)->GetStatus() == Loader::ResultStatus::Success; 536 content_provider.GetEntry(entry)->GetStatus() ==
537 Loader::ResultStatus::Success;
542 }); 538 });
543 if (!dlc_match.empty()) { 539 if (!dlc_match.empty()) {
544 // Ensure sorted so DLC IDs show in order. 540 // Ensure sorted so DLC IDs show in order.
@@ -559,19 +555,16 @@ PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile u
559} 555}
560 556
561std::optional<u32> PatchManager::GetGameVersion() const { 557std::optional<u32> PatchManager::GetGameVersion() const {
562 const auto& installed = Core::System::GetInstance().GetContentProvider();
563 const auto update_tid = GetUpdateTitleID(title_id); 558 const auto update_tid = GetUpdateTitleID(title_id);
564 if (installed.HasEntry(update_tid, ContentRecordType::Program)) { 559 if (content_provider.HasEntry(update_tid, ContentRecordType::Program)) {
565 return installed.GetEntryVersion(update_tid); 560 return content_provider.GetEntryVersion(update_tid);
566 } 561 }
567 562
568 return installed.GetEntryVersion(title_id); 563 return content_provider.GetEntryVersion(title_id);
569} 564}
570 565
571PatchManager::Metadata PatchManager::GetControlMetadata() const { 566PatchManager::Metadata PatchManager::GetControlMetadata() const {
572 const auto& installed = Core::System::GetInstance().GetContentProvider(); 567 const auto base_control_nca = content_provider.GetEntry(title_id, ContentRecordType::Control);
573
574 const auto base_control_nca = installed.GetEntry(title_id, ContentRecordType::Control);
575 if (base_control_nca == nullptr) { 568 if (base_control_nca == nullptr) {
576 return {}; 569 return {};
577 } 570 }
diff --git a/src/core/file_sys/patch_manager.h b/src/core/file_sys/patch_manager.h
index 1f28c6241..fb1853035 100644
--- a/src/core/file_sys/patch_manager.h
+++ b/src/core/file_sys/patch_manager.h
@@ -17,8 +17,13 @@ namespace Core {
17class System; 17class System;
18} 18}
19 19
20namespace Service::FileSystem {
21class FileSystemController;
22}
23
20namespace FileSys { 24namespace FileSys {
21 25
26class ContentProvider;
22class NCA; 27class NCA;
23class NACP; 28class NACP;
24 29
@@ -29,7 +34,9 @@ public:
29 using Metadata = std::pair<std::unique_ptr<NACP>, VirtualFile>; 34 using Metadata = std::pair<std::unique_ptr<NACP>, VirtualFile>;
30 using PatchVersionNames = std::map<std::string, std::string, std::less<>>; 35 using PatchVersionNames = std::map<std::string, std::string, std::less<>>;
31 36
32 explicit PatchManager(u64 title_id); 37 explicit PatchManager(u64 title_id_,
38 const Service::FileSystem::FileSystemController& fs_controller_,
39 const ContentProvider& content_provider_);
33 ~PatchManager(); 40 ~PatchManager();
34 41
35 [[nodiscard]] u64 GetTitleID() const; 42 [[nodiscard]] u64 GetTitleID() const;
@@ -50,7 +57,7 @@ public:
50 57
51 // Creates a CheatList object with all 58 // Creates a CheatList object with all
52 [[nodiscard]] std::vector<Core::Memory::CheatEntry> CreateCheatList( 59 [[nodiscard]] std::vector<Core::Memory::CheatEntry> CreateCheatList(
53 const Core::System& system, const BuildID& build_id) const; 60 const BuildID& build_id) const;
54 61
55 // Currently tracked RomFS patches: 62 // Currently tracked RomFS patches:
56 // - Game Updates 63 // - Game Updates
@@ -80,6 +87,8 @@ private:
80 const std::string& build_id) const; 87 const std::string& build_id) const;
81 88
82 u64 title_id; 89 u64 title_id;
90 const Service::FileSystem::FileSystemController& fs_controller;
91 const ContentProvider& content_provider;
83}; 92};
84 93
85} // namespace FileSys 94} // namespace FileSys
diff --git a/src/core/file_sys/romfs_factory.cpp b/src/core/file_sys/romfs_factory.cpp
index e967a254e..987199747 100644
--- a/src/core/file_sys/romfs_factory.cpp
+++ b/src/core/file_sys/romfs_factory.cpp
@@ -37,10 +37,12 @@ void RomFSFactory::SetPackedUpdate(VirtualFile update_raw) {
37} 37}
38 38
39ResultVal<VirtualFile> RomFSFactory::OpenCurrentProcess(u64 current_process_title_id) const { 39ResultVal<VirtualFile> RomFSFactory::OpenCurrentProcess(u64 current_process_title_id) const {
40 if (!updatable) 40 if (!updatable) {
41 return MakeResult<VirtualFile>(file); 41 return MakeResult<VirtualFile>(file);
42 }
42 43
43 const PatchManager patch_manager(current_process_title_id); 44 const PatchManager patch_manager{current_process_title_id, filesystem_controller,
45 content_provider};
44 return MakeResult<VirtualFile>( 46 return MakeResult<VirtualFile>(
45 patch_manager.PatchRomFS(file, ivfc_offset, ContentRecordType::Program, update_raw)); 47 patch_manager.PatchRomFS(file, ivfc_offset, ContentRecordType::Program, update_raw));
46} 48}
diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp
index ded52ea0b..c2c11dbcb 100644
--- a/src/core/hle/service/acc/acc.cpp
+++ b/src/core/hle/service/acc/acc.cpp
@@ -742,8 +742,10 @@ void Module::Interface::IsUserAccountSwitchLocked(Kernel::HLERequestContext& ctx
742 bool is_locked = false; 742 bool is_locked = false;
743 743
744 if (res != Loader::ResultStatus::Success) { 744 if (res != Loader::ResultStatus::Success) {
745 FileSys::PatchManager pm{system.CurrentProcess()->GetTitleID()}; 745 const FileSys::PatchManager pm{system.CurrentProcess()->GetTitleID(),
746 auto nacp_unique = pm.GetControlMetadata().first; 746 system.GetFileSystemController(),
747 system.GetContentProvider()};
748 const auto nacp_unique = pm.GetControlMetadata().first;
747 749
748 if (nacp_unique != nullptr) { 750 if (nacp_unique != nullptr) {
749 is_locked = nacp_unique->GetUserAccountSwitchLock(); 751 is_locked = nacp_unique->GetUserAccountSwitchLock();
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index eb097738a..63421b963 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -1381,13 +1381,16 @@ void IApplicationFunctions::GetDisplayVersion(Kernel::HLERequestContext& ctx) {
1381 const auto res = [this] { 1381 const auto res = [this] {
1382 const auto title_id = system.CurrentProcess()->GetTitleID(); 1382 const auto title_id = system.CurrentProcess()->GetTitleID();
1383 1383
1384 FileSys::PatchManager pm{title_id}; 1384 const FileSys::PatchManager pm{title_id, system.GetFileSystemController(),
1385 system.GetContentProvider()};
1385 auto res = pm.GetControlMetadata(); 1386 auto res = pm.GetControlMetadata();
1386 if (res.first != nullptr) { 1387 if (res.first != nullptr) {
1387 return res; 1388 return res;
1388 } 1389 }
1389 1390
1390 FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(title_id)}; 1391 const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(title_id),
1392 system.GetFileSystemController(),
1393 system.GetContentProvider()};
1391 return pm_update.GetControlMetadata(); 1394 return pm_update.GetControlMetadata();
1392 }(); 1395 }();
1393 1396
@@ -1415,13 +1418,16 @@ void IApplicationFunctions::GetDesiredLanguage(Kernel::HLERequestContext& ctx) {
1415 const auto res = [this] { 1418 const auto res = [this] {
1416 const auto title_id = system.CurrentProcess()->GetTitleID(); 1419 const auto title_id = system.CurrentProcess()->GetTitleID();
1417 1420
1418 FileSys::PatchManager pm{title_id}; 1421 const FileSys::PatchManager pm{title_id, system.GetFileSystemController(),
1422 system.GetContentProvider()};
1419 auto res = pm.GetControlMetadata(); 1423 auto res = pm.GetControlMetadata();
1420 if (res.first != nullptr) { 1424 if (res.first != nullptr) {
1421 return res; 1425 return res;
1422 } 1426 }
1423 1427
1424 FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(title_id)}; 1428 const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(title_id),
1429 system.GetFileSystemController(),
1430 system.GetContentProvider()};
1425 return pm_update.GetControlMetadata(); 1431 return pm_update.GetControlMetadata();
1426 }(); 1432 }();
1427 1433
diff --git a/src/core/hle/service/aoc/aoc_u.cpp b/src/core/hle/service/aoc/aoc_u.cpp
index e58b2c518..173b36da4 100644
--- a/src/core/hle/service/aoc/aoc_u.cpp
+++ b/src/core/hle/service/aoc/aoc_u.cpp
@@ -164,7 +164,8 @@ void AOC_U::GetAddOnContentBaseId(Kernel::HLERequestContext& ctx) {
164 rb.Push(RESULT_SUCCESS); 164 rb.Push(RESULT_SUCCESS);
165 165
166 const auto title_id = system.CurrentProcess()->GetTitleID(); 166 const auto title_id = system.CurrentProcess()->GetTitleID();
167 FileSys::PatchManager pm{title_id}; 167 const FileSys::PatchManager pm{title_id, system.GetFileSystemController(),
168 system.GetContentProvider()};
168 169
169 const auto res = pm.GetControlMetadata(); 170 const auto res = pm.GetControlMetadata();
170 if (res.first == nullptr) { 171 if (res.first == nullptr) {
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp
index 3cdef4888..2e53cae5b 100644
--- a/src/core/hle/service/filesystem/filesystem.cpp
+++ b/src/core/hle/service/filesystem/filesystem.cpp
@@ -455,7 +455,9 @@ FileSys::SaveDataSize FileSystemController::ReadSaveDataSize(FileSys::SaveDataTy
455 const auto res = system.GetAppLoader().ReadControlData(nacp); 455 const auto res = system.GetAppLoader().ReadControlData(nacp);
456 456
457 if (res != Loader::ResultStatus::Success) { 457 if (res != Loader::ResultStatus::Success) {
458 FileSys::PatchManager pm{system.CurrentProcess()->GetTitleID()}; 458 const FileSys::PatchManager pm{system.CurrentProcess()->GetTitleID(),
459 system.GetFileSystemController(),
460 system.GetContentProvider()};
459 const auto metadata = pm.GetControlMetadata(); 461 const auto metadata = pm.GetControlMetadata();
460 const auto& nacp_unique = metadata.first; 462 const auto& nacp_unique = metadata.first;
461 463
@@ -728,7 +730,8 @@ void FileSystemController::CreateFactories(FileSys::VfsFilesystem& vfs, bool ove
728void InstallInterfaces(Core::System& system) { 730void InstallInterfaces(Core::System& system) {
729 std::make_shared<FSP_LDR>()->InstallAsService(system.ServiceManager()); 731 std::make_shared<FSP_LDR>()->InstallAsService(system.ServiceManager());
730 std::make_shared<FSP_PR>()->InstallAsService(system.ServiceManager()); 732 std::make_shared<FSP_PR>()->InstallAsService(system.ServiceManager());
731 std::make_shared<FSP_SRV>(system.GetFileSystemController(), system.GetReporter()) 733 std::make_shared<FSP_SRV>(system.GetFileSystemController(), system.GetContentProvider(),
734 system.GetReporter())
732 ->InstallAsService(system.ServiceManager()); 735 ->InstallAsService(system.ServiceManager());
733} 736}
734 737
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp
index 649128be4..031c6dbf6 100644
--- a/src/core/hle/service/filesystem/fsp_srv.cpp
+++ b/src/core/hle/service/filesystem/fsp_srv.cpp
@@ -650,8 +650,10 @@ private:
650 u64 next_entry_index = 0; 650 u64 next_entry_index = 0;
651}; 651};
652 652
653FSP_SRV::FSP_SRV(FileSystemController& fsc, const Core::Reporter& reporter) 653FSP_SRV::FSP_SRV(FileSystemController& fsc_, const FileSys::ContentProvider& content_provider_,
654 : ServiceFramework("fsp-srv"), fsc(fsc), reporter(reporter) { 654 const Core::Reporter& reporter_)
655 : ServiceFramework("fsp-srv"), fsc(fsc_), content_provider{content_provider_},
656 reporter(reporter_) {
655 // clang-format off 657 // clang-format off
656 static const FunctionInfo functions[] = { 658 static const FunctionInfo functions[] = {
657 {0, nullptr, "OpenFileSystem"}, 659 {0, nullptr, "OpenFileSystem"},
@@ -968,7 +970,7 @@ void FSP_SRV::OpenDataStorageByDataId(Kernel::HLERequestContext& ctx) {
968 return; 970 return;
969 } 971 }
970 972
971 FileSys::PatchManager pm{title_id}; 973 const FileSys::PatchManager pm{title_id, fsc, content_provider};
972 974
973 auto storage = std::make_shared<IStorage>( 975 auto storage = std::make_shared<IStorage>(
974 pm.PatchRomFS(std::move(data.Unwrap()), 0, FileSys::ContentRecordType::Data)); 976 pm.PatchRomFS(std::move(data.Unwrap()), 0, FileSys::ContentRecordType::Data));
diff --git a/src/core/hle/service/filesystem/fsp_srv.h b/src/core/hle/service/filesystem/fsp_srv.h
index 4964e874e..6c7239e6a 100644
--- a/src/core/hle/service/filesystem/fsp_srv.h
+++ b/src/core/hle/service/filesystem/fsp_srv.h
@@ -12,8 +12,9 @@ class Reporter;
12} 12}
13 13
14namespace FileSys { 14namespace FileSys {
15class ContentProvider;
15class FileSystemBackend; 16class FileSystemBackend;
16} 17} // namespace FileSys
17 18
18namespace Service::FileSystem { 19namespace Service::FileSystem {
19 20
@@ -32,7 +33,8 @@ enum class LogMode : u32 {
32 33
33class FSP_SRV final : public ServiceFramework<FSP_SRV> { 34class FSP_SRV final : public ServiceFramework<FSP_SRV> {
34public: 35public:
35 explicit FSP_SRV(FileSystemController& fsc, const Core::Reporter& reporter); 36 explicit FSP_SRV(FileSystemController& fsc_, const FileSys::ContentProvider& content_provider_,
37 const Core::Reporter& reporter_);
36 ~FSP_SRV() override; 38 ~FSP_SRV() override;
37 39
38private: 40private:
@@ -55,6 +57,7 @@ private:
55 void OpenMultiCommitManager(Kernel::HLERequestContext& ctx); 57 void OpenMultiCommitManager(Kernel::HLERequestContext& ctx);
56 58
57 FileSystemController& fsc; 59 FileSystemController& fsc;
60 const FileSys::ContentProvider& content_provider;
58 61
59 FileSys::VirtualFile romfs; 62 FileSys::VirtualFile romfs;
60 u64 current_process_id = 0; 63 u64 current_process_id = 0;
diff --git a/src/core/hle/service/ns/ns.cpp b/src/core/hle/service/ns/ns.cpp
index 58ee1f712..2594e6839 100644
--- a/src/core/hle/service/ns/ns.cpp
+++ b/src/core/hle/service/ns/ns.cpp
@@ -3,6 +3,7 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/logging/log.h" 5#include "common/logging/log.h"
6#include "core/core.h"
6#include "core/file_sys/control_metadata.h" 7#include "core/file_sys/control_metadata.h"
7#include "core/file_sys/patch_manager.h" 8#include "core/file_sys/patch_manager.h"
8#include "core/file_sys/vfs.h" 9#include "core/file_sys/vfs.h"
@@ -29,8 +30,8 @@ IAccountProxyInterface::IAccountProxyInterface() : ServiceFramework{"IAccountPro
29 30
30IAccountProxyInterface::~IAccountProxyInterface() = default; 31IAccountProxyInterface::~IAccountProxyInterface() = default;
31 32
32IApplicationManagerInterface::IApplicationManagerInterface() 33IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_)
33 : ServiceFramework{"IApplicationManagerInterface"} { 34 : ServiceFramework{"IApplicationManagerInterface"}, system{system_} {
34 // clang-format off 35 // clang-format off
35 static const FunctionInfo functions[] = { 36 static const FunctionInfo functions[] = {
36 {0, nullptr, "ListApplicationRecord"}, 37 {0, nullptr, "ListApplicationRecord"},
@@ -298,7 +299,8 @@ void IApplicationManagerInterface::GetApplicationControlData(Kernel::HLERequestC
298 299
299 const auto size = ctx.GetWriteBufferSize(); 300 const auto size = ctx.GetWriteBufferSize();
300 301
301 const FileSys::PatchManager pm{title_id}; 302 const FileSys::PatchManager pm{title_id, system.GetFileSystemController(),
303 system.GetContentProvider()};
302 const auto control = pm.GetControlMetadata(); 304 const auto control = pm.GetControlMetadata();
303 305
304 std::vector<u8> out; 306 std::vector<u8> out;
@@ -538,14 +540,14 @@ IFactoryResetInterface::IFactoryResetInterface::IFactoryResetInterface()
538 540
539IFactoryResetInterface::~IFactoryResetInterface() = default; 541IFactoryResetInterface::~IFactoryResetInterface() = default;
540 542
541NS::NS(const char* name) : ServiceFramework{name} { 543NS::NS(const char* name, Core::System& system_) : ServiceFramework{name}, system{system_} {
542 // clang-format off 544 // clang-format off
543 static const FunctionInfo functions[] = { 545 static const FunctionInfo functions[] = {
544 {7992, &NS::PushInterface<IECommerceInterface>, "GetECommerceInterface"}, 546 {7992, &NS::PushInterface<IECommerceInterface>, "GetECommerceInterface"},
545 {7993, &NS::PushInterface<IApplicationVersionInterface>, "GetApplicationVersionInterface"}, 547 {7993, &NS::PushInterface<IApplicationVersionInterface>, "GetApplicationVersionInterface"},
546 {7994, &NS::PushInterface<IFactoryResetInterface>, "GetFactoryResetInterface"}, 548 {7994, &NS::PushInterface<IFactoryResetInterface>, "GetFactoryResetInterface"},
547 {7995, &NS::PushInterface<IAccountProxyInterface>, "GetAccountProxyInterface"}, 549 {7995, &NS::PushInterface<IAccountProxyInterface>, "GetAccountProxyInterface"},
548 {7996, &NS::PushInterface<IApplicationManagerInterface>, "GetApplicationManagerInterface"}, 550 {7996, &NS::PushIApplicationManagerInterface, "GetApplicationManagerInterface"},
549 {7997, &NS::PushInterface<IDownloadTaskInterface>, "GetDownloadTaskInterface"}, 551 {7997, &NS::PushInterface<IDownloadTaskInterface>, "GetDownloadTaskInterface"},
550 {7998, &NS::PushInterface<IContentManagementInterface>, "GetContentManagementInterface"}, 552 {7998, &NS::PushInterface<IContentManagementInterface>, "GetContentManagementInterface"},
551 {7999, &NS::PushInterface<IDocumentInterface>, "GetDocumentInterface"}, 553 {7999, &NS::PushInterface<IDocumentInterface>, "GetDocumentInterface"},
@@ -558,7 +560,7 @@ NS::NS(const char* name) : ServiceFramework{name} {
558NS::~NS() = default; 560NS::~NS() = default;
559 561
560std::shared_ptr<IApplicationManagerInterface> NS::GetApplicationManagerInterface() const { 562std::shared_ptr<IApplicationManagerInterface> NS::GetApplicationManagerInterface() const {
561 return GetInterface<IApplicationManagerInterface>(); 563 return GetInterface<IApplicationManagerInterface>(system);
562} 564}
563 565
564class NS_DEV final : public ServiceFramework<NS_DEV> { 566class NS_DEV final : public ServiceFramework<NS_DEV> {
@@ -678,11 +680,11 @@ public:
678 680
679void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) { 681void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) {
680 682
681 std::make_shared<NS>("ns:am2")->InstallAsService(service_manager); 683 std::make_shared<NS>("ns:am2", system)->InstallAsService(service_manager);
682 std::make_shared<NS>("ns:ec")->InstallAsService(service_manager); 684 std::make_shared<NS>("ns:ec", system)->InstallAsService(service_manager);
683 std::make_shared<NS>("ns:rid")->InstallAsService(service_manager); 685 std::make_shared<NS>("ns:rid", system)->InstallAsService(service_manager);
684 std::make_shared<NS>("ns:rt")->InstallAsService(service_manager); 686 std::make_shared<NS>("ns:rt", system)->InstallAsService(service_manager);
685 std::make_shared<NS>("ns:web")->InstallAsService(service_manager); 687 std::make_shared<NS>("ns:web", system)->InstallAsService(service_manager);
686 688
687 std::make_shared<NS_DEV>()->InstallAsService(service_manager); 689 std::make_shared<NS_DEV>()->InstallAsService(service_manager);
688 std::make_shared<NS_SU>()->InstallAsService(service_manager); 690 std::make_shared<NS_SU>()->InstallAsService(service_manager);
diff --git a/src/core/hle/service/ns/ns.h b/src/core/hle/service/ns/ns.h
index c2554b878..c90ccd755 100644
--- a/src/core/hle/service/ns/ns.h
+++ b/src/core/hle/service/ns/ns.h
@@ -6,6 +6,10 @@
6 6
7#include "core/hle/service/service.h" 7#include "core/hle/service/service.h"
8 8
9namespace Core {
10class System;
11}
12
9namespace Service { 13namespace Service {
10 14
11namespace FileSystem { 15namespace FileSystem {
@@ -22,7 +26,7 @@ public:
22 26
23class IApplicationManagerInterface final : public ServiceFramework<IApplicationManagerInterface> { 27class IApplicationManagerInterface final : public ServiceFramework<IApplicationManagerInterface> {
24public: 28public:
25 explicit IApplicationManagerInterface(); 29 explicit IApplicationManagerInterface(Core::System& system_);
26 ~IApplicationManagerInterface() override; 30 ~IApplicationManagerInterface() override;
27 31
28 ResultVal<u8> GetApplicationDesiredLanguage(u32 supported_languages); 32 ResultVal<u8> GetApplicationDesiredLanguage(u32 supported_languages);
@@ -32,6 +36,8 @@ private:
32 void GetApplicationControlData(Kernel::HLERequestContext& ctx); 36 void GetApplicationControlData(Kernel::HLERequestContext& ctx);
33 void GetApplicationDesiredLanguage(Kernel::HLERequestContext& ctx); 37 void GetApplicationDesiredLanguage(Kernel::HLERequestContext& ctx);
34 void ConvertApplicationLanguageToLanguageCode(Kernel::HLERequestContext& ctx); 38 void ConvertApplicationLanguageToLanguageCode(Kernel::HLERequestContext& ctx);
39
40 Core::System& system;
35}; 41};
36 42
37class IApplicationVersionInterface final : public ServiceFramework<IApplicationVersionInterface> { 43class IApplicationVersionInterface final : public ServiceFramework<IApplicationVersionInterface> {
@@ -72,13 +78,13 @@ public:
72 78
73class NS final : public ServiceFramework<NS> { 79class NS final : public ServiceFramework<NS> {
74public: 80public:
75 explicit NS(const char* name); 81 explicit NS(const char* name, Core::System& system_);
76 ~NS() override; 82 ~NS() override;
77 83
78 std::shared_ptr<IApplicationManagerInterface> GetApplicationManagerInterface() const; 84 std::shared_ptr<IApplicationManagerInterface> GetApplicationManagerInterface() const;
79 85
80private: 86private:
81 template <typename T> 87 template <typename T, typename... Args>
82 void PushInterface(Kernel::HLERequestContext& ctx) { 88 void PushInterface(Kernel::HLERequestContext& ctx) {
83 LOG_DEBUG(Service_NS, "called"); 89 LOG_DEBUG(Service_NS, "called");
84 90
@@ -87,13 +93,23 @@ private:
87 rb.PushIpcInterface<T>(); 93 rb.PushIpcInterface<T>();
88 } 94 }
89 95
90 template <typename T> 96 void PushIApplicationManagerInterface(Kernel::HLERequestContext& ctx) {
91 std::shared_ptr<T> GetInterface() const { 97 LOG_DEBUG(Service_NS, "called");
98
99 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
100 rb.Push(RESULT_SUCCESS);
101 rb.PushIpcInterface<IApplicationManagerInterface>(system);
102 }
103
104 template <typename T, typename... Args>
105 std::shared_ptr<T> GetInterface(Args&&... args) const {
92 static_assert(std::is_base_of_v<Kernel::SessionRequestHandler, T>, 106 static_assert(std::is_base_of_v<Kernel::SessionRequestHandler, T>,
93 "Not a base of ServiceFrameworkBase"); 107 "Not a base of ServiceFrameworkBase");
94 108
95 return std::make_shared<T>(); 109 return std::make_shared<T>(std::forward<Args>(args)...);
96 } 110 }
111
112 Core::System& system;
97}; 113};
98 114
99/// Registers all NS services with the specified service manager. 115/// Registers all NS services with the specified service manager.
diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp
index 394a1bf26..2002dc4f2 100644
--- a/src/core/loader/deconstructed_rom_directory.cpp
+++ b/src/core/loader/deconstructed_rom_directory.cpp
@@ -114,7 +114,8 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect
114 } 114 }
115 115
116 if (override_update) { 116 if (override_update) {
117 const FileSys::PatchManager patch_manager(metadata.GetTitleID()); 117 const FileSys::PatchManager patch_manager(
118 metadata.GetTitleID(), system.GetFileSystemController(), system.GetContentProvider());
118 dir = patch_manager.PatchExeFS(dir); 119 dir = patch_manager.PatchExeFS(dir);
119 } 120 }
120 121
@@ -160,7 +161,8 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect
160 modules.clear(); 161 modules.clear();
161 const VAddr base_address{process.PageTable().GetCodeRegionStart()}; 162 const VAddr base_address{process.PageTable().GetCodeRegionStart()};
162 VAddr next_load_addr{base_address}; 163 VAddr next_load_addr{base_address};
163 const FileSys::PatchManager pm{metadata.GetTitleID()}; 164 const FileSys::PatchManager pm{metadata.GetTitleID(), system.GetFileSystemController(),
165 system.GetContentProvider()};
164 for (const auto& module : static_modules) { 166 for (const auto& module : static_modules) {
165 const FileSys::VirtualFile module_file{dir->GetFile(module)}; 167 const FileSys::VirtualFile module_file{dir->GetFile(module)};
166 if (!module_file) { 168 if (!module_file) {
diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp
index 9bc3a8840..deffe7379 100644
--- a/src/core/loader/loader.cpp
+++ b/src/core/loader/loader.cpp
@@ -10,6 +10,7 @@
10#include "common/file_util.h" 10#include "common/file_util.h"
11#include "common/logging/log.h" 11#include "common/logging/log.h"
12#include "common/string_util.h" 12#include "common/string_util.h"
13#include "core/core.h"
13#include "core/hle/kernel/process.h" 14#include "core/hle/kernel/process.h"
14#include "core/loader/deconstructed_rom_directory.h" 15#include "core/loader/deconstructed_rom_directory.h"
15#include "core/loader/elf.h" 16#include "core/loader/elf.h"
@@ -194,15 +195,14 @@ AppLoader::~AppLoader() = default;
194 195
195/** 196/**
196 * Get a loader for a file with a specific type 197 * Get a loader for a file with a specific type
197 * @param file The file to load 198 * @param system The system context to use.
198 * @param type The type of the file 199 * @param file The file to retrieve the loader for
199 * @param file the file to retrieve the loader for 200 * @param type The file type
200 * @param type the file type
201 * @return std::unique_ptr<AppLoader> a pointer to a loader object; nullptr for unsupported type 201 * @return std::unique_ptr<AppLoader> a pointer to a loader object; nullptr for unsupported type
202 */ 202 */
203static std::unique_ptr<AppLoader> GetFileLoader(FileSys::VirtualFile file, FileType type) { 203static std::unique_ptr<AppLoader> GetFileLoader(Core::System& system, FileSys::VirtualFile file,
204 FileType type) {
204 switch (type) { 205 switch (type) {
205
206 // Standard ELF file format. 206 // Standard ELF file format.
207 case FileType::ELF: 207 case FileType::ELF:
208 return std::make_unique<AppLoader_ELF>(std::move(file)); 208 return std::make_unique<AppLoader_ELF>(std::move(file));
@@ -221,7 +221,8 @@ static std::unique_ptr<AppLoader> GetFileLoader(FileSys::VirtualFile file, FileT
221 221
222 // NX XCI (nX Card Image) file format. 222 // NX XCI (nX Card Image) file format.
223 case FileType::XCI: 223 case FileType::XCI:
224 return std::make_unique<AppLoader_XCI>(std::move(file)); 224 return std::make_unique<AppLoader_XCI>(std::move(file), system.GetFileSystemController(),
225 system.GetContentProvider());
225 226
226 // NX NAX (NintendoAesXts) file format. 227 // NX NAX (NintendoAesXts) file format.
227 case FileType::NAX: 228 case FileType::NAX:
@@ -229,7 +230,8 @@ static std::unique_ptr<AppLoader> GetFileLoader(FileSys::VirtualFile file, FileT
229 230
230 // NX NSP (Nintendo Submission Package) file format 231 // NX NSP (Nintendo Submission Package) file format
231 case FileType::NSP: 232 case FileType::NSP:
232 return std::make_unique<AppLoader_NSP>(std::move(file)); 233 return std::make_unique<AppLoader_NSP>(std::move(file), system.GetFileSystemController(),
234 system.GetContentProvider());
233 235
234 // NX KIP (Kernel Internal Process) file format 236 // NX KIP (Kernel Internal Process) file format
235 case FileType::KIP: 237 case FileType::KIP:
@@ -244,20 +246,21 @@ static std::unique_ptr<AppLoader> GetFileLoader(FileSys::VirtualFile file, FileT
244 } 246 }
245} 247}
246 248
247std::unique_ptr<AppLoader> GetLoader(FileSys::VirtualFile file) { 249std::unique_ptr<AppLoader> GetLoader(Core::System& system, FileSys::VirtualFile file) {
248 FileType type = IdentifyFile(file); 250 FileType type = IdentifyFile(file);
249 FileType filename_type = GuessFromFilename(file->GetName()); 251 const FileType filename_type = GuessFromFilename(file->GetName());
250 252
251 // Special case: 00 is either a NCA or NAX. 253 // Special case: 00 is either a NCA or NAX.
252 if (type != filename_type && !(file->GetName() == "00" && type == FileType::NAX)) { 254 if (type != filename_type && !(file->GetName() == "00" && type == FileType::NAX)) {
253 LOG_WARNING(Loader, "File {} has a different type than its extension.", file->GetName()); 255 LOG_WARNING(Loader, "File {} has a different type than its extension.", file->GetName());
254 if (FileType::Unknown == type) 256 if (FileType::Unknown == type) {
255 type = filename_type; 257 type = filename_type;
258 }
256 } 259 }
257 260
258 LOG_DEBUG(Loader, "Loading file {} as {}...", file->GetName(), GetFileTypeString(type)); 261 LOG_DEBUG(Loader, "Loading file {} as {}...", file->GetName(), GetFileTypeString(type));
259 262
260 return GetFileLoader(std::move(file), type); 263 return GetFileLoader(system, std::move(file), type);
261} 264}
262 265
263} // namespace Loader 266} // namespace Loader
diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h
index ac60b097a..8dc2d7615 100644
--- a/src/core/loader/loader.h
+++ b/src/core/loader/loader.h
@@ -290,9 +290,12 @@ protected:
290 290
291/** 291/**
292 * Identifies a bootable file and return a suitable loader 292 * Identifies a bootable file and return a suitable loader
293 * @param file The bootable file 293 *
294 * @return the best loader for this file 294 * @param system The system context.
295 * @param file The bootable file.
296 *
297 * @return the best loader for this file.
295 */ 298 */
296std::unique_ptr<AppLoader> GetLoader(FileSys::VirtualFile file); 299std::unique_ptr<AppLoader> GetLoader(Core::System& system, FileSys::VirtualFile file);
297 300
298} // namespace Loader 301} // namespace Loader
diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp
index 497f438a1..aa85c1a29 100644
--- a/src/core/loader/nso.cpp
+++ b/src/core/loader/nso.cpp
@@ -149,7 +149,7 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process, Core::S
149 // Apply cheats if they exist and the program has a valid title ID 149 // Apply cheats if they exist and the program has a valid title ID
150 if (pm) { 150 if (pm) {
151 system.SetCurrentProcessBuildID(nso_header.build_id); 151 system.SetCurrentProcessBuildID(nso_header.build_id);
152 const auto cheats = pm->CreateCheatList(system, nso_header.build_id); 152 const auto cheats = pm->CreateCheatList(nso_header.build_id);
153 if (!cheats.empty()) { 153 if (!cheats.empty()) {
154 system.RegisterCheatList(cheats, nso_header.build_id, load_base, image_size); 154 system.RegisterCheatList(cheats, nso_header.build_id, load_base, image_size);
155 } 155 }
diff --git a/src/core/loader/nsp.cpp b/src/core/loader/nsp.cpp
index 15e528fa8..e821937fd 100644
--- a/src/core/loader/nsp.cpp
+++ b/src/core/loader/nsp.cpp
@@ -21,26 +21,33 @@
21 21
22namespace Loader { 22namespace Loader {
23 23
24AppLoader_NSP::AppLoader_NSP(FileSys::VirtualFile file) 24AppLoader_NSP::AppLoader_NSP(FileSys::VirtualFile file,
25 const Service::FileSystem::FileSystemController& fsc,
26 const FileSys::ContentProvider& content_provider)
25 : AppLoader(file), nsp(std::make_unique<FileSys::NSP>(file)), 27 : AppLoader(file), nsp(std::make_unique<FileSys::NSP>(file)),
26 title_id(nsp->GetProgramTitleID()) { 28 title_id(nsp->GetProgramTitleID()) {
27 29
28 if (nsp->GetStatus() != ResultStatus::Success) 30 if (nsp->GetStatus() != ResultStatus::Success) {
29 return; 31 return;
32 }
30 33
31 if (nsp->IsExtractedType()) { 34 if (nsp->IsExtractedType()) {
32 secondary_loader = std::make_unique<AppLoader_DeconstructedRomDirectory>(nsp->GetExeFS()); 35 secondary_loader = std::make_unique<AppLoader_DeconstructedRomDirectory>(nsp->GetExeFS());
33 } else { 36 } else {
34 const auto control_nca = 37 const auto control_nca =
35 nsp->GetNCA(nsp->GetProgramTitleID(), FileSys::ContentRecordType::Control); 38 nsp->GetNCA(nsp->GetProgramTitleID(), FileSys::ContentRecordType::Control);
36 if (control_nca == nullptr || control_nca->GetStatus() != ResultStatus::Success) 39 if (control_nca == nullptr || control_nca->GetStatus() != ResultStatus::Success) {
37 return; 40 return;
41 }
38 42
39 std::tie(nacp_file, icon_file) = 43 std::tie(nacp_file, icon_file) = [this, &content_provider, &control_nca, &fsc] {
40 FileSys::PatchManager(nsp->GetProgramTitleID()).ParseControlNCA(*control_nca); 44 const FileSys::PatchManager pm{nsp->GetProgramTitleID(), fsc, content_provider};
45 return pm.ParseControlNCA(*control_nca);
46 }();
41 47
42 if (title_id == 0) 48 if (title_id == 0) {
43 return; 49 return;
50 }
44 51
45 secondary_loader = std::make_unique<AppLoader_NCA>( 52 secondary_loader = std::make_unique<AppLoader_NCA>(
46 nsp->GetNCAFile(title_id, FileSys::ContentRecordType::Program)); 53 nsp->GetNCAFile(title_id, FileSys::ContentRecordType::Program));
diff --git a/src/core/loader/nsp.h b/src/core/loader/nsp.h
index b27deb686..36e8e3533 100644
--- a/src/core/loader/nsp.h
+++ b/src/core/loader/nsp.h
@@ -9,15 +9,16 @@
9#include "core/file_sys/vfs.h" 9#include "core/file_sys/vfs.h"
10#include "core/loader/loader.h" 10#include "core/loader/loader.h"
11 11
12namespace Core {
13class System;
14}
15
16namespace FileSys { 12namespace FileSys {
13class ContentProvider;
17class NACP; 14class NACP;
18class NSP; 15class NSP;
19} // namespace FileSys 16} // namespace FileSys
20 17
18namespace Service::FileSystem {
19class FileSystemController;
20}
21
21namespace Loader { 22namespace Loader {
22 23
23class AppLoader_NCA; 24class AppLoader_NCA;
@@ -25,7 +26,9 @@ class AppLoader_NCA;
25/// Loads an XCI file 26/// Loads an XCI file
26class AppLoader_NSP final : public AppLoader { 27class AppLoader_NSP final : public AppLoader {
27public: 28public:
28 explicit AppLoader_NSP(FileSys::VirtualFile file); 29 explicit AppLoader_NSP(FileSys::VirtualFile file,
30 const Service::FileSystem::FileSystemController& fsc,
31 const FileSys::ContentProvider& content_provider);
29 ~AppLoader_NSP() override; 32 ~AppLoader_NSP() override;
30 33
31 /** 34 /**
diff --git a/src/core/loader/xci.cpp b/src/core/loader/xci.cpp
index 25e83af0f..536e721fc 100644
--- a/src/core/loader/xci.cpp
+++ b/src/core/loader/xci.cpp
@@ -20,18 +20,24 @@
20 20
21namespace Loader { 21namespace Loader {
22 22
23AppLoader_XCI::AppLoader_XCI(FileSys::VirtualFile file) 23AppLoader_XCI::AppLoader_XCI(FileSys::VirtualFile file,
24 const Service::FileSystem::FileSystemController& fsc,
25 const FileSys::ContentProvider& content_provider)
24 : AppLoader(file), xci(std::make_unique<FileSys::XCI>(file)), 26 : AppLoader(file), xci(std::make_unique<FileSys::XCI>(file)),
25 nca_loader(std::make_unique<AppLoader_NCA>(xci->GetProgramNCAFile())) { 27 nca_loader(std::make_unique<AppLoader_NCA>(xci->GetProgramNCAFile())) {
26 if (xci->GetStatus() != ResultStatus::Success) 28 if (xci->GetStatus() != ResultStatus::Success) {
27 return; 29 return;
30 }
28 31
29 const auto control_nca = xci->GetNCAByType(FileSys::NCAContentType::Control); 32 const auto control_nca = xci->GetNCAByType(FileSys::NCAContentType::Control);
30 if (control_nca == nullptr || control_nca->GetStatus() != ResultStatus::Success) 33 if (control_nca == nullptr || control_nca->GetStatus() != ResultStatus::Success) {
31 return; 34 return;
35 }
32 36
33 std::tie(nacp_file, icon_file) = 37 std::tie(nacp_file, icon_file) = [this, &content_provider, &control_nca, &fsc] {
34 FileSys::PatchManager(xci->GetProgramTitleID()).ParseControlNCA(*control_nca); 38 const FileSys::PatchManager pm{xci->GetProgramTitleID(), fsc, content_provider};
39 return pm.ParseControlNCA(*control_nca);
40 }();
35} 41}
36 42
37AppLoader_XCI::~AppLoader_XCI() = default; 43AppLoader_XCI::~AppLoader_XCI() = default;
diff --git a/src/core/loader/xci.h b/src/core/loader/xci.h
index 04aea286f..6dc1f9243 100644
--- a/src/core/loader/xci.h
+++ b/src/core/loader/xci.h
@@ -9,15 +9,16 @@
9#include "core/file_sys/vfs.h" 9#include "core/file_sys/vfs.h"
10#include "core/loader/loader.h" 10#include "core/loader/loader.h"
11 11
12namespace Core {
13class System;
14}
15
16namespace FileSys { 12namespace FileSys {
13class ContentProvider;
17class NACP; 14class NACP;
18class XCI; 15class XCI;
19} // namespace FileSys 16} // namespace FileSys
20 17
18namespace Service::FileSystem {
19class FileSystemController;
20}
21
21namespace Loader { 22namespace Loader {
22 23
23class AppLoader_NCA; 24class AppLoader_NCA;
@@ -25,7 +26,9 @@ class AppLoader_NCA;
25/// Loads an XCI file 26/// Loads an XCI file
26class AppLoader_XCI final : public AppLoader { 27class AppLoader_XCI final : public AppLoader {
27public: 28public:
28 explicit AppLoader_XCI(FileSys::VirtualFile file); 29 explicit AppLoader_XCI(FileSys::VirtualFile file,
30 const Service::FileSystem::FileSystemController& fsc,
31 const FileSys::ContentProvider& content_provider);
29 ~AppLoader_XCI() override; 32 ~AppLoader_XCI() override;
30 33
31 /** 34 /**
diff --git a/src/core/telemetry_session.cpp b/src/core/telemetry_session.cpp
index e0908186b..d11b15f38 100644
--- a/src/core/telemetry_session.cpp
+++ b/src/core/telemetry_session.cpp
@@ -147,7 +147,9 @@ TelemetrySession::~TelemetrySession() {
147 } 147 }
148} 148}
149 149
150void TelemetrySession::AddInitialInfo(Loader::AppLoader& app_loader) { 150void TelemetrySession::AddInitialInfo(Loader::AppLoader& app_loader,
151 const Service::FileSystem::FileSystemController& fsc,
152 const FileSys::ContentProvider& content_provider) {
151 // Log one-time top-level information 153 // Log one-time top-level information
152 AddField(Telemetry::FieldType::None, "TelemetryId", GetTelemetryId()); 154 AddField(Telemetry::FieldType::None, "TelemetryId", GetTelemetryId());
153 155
@@ -167,7 +169,10 @@ void TelemetrySession::AddInitialInfo(Loader::AppLoader& app_loader) {
167 app_loader.ReadTitle(name); 169 app_loader.ReadTitle(name);
168 170
169 if (name.empty()) { 171 if (name.empty()) {
170 const auto metadata = FileSys::PatchManager(program_id).GetControlMetadata(); 172 const auto metadata = [&content_provider, &fsc, program_id] {
173 const FileSys::PatchManager pm{program_id, fsc, content_provider};
174 return pm.GetControlMetadata();
175 }();
171 if (metadata.first != nullptr) { 176 if (metadata.first != nullptr) {
172 name = metadata.first->GetApplicationName(); 177 name = metadata.first->GetApplicationName();
173 } 178 }
diff --git a/src/core/telemetry_session.h b/src/core/telemetry_session.h
index 66789d4bd..6f3d45bea 100644
--- a/src/core/telemetry_session.h
+++ b/src/core/telemetry_session.h
@@ -7,10 +7,18 @@
7#include <string> 7#include <string>
8#include "common/telemetry.h" 8#include "common/telemetry.h"
9 9
10namespace FileSys {
11class ContentProvider;
12}
13
10namespace Loader { 14namespace Loader {
11class AppLoader; 15class AppLoader;
12} 16}
13 17
18namespace Service::FileSystem {
19class FileSystemController;
20}
21
14namespace Core { 22namespace Core {
15 23
16/** 24/**
@@ -40,10 +48,14 @@ public:
40 * - Title file format 48 * - Title file format
41 * - Miscellaneous settings values. 49 * - Miscellaneous settings values.
42 * 50 *
43 * @param app_loader The application loader to use to retrieve 51 * @param app_loader The application loader to use to retrieve
44 * title-specific information. 52 * title-specific information.
53 * @param fsc Filesystem controller to use to retrieve info.
54 * @param content_provider Content provider to use to retrieve info.
45 */ 55 */
46 void AddInitialInfo(Loader::AppLoader& app_loader); 56 void AddInitialInfo(Loader::AppLoader& app_loader,
57 const Service::FileSystem::FileSystemController& fsc,
58 const FileSys::ContentProvider& content_provider);
47 59
48 /** 60 /**
49 * Wrapper around the Telemetry::FieldCollection::AddField method. 61 * Wrapper around the Telemetry::FieldCollection::AddField method.
diff --git a/src/yuzu/configuration/configure_per_game.cpp b/src/yuzu/configuration/configure_per_game.cpp
index 81464dd37..8eac3bd9d 100644
--- a/src/yuzu/configuration/configure_per_game.cpp
+++ b/src/yuzu/configuration/configure_per_game.cpp
@@ -16,6 +16,7 @@
16 16
17#include "common/common_paths.h" 17#include "common/common_paths.h"
18#include "common/file_util.h" 18#include "common/file_util.h"
19#include "core/core.h"
19#include "core/file_sys/control_metadata.h" 20#include "core/file_sys/control_metadata.h"
20#include "core/file_sys/patch_manager.h" 21#include "core/file_sys/patch_manager.h"
21#include "core/file_sys/xts_archive.h" 22#include "core/file_sys/xts_archive.h"
@@ -89,9 +90,11 @@ void ConfigurePerGame::LoadConfiguration() {
89 ui->display_title_id->setText( 90 ui->display_title_id->setText(
90 QStringLiteral("%1").arg(title_id, 16, 16, QLatin1Char{'0'}).toUpper()); 91 QStringLiteral("%1").arg(title_id, 16, 16, QLatin1Char{'0'}).toUpper());
91 92
92 FileSys::PatchManager pm{title_id}; 93 auto& system = Core::System::GetInstance();
94 const FileSys::PatchManager pm{title_id, system.GetFileSystemController(),
95 system.GetContentProvider()};
93 const auto control = pm.GetControlMetadata(); 96 const auto control = pm.GetControlMetadata();
94 const auto loader = Loader::GetLoader(file); 97 const auto loader = Loader::GetLoader(system, file);
95 98
96 if (control.first != nullptr) { 99 if (control.first != nullptr) {
97 ui->display_version->setText(QString::fromStdString(control.first->GetVersionString())); 100 ui->display_version->setText(QString::fromStdString(control.first->GetVersionString()));
diff --git a/src/yuzu/configuration/configure_per_game_addons.cpp b/src/yuzu/configuration/configure_per_game_addons.cpp
index 793fd8975..cdeeec01c 100644
--- a/src/yuzu/configuration/configure_per_game_addons.cpp
+++ b/src/yuzu/configuration/configure_per_game_addons.cpp
@@ -112,8 +112,10 @@ void ConfigurePerGameAddons::LoadConfiguration() {
112 return; 112 return;
113 } 113 }
114 114
115 FileSys::PatchManager pm{title_id}; 115 auto& system = Core::System::GetInstance();
116 const auto loader = Loader::GetLoader(file); 116 const FileSys::PatchManager pm{title_id, system.GetFileSystemController(),
117 system.GetContentProvider()};
118 const auto loader = Loader::GetLoader(system, file);
117 119
118 FileSys::VirtualFile update_raw; 120 FileSys::VirtualFile update_raw;
119 loader->ReadUpdateRaw(update_raw); 121 loader->ReadUpdateRaw(update_raw);
diff --git a/src/yuzu/game_list_worker.cpp b/src/yuzu/game_list_worker.cpp
index e0ce45fd9..23643aea2 100644
--- a/src/yuzu/game_list_worker.cpp
+++ b/src/yuzu/game_list_worker.cpp
@@ -235,12 +235,11 @@ GameListWorker::~GameListWorker() = default;
235void GameListWorker::AddTitlesToGameList(GameListDir* parent_dir) { 235void GameListWorker::AddTitlesToGameList(GameListDir* parent_dir) {
236 using namespace FileSys; 236 using namespace FileSys;
237 237
238 const auto& cache = 238 auto& system = Core::System::GetInstance();
239 dynamic_cast<ContentProviderUnion&>(Core::System::GetInstance().GetContentProvider()); 239 const auto& cache = dynamic_cast<ContentProviderUnion&>(system.GetContentProvider());
240 240
241 std::vector<std::pair<ContentProviderUnionSlot, ContentProviderEntry>> installed_games; 241 auto installed_games = cache.ListEntriesFilterOrigin(std::nullopt, TitleType::Application,
242 installed_games = cache.ListEntriesFilterOrigin(std::nullopt, TitleType::Application, 242 ContentRecordType::Program);
243 ContentRecordType::Program);
244 243
245 if (parent_dir->type() == static_cast<int>(GameListItemType::SdmcDir)) { 244 if (parent_dir->type() == static_cast<int>(GameListItemType::SdmcDir)) {
246 installed_games = cache.ListEntriesFilterOrigin( 245 installed_games = cache.ListEntriesFilterOrigin(
@@ -254,23 +253,27 @@ void GameListWorker::AddTitlesToGameList(GameListDir* parent_dir) {
254 } 253 }
255 254
256 for (const auto& [slot, game] : installed_games) { 255 for (const auto& [slot, game] : installed_games) {
257 if (slot == ContentProviderUnionSlot::FrontendManual) 256 if (slot == ContentProviderUnionSlot::FrontendManual) {
258 continue; 257 continue;
258 }
259 259
260 const auto file = cache.GetEntryUnparsed(game.title_id, game.type); 260 const auto file = cache.GetEntryUnparsed(game.title_id, game.type);
261 std::unique_ptr<Loader::AppLoader> loader = Loader::GetLoader(file); 261 std::unique_ptr<Loader::AppLoader> loader = Loader::GetLoader(system, file);
262 if (!loader) 262 if (!loader) {
263 continue; 263 continue;
264 }
264 265
265 std::vector<u8> icon; 266 std::vector<u8> icon;
266 std::string name; 267 std::string name;
267 u64 program_id = 0; 268 u64 program_id = 0;
268 loader->ReadProgramId(program_id); 269 loader->ReadProgramId(program_id);
269 270
270 const PatchManager patch{program_id}; 271 const PatchManager patch{program_id, system.GetFileSystemController(),
272 system.GetContentProvider()};
271 const auto control = cache.GetEntry(game.title_id, ContentRecordType::Control); 273 const auto control = cache.GetEntry(game.title_id, ContentRecordType::Control);
272 if (control != nullptr) 274 if (control != nullptr) {
273 GetMetadataFromControlNCA(patch, *control, icon, name); 275 GetMetadataFromControlNCA(patch, *control, icon, name);
276 }
274 277
275 emit EntryReady(MakeGameListEntry(file->GetFullPath(), name, icon, *loader, program_id, 278 emit EntryReady(MakeGameListEntry(file->GetFullPath(), name, icon, *loader, program_id,
276 compatibility_list, patch), 279 compatibility_list, patch),
@@ -280,9 +283,11 @@ void GameListWorker::AddTitlesToGameList(GameListDir* parent_dir) {
280 283
281void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_path, 284void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_path,
282 unsigned int recursion, GameListDir* parent_dir) { 285 unsigned int recursion, GameListDir* parent_dir) {
283 const auto callback = [this, target, recursion, 286 auto& system = Core::System::GetInstance();
284 parent_dir](u64* num_entries_out, const std::string& directory, 287
285 const std::string& virtual_name) -> bool { 288 const auto callback = [this, target, recursion, parent_dir,
289 &system](u64* num_entries_out, const std::string& directory,
290 const std::string& virtual_name) -> bool {
286 if (stop_processing) { 291 if (stop_processing) {
287 // Breaks the callback loop. 292 // Breaks the callback loop.
288 return false; 293 return false;
@@ -293,7 +298,7 @@ void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_pa
293 if (!is_dir && 298 if (!is_dir &&
294 (HasSupportedFileExtension(physical_name) || IsExtractedNCAMain(physical_name))) { 299 (HasSupportedFileExtension(physical_name) || IsExtractedNCAMain(physical_name))) {
295 const auto file = vfs->OpenFile(physical_name, FileSys::Mode::Read); 300 const auto file = vfs->OpenFile(physical_name, FileSys::Mode::Read);
296 auto loader = Loader::GetLoader(file); 301 auto loader = Loader::GetLoader(system, file);
297 if (!loader) { 302 if (!loader) {
298 return true; 303 return true;
299 } 304 }
@@ -331,7 +336,8 @@ void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_pa
331 std::string name = " "; 336 std::string name = " ";
332 [[maybe_unused]] const auto res3 = loader->ReadTitle(name); 337 [[maybe_unused]] const auto res3 = loader->ReadTitle(name);
333 338
334 const FileSys::PatchManager patch{program_id}; 339 const FileSys::PatchManager patch{program_id, system.GetFileSystemController(),
340 system.GetContentProvider()};
335 341
336 emit EntryReady(MakeGameListEntry(physical_name, name, icon, *loader, program_id, 342 emit EntryReady(MakeGameListEntry(physical_name, name, icon, *loader, program_id,
337 compatibility_list, patch), 343 compatibility_list, patch),
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 9dabd8889..e704cc656 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -1090,9 +1090,9 @@ void GMainWindow::BootGame(const QString& filename) {
1090 StoreRecentFile(filename); // Put the filename on top of the list 1090 StoreRecentFile(filename); // Put the filename on top of the list
1091 1091
1092 u64 title_id{0}; 1092 u64 title_id{0};
1093 1093 auto& system = Core::System::GetInstance();
1094 const auto v_file = Core::GetGameFileFromPath(vfs, filename.toUtf8().constData()); 1094 const auto v_file = Core::GetGameFileFromPath(vfs, filename.toUtf8().constData());
1095 const auto loader = Loader::GetLoader(v_file); 1095 const auto loader = Loader::GetLoader(system, v_file);
1096 if (!(loader == nullptr || loader->ReadProgramId(title_id) != Loader::ResultStatus::Success)) { 1096 if (!(loader == nullptr || loader->ReadProgramId(title_id) != Loader::ResultStatus::Success)) {
1097 // Load per game settings 1097 // Load per game settings
1098 Config per_game_config(fmt::format("{:016X}", title_id), Config::ConfigType::PerGameConfig); 1098 Config per_game_config(fmt::format("{:016X}", title_id), Config::ConfigType::PerGameConfig);
@@ -1144,9 +1144,13 @@ void GMainWindow::BootGame(const QString& filename) {
1144 1144
1145 std::string title_name; 1145 std::string title_name;
1146 std::string title_version; 1146 std::string title_version;
1147 const auto res = Core::System::GetInstance().GetGameName(title_name); 1147 const auto res = system.GetGameName(title_name);
1148 1148
1149 const auto metadata = FileSys::PatchManager(title_id).GetControlMetadata(); 1149 const auto metadata = [&system, title_id] {
1150 const FileSys::PatchManager pm(title_id, system.GetFileSystemController(),
1151 system.GetContentProvider());
1152 return pm.GetControlMetadata();
1153 }();
1150 if (metadata.first != nullptr) { 1154 if (metadata.first != nullptr) {
1151 title_version = metadata.first->GetVersionString(); 1155 title_version = metadata.first->GetVersionString();
1152 title_name = metadata.first->GetApplicationName(); 1156 title_name = metadata.first->GetApplicationName();
@@ -1157,7 +1161,7 @@ void GMainWindow::BootGame(const QString& filename) {
1157 LOG_INFO(Frontend, "Booting game: {:016X} | {} | {}", title_id, title_name, title_version); 1161 LOG_INFO(Frontend, "Booting game: {:016X} | {} | {}", title_id, title_name, title_version);
1158 UpdateWindowTitle(title_name, title_version); 1162 UpdateWindowTitle(title_name, title_version);
1159 1163
1160 loading_screen->Prepare(Core::System::GetInstance().GetAppLoader()); 1164 loading_screen->Prepare(system.GetAppLoader());
1161 loading_screen->show(); 1165 loading_screen->show();
1162 1166
1163 emulation_running = true; 1167 emulation_running = true;
@@ -1276,16 +1280,18 @@ void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target
1276 const std::string& game_path) { 1280 const std::string& game_path) {
1277 std::string path; 1281 std::string path;
1278 QString open_target; 1282 QString open_target;
1283 auto& system = Core::System::GetInstance();
1279 1284
1280 const auto [user_save_size, device_save_size] = [this, &program_id, &game_path] { 1285 const auto [user_save_size, device_save_size] = [this, &game_path, &program_id, &system] {
1281 FileSys::PatchManager pm{program_id}; 1286 const FileSys::PatchManager pm{program_id, system.GetFileSystemController(),
1287 system.GetContentProvider()};
1282 const auto control = pm.GetControlMetadata().first; 1288 const auto control = pm.GetControlMetadata().first;
1283 if (control != nullptr) { 1289 if (control != nullptr) {
1284 return std::make_pair(control->GetDefaultNormalSaveSize(), 1290 return std::make_pair(control->GetDefaultNormalSaveSize(),
1285 control->GetDeviceSaveDataSize()); 1291 control->GetDeviceSaveDataSize());
1286 } else { 1292 } else {
1287 const auto file = Core::GetGameFileFromPath(vfs, game_path); 1293 const auto file = Core::GetGameFileFromPath(vfs, game_path);
1288 const auto loader = Loader::GetLoader(file); 1294 const auto loader = Loader::GetLoader(system, file);
1289 1295
1290 FileSys::NACP nacp{}; 1296 FileSys::NACP nacp{};
1291 loader->ReadControlData(nacp); 1297 loader->ReadControlData(nacp);
@@ -1612,7 +1618,8 @@ void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_pa
1612 "cancelled the operation.")); 1618 "cancelled the operation."));
1613 }; 1619 };
1614 1620
1615 const auto loader = Loader::GetLoader(vfs->OpenFile(game_path, FileSys::Mode::Read)); 1621 auto& system = Core::System::GetInstance();
1622 const auto loader = Loader::GetLoader(system, vfs->OpenFile(game_path, FileSys::Mode::Read));
1616 if (loader == nullptr) { 1623 if (loader == nullptr) {
1617 failed(); 1624 failed();
1618 return; 1625 return;
@@ -1624,7 +1631,7 @@ void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_pa
1624 return; 1631 return;
1625 } 1632 }
1626 1633
1627 const auto& installed = Core::System::GetInstance().GetContentProvider(); 1634 const auto& installed = system.GetContentProvider();
1628 const auto romfs_title_id = SelectRomFSDumpTarget(installed, program_id); 1635 const auto romfs_title_id = SelectRomFSDumpTarget(installed, program_id);
1629 1636
1630 if (!romfs_title_id) { 1637 if (!romfs_title_id) {
@@ -1639,7 +1646,7 @@ void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_pa
1639 1646
1640 if (*romfs_title_id == program_id) { 1647 if (*romfs_title_id == program_id) {
1641 const u64 ivfc_offset = loader->ReadRomFSIVFCOffset(); 1648 const u64 ivfc_offset = loader->ReadRomFSIVFCOffset();
1642 FileSys::PatchManager pm{program_id}; 1649 const FileSys::PatchManager pm{program_id, system.GetFileSystemController(), installed};
1643 romfs = pm.PatchRomFS(file, ivfc_offset, FileSys::ContentRecordType::Program); 1650 romfs = pm.PatchRomFS(file, ivfc_offset, FileSys::ContentRecordType::Program);
1644 } else { 1651 } else {
1645 romfs = installed.GetEntry(*romfs_title_id, FileSys::ContentRecordType::Data)->GetRomFS(); 1652 romfs = installed.GetEntry(*romfs_title_id, FileSys::ContentRecordType::Data)->GetRomFS();
@@ -1756,7 +1763,8 @@ void GMainWindow::OnGameListShowList(bool show) {
1756void GMainWindow::OnGameListOpenPerGameProperties(const std::string& file) { 1763void GMainWindow::OnGameListOpenPerGameProperties(const std::string& file) {
1757 u64 title_id{}; 1764 u64 title_id{};
1758 const auto v_file = Core::GetGameFileFromPath(vfs, file); 1765 const auto v_file = Core::GetGameFileFromPath(vfs, file);
1759 const auto loader = Loader::GetLoader(v_file); 1766 const auto loader = Loader::GetLoader(Core::System::GetInstance(), v_file);
1767
1760 if (loader == nullptr || loader->ReadProgramId(title_id) != Loader::ResultStatus::Success) { 1768 if (loader == nullptr || loader->ReadProgramId(title_id) != Loader::ResultStatus::Success) {
1761 QMessageBox::information(this, tr("Properties"), 1769 QMessageBox::information(this, tr("Properties"),
1762 tr("The game properties could not be loaded.")); 1770 tr("The game properties could not be loaded."));