diff options
Diffstat (limited to '')
| -rw-r--r-- | src/core/file_sys/ips_layer.cpp | 45 | ||||
| -rw-r--r-- | src/core/file_sys/ips_layer.h | 3 | ||||
| -rw-r--r-- | src/core/file_sys/patch_manager.h | 1 |
3 files changed, 41 insertions, 8 deletions
diff --git a/src/core/file_sys/ips_layer.cpp b/src/core/file_sys/ips_layer.cpp index 6bce138a8..6c5535f83 100644 --- a/src/core/file_sys/ips_layer.cpp +++ b/src/core/file_sys/ips_layer.cpp | |||
| @@ -17,6 +17,11 @@ enum class IPSFileType { | |||
| 17 | Error, | 17 | Error, |
| 18 | }; | 18 | }; |
| 19 | 19 | ||
| 20 | const std::map<const char*, const char*> ESCAPE_CHARACTER_MAP{ | ||
| 21 | {"\\a", "\a"}, {"\\b", "\b"}, {"\\f", "\f"}, {"\\n", "\n"}, {"\\r", "\r"}, {"\\t", "\t"}, | ||
| 22 | {"\\v", "\v"}, {"\\\\", "\\"}, {"\\\'", "\'"}, {"\\\"", "\""}, {"\\\?", "\?"}, | ||
| 23 | }; | ||
| 24 | |||
| 20 | static IPSFileType IdentifyMagic(const std::vector<u8>& magic) { | 25 | static IPSFileType IdentifyMagic(const std::vector<u8>& magic) { |
| 21 | if (magic.size() != 5) | 26 | if (magic.size() != 5) |
| 22 | return IPSFileType::Error; | 27 | return IPSFileType::Error; |
| @@ -89,7 +94,7 @@ VirtualFile PatchIPS(const VirtualFile& in, const VirtualFile& ips) { | |||
| 89 | 94 | ||
| 90 | IPSwitchCompiler::IPSwitchCompiler(VirtualFile patch_text_) | 95 | IPSwitchCompiler::IPSwitchCompiler(VirtualFile patch_text_) |
| 91 | : valid(false), patch_text(std::move(patch_text_)), nso_build_id{}, is_little_endian(false), | 96 | : valid(false), patch_text(std::move(patch_text_)), nso_build_id{}, is_little_endian(false), |
| 92 | offset_shift(0), print_values(false) { | 97 | offset_shift(0), print_values(false), last_comment("") { |
| 93 | Parse(); | 98 | Parse(); |
| 94 | } | 99 | } |
| 95 | 100 | ||
| @@ -105,6 +110,18 @@ static bool StartsWith(const std::string& base, const std::string& check) { | |||
| 105 | return base.size() >= check.size() && base.substr(0, check.size()) == check; | 110 | return base.size() >= check.size() && base.substr(0, check.size()) == check; |
| 106 | } | 111 | } |
| 107 | 112 | ||
| 113 | static std::string EscapeStringSequences(std::string in) { | ||
| 114 | for (const auto& seq : ESCAPE_CHARACTER_MAP) { | ||
| 115 | for (auto index = in.find(seq.first); index != std::string::npos; | ||
| 116 | index = in.find(seq.first, index)) { | ||
| 117 | in.replace(index, std::strlen(seq.first), seq.second); | ||
| 118 | index += std::strlen(seq.second); | ||
| 119 | } | ||
| 120 | } | ||
| 121 | |||
| 122 | return in; | ||
| 123 | } | ||
| 124 | |||
| 108 | void IPSwitchCompiler::Parse() { | 125 | void IPSwitchCompiler::Parse() { |
| 109 | const auto bytes = patch_text->ReadAllBytes(); | 126 | const auto bytes = patch_text->ReadAllBytes(); |
| 110 | std::stringstream s; | 127 | std::stringstream s; |
| @@ -121,6 +138,13 @@ void IPSwitchCompiler::Parse() { | |||
| 121 | 138 | ||
| 122 | for (std::size_t i = 0; i < lines.size(); ++i) { | 139 | for (std::size_t i = 0; i < lines.size(); ++i) { |
| 123 | auto line = lines[i]; | 140 | auto line = lines[i]; |
| 141 | |||
| 142 | // Remove midline comments | ||
| 143 | if (!StartsWith(line, "//") && line.find("//") != std::string::npos) { | ||
| 144 | last_comment = line.substr(line.find("//") + 2); | ||
| 145 | line = line.substr(0, line.find("//")); | ||
| 146 | } | ||
| 147 | |||
| 124 | if (StartsWith(line, "@stop")) { | 148 | if (StartsWith(line, "@stop")) { |
| 125 | // Force stop | 149 | // Force stop |
| 126 | break; | 150 | break; |
| @@ -132,11 +156,18 @@ void IPSwitchCompiler::Parse() { | |||
| 132 | nso_build_id = Common::HexStringToArray<0x20>(raw_build_id); | 156 | nso_build_id = Common::HexStringToArray<0x20>(raw_build_id); |
| 133 | } else if (StartsWith(line, "@flag offset_shift ")) { | 157 | } else if (StartsWith(line, "@flag offset_shift ")) { |
| 134 | // Offset Shift Flag | 158 | // Offset Shift Flag |
| 135 | offset_shift = std::stoull(line.substr(19), nullptr, 0); | 159 | offset_shift = std::stoll(line.substr(19), nullptr, 0); |
| 136 | } else if (StartsWith(line, "#")) { | 160 | } else if (StartsWith(line, "#")) { |
| 137 | // Mandatory Comment | 161 | // Mandatory Comment |
| 138 | LOG_INFO(Loader, "[IPSwitchCompiler ('{}')] Forced output comment: {}", | 162 | LOG_INFO(Loader, "[IPSwitchCompiler ('{}')] Forced output comment: {}", |
| 139 | patch_text->GetName(), line.substr(1)); | 163 | patch_text->GetName(), line.substr(1)); |
| 164 | } else if (StartsWith(line, "//")) { | ||
| 165 | // Normal Comment | ||
| 166 | last_comment = line.substr(2); | ||
| 167 | if (last_comment.find_first_not_of(' ') == std::string::npos) | ||
| 168 | continue; | ||
| 169 | if (last_comment.find_first_not_of(' ') != 0) | ||
| 170 | last_comment = last_comment.substr(last_comment.find_first_not_of(' ')); | ||
| 140 | } else if (StartsWith(line, "@little-endian")) { | 171 | } else if (StartsWith(line, "@little-endian")) { |
| 141 | // Set values to read as little endian | 172 | // Set values to read as little endian |
| 142 | is_little_endian = true; | 173 | is_little_endian = true; |
| @@ -151,11 +182,10 @@ void IPSwitchCompiler::Parse() { | |||
| 151 | const auto enabled = StartsWith(line, "@enabled"); | 182 | const auto enabled = StartsWith(line, "@enabled"); |
| 152 | if (i == 0) | 183 | if (i == 0) |
| 153 | return; | 184 | return; |
| 154 | const auto name = lines[i - 1].substr(3); | ||
| 155 | LOG_INFO(Loader, "[IPSwitchCompiler ('{}')] Parsing patch '{}' ({})", | 185 | LOG_INFO(Loader, "[IPSwitchCompiler ('{}')] Parsing patch '{}' ({})", |
| 156 | patch_text->GetName(), name, line.substr(1)); | 186 | patch_text->GetName(), last_comment, line.substr(1)); |
| 157 | 187 | ||
| 158 | IPSwitchPatch patch{name, enabled, {}}; | 188 | IPSwitchPatch patch{last_comment, enabled, {}}; |
| 159 | 189 | ||
| 160 | // Read rest of patch | 190 | // Read rest of patch |
| 161 | while (true) { | 191 | while (true) { |
| @@ -173,10 +203,11 @@ void IPSwitchCompiler::Parse() { | |||
| 173 | // 9 - first char of replacement val | 203 | // 9 - first char of replacement val |
| 174 | if (line[9] == '\"') { | 204 | if (line[9] == '\"') { |
| 175 | // string replacement | 205 | // string replacement |
| 176 | const auto end_index = line.find_last_of('\"'); | 206 | const auto end_index = line.find('\"', 10); |
| 177 | if (end_index == std::string::npos || end_index < 10) | 207 | if (end_index == std::string::npos || end_index < 10) |
| 178 | return; | 208 | return; |
| 179 | const auto value = line.substr(10, end_index - 10); | 209 | auto value = line.substr(10, end_index - 10); |
| 210 | value = EscapeStringSequences(value); | ||
| 180 | replace.reserve(value.size()); | 211 | replace.reserve(value.size()); |
| 181 | std::copy(value.begin(), value.end(), std::back_inserter(replace)); | 212 | std::copy(value.begin(), value.end(), std::back_inserter(replace)); |
| 182 | } else { | 213 | } else { |
diff --git a/src/core/file_sys/ips_layer.h b/src/core/file_sys/ips_layer.h index bb35542c8..847e9bf3c 100644 --- a/src/core/file_sys/ips_layer.h +++ b/src/core/file_sys/ips_layer.h | |||
| @@ -34,8 +34,9 @@ private: | |||
| 34 | std::vector<IPSwitchPatch> patches; | 34 | std::vector<IPSwitchPatch> patches; |
| 35 | std::array<u8, 0x20> nso_build_id; | 35 | std::array<u8, 0x20> nso_build_id; |
| 36 | bool is_little_endian; | 36 | bool is_little_endian; |
| 37 | u64 offset_shift; | 37 | s64 offset_shift; |
| 38 | bool print_values; | 38 | bool print_values; |
| 39 | std::string last_comment; | ||
| 39 | }; | 40 | }; |
| 40 | 41 | ||
| 41 | } // namespace FileSys | 42 | } // namespace FileSys |
diff --git a/src/core/file_sys/patch_manager.h b/src/core/file_sys/patch_manager.h index 6a864ec43..66fdba148 100644 --- a/src/core/file_sys/patch_manager.h +++ b/src/core/file_sys/patch_manager.h | |||
| @@ -36,6 +36,7 @@ public: | |||
| 36 | 36 | ||
| 37 | // Currently tracked NSO patches: | 37 | // Currently tracked NSO patches: |
| 38 | // - IPS | 38 | // - IPS |
| 39 | // - IPSwitch | ||
| 39 | std::vector<u8> PatchNSO(const std::vector<u8>& nso) const; | 40 | std::vector<u8> PatchNSO(const std::vector<u8>& nso) const; |
| 40 | 41 | ||
| 41 | // Checks to see if PatchNSO() will have any effect given the NSO's build ID. | 42 | // Checks to see if PatchNSO() will have any effect given the NSO's build ID. |