#include "stdio.h" #include "unistd.h" #include "string.h" #include "stdlib.h" #define MIN(x,y) ( x < y ? x : y ) int main(int argc, char *argv[]) { if(argc != 4) { fprintf(stderr, "Usage: %s filetopatch output patch.ips\n", argv[0]); exit(-1); } FILE *patch, *input, *output; patch = fopen(argv[3], "rb"); if(!patch) { fprintf(stderr, "Unable to open file: %s\n", argv[3]); exit(-2); } input = fopen(argv[1], "rb"); if(!input) { fprintf(stderr, "Unable to open file: %s\n", argv[1]); exit(-2); } output = fopen(argv[2], "wb+"); if(!output) { fprintf(stderr, "Unable to open file: %s\n", argv[2]); exit(-2); } unsigned char buf[7]; fread(buf, sizeof(buf[0]), 5, patch); buf[5] = 0; if(strcmp("PATCH", buf)) { fprintf(stderr, "Invalid patch file\n"); exit(-1); } // Loop until end // Assuming that patch addresses are monotonically increasing int posin = 0; unsigned char *bigbuf = malloc(sizeof(char) * 65536); unsigned int addr, patchsize; int tmp, result; unsigned int furthest = 0; while(!feof(patch)) { fread(buf, sizeof(buf[0]), 5, patch); addr = (buf[0] << 16) + (buf[1] << 8) + buf[2]; printf("%6x\n", addr ); if(addr < furthest ) { fseek(input, addr, SEEK_SET); fclose(output); output = fopen(argv[2], "rb+"); if(!output) { fprintf(stderr, "Unable to open file: %s\n", argv[2]); exit(-2); } fseek(output, addr, SEEK_SET); } else { while(posin < addr) { tmp = MIN(addr - posin, 65536); result = fread(bigbuf, sizeof(buf[0]), tmp, input); if (result < tmp) { printf("Expected %i, got %i", tmp, result); perror("On noes!"); exit(-1); } fwrite(bigbuf, sizeof(buf[0]), tmp, output); posin += tmp; } } fprintf(stderr, "%08x vs. %08x\n", addr, ftell(input)); patchsize = (buf[3] << 8) + buf[4]; if (patchsize == 0) { // RLE printf("Runlength Encoding\n"); fread(buf, sizeof(buf[0]), 3, patch); patchsize = (buf[0] << 8) + buf[1]; for(tmp = 0; tmp < patchsize; tmp ++) { fwrite(&buf[2], sizeof(buf[0]), 1, output); } } else { printf("Encoding %u digits\n", patchsize); printf("First few characters: "); int j = 0; switch(patchsize) { default: printf("%02x", bigbuf[j++] & 0xff); case 3: printf("%02x", bigbuf[j++] & 0xff); case 2: printf("%02x", bigbuf[j++] & 0xff); case 1: printf("%02x", bigbuf[j++] & 0xff); } printf("\n"); fread(bigbuf, sizeof(buf[0]), patchsize, patch); fwrite(bigbuf, sizeof(buf[0]), patchsize, output); } posin += patchsize; if(posin > furthest) { furthest = posin; } else { // Move to end fseek(output, 0, SEEK_END); posin = furthest; } fseek(input, furthest, SEEK_SET); fprintf(stderr, "Furthest: %08x\n", furthest); } // Finish up rest of patch file fseek(output, furthest, SEEK_SET); fread(bigbuf, sizeof(char), 1, input); while(!feof(input)) { fwrite(bigbuf, sizeof(char), 1, output); fread(bigbuf, sizeof(char), 1, input); } }