diff options
Diffstat (limited to 'src/core/file_sys/patch_manager.cpp')
| -rw-r--r-- | src/core/file_sys/patch_manager.cpp | 68 |
1 files changed, 50 insertions, 18 deletions
diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp index ada8c44e78..4fd7dc6c71 100644 --- a/src/core/file_sys/patch_manager.cpp +++ b/src/core/file_sys/patch_manager.cpp @@ -9,6 +9,7 @@ #include <cstddef> #include <cstring> +#include "common/assert.h" #include "common/hex_util.h" #include "common/logging.h" #include "common/settings.h" @@ -156,12 +157,15 @@ std::string GetUpdateVersionStringFromSlot(const ContentProvider* provider, u64 NACP nacp{nacp_file}; return nacp.GetVersionString(); } +YUZU_NO_INLINE std::optional<u64> GetParentApplicationId(const ContentProvider* provider, u64 title_id) { + return provider == nullptr ? std::nullopt : provider->GetParentApplicationId(title_id); +} } // Anonymous namespace 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_} {} + : title_id{title_id_}, parent_title_id{GetParentApplicationId(std::addressof(content_provider_), title_id_)}, fs_controller{fs_controller_}, content_provider{content_provider_} {} PatchManager::~PatchManager() = default; @@ -169,13 +173,35 @@ u64 PatchManager::GetTitleID() const { return title_id; } +VirtualDir PatchManager::GetModificationLoadRoot(bool sdmc) const { + const auto get_root = [&](u64 id) { + return sdmc ? fs_controller.GetSDMCModificationLoadRoot(id) : fs_controller.GetModificationLoadRoot(id); + }; + auto root = get_root(title_id); + if (!parent_title_id) { + return root; + } + std::vector<VirtualDir> roots{std::move(root), get_root(*parent_title_id)}; + std::erase(roots, nullptr); + return LayeredVfsDirectory::MakeLayeredDirectory(std::move(roots)); +} + +std::vector<std::string> PatchManager::GetDisabledAddons() const { + auto disabled = Settings::values.disabled_addons[title_id]; + if (parent_title_id) { + const auto& shared = Settings::values.disabled_addons[*parent_title_id]; + disabled.insert(disabled.end(), shared.begin(), shared.end()); + } + return disabled; +} + VirtualDir PatchManager::PatchExeFS(VirtualDir exefs) const { LOG_INFO(Loader, "Patching ExeFS for title_id={:016X}", title_id); if (exefs == nullptr) return exefs; - const auto& disabled = Settings::values.disabled_addons[title_id]; + const auto disabled = GetDisabledAddons(); bool update_disabled = true; std::optional<u32> enabled_version; @@ -303,8 +329,8 @@ VirtualDir PatchManager::PatchExeFS(VirtualDir exefs) const { } // LayeredExeFS - const auto load_dir = fs_controller.GetModificationLoadRoot(title_id); - const auto sdmc_load_dir = fs_controller.GetSDMCModificationLoadRoot(title_id); + const auto load_dir = GetModificationLoadRoot(); + const auto sdmc_load_dir = GetModificationLoadRoot(true); std::vector<VirtualDir> patch_dirs = {sdmc_load_dir}; if (load_dir != nullptr) { @@ -346,7 +372,7 @@ VirtualDir PatchManager::PatchExeFS(VirtualDir exefs) const { } std::vector<VirtualFile> PatchManager::CollectPatches(const std::vector<VirtualDir>& patch_dirs, const std::string& build_id) const { - const auto& disabled = Settings::values.disabled_addons[title_id]; + const auto disabled = GetDisabledAddons(); const auto nso_build_id = fmt::format("{:0<64}", build_id); std::vector<VirtualFile> out; @@ -405,7 +431,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 = fs_controller.GetModificationLoadRoot(title_id); + const auto load_dir = GetModificationLoadRoot(); if (load_dir == nullptr) { LOG_ERROR(Loader, "Cannot load mods for invalid title_id={:016X}", title_id); return nso; @@ -448,7 +474,7 @@ bool PatchManager::HasNSOPatch(const BuildID& build_id_, std::string_view name) LOG_INFO(Loader, "Querying NSO patch existence for build_id={}, name={}", build_id, name); - const auto load_dir = fs_controller.GetModificationLoadRoot(title_id); + const auto load_dir = GetModificationLoadRoot(); if (load_dir == nullptr) { LOG_ERROR(Loader, "Cannot load mods for invalid title_id={:016X}", title_id); return false; @@ -462,13 +488,13 @@ bool PatchManager::HasNSOPatch(const BuildID& build_id_, std::string_view name) } std::vector<Core::Memory::CheatEntry> PatchManager::CreateCheatList(const BuildID& build_id_) const { - const auto load_dir = fs_controller.GetModificationLoadRoot(title_id); + const auto load_dir = GetModificationLoadRoot(); if (load_dir == nullptr) { LOG_ERROR(Loader, "Cannot load mods for invalid title_id={:016X}", title_id); return {}; } - const auto& disabled = Settings::values.disabled_addons[title_id]; + const auto disabled = GetDisabledAddons(); auto patch_dirs = load_dir->GetSubdirectories(); std::sort(patch_dirs.begin(), patch_dirs.end(), [](auto const& l, auto const& r) { return l->GetName() < r->GetName(); }); @@ -502,17 +528,16 @@ std::vector<Core::Memory::CheatEntry> PatchManager::CreateCheatList(const BuildI return out; } -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); - const auto sdmc_load_dir = fs_controller.GetSDMCModificationLoadRoot(title_id); +void PatchManager::ApplyLayeredFS(VirtualFile& romfs, ContentRecordType type) const { + const auto load_dir = GetModificationLoadRoot(); + const auto sdmc_load_dir = GetModificationLoadRoot(true); if ((type != ContentRecordType::Program && type != ContentRecordType::Data && type != ContentRecordType::HtmlDocument) || (load_dir == nullptr && sdmc_load_dir == nullptr)) { return; } - const auto& disabled = Settings::values.disabled_addons[title_id]; + const auto disabled = GetDisabledAddons(); std::vector<VirtualDir> patch_dirs = load_dir->GetSubdirectories(); if (std::find(disabled.cbegin(), disabled.cend(), "SDMC") == disabled.cend()) { patch_dirs.push_back(sdmc_load_dir); @@ -591,7 +616,7 @@ VirtualFile PatchManager::PatchRomFS(const NCA* base_nca, VirtualFile base_romfs // Game Updates const auto update_tid = GetUpdateTitleID(title_id); - const auto& disabled = Settings::values.disabled_addons[title_id]; + const auto disabled = GetDisabledAddons(); bool update_disabled = true; std::optional<u32> enabled_version; @@ -698,7 +723,7 @@ VirtualFile PatchManager::PatchRomFS(const NCA* base_nca, VirtualFile base_romfs // LayeredFS if (apply_layeredfs) { - ApplyLayeredFS(romfs, title_id, type, fs_controller); + ApplyLayeredFS(romfs, type); } return romfs; @@ -1072,15 +1097,22 @@ std::vector<Patch> PatchManager::GetPatches(VirtualFile update_raw) const { std::optional<u32> PatchManager::GetGameVersion() const { const auto update_tid = GetUpdateTitleID(title_id); if (content_provider.HasEntry(update_tid, ContentRecordType::Program)) { - return content_provider.GetEntryVersion(update_tid); + const auto version = content_provider.GetEntryVersion(update_tid); + return version || !parent_title_id ? version : content_provider.GetEntryVersion(GetUpdateTitleID(*parent_title_id)); } - return content_provider.GetEntryVersion(title_id); + const auto version = content_provider.GetEntryVersion(title_id); + return version || !parent_title_id ? version : content_provider.GetEntryVersion(*parent_title_id); } PatchManager::Metadata PatchManager::GetControlMetadata() const { const auto base_control_nca = content_provider.GetEntry(title_id, ContentRecordType::Control); if (base_control_nca == nullptr) { + if (parent_title_id) { + const auto control_id = content_provider.HasEntry(*parent_title_id, ContentRecordType::Control) ? *parent_title_id : GetUpdateTitleID(*parent_title_id); + const PatchManager parent{control_id, fs_controller, content_provider}; + return parent.GetControlMetadata(); + } return {}; } |
