From 6f8a06bac58790d20dae3c1adb4de3b441f07b30 Mon Sep 17 00:00:00 2001
From: Lioncash <mathew1800@gmail.com>
Date: Wed, 18 Nov 2020 07:53:10 -0500
Subject: [PATCH] patch_manager: Remove usages of the global system instance

With this, only 19 usages of the global system instance remain within
the core library.

We're almost there.
---
 src/core/core.cpp                             |  6 +-
 src/core/file_sys/patch_manager.cpp           | 81 +++++++++----------
 src/core/file_sys/patch_manager.h             | 13 ++-
 src/core/file_sys/romfs_factory.cpp           |  6 +-
 src/core/hle/service/acc/acc.cpp              |  6 +-
 src/core/hle/service/am/am.cpp                | 14 +++-
 src/core/hle/service/aoc/aoc_u.cpp            |  3 +-
 .../hle/service/filesystem/filesystem.cpp     |  7 +-
 src/core/hle/service/filesystem/fsp_srv.cpp   |  8 +-
 src/core/hle/service/filesystem/fsp_srv.h     |  7 +-
 src/core/hle/service/ns/ns.cpp                | 24 +++---
 src/core/hle/service/ns/ns.h                  | 28 +++++--
 .../loader/deconstructed_rom_directory.cpp    |  6 +-
 src/core/loader/loader.cpp                    | 27 ++++---
 src/core/loader/loader.h                      |  9 ++-
 src/core/loader/nso.cpp                       |  2 +-
 src/core/loader/nsp.cpp                       | 19 +++--
 src/core/loader/nsp.h                         | 13 +--
 src/core/loader/xci.cpp                       | 16 ++--
 src/core/loader/xci.h                         | 13 +--
 src/core/telemetry_session.cpp                |  9 ++-
 src/core/telemetry_session.h                  | 18 ++++-
 src/yuzu/configuration/configure_per_game.cpp |  7 +-
 .../configure_per_game_addons.cpp             |  6 +-
 src/yuzu/game_list_worker.cpp                 | 36 +++++----
 src/yuzu/main.cpp                             | 32 +++++---
 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 {
 
     ResultStatus Load(System& system, Frontend::EmuWindow& emu_window,
                       const std::string& filepath) {
-        app_loader = Loader::GetLoader(GetGameFileFromPath(virtual_filesystem, filepath));
+        app_loader = Loader::GetLoader(system, GetGameFileFromPath(virtual_filesystem, filepath));
         if (!app_loader) {
             LOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath);
             return ResultStatus::ErrorGetLoader;
@@ -224,7 +224,7 @@ struct System::Impl {
             return init_result;
         }
 
-        telemetry_session->AddInitialInfo(*app_loader);
+        telemetry_session->AddInitialInfo(*app_loader, fs_controller, *content_provider);
         auto main_process =
             Kernel::Process::Create(system, "main", Kernel::Process::ProcessType::Userland);
         const auto [load_result, load_parameters] = app_loader->Load(*main_process, system);
@@ -338,7 +338,7 @@ struct System::Impl {
         Service::Glue::ApplicationLaunchProperty launch{};
         launch.title_id = process.GetTitleID();
 
-        FileSys::PatchManager pm{launch.title_id};
+        FileSys::PatchManager pm{launch.title_id, fs_controller, *content_provider};
         launch.version = pm.GetGameVersion().value_or(0);
 
         // 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) {
 }
 } // Anonymous namespace
 
-PatchManager::PatchManager(u64 title_id) : title_id(title_id) {}
+PatchManager::PatchManager(u64 title_id_,
+                           const Service::FileSystem::FileSystemController& fs_controller_,
+                           const ContentProvider& content_provider_)
+    : title_id{title_id_}, fs_controller{fs_controller_}, content_provider{content_provider_} {}
 
 PatchManager::~PatchManager() = default;
 
@@ -128,34 +131,30 @@ VirtualDir PatchManager::PatchExeFS(VirtualDir exefs) const {
 
     if (Settings::values.dump_exefs) {
         LOG_INFO(Loader, "Dumping ExeFS for title_id={:016X}", title_id);
-        const auto dump_dir =
-            Core::System::GetInstance().GetFileSystemController().GetModificationDumpRoot(title_id);
+        const auto dump_dir = fs_controller.GetModificationDumpRoot(title_id);
         if (dump_dir != nullptr) {
             const auto exefs_dir = GetOrCreateDirectoryRelative(dump_dir, "/exefs");
             VfsRawCopyD(exefs, exefs_dir);
         }
     }
 
-    const auto& installed = Core::System::GetInstance().GetContentProvider();
-
     const auto& disabled = Settings::values.disabled_addons[title_id];
     const auto update_disabled =
         std::find(disabled.cbegin(), disabled.cend(), "Update") != disabled.cend();
 
     // Game Updates
     const auto update_tid = GetUpdateTitleID(title_id);
-    const auto update = installed.GetEntry(update_tid, ContentRecordType::Program);
+    const auto update = content_provider.GetEntry(update_tid, ContentRecordType::Program);
 
     if (!update_disabled && update != nullptr && update->GetExeFS() != nullptr &&
         update->GetStatus() == Loader::ResultStatus::ErrorMissingBKTRBaseRomFS) {
         LOG_INFO(Loader, "    ExeFS: Update ({}) applied successfully",
-                 FormatTitleVersion(installed.GetEntryVersion(update_tid).value_or(0)));
+                 FormatTitleVersion(content_provider.GetEntryVersion(update_tid).value_or(0)));
         exefs = update->GetExeFS();
     }
 
     // LayeredExeFS
-    const auto load_dir =
-        Core::System::GetInstance().GetFileSystemController().GetModificationLoadRoot(title_id);
+    const auto load_dir = fs_controller.GetModificationLoadRoot(title_id);
     if (load_dir != nullptr && load_dir->GetSize() > 0) {
         auto patch_dirs = load_dir->GetSubdirectories();
         std::sort(
@@ -241,8 +240,7 @@ std::vector<u8> PatchManager::PatchNSO(const std::vector<u8>& nso, const std::st
     if (Settings::values.dump_nso) {
         LOG_INFO(Loader, "Dumping NSO for name={}, build_id={}, title_id={:016X}", name, build_id,
                  title_id);
-        const auto dump_dir =
-            Core::System::GetInstance().GetFileSystemController().GetModificationDumpRoot(title_id);
+        const auto dump_dir = fs_controller.GetModificationDumpRoot(title_id);
         if (dump_dir != nullptr) {
             const auto nso_dir = GetOrCreateDirectoryRelative(dump_dir, "/nso");
             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
 
     LOG_INFO(Loader, "Patching NSO for name={}, build_id={}", name, build_id);
 
-    const auto load_dir =
-        Core::System::GetInstance().GetFileSystemController().GetModificationLoadRoot(title_id);
+    const auto load_dir = fs_controller.GetModificationLoadRoot(title_id);
     if (load_dir == nullptr) {
         LOG_ERROR(Loader, "Cannot load mods for invalid title_id={:016X}", title_id);
         return nso;
@@ -298,8 +295,7 @@ bool PatchManager::HasNSOPatch(const BuildID& build_id_) const {
 
     LOG_INFO(Loader, "Querying NSO patch existence for build_id={}", build_id);
 
-    const auto load_dir =
-        Core::System::GetInstance().GetFileSystemController().GetModificationLoadRoot(title_id);
+    const auto load_dir = fs_controller.GetModificationLoadRoot(title_id);
     if (load_dir == nullptr) {
         LOG_ERROR(Loader, "Cannot load mods for invalid title_id={:016X}", title_id);
         return false;
@@ -313,8 +309,8 @@ bool PatchManager::HasNSOPatch(const BuildID& build_id_) const {
 }
 
 std::vector<Core::Memory::CheatEntry> PatchManager::CreateCheatList(
-    const Core::System& system, const BuildID& build_id_) const {
-    const auto load_dir = system.GetFileSystemController().GetModificationLoadRoot(title_id);
+    const BuildID& build_id_) const {
+    const auto load_dir = fs_controller.GetModificationLoadRoot(title_id);
     if (load_dir == nullptr) {
         LOG_ERROR(Loader, "Cannot load mods for invalid title_id={:016X}", title_id);
         return {};
@@ -347,9 +343,9 @@ std::vector<Core::Memory::CheatEntry> PatchManager::CreateCheatList(
     return out;
 }
 
-static void ApplyLayeredFS(VirtualFile& romfs, u64 title_id, ContentRecordType type) {
-    const auto load_dir =
-        Core::System::GetInstance().GetFileSystemController().GetModificationLoadRoot(title_id);
+static void ApplyLayeredFS(VirtualFile& romfs, u64 title_id, ContentRecordType type,
+                           const Service::FileSystem::FileSystemController& fs_controller) {
+    const auto load_dir = fs_controller.GetModificationLoadRoot(title_id);
     if ((type != ContentRecordType::Program && type != ContentRecordType::Data) ||
         load_dir == nullptr || load_dir->GetSize() <= 0) {
         return;
@@ -411,19 +407,19 @@ VirtualFile PatchManager::PatchRomFS(VirtualFile romfs, u64 ivfc_offset, Content
     const auto log_string = fmt::format("Patching RomFS for title_id={:016X}, type={:02X}",
                                         title_id, static_cast<u8>(type));
 
-    if (type == ContentRecordType::Program || type == ContentRecordType::Data)
+    if (type == ContentRecordType::Program || type == ContentRecordType::Data) {
         LOG_INFO(Loader, "{}", log_string);
-    else
+    } else {
         LOG_DEBUG(Loader, "{}", log_string);
+    }
 
-    if (romfs == nullptr)
+    if (romfs == nullptr) {
         return romfs;
-
-    const auto& installed = Core::System::GetInstance().GetContentProvider();
+    }
 
     // Game Updates
     const auto update_tid = GetUpdateTitleID(title_id);
-    const auto update = installed.GetEntryRaw(update_tid, type);
+    const auto update = content_provider.GetEntryRaw(update_tid, type);
 
     const auto& disabled = Settings::values.disabled_addons[title_id];
     const auto update_disabled =
@@ -434,7 +430,7 @@ VirtualFile PatchManager::PatchRomFS(VirtualFile romfs, u64 ivfc_offset, Content
         if (new_nca->GetStatus() == Loader::ResultStatus::Success &&
             new_nca->GetRomFS() != nullptr) {
             LOG_INFO(Loader, "    RomFS: Update ({}) applied successfully",
-                     FormatTitleVersion(installed.GetEntryVersion(update_tid).value_or(0)));
+                     FormatTitleVersion(content_provider.GetEntryVersion(update_tid).value_or(0)));
             romfs = new_nca->GetRomFS();
         }
     } else if (!update_disabled && update_raw != nullptr) {
@@ -447,7 +443,7 @@ VirtualFile PatchManager::PatchRomFS(VirtualFile romfs, u64 ivfc_offset, Content
     }
 
     // LayeredFS
-    ApplyLayeredFS(romfs, title_id, type);
+    ApplyLayeredFS(romfs, title_id, type, fs_controller);
 
     return romfs;
 }
@@ -458,12 +454,11 @@ PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile u
     }
 
     std::map<std::string, std::string, std::less<>> out;
-    const auto& installed = Core::System::GetInstance().GetContentProvider();
     const auto& disabled = Settings::values.disabled_addons[title_id];
 
     // Game Updates
     const auto update_tid = GetUpdateTitleID(title_id);
-    PatchManager update{update_tid};
+    PatchManager update{update_tid, fs_controller, content_provider};
     const auto metadata = update.GetControlMetadata();
     const auto& nacp = metadata.first;
 
@@ -474,8 +469,8 @@ PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile u
     if (nacp != nullptr) {
         out.insert_or_assign(update_label, nacp->GetVersionString());
     } else {
-        if (installed.HasEntry(update_tid, ContentRecordType::Program)) {
-            const auto meta_ver = installed.GetEntryVersion(update_tid);
+        if (content_provider.HasEntry(update_tid, ContentRecordType::Program)) {
+            const auto meta_ver = content_provider.GetEntryVersion(update_tid);
             if (meta_ver.value_or(0) == 0) {
                 out.insert_or_assign(update_label, "");
             } else {
@@ -487,8 +482,7 @@ PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile u
     }
 
     // General Mods (LayeredFS and IPS)
-    const auto mod_dir =
-        Core::System::GetInstance().GetFileSystemController().GetModificationLoadRoot(title_id);
+    const auto mod_dir = fs_controller.GetModificationLoadRoot(title_id);
     if (mod_dir != nullptr && mod_dir->GetSize() > 0) {
         for (const auto& mod : mod_dir->GetSubdirectories()) {
             std::string types;
@@ -532,13 +526,15 @@ PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile u
     }
 
     // DLC
-    const auto dlc_entries = installed.ListEntriesFilter(TitleType::AOC, ContentRecordType::Data);
+    const auto dlc_entries =
+        content_provider.ListEntriesFilter(TitleType::AOC, ContentRecordType::Data);
     std::vector<ContentProviderEntry> dlc_match;
     dlc_match.reserve(dlc_entries.size());
     std::copy_if(dlc_entries.begin(), dlc_entries.end(), std::back_inserter(dlc_match),
-                 [this, &installed](const ContentProviderEntry& entry) {
+                 [this](const ContentProviderEntry& entry) {
                      return (entry.title_id & DLC_BASE_TITLE_ID_MASK) == title_id &&
-                            installed.GetEntry(entry)->GetStatus() == Loader::ResultStatus::Success;
+                            content_provider.GetEntry(entry)->GetStatus() ==
+                                Loader::ResultStatus::Success;
                  });
     if (!dlc_match.empty()) {
         // Ensure sorted so DLC IDs show in order.
@@ -559,19 +555,16 @@ PatchManager::PatchVersionNames PatchManager::GetPatchVersionNames(VirtualFile u
 }
 
 std::optional<u32> PatchManager::GetGameVersion() const {
-    const auto& installed = Core::System::GetInstance().GetContentProvider();
     const auto update_tid = GetUpdateTitleID(title_id);
-    if (installed.HasEntry(update_tid, ContentRecordType::Program)) {
-        return installed.GetEntryVersion(update_tid);
+    if (content_provider.HasEntry(update_tid, ContentRecordType::Program)) {
+        return content_provider.GetEntryVersion(update_tid);
     }
 
-    return installed.GetEntryVersion(title_id);
+    return content_provider.GetEntryVersion(title_id);
 }
 
 PatchManager::Metadata PatchManager::GetControlMetadata() const {
-    const auto& installed = Core::System::GetInstance().GetContentProvider();
-
-    const auto base_control_nca = installed.GetEntry(title_id, ContentRecordType::Control);
+    const auto base_control_nca = content_provider.GetEntry(title_id, ContentRecordType::Control);
     if (base_control_nca == nullptr) {
         return {};
     }
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 {
 class System;
 }
 
+namespace Service::FileSystem {
+class FileSystemController;
+}
+
 namespace FileSys {
 
+class ContentProvider;
 class NCA;
 class NACP;
 
@@ -29,7 +34,9 @@ public:
     using Metadata = std::pair<std::unique_ptr<NACP>, VirtualFile>;
     using PatchVersionNames = std::map<std::string, std::string, std::less<>>;
 
-    explicit PatchManager(u64 title_id);
+    explicit PatchManager(u64 title_id_,
+                          const Service::FileSystem::FileSystemController& fs_controller_,
+                          const ContentProvider& content_provider_);
     ~PatchManager();
 
     [[nodiscard]] u64 GetTitleID() const;
@@ -50,7 +57,7 @@ public:
 
     // Creates a CheatList object with all
     [[nodiscard]] std::vector<Core::Memory::CheatEntry> CreateCheatList(
-        const Core::System& system, const BuildID& build_id) const;
+        const BuildID& build_id) const;
 
     // Currently tracked RomFS patches:
     // - Game Updates
@@ -80,6 +87,8 @@ private:
                                                           const std::string& build_id) const;
 
     u64 title_id;
+    const Service::FileSystem::FileSystemController& fs_controller;
+    const ContentProvider& content_provider;
 };
 
 } // 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) {
 }
 
 ResultVal<VirtualFile> RomFSFactory::OpenCurrentProcess(u64 current_process_title_id) const {
-    if (!updatable)
+    if (!updatable) {
         return MakeResult<VirtualFile>(file);
+    }
 
-    const PatchManager patch_manager(current_process_title_id);
+    const PatchManager patch_manager{current_process_title_id, filesystem_controller,
+                                     content_provider};
     return MakeResult<VirtualFile>(
         patch_manager.PatchRomFS(file, ivfc_offset, ContentRecordType::Program, update_raw));
 }
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
     bool is_locked = false;
 
     if (res != Loader::ResultStatus::Success) {
-        FileSys::PatchManager pm{system.CurrentProcess()->GetTitleID()};
-        auto nacp_unique = pm.GetControlMetadata().first;
+        const FileSys::PatchManager pm{system.CurrentProcess()->GetTitleID(),
+                                       system.GetFileSystemController(),
+                                       system.GetContentProvider()};
+        const auto nacp_unique = pm.GetControlMetadata().first;
 
         if (nacp_unique != nullptr) {
             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) {
     const auto res = [this] {
         const auto title_id = system.CurrentProcess()->GetTitleID();
 
-        FileSys::PatchManager pm{title_id};
+        const FileSys::PatchManager pm{title_id, system.GetFileSystemController(),
+                                       system.GetContentProvider()};
         auto res = pm.GetControlMetadata();
         if (res.first != nullptr) {
             return res;
         }
 
-        FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(title_id)};
+        const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(title_id),
+                                              system.GetFileSystemController(),
+                                              system.GetContentProvider()};
         return pm_update.GetControlMetadata();
     }();
 
@@ -1415,13 +1418,16 @@ void IApplicationFunctions::GetDesiredLanguage(Kernel::HLERequestContext& ctx) {
     const auto res = [this] {
         const auto title_id = system.CurrentProcess()->GetTitleID();
 
-        FileSys::PatchManager pm{title_id};
+        const FileSys::PatchManager pm{title_id, system.GetFileSystemController(),
+                                       system.GetContentProvider()};
         auto res = pm.GetControlMetadata();
         if (res.first != nullptr) {
             return res;
         }
 
-        FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(title_id)};
+        const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(title_id),
+                                              system.GetFileSystemController(),
+                                              system.GetContentProvider()};
         return pm_update.GetControlMetadata();
     }();
 
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) {
     rb.Push(RESULT_SUCCESS);
 
     const auto title_id = system.CurrentProcess()->GetTitleID();
-    FileSys::PatchManager pm{title_id};
+    const FileSys::PatchManager pm{title_id, system.GetFileSystemController(),
+                                   system.GetContentProvider()};
 
     const auto res = pm.GetControlMetadata();
     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
         const auto res = system.GetAppLoader().ReadControlData(nacp);
 
         if (res != Loader::ResultStatus::Success) {
-            FileSys::PatchManager pm{system.CurrentProcess()->GetTitleID()};
+            const FileSys::PatchManager pm{system.CurrentProcess()->GetTitleID(),
+                                           system.GetFileSystemController(),
+                                           system.GetContentProvider()};
             const auto metadata = pm.GetControlMetadata();
             const auto& nacp_unique = metadata.first;
 
@@ -728,7 +730,8 @@ void FileSystemController::CreateFactories(FileSys::VfsFilesystem& vfs, bool ove
 void InstallInterfaces(Core::System& system) {
     std::make_shared<FSP_LDR>()->InstallAsService(system.ServiceManager());
     std::make_shared<FSP_PR>()->InstallAsService(system.ServiceManager());
-    std::make_shared<FSP_SRV>(system.GetFileSystemController(), system.GetReporter())
+    std::make_shared<FSP_SRV>(system.GetFileSystemController(), system.GetContentProvider(),
+                              system.GetReporter())
         ->InstallAsService(system.ServiceManager());
 }
 
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:
     u64 next_entry_index = 0;
 };
 
-FSP_SRV::FSP_SRV(FileSystemController& fsc, const Core::Reporter& reporter)
-    : ServiceFramework("fsp-srv"), fsc(fsc), reporter(reporter) {
+FSP_SRV::FSP_SRV(FileSystemController& fsc_, const FileSys::ContentProvider& content_provider_,
+                 const Core::Reporter& reporter_)
+    : ServiceFramework("fsp-srv"), fsc(fsc_), content_provider{content_provider_},
+      reporter(reporter_) {
     // clang-format off
     static const FunctionInfo functions[] = {
         {0, nullptr, "OpenFileSystem"},
@@ -968,7 +970,7 @@ void FSP_SRV::OpenDataStorageByDataId(Kernel::HLERequestContext& ctx) {
         return;
     }
 
-    FileSys::PatchManager pm{title_id};
+    const FileSys::PatchManager pm{title_id, fsc, content_provider};
 
     auto storage = std::make_shared<IStorage>(
         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;
 }
 
 namespace FileSys {
+class ContentProvider;
 class FileSystemBackend;
-}
+} // namespace FileSys
 
 namespace Service::FileSystem {
 
@@ -32,7 +33,8 @@ enum class LogMode : u32 {
 
 class FSP_SRV final : public ServiceFramework<FSP_SRV> {
 public:
-    explicit FSP_SRV(FileSystemController& fsc, const Core::Reporter& reporter);
+    explicit FSP_SRV(FileSystemController& fsc_, const FileSys::ContentProvider& content_provider_,
+                     const Core::Reporter& reporter_);
     ~FSP_SRV() override;
 
 private:
@@ -55,6 +57,7 @@ private:
     void OpenMultiCommitManager(Kernel::HLERequestContext& ctx);
 
     FileSystemController& fsc;
+    const FileSys::ContentProvider& content_provider;
 
     FileSys::VirtualFile romfs;
     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 @@
 // Refer to the license.txt file included.
 
 #include "common/logging/log.h"
+#include "core/core.h"
 #include "core/file_sys/control_metadata.h"
 #include "core/file_sys/patch_manager.h"
 #include "core/file_sys/vfs.h"
@@ -29,8 +30,8 @@ IAccountProxyInterface::IAccountProxyInterface() : ServiceFramework{"IAccountPro
 
 IAccountProxyInterface::~IAccountProxyInterface() = default;
 
-IApplicationManagerInterface::IApplicationManagerInterface()
-    : ServiceFramework{"IApplicationManagerInterface"} {
+IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_)
+    : ServiceFramework{"IApplicationManagerInterface"}, system{system_} {
     // clang-format off
     static const FunctionInfo functions[] = {
         {0, nullptr, "ListApplicationRecord"},
@@ -298,7 +299,8 @@ void IApplicationManagerInterface::GetApplicationControlData(Kernel::HLERequestC
 
     const auto size = ctx.GetWriteBufferSize();
 
-    const FileSys::PatchManager pm{title_id};
+    const FileSys::PatchManager pm{title_id, system.GetFileSystemController(),
+                                   system.GetContentProvider()};
     const auto control = pm.GetControlMetadata();
 
     std::vector<u8> out;
@@ -538,14 +540,14 @@ IFactoryResetInterface::IFactoryResetInterface::IFactoryResetInterface()
 
 IFactoryResetInterface::~IFactoryResetInterface() = default;
 
-NS::NS(const char* name) : ServiceFramework{name} {
+NS::NS(const char* name, Core::System& system_) : ServiceFramework{name}, system{system_} {
     // clang-format off
     static const FunctionInfo functions[] = {
         {7992, &NS::PushInterface<IECommerceInterface>, "GetECommerceInterface"},
         {7993, &NS::PushInterface<IApplicationVersionInterface>, "GetApplicationVersionInterface"},
         {7994, &NS::PushInterface<IFactoryResetInterface>, "GetFactoryResetInterface"},
         {7995, &NS::PushInterface<IAccountProxyInterface>, "GetAccountProxyInterface"},
-        {7996, &NS::PushInterface<IApplicationManagerInterface>, "GetApplicationManagerInterface"},
+        {7996, &NS::PushIApplicationManagerInterface, "GetApplicationManagerInterface"},
         {7997, &NS::PushInterface<IDownloadTaskInterface>, "GetDownloadTaskInterface"},
         {7998, &NS::PushInterface<IContentManagementInterface>, "GetContentManagementInterface"},
         {7999, &NS::PushInterface<IDocumentInterface>, "GetDocumentInterface"},
@@ -558,7 +560,7 @@ NS::NS(const char* name) : ServiceFramework{name} {
 NS::~NS() = default;
 
 std::shared_ptr<IApplicationManagerInterface> NS::GetApplicationManagerInterface() const {
-    return GetInterface<IApplicationManagerInterface>();
+    return GetInterface<IApplicationManagerInterface>(system);
 }
 
 class NS_DEV final : public ServiceFramework<NS_DEV> {
@@ -678,11 +680,11 @@ public:
 
 void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) {
 
-    std::make_shared<NS>("ns:am2")->InstallAsService(service_manager);
-    std::make_shared<NS>("ns:ec")->InstallAsService(service_manager);
-    std::make_shared<NS>("ns:rid")->InstallAsService(service_manager);
-    std::make_shared<NS>("ns:rt")->InstallAsService(service_manager);
-    std::make_shared<NS>("ns:web")->InstallAsService(service_manager);
+    std::make_shared<NS>("ns:am2", system)->InstallAsService(service_manager);
+    std::make_shared<NS>("ns:ec", system)->InstallAsService(service_manager);
+    std::make_shared<NS>("ns:rid", system)->InstallAsService(service_manager);
+    std::make_shared<NS>("ns:rt", system)->InstallAsService(service_manager);
+    std::make_shared<NS>("ns:web", system)->InstallAsService(service_manager);
 
     std::make_shared<NS_DEV>()->InstallAsService(service_manager);
     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 @@
 
 #include "core/hle/service/service.h"
 
+namespace Core {
+class System;
+}
+
 namespace Service {
 
 namespace FileSystem {
@@ -22,7 +26,7 @@ public:
 
 class IApplicationManagerInterface final : public ServiceFramework<IApplicationManagerInterface> {
 public:
-    explicit IApplicationManagerInterface();
+    explicit IApplicationManagerInterface(Core::System& system_);
     ~IApplicationManagerInterface() override;
 
     ResultVal<u8> GetApplicationDesiredLanguage(u32 supported_languages);
@@ -32,6 +36,8 @@ private:
     void GetApplicationControlData(Kernel::HLERequestContext& ctx);
     void GetApplicationDesiredLanguage(Kernel::HLERequestContext& ctx);
     void ConvertApplicationLanguageToLanguageCode(Kernel::HLERequestContext& ctx);
+
+    Core::System& system;
 };
 
 class IApplicationVersionInterface final : public ServiceFramework<IApplicationVersionInterface> {
@@ -72,13 +78,13 @@ public:
 
 class NS final : public ServiceFramework<NS> {
 public:
-    explicit NS(const char* name);
+    explicit NS(const char* name, Core::System& system_);
     ~NS() override;
 
     std::shared_ptr<IApplicationManagerInterface> GetApplicationManagerInterface() const;
 
 private:
-    template <typename T>
+    template <typename T, typename... Args>
     void PushInterface(Kernel::HLERequestContext& ctx) {
         LOG_DEBUG(Service_NS, "called");
 
@@ -87,13 +93,23 @@ private:
         rb.PushIpcInterface<T>();
     }
 
-    template <typename T>
-    std::shared_ptr<T> GetInterface() const {
+    void PushIApplicationManagerInterface(Kernel::HLERequestContext& ctx) {
+        LOG_DEBUG(Service_NS, "called");
+
+        IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+        rb.Push(RESULT_SUCCESS);
+        rb.PushIpcInterface<IApplicationManagerInterface>(system);
+    }
+
+    template <typename T, typename... Args>
+    std::shared_ptr<T> GetInterface(Args&&... args) const {
         static_assert(std::is_base_of_v<Kernel::SessionRequestHandler, T>,
                       "Not a base of ServiceFrameworkBase");
 
-        return std::make_shared<T>();
+        return std::make_shared<T>(std::forward<Args>(args)...);
     }
+
+    Core::System& system;
 };
 
 /// 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
     }
 
     if (override_update) {
-        const FileSys::PatchManager patch_manager(metadata.GetTitleID());
+        const FileSys::PatchManager patch_manager(
+            metadata.GetTitleID(), system.GetFileSystemController(), system.GetContentProvider());
         dir = patch_manager.PatchExeFS(dir);
     }
 
@@ -160,7 +161,8 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect
     modules.clear();
     const VAddr base_address{process.PageTable().GetCodeRegionStart()};
     VAddr next_load_addr{base_address};
-    const FileSys::PatchManager pm{metadata.GetTitleID()};
+    const FileSys::PatchManager pm{metadata.GetTitleID(), system.GetFileSystemController(),
+                                   system.GetContentProvider()};
     for (const auto& module : static_modules) {
         const FileSys::VirtualFile module_file{dir->GetFile(module)};
         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 @@
 #include "common/file_util.h"
 #include "common/logging/log.h"
 #include "common/string_util.h"
+#include "core/core.h"
 #include "core/hle/kernel/process.h"
 #include "core/loader/deconstructed_rom_directory.h"
 #include "core/loader/elf.h"
@@ -194,15 +195,14 @@ AppLoader::~AppLoader() = default;
 
 /**
  * Get a loader for a file with a specific type
- * @param file The file to load
- * @param type The type of the file
- * @param file the file to retrieve the loader for
- * @param type the file type
+ * @param system The system context to use.
+ * @param file   The file to retrieve the loader for
+ * @param type   The file type
  * @return std::unique_ptr<AppLoader> a pointer to a loader object;  nullptr for unsupported type
  */
-static std::unique_ptr<AppLoader> GetFileLoader(FileSys::VirtualFile file, FileType type) {
+static std::unique_ptr<AppLoader> GetFileLoader(Core::System& system, FileSys::VirtualFile file,
+                                                FileType type) {
     switch (type) {
-
     // Standard ELF file format.
     case FileType::ELF:
         return std::make_unique<AppLoader_ELF>(std::move(file));
@@ -221,7 +221,8 @@ static std::unique_ptr<AppLoader> GetFileLoader(FileSys::VirtualFile file, FileT
 
     // NX XCI (nX Card Image) file format.
     case FileType::XCI:
-        return std::make_unique<AppLoader_XCI>(std::move(file));
+        return std::make_unique<AppLoader_XCI>(std::move(file), system.GetFileSystemController(),
+                                               system.GetContentProvider());
 
     // NX NAX (NintendoAesXts) file format.
     case FileType::NAX:
@@ -229,7 +230,8 @@ static std::unique_ptr<AppLoader> GetFileLoader(FileSys::VirtualFile file, FileT
 
     // NX NSP (Nintendo Submission Package) file format
     case FileType::NSP:
-        return std::make_unique<AppLoader_NSP>(std::move(file));
+        return std::make_unique<AppLoader_NSP>(std::move(file), system.GetFileSystemController(),
+                                               system.GetContentProvider());
 
     // NX KIP (Kernel Internal Process) file format
     case FileType::KIP:
@@ -244,20 +246,21 @@ static std::unique_ptr<AppLoader> GetFileLoader(FileSys::VirtualFile file, FileT
     }
 }
 
-std::unique_ptr<AppLoader> GetLoader(FileSys::VirtualFile file) {
+std::unique_ptr<AppLoader> GetLoader(Core::System& system, FileSys::VirtualFile file) {
     FileType type = IdentifyFile(file);
-    FileType filename_type = GuessFromFilename(file->GetName());
+    const FileType filename_type = GuessFromFilename(file->GetName());
 
     // Special case: 00 is either a NCA or NAX.
     if (type != filename_type && !(file->GetName() == "00" && type == FileType::NAX)) {
         LOG_WARNING(Loader, "File {} has a different type than its extension.", file->GetName());
-        if (FileType::Unknown == type)
+        if (FileType::Unknown == type) {
             type = filename_type;
+        }
     }
 
     LOG_DEBUG(Loader, "Loading file {} as {}...", file->GetName(), GetFileTypeString(type));
 
-    return GetFileLoader(std::move(file), type);
+    return GetFileLoader(system, std::move(file), type);
 }
 
 } // 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:
 
 /**
  * Identifies a bootable file and return a suitable loader
- * @param file The bootable file
- * @return the best loader for this file
+ *
+ * @param system The system context.
+ * @param file   The bootable file.
+ *
+ * @return the best loader for this file.
  */
-std::unique_ptr<AppLoader> GetLoader(FileSys::VirtualFile file);
+std::unique_ptr<AppLoader> GetLoader(Core::System& system, FileSys::VirtualFile file);
 
 } // 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
     // Apply cheats if they exist and the program has a valid title ID
     if (pm) {
         system.SetCurrentProcessBuildID(nso_header.build_id);
-        const auto cheats = pm->CreateCheatList(system, nso_header.build_id);
+        const auto cheats = pm->CreateCheatList(nso_header.build_id);
         if (!cheats.empty()) {
             system.RegisterCheatList(cheats, nso_header.build_id, load_base, image_size);
         }
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 @@
 
 namespace Loader {
 
-AppLoader_NSP::AppLoader_NSP(FileSys::VirtualFile file)
+AppLoader_NSP::AppLoader_NSP(FileSys::VirtualFile file,
+                             const Service::FileSystem::FileSystemController& fsc,
+                             const FileSys::ContentProvider& content_provider)
     : AppLoader(file), nsp(std::make_unique<FileSys::NSP>(file)),
       title_id(nsp->GetProgramTitleID()) {
 
-    if (nsp->GetStatus() != ResultStatus::Success)
+    if (nsp->GetStatus() != ResultStatus::Success) {
         return;
+    }
 
     if (nsp->IsExtractedType()) {
         secondary_loader = std::make_unique<AppLoader_DeconstructedRomDirectory>(nsp->GetExeFS());
     } else {
         const auto control_nca =
             nsp->GetNCA(nsp->GetProgramTitleID(), FileSys::ContentRecordType::Control);
-        if (control_nca == nullptr || control_nca->GetStatus() != ResultStatus::Success)
+        if (control_nca == nullptr || control_nca->GetStatus() != ResultStatus::Success) {
             return;
+        }
 
-        std::tie(nacp_file, icon_file) =
-            FileSys::PatchManager(nsp->GetProgramTitleID()).ParseControlNCA(*control_nca);
+        std::tie(nacp_file, icon_file) = [this, &content_provider, &control_nca, &fsc] {
+            const FileSys::PatchManager pm{nsp->GetProgramTitleID(), fsc, content_provider};
+            return pm.ParseControlNCA(*control_nca);
+        }();
 
-        if (title_id == 0)
+        if (title_id == 0) {
             return;
+        }
 
         secondary_loader = std::make_unique<AppLoader_NCA>(
             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 @@
 #include "core/file_sys/vfs.h"
 #include "core/loader/loader.h"
 
-namespace Core {
-class System;
-}
-
 namespace FileSys {
+class ContentProvider;
 class NACP;
 class NSP;
 } // namespace FileSys
 
+namespace Service::FileSystem {
+class FileSystemController;
+}
+
 namespace Loader {
 
 class AppLoader_NCA;
@@ -25,7 +26,9 @@ class AppLoader_NCA;
 /// Loads an XCI file
 class AppLoader_NSP final : public AppLoader {
 public:
-    explicit AppLoader_NSP(FileSys::VirtualFile file);
+    explicit AppLoader_NSP(FileSys::VirtualFile file,
+                           const Service::FileSystem::FileSystemController& fsc,
+                           const FileSys::ContentProvider& content_provider);
     ~AppLoader_NSP() override;
 
     /**
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 @@
 
 namespace Loader {
 
-AppLoader_XCI::AppLoader_XCI(FileSys::VirtualFile file)
+AppLoader_XCI::AppLoader_XCI(FileSys::VirtualFile file,
+                             const Service::FileSystem::FileSystemController& fsc,
+                             const FileSys::ContentProvider& content_provider)
     : AppLoader(file), xci(std::make_unique<FileSys::XCI>(file)),
       nca_loader(std::make_unique<AppLoader_NCA>(xci->GetProgramNCAFile())) {
-    if (xci->GetStatus() != ResultStatus::Success)
+    if (xci->GetStatus() != ResultStatus::Success) {
         return;
+    }
 
     const auto control_nca = xci->GetNCAByType(FileSys::NCAContentType::Control);
-    if (control_nca == nullptr || control_nca->GetStatus() != ResultStatus::Success)
+    if (control_nca == nullptr || control_nca->GetStatus() != ResultStatus::Success) {
         return;
+    }
 
-    std::tie(nacp_file, icon_file) =
-        FileSys::PatchManager(xci->GetProgramTitleID()).ParseControlNCA(*control_nca);
+    std::tie(nacp_file, icon_file) = [this, &content_provider, &control_nca, &fsc] {
+        const FileSys::PatchManager pm{xci->GetProgramTitleID(), fsc, content_provider};
+        return pm.ParseControlNCA(*control_nca);
+    }();
 }
 
 AppLoader_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 @@
 #include "core/file_sys/vfs.h"
 #include "core/loader/loader.h"
 
-namespace Core {
-class System;
-}
-
 namespace FileSys {
+class ContentProvider;
 class NACP;
 class XCI;
 } // namespace FileSys
 
+namespace Service::FileSystem {
+class FileSystemController;
+}
+
 namespace Loader {
 
 class AppLoader_NCA;
@@ -25,7 +26,9 @@ class AppLoader_NCA;
 /// Loads an XCI file
 class AppLoader_XCI final : public AppLoader {
 public:
-    explicit AppLoader_XCI(FileSys::VirtualFile file);
+    explicit AppLoader_XCI(FileSys::VirtualFile file,
+                           const Service::FileSystem::FileSystemController& fsc,
+                           const FileSys::ContentProvider& content_provider);
     ~AppLoader_XCI() override;
 
     /**
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() {
     }
 }
 
-void TelemetrySession::AddInitialInfo(Loader::AppLoader& app_loader) {
+void TelemetrySession::AddInitialInfo(Loader::AppLoader& app_loader,
+                                      const Service::FileSystem::FileSystemController& fsc,
+                                      const FileSys::ContentProvider& content_provider) {
     // Log one-time top-level information
     AddField(Telemetry::FieldType::None, "TelemetryId", GetTelemetryId());
 
@@ -167,7 +169,10 @@ void TelemetrySession::AddInitialInfo(Loader::AppLoader& app_loader) {
         app_loader.ReadTitle(name);
 
         if (name.empty()) {
-            const auto metadata = FileSys::PatchManager(program_id).GetControlMetadata();
+            const auto metadata = [&content_provider, &fsc, program_id] {
+                const FileSys::PatchManager pm{program_id, fsc, content_provider};
+                return pm.GetControlMetadata();
+            }();
             if (metadata.first != nullptr) {
                 name = metadata.first->GetApplicationName();
             }
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 @@
 #include <string>
 #include "common/telemetry.h"
 
+namespace FileSys {
+class ContentProvider;
+}
+
 namespace Loader {
 class AppLoader;
 }
 
+namespace Service::FileSystem {
+class FileSystemController;
+}
+
 namespace Core {
 
 /**
@@ -40,10 +48,14 @@ public:
      *   - Title file format
      *   - Miscellaneous settings values.
      *
-     * @param app_loader The application loader to use to retrieve
-     *                   title-specific information.
+     * @param app_loader       The application loader to use to retrieve
+     *                         title-specific information.
+     * @param fsc              Filesystem controller to use to retrieve info.
+     * @param content_provider Content provider to use to retrieve info.
      */
-    void AddInitialInfo(Loader::AppLoader& app_loader);
+    void AddInitialInfo(Loader::AppLoader& app_loader,
+                        const Service::FileSystem::FileSystemController& fsc,
+                        const FileSys::ContentProvider& content_provider);
 
     /**
      * 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 @@
 
 #include "common/common_paths.h"
 #include "common/file_util.h"
+#include "core/core.h"
 #include "core/file_sys/control_metadata.h"
 #include "core/file_sys/patch_manager.h"
 #include "core/file_sys/xts_archive.h"
@@ -89,9 +90,11 @@ void ConfigurePerGame::LoadConfiguration() {
     ui->display_title_id->setText(
         QStringLiteral("%1").arg(title_id, 16, 16, QLatin1Char{'0'}).toUpper());
 
-    FileSys::PatchManager pm{title_id};
+    auto& system = Core::System::GetInstance();
+    const FileSys::PatchManager pm{title_id, system.GetFileSystemController(),
+                                   system.GetContentProvider()};
     const auto control = pm.GetControlMetadata();
-    const auto loader = Loader::GetLoader(file);
+    const auto loader = Loader::GetLoader(system, file);
 
     if (control.first != nullptr) {
         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() {
         return;
     }
 
-    FileSys::PatchManager pm{title_id};
-    const auto loader = Loader::GetLoader(file);
+    auto& system = Core::System::GetInstance();
+    const FileSys::PatchManager pm{title_id, system.GetFileSystemController(),
+                                   system.GetContentProvider()};
+    const auto loader = Loader::GetLoader(system, file);
 
     FileSys::VirtualFile update_raw;
     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;
 void GameListWorker::AddTitlesToGameList(GameListDir* parent_dir) {
     using namespace FileSys;
 
-    const auto& cache =
-        dynamic_cast<ContentProviderUnion&>(Core::System::GetInstance().GetContentProvider());
+    auto& system = Core::System::GetInstance();
+    const auto& cache = dynamic_cast<ContentProviderUnion&>(system.GetContentProvider());
 
-    std::vector<std::pair<ContentProviderUnionSlot, ContentProviderEntry>> installed_games;
-    installed_games = cache.ListEntriesFilterOrigin(std::nullopt, TitleType::Application,
-                                                    ContentRecordType::Program);
+    auto installed_games = cache.ListEntriesFilterOrigin(std::nullopt, TitleType::Application,
+                                                         ContentRecordType::Program);
 
     if (parent_dir->type() == static_cast<int>(GameListItemType::SdmcDir)) {
         installed_games = cache.ListEntriesFilterOrigin(
@@ -254,23 +253,27 @@ void GameListWorker::AddTitlesToGameList(GameListDir* parent_dir) {
     }
 
     for (const auto& [slot, game] : installed_games) {
-        if (slot == ContentProviderUnionSlot::FrontendManual)
+        if (slot == ContentProviderUnionSlot::FrontendManual) {
             continue;
+        }
 
         const auto file = cache.GetEntryUnparsed(game.title_id, game.type);
-        std::unique_ptr<Loader::AppLoader> loader = Loader::GetLoader(file);
-        if (!loader)
+        std::unique_ptr<Loader::AppLoader> loader = Loader::GetLoader(system, file);
+        if (!loader) {
             continue;
+        }
 
         std::vector<u8> icon;
         std::string name;
         u64 program_id = 0;
         loader->ReadProgramId(program_id);
 
-        const PatchManager patch{program_id};
+        const PatchManager patch{program_id, system.GetFileSystemController(),
+                                 system.GetContentProvider()};
         const auto control = cache.GetEntry(game.title_id, ContentRecordType::Control);
-        if (control != nullptr)
+        if (control != nullptr) {
             GetMetadataFromControlNCA(patch, *control, icon, name);
+        }
 
         emit EntryReady(MakeGameListEntry(file->GetFullPath(), name, icon, *loader, program_id,
                                           compatibility_list, patch),
@@ -280,9 +283,11 @@ void GameListWorker::AddTitlesToGameList(GameListDir* parent_dir) {
 
 void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_path,
                                     unsigned int recursion, GameListDir* parent_dir) {
-    const auto callback = [this, target, recursion,
-                           parent_dir](u64* num_entries_out, const std::string& directory,
-                                       const std::string& virtual_name) -> bool {
+    auto& system = Core::System::GetInstance();
+
+    const auto callback = [this, target, recursion, parent_dir,
+                           &system](u64* num_entries_out, const std::string& directory,
+                                    const std::string& virtual_name) -> bool {
         if (stop_processing) {
             // Breaks the callback loop.
             return false;
@@ -293,7 +298,7 @@ void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_pa
         if (!is_dir &&
             (HasSupportedFileExtension(physical_name) || IsExtractedNCAMain(physical_name))) {
             const auto file = vfs->OpenFile(physical_name, FileSys::Mode::Read);
-            auto loader = Loader::GetLoader(file);
+            auto loader = Loader::GetLoader(system, file);
             if (!loader) {
                 return true;
             }
@@ -331,7 +336,8 @@ void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_pa
                 std::string name = " ";
                 [[maybe_unused]] const auto res3 = loader->ReadTitle(name);
 
-                const FileSys::PatchManager patch{program_id};
+                const FileSys::PatchManager patch{program_id, system.GetFileSystemController(),
+                                                  system.GetContentProvider()};
 
                 emit EntryReady(MakeGameListEntry(physical_name, name, icon, *loader, program_id,
                                                   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) {
     StoreRecentFile(filename); // Put the filename on top of the list
 
     u64 title_id{0};
-
+    auto& system = Core::System::GetInstance();
     const auto v_file = Core::GetGameFileFromPath(vfs, filename.toUtf8().constData());
-    const auto loader = Loader::GetLoader(v_file);
+    const auto loader = Loader::GetLoader(system, v_file);
     if (!(loader == nullptr || loader->ReadProgramId(title_id) != Loader::ResultStatus::Success)) {
         // Load per game settings
         Config per_game_config(fmt::format("{:016X}", title_id), Config::ConfigType::PerGameConfig);
@@ -1144,9 +1144,13 @@ void GMainWindow::BootGame(const QString& filename) {
 
     std::string title_name;
     std::string title_version;
-    const auto res = Core::System::GetInstance().GetGameName(title_name);
+    const auto res = system.GetGameName(title_name);
 
-    const auto metadata = FileSys::PatchManager(title_id).GetControlMetadata();
+    const auto metadata = [&system, title_id] {
+        const FileSys::PatchManager pm(title_id, system.GetFileSystemController(),
+                                       system.GetContentProvider());
+        return pm.GetControlMetadata();
+    }();
     if (metadata.first != nullptr) {
         title_version = metadata.first->GetVersionString();
         title_name = metadata.first->GetApplicationName();
@@ -1157,7 +1161,7 @@ void GMainWindow::BootGame(const QString& filename) {
     LOG_INFO(Frontend, "Booting game: {:016X} | {} | {}", title_id, title_name, title_version);
     UpdateWindowTitle(title_name, title_version);
 
-    loading_screen->Prepare(Core::System::GetInstance().GetAppLoader());
+    loading_screen->Prepare(system.GetAppLoader());
     loading_screen->show();
 
     emulation_running = true;
@@ -1276,16 +1280,18 @@ void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target
                                        const std::string& game_path) {
     std::string path;
     QString open_target;
+    auto& system = Core::System::GetInstance();
 
-    const auto [user_save_size, device_save_size] = [this, &program_id, &game_path] {
-        FileSys::PatchManager pm{program_id};
+    const auto [user_save_size, device_save_size] = [this, &game_path, &program_id, &system] {
+        const FileSys::PatchManager pm{program_id, system.GetFileSystemController(),
+                                       system.GetContentProvider()};
         const auto control = pm.GetControlMetadata().first;
         if (control != nullptr) {
             return std::make_pair(control->GetDefaultNormalSaveSize(),
                                   control->GetDeviceSaveDataSize());
         } else {
             const auto file = Core::GetGameFileFromPath(vfs, game_path);
-            const auto loader = Loader::GetLoader(file);
+            const auto loader = Loader::GetLoader(system, file);
 
             FileSys::NACP nacp{};
             loader->ReadControlData(nacp);
@@ -1612,7 +1618,8 @@ void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_pa
                                 "cancelled the operation."));
     };
 
-    const auto loader = Loader::GetLoader(vfs->OpenFile(game_path, FileSys::Mode::Read));
+    auto& system = Core::System::GetInstance();
+    const auto loader = Loader::GetLoader(system, vfs->OpenFile(game_path, FileSys::Mode::Read));
     if (loader == nullptr) {
         failed();
         return;
@@ -1624,7 +1631,7 @@ void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_pa
         return;
     }
 
-    const auto& installed = Core::System::GetInstance().GetContentProvider();
+    const auto& installed = system.GetContentProvider();
     const auto romfs_title_id = SelectRomFSDumpTarget(installed, program_id);
 
     if (!romfs_title_id) {
@@ -1639,7 +1646,7 @@ void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_pa
 
     if (*romfs_title_id == program_id) {
         const u64 ivfc_offset = loader->ReadRomFSIVFCOffset();
-        FileSys::PatchManager pm{program_id};
+        const FileSys::PatchManager pm{program_id, system.GetFileSystemController(), installed};
         romfs = pm.PatchRomFS(file, ivfc_offset, FileSys::ContentRecordType::Program);
     } else {
         romfs = installed.GetEntry(*romfs_title_id, FileSys::ContentRecordType::Data)->GetRomFS();
@@ -1756,7 +1763,8 @@ void GMainWindow::OnGameListShowList(bool show) {
 void GMainWindow::OnGameListOpenPerGameProperties(const std::string& file) {
     u64 title_id{};
     const auto v_file = Core::GetGameFileFromPath(vfs, file);
-    const auto loader = Loader::GetLoader(v_file);
+    const auto loader = Loader::GetLoader(Core::System::GetInstance(), v_file);
+
     if (loader == nullptr || loader->ReadProgramId(title_id) != Loader::ResultStatus::Success) {
         QMessageBox::information(this, tr("Properties"),
                                  tr("The game properties could not be loaded."));