#include "helpers/patches.hpp" #include #include #include #include #include "helpers/utils.hpp" namespace hex { static void pushBytesBack(std::vector &buffer, const char* bytes) { std::string_view string(bytes); buffer.resize(buffer.size() + string.length()); std::memcpy((&buffer.back() - string.length()) + 1, string.begin(), string.length()); } template static void pushBytesBack(std::vector &buffer, T bytes) { buffer.resize(buffer.size() + sizeof(T)); std::memcpy((&buffer.back() - sizeof(T)) + 1, &bytes, sizeof(T)); } std::vector generateIPSPatch(const Patches &patches) { std::vector result; pushBytesBack(result, "PATCH"); std::vector addresses; std::vector values; for (const auto &[address, value] : patches) { addresses.push_back(address); values.push_back(value); } std::optional startAddress; std::vector bytes; for (u32 i = 0; i < addresses.size(); i++) { if (!startAddress.has_value()) startAddress = addresses[i]; if (i != addresses.size() - 1 && addresses[i] == (addresses[i + 1] - 1)) { bytes.push_back(values[i]); } else { bytes.push_back(values[i]); if (bytes.size() > 0xFFFF || startAddress > 0xFF'FFFF) return { }; u32 address = startAddress.value(); auto addressBytes = reinterpret_cast(&address); result.push_back(addressBytes[2]); result.push_back(addressBytes[1]); result.push_back(addressBytes[0]); pushBytesBack(result, changeEndianess(bytes.size(), std::endian::big)); for (auto byte : bytes) result.push_back(byte); bytes.clear(); startAddress = { }; } } pushBytesBack(result, "EOF"); return result; } std::vector generateIPS32Patch(const Patches &patches) { std::vector result; pushBytesBack(result, "IPS32"); std::vector addresses; std::vector values; for (const auto &[address, value] : patches) { addresses.push_back(address); values.push_back(value); } std::optional startAddress; std::vector bytes; for (u32 i = 0; i < addresses.size(); i++) { if (!startAddress.has_value()) startAddress = addresses[i]; if (i != addresses.size() - 1 && addresses[i] == (addresses[i + 1] - 1)) { bytes.push_back(values[i]); } else { bytes.push_back(values[i]); if (bytes.size() > 0xFFFF || startAddress > 0xFFFF'FFFF) return { }; u32 address = startAddress.value(); auto addressBytes = reinterpret_cast(&address); result.push_back(addressBytes[3]); result.push_back(addressBytes[2]); result.push_back(addressBytes[1]); result.push_back(addressBytes[0]); pushBytesBack(result, changeEndianess(bytes.size(), std::endian::big)); for (auto byte : bytes) result.push_back(byte); bytes.clear(); startAddress = { }; } } pushBytesBack(result, "EEOF"); return result; } }