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