diff options
| author | Zach Hilman <zachhilman@gmail.com> | 2018-10-01 08:31:34 -0400 | 
|---|---|---|
| committer | Zach Hilman <zachhilman@gmail.com> | 2018-10-04 11:34:30 -0400 | 
| commit | 9669cdb710e3242b7c0b705ea613587d36f79e00 (patch) | |
| tree | 35f69b6a9679f7f7309b3b7305a954778b8592d3 /src/core/file_sys | |
| parent | 8886f2e55ef7a1acc5dab613c42cce8022fae996 (diff) | |
ips_layer: Add support for escape sequences and midline comments
More accurately follows IPSwitch specification.
Diffstat (limited to 'src/core/file_sys')
| -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 {      Error,  }; +const std::map<const char*, const char*> ESCAPE_CHARACTER_MAP{ +    {"\\a", "\a"}, {"\\b", "\b"},  {"\\f", "\f"},  {"\\n", "\n"},  {"\\r", "\r"},  {"\\t", "\t"}, +    {"\\v", "\v"}, {"\\\\", "\\"}, {"\\\'", "\'"}, {"\\\"", "\""}, {"\\\?", "\?"}, +}; +  static IPSFileType IdentifyMagic(const std::vector<u8>& magic) {      if (magic.size() != 5)          return IPSFileType::Error; @@ -89,7 +94,7 @@ VirtualFile PatchIPS(const VirtualFile& in, const VirtualFile& ips) {  IPSwitchCompiler::IPSwitchCompiler(VirtualFile patch_text_)      : valid(false), patch_text(std::move(patch_text_)), nso_build_id{}, is_little_endian(false), -      offset_shift(0), print_values(false) { +      offset_shift(0), print_values(false), last_comment("") {      Parse();  } @@ -105,6 +110,18 @@ static bool StartsWith(const std::string& base, const std::string& check) {      return base.size() >= check.size() && base.substr(0, check.size()) == check;  } +static std::string EscapeStringSequences(std::string in) { +    for (const auto& seq : ESCAPE_CHARACTER_MAP) { +        for (auto index = in.find(seq.first); index != std::string::npos; +             index = in.find(seq.first, index)) { +            in.replace(index, std::strlen(seq.first), seq.second); +            index += std::strlen(seq.second); +        } +    } + +    return in; +} +  void IPSwitchCompiler::Parse() {      const auto bytes = patch_text->ReadAllBytes();      std::stringstream s; @@ -121,6 +138,13 @@ void IPSwitchCompiler::Parse() {      for (std::size_t i = 0; i < lines.size(); ++i) {          auto line = lines[i]; + +        // Remove midline comments +        if (!StartsWith(line, "//") && line.find("//") != std::string::npos) { +            last_comment = line.substr(line.find("//") + 2); +            line = line.substr(0, line.find("//")); +        } +          if (StartsWith(line, "@stop")) {              // Force stop              break; @@ -132,11 +156,18 @@ void IPSwitchCompiler::Parse() {              nso_build_id = Common::HexStringToArray<0x20>(raw_build_id);          } else if (StartsWith(line, "@flag offset_shift ")) {              // Offset Shift Flag -            offset_shift = std::stoull(line.substr(19), nullptr, 0); +            offset_shift = std::stoll(line.substr(19), nullptr, 0);          } else if (StartsWith(line, "#")) {              // Mandatory Comment              LOG_INFO(Loader, "[IPSwitchCompiler ('{}')] Forced output comment: {}",                       patch_text->GetName(), line.substr(1)); +        } else if (StartsWith(line, "//")) { +            // Normal Comment +            last_comment = line.substr(2); +            if (last_comment.find_first_not_of(' ') == std::string::npos) +                continue; +            if (last_comment.find_first_not_of(' ') != 0) +                last_comment = last_comment.substr(last_comment.find_first_not_of(' '));          } else if (StartsWith(line, "@little-endian")) {              // Set values to read as little endian              is_little_endian = true; @@ -151,11 +182,10 @@ void IPSwitchCompiler::Parse() {              const auto enabled = StartsWith(line, "@enabled");              if (i == 0)                  return; -            const auto name = lines[i - 1].substr(3);              LOG_INFO(Loader, "[IPSwitchCompiler ('{}')] Parsing patch '{}' ({})", -                     patch_text->GetName(), name, line.substr(1)); +                     patch_text->GetName(), last_comment, line.substr(1)); -            IPSwitchPatch patch{name, enabled, {}}; +            IPSwitchPatch patch{last_comment, enabled, {}};              // Read rest of patch              while (true) { @@ -173,10 +203,11 @@ void IPSwitchCompiler::Parse() {                  // 9 - first char of replacement val                  if (line[9] == '\"') {                      // string replacement -                    const auto end_index = line.find_last_of('\"'); +                    const auto end_index = line.find('\"', 10);                      if (end_index == std::string::npos || end_index < 10)                          return; -                    const auto value = line.substr(10, end_index - 10); +                    auto value = line.substr(10, end_index - 10); +                    value = EscapeStringSequences(value);                      replace.reserve(value.size());                      std::copy(value.begin(), value.end(), std::back_inserter(replace));                  } 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:      std::vector<IPSwitchPatch> patches;      std::array<u8, 0x20> nso_build_id;      bool is_little_endian; -    u64 offset_shift; +    s64 offset_shift;      bool print_values; +    std::string last_comment;  };  } // 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:      // Currently tracked NSO patches:      // - IPS +    // - IPSwitch      std::vector<u8> PatchNSO(const std::vector<u8>& nso) const;      // Checks to see if PatchNSO() will have any effect given the NSO's build ID.  | 
