#ifndef NALL_IPS_HPP #define NALL_IPS_HPP #include #include #include namespace nall { struct ips { inline bool apply(); inline void source(const uint8_t *data, unsigned size); inline void modify(const uint8_t *data, unsigned size); inline bool source(const string &filename); inline bool modify(const string &filename); inline ips(); inline ~ips(); uint8_t *data; unsigned size; const uint8_t *sourceData; unsigned sourceSize; const uint8_t *modifyData; unsigned modifySize; }; bool ips::apply() { if(modifySize < 8) return false; if(modifyData[0] != 'P') return false; if(modifyData[1] != 'A') return false; if(modifyData[2] != 'T') return false; if(modifyData[3] != 'C') return false; if(modifyData[4] != 'H') return false; if(data) delete[] data; data = new uint8_t[16 * 1024 * 1024 + 65536](); //maximum size of IPS patch + single-tag padding size = sourceSize; memcpy(data, sourceData, sourceSize); unsigned offset = 5; while(true) { unsigned address, length; if(offset > modifySize - 3) break; address = modifyData[offset++] << 16; address |= modifyData[offset++] << 8; address |= modifyData[offset++] << 0; if(address == 0x454f46) { //EOF if(offset == modifySize) return true; if(offset == modifySize - 3) { size = modifyData[offset++] << 16; size |= modifyData[offset++] << 8; size |= modifyData[offset++] << 0; return true; } } if(offset > modifySize - 2) break; length = modifyData[offset++] << 8; length |= modifyData[offset++] << 0; if(length) { //Copy if(offset > modifySize - length) break; while(length--) data[address++] = modifyData[offset++]; } else { //RLE if(offset > modifySize - 3) break; length = modifyData[offset++] << 8; length |= modifyData[offset++] << 0; if(length == 0) break; //illegal while(length--) data[address++] = modifyData[offset]; offset++; } size = max(size, address); } delete[] data; data = nullptr; return false; } void ips::source(const uint8_t *data, unsigned size) { sourceData = data, sourceSize = size; } void ips::modify(const uint8_t *data, unsigned size) { modifyData = data, modifySize = size; } bool ips::source(const string &filename) { return file::read(filename, sourceData, sourceSize); } bool ips::modify(const string &filename) { return file::read(filename, modifyData, modifySize); } ips::ips() : data(nullptr), sourceData(nullptr), modifyData(nullptr) { } ips::~ips() { if(data) delete[] data; if(sourceData) delete[] sourceData; if(modifyData) delete[] modifyData; } } #endif