diff --git a/src/core/file_sys/ips_layer.cpp b/src/core/file_sys/ips_layer.cpp index 0cadbc375..6c072d0a3 100644 --- a/src/core/file_sys/ips_layer.cpp +++ b/src/core/file_sys/ips_layer.cpp @@ -2,9 +2,15 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include +#include +#include #include -#include "common/assert.h" +#include +#include + #include "common/hex_util.h" +#include "common/logging/log.h" #include "common/swap.h" #include "core/file_sys/ips_layer.h" #include "core/file_sys/vfs_vector.h" @@ -17,22 +23,48 @@ enum class IPSFileType { Error, }; -constexpr std::array, 11> ESCAPE_CHARACTER_MAP{ - std::pair{"\\a", "\a"}, {"\\b", "\b"}, {"\\f", "\f"}, {"\\n", "\n"}, - {"\\r", "\r"}, {"\\t", "\t"}, {"\\v", "\v"}, {"\\\\", "\\"}, - {"\\\'", "\'"}, {"\\\"", "\""}, {"\\\?", "\?"}, -}; +constexpr std::array, 11> ESCAPE_CHARACTER_MAP{{ + {"\\a", "\a"}, + {"\\b", "\b"}, + {"\\f", "\f"}, + {"\\n", "\n"}, + {"\\r", "\r"}, + {"\\t", "\t"}, + {"\\v", "\v"}, + {"\\\\", "\\"}, + {"\\\'", "\'"}, + {"\\\"", "\""}, + {"\\\?", "\?"}, +}}; static IPSFileType IdentifyMagic(const std::vector& magic) { - if (magic.size() != 5) + if (magic.size() != 5) { return IPSFileType::Error; - if (magic == std::vector{'P', 'A', 'T', 'C', 'H'}) + } + + constexpr std::array patch_magic{{'P', 'A', 'T', 'C', 'H'}}; + if (std::equal(magic.begin(), magic.end(), patch_magic.begin())) { return IPSFileType::IPS; - if (magic == std::vector{'I', 'P', 'S', '3', '2'}) + } + + constexpr std::array ips32_magic{{'I', 'P', 'S', '3', '2'}}; + if (std::equal(magic.begin(), magic.end(), ips32_magic.begin())) { return IPSFileType::IPS32; + } + return IPSFileType::Error; } +static bool IsEOF(IPSFileType type, const std::vector& data) { + constexpr std::array eof{{'E', 'O', 'F'}}; + if (type == IPSFileType::IPS && std::equal(data.begin(), data.end(), eof.begin())) { + return true; + } + + constexpr std::array eeof{{'E', 'E', 'O', 'F'}}; + return type == IPSFileType::IPS32 && std::equal(data.begin(), data.end(), eeof.begin()); +} + VirtualFile PatchIPS(const VirtualFile& in, const VirtualFile& ips) { if (in == nullptr || ips == nullptr) return nullptr; @@ -47,8 +79,7 @@ VirtualFile PatchIPS(const VirtualFile& in, const VirtualFile& ips) { u64 offset = 5; // After header while (ips->Read(temp.data(), temp.size(), offset) == temp.size()) { offset += temp.size(); - if (type == IPSFileType::IPS32 && temp == std::vector{'E', 'E', 'O', 'F'} || - type == IPSFileType::IPS && temp == std::vector{'E', 'O', 'F'}) { + if (IsEOF(type, temp)) { break; } @@ -88,11 +119,20 @@ VirtualFile PatchIPS(const VirtualFile& in, const VirtualFile& ips) { } } - if (temp != std::vector{'E', 'E', 'O', 'F'} && temp != std::vector{'E', 'O', 'F'}) + if (!IsEOF(type, temp)) { return nullptr; - return std::make_shared(in_data, in->GetName(), in->GetContainingDirectory()); + } + + return std::make_shared(std::move(in_data), in->GetName(), + in->GetContainingDirectory()); } +struct IPSwitchCompiler::IPSwitchPatch { + std::string name; + bool enabled; + std::map> records; +}; + IPSwitchCompiler::IPSwitchCompiler(VirtualFile patch_text_) : patch_text(std::move(patch_text_)) { Parse(); } @@ -291,7 +331,8 @@ VirtualFile IPSwitchCompiler::Apply(const VirtualFile& in) const { } } - return std::make_shared(in_data, in->GetName(), in->GetContainingDirectory()); + return std::make_shared(std::move(in_data), in->GetName(), + in->GetContainingDirectory()); } } // namespace FileSys diff --git a/src/core/file_sys/ips_layer.h b/src/core/file_sys/ips_layer.h index 57da00da8..450b2f71e 100644 --- a/src/core/file_sys/ips_layer.h +++ b/src/core/file_sys/ips_layer.h @@ -4,8 +4,11 @@ #pragma once +#include #include +#include +#include "common/common_types.h" #include "core/file_sys/vfs.h" namespace FileSys { @@ -22,17 +25,13 @@ public: VirtualFile Apply(const VirtualFile& in) const; private: + struct IPSwitchPatch; + void ParseFlag(const std::string& flag); void Parse(); bool valid = false; - struct IPSwitchPatch { - std::string name; - bool enabled; - std::map> records; - }; - VirtualFile patch_text; std::vector patches; std::array nso_build_id{};