summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/core/file_sys/patch_manager.cpp78
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
76static std::vector<VirtualFile> CollectIPSPatches(const std::vector<VirtualDir>& patch_dirs, 76static 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
99std::vector<u8> PatchManager::PatchNSO(const std::vector<u8>& nso) const { 110std::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
149static void ApplyLayeredFS(VirtualFile& romfs, u64 title_id, ContentRecordType type) { 169static 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