diff options
| author | 2018-09-30 18:13:38 -0400 | |
|---|---|---|
| committer | 2018-10-04 11:34:06 -0400 | |
| commit | 8886f2e55ef7a1acc5dab613c42cce8022fae996 (patch) | |
| tree | c4401330051d3ad4f8ef89670b8981d56a95b068 /src | |
| parent | ips_layer: Add IPSwitchCompiler to process IPSwitch format (diff) | |
| download | yuzu-8886f2e55ef7a1acc5dab613c42cce8022fae996.tar.gz yuzu-8886f2e55ef7a1acc5dab613c42cce8022fae996.tar.xz yuzu-8886f2e55ef7a1acc5dab613c42cce8022fae996.zip | |
patch_manager: Add support for IPSwitch format patches
Diffstat (limited to '')
| -rw-r--r-- | src/core/file_sys/patch_manager.cpp | 78 |
1 files changed, 56 insertions, 22 deletions
diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp index 539698f6e..f148e7719 100644 --- a/src/core/file_sys/patch_manager.cpp +++ b/src/core/file_sys/patch_manager.cpp | |||
| @@ -73,27 +73,38 @@ VirtualDir PatchManager::PatchExeFS(VirtualDir exefs) const { | |||
| 73 | return exefs; | 73 | return exefs; |
| 74 | } | 74 | } |
| 75 | 75 | ||
| 76 | static std::vector<VirtualFile> CollectIPSPatches(const std::vector<VirtualDir>& patch_dirs, | 76 | static std::vector<VirtualFile> CollectPatches(const std::vector<VirtualDir>& patch_dirs, |
| 77 | const std::string& build_id) { | 77 | const std::string& build_id) { |
| 78 | std::vector<VirtualFile> ips; | 78 | std::vector<VirtualFile> out; |
| 79 | ips.reserve(patch_dirs.size()); | 79 | ips.reserve(patch_dirs.size()); |
| 80 | for (const auto& subdir : patch_dirs) { | 80 | for (const auto& subdir : patch_dirs) { |
| 81 | auto exefs_dir = subdir->GetSubdirectory("exefs"); | 81 | auto exefs_dir = subdir->GetSubdirectory("exefs"); |
| 82 | if (exefs_dir != nullptr) { | 82 | if (exefs_dir != nullptr) { |
| 83 | for (const auto& file : exefs_dir->GetFiles()) { | 83 | for (const auto& file : exefs_dir->GetFiles()) { |
| 84 | if (file->GetExtension() != "ips") | 84 | if (file->GetExtension() == "ips") { |
| 85 | continue; | 85 | auto name = file->GetName(); |
| 86 | auto name = file->GetName(); | 86 | const auto p1 = name.substr(0, name.find('.')); |
| 87 | const auto p1 = name.substr(0, name.find('.')); | 87 | const auto this_build_id = p1.substr(0, p1.find_last_not_of('0') + 1); |
| 88 | const auto this_build_id = p1.substr(0, p1.find_last_not_of('0') + 1); | 88 | |
| 89 | 89 | if (build_id == this_build_id) | |
| 90 | if (build_id == this_build_id) | 90 | out.push_back(file); |
| 91 | ips.push_back(file); | 91 | } else if (file->GetExtension() == "pchtxt") { |
| 92 | IPSwitchCompiler compiler{file}; | ||
| 93 | if (!compiler.IsValid()) | ||
| 94 | continue; | ||
| 95 | |||
| 96 | auto this_build_id = Common::HexArrayToString(compiler.GetBuildID()); | ||
| 97 | this_build_id = | ||
| 98 | this_build_id.substr(0, this_build_id.find_last_not_of('0') + 1); | ||
| 99 | |||
| 100 | if (build_id == this_build_id) | ||
| 101 | out.push_back(file); | ||
| 102 | } | ||
| 92 | } | 103 | } |
| 93 | } | 104 | } |
| 94 | } | 105 | } |
| 95 | 106 | ||
| 96 | return ips; | 107 | return out; |
| 97 | } | 108 | } |
| 98 | 109 | ||
| 99 | std::vector<u8> PatchManager::PatchNSO(const std::vector<u8>& nso) const { | 110 | std::vector<u8> PatchManager::PatchNSO(const std::vector<u8>& nso) const { |
| @@ -115,15 +126,24 @@ std::vector<u8> PatchManager::PatchNSO(const std::vector<u8>& nso) const { | |||
| 115 | auto patch_dirs = load_dir->GetSubdirectories(); | 126 | auto patch_dirs = load_dir->GetSubdirectories(); |
| 116 | std::sort(patch_dirs.begin(), patch_dirs.end(), | 127 | std::sort(patch_dirs.begin(), patch_dirs.end(), |
| 117 | [](const VirtualDir& l, const VirtualDir& r) { return l->GetName() < r->GetName(); }); | 128 | [](const VirtualDir& l, const VirtualDir& r) { return l->GetName() < r->GetName(); }); |
| 118 | const auto ips = CollectIPSPatches(patch_dirs, build_id); | 129 | const auto patches = CollectPatches(patch_dirs, build_id); |
| 119 | 130 | ||
| 120 | auto out = nso; | 131 | auto out = nso; |
| 121 | for (const auto& ips_file : ips) { | 132 | for (const auto& patch_file : patches) { |
| 122 | LOG_INFO(Loader, " - Appling IPS patch from mod \"{}\"", | 133 | if (patch_file->GetExtension() == "ips") { |
| 123 | ips_file->GetContainingDirectory()->GetParentDirectory()->GetName()); | 134 | LOG_INFO(Loader, " - Applying IPS patch from mod \"{}\"", |
| 124 | const auto patched = PatchIPS(std::make_shared<VectorVfsFile>(out), ips_file); | 135 | patch_file->GetContainingDirectory()->GetParentDirectory()->GetName()); |
| 125 | if (patched != nullptr) | 136 | const auto patched = PatchIPS(std::make_shared<VectorVfsFile>(out), patch_file); |
| 126 | out = patched->ReadAllBytes(); | 137 | if (patched != nullptr) |
| 138 | out = patched->ReadAllBytes(); | ||
| 139 | } else if (patch_file->GetExtension() == "pchtxt") { | ||
| 140 | LOG_INFO(Loader, " - Applying IPSwitch patch from mod \"{}\"", | ||
| 141 | patch_file->GetContainingDirectory()->GetParentDirectory()->GetName()); | ||
| 142 | const IPSwitchCompiler compiler{patch_file}; | ||
| 143 | const auto patched = compiler.Apply(std::make_shared<VectorVfsFile>(out)); | ||
| 144 | if (patched != nullptr) | ||
| 145 | out = patched->ReadAllBytes(); | ||
| 146 | } | ||
| 127 | } | 147 | } |
| 128 | 148 | ||
| 129 | if (out.size() < 0x100) | 149 | if (out.size() < 0x100) |
| @@ -143,7 +163,7 @@ bool PatchManager::HasNSOPatch(const std::array<u8, 32>& build_id_) const { | |||
| 143 | std::sort(patch_dirs.begin(), patch_dirs.end(), | 163 | std::sort(patch_dirs.begin(), patch_dirs.end(), |
| 144 | [](const VirtualDir& l, const VirtualDir& r) { return l->GetName() < r->GetName(); }); | 164 | [](const VirtualDir& l, const VirtualDir& r) { return l->GetName() < r->GetName(); }); |
| 145 | 165 | ||
| 146 | return !CollectIPSPatches(patch_dirs, build_id).empty(); | 166 | return !CollectPatches(patch_dirs, build_id).empty(); |
| 147 | } | 167 | } |
| 148 | 168 | ||
| 149 | static void ApplyLayeredFS(VirtualFile& romfs, u64 title_id, ContentRecordType type) { | 169 | static void ApplyLayeredFS(VirtualFile& romfs, u64 title_id, ContentRecordType type) { |
| @@ -253,8 +273,22 @@ std::map<std::string, std::string, std::less<>> PatchManager::GetPatchVersionNam | |||
| 253 | if (mod_dir != nullptr && mod_dir->GetSize() > 0) { | 273 | if (mod_dir != nullptr && mod_dir->GetSize() > 0) { |
| 254 | for (const auto& mod : mod_dir->GetSubdirectories()) { | 274 | for (const auto& mod : mod_dir->GetSubdirectories()) { |
| 255 | std::string types; | 275 | std::string types; |
| 256 | if (IsDirValidAndNonEmpty(mod->GetSubdirectory("exefs"))) | 276 | if (IsDirValidAndNonEmpty(mod->GetSubdirectory("exefs"))) { |
| 257 | AppendCommaIfNotEmpty(types, "IPS"); | 277 | bool ips = false; |
| 278 | bool ipswitch = false; | ||
| 279 | |||
| 280 | for (const auto& file : mod->GetSubdirectory("exefs")->GetFiles()) { | ||
| 281 | if (file->GetExtension() == "ips") | ||
| 282 | ips = true; | ||
| 283 | else if (file->GetExtension() == "pchtxt") | ||
| 284 | ipswitch = true; | ||
| 285 | } | ||
| 286 | |||
| 287 | if (ips) | ||
| 288 | AppendCommaIfNotEmpty(types, "IPS"); | ||
| 289 | if (ipswitch) | ||
| 290 | AppendCommaIfNotEmpty(types, "IPSwitch"); | ||
| 291 | } | ||
| 258 | if (IsDirValidAndNonEmpty(mod->GetSubdirectory("romfs"))) | 292 | if (IsDirValidAndNonEmpty(mod->GetSubdirectory("romfs"))) |
| 259 | AppendCommaIfNotEmpty(types, "LayeredFS"); | 293 | AppendCommaIfNotEmpty(types, "LayeredFS"); |
| 260 | 294 | ||