#pragma once namespace nall::IPS { inline auto apply(array_view source, array_view patch, maybe result = {}) -> maybe> { #define error(text) { if(result) *result = {"error: ", text}; return {}; } #define success() { if(result) *result = ""; return target; } vector target; for (u32 i : range(source.size())) { target.append(source[i]); } u32 patchOffset = 0; auto read = [&]() -> u8 { return patch[patchOffset++]; }; auto readOffset = [&]() -> u32 { u32 result = read() << 16; result |= read() << 8; result |= read(); return result; }; auto readLength = [&]() -> u32 { u32 result = read() << 8; result |= read(); return result; }; auto write = [&](u32 index, u8 data) { target[index] = data; }; if(read() != 'P') error("IPS header invalid"); if(read() != 'A') error("IPS header invalid"); if(read() != 'T') error("IPS header invalid"); if(read() != 'C') error("IPS header invalid"); if(read() != 'H') error("IPS header invalid"); u32 patchSize = patch.size(); while (patchOffset < patchSize - 3) { u32 offset = readOffset(); u32 length = readLength(); bool rleRecord = false; if (length == 0) { length = readLength(); rleRecord = true; } if(target.size() < offset + length) { target.resize(target.size() + ((u64)(offset + length) - target.size()), 0); } if(rleRecord) { u8 data = read(); for (u32 i : range(length)) write(offset + i, data); } else { for (u32 i : range(length)) write(offset + i, read()); } } if(read() != 'E') error("IPS footer invalid"); if(read() != 'O') error("IPS footer invalid"); if(read() != 'F') error("IPS footer invalid"); success(); #undef error #undef success } }