diff options
Diffstat (limited to 'tools/br_ips/ips_patch.c')
-rw-r--r-- | tools/br_ips/ips_patch.c | 28 |
1 files changed, 25 insertions, 3 deletions
diff --git a/tools/br_ips/ips_patch.c b/tools/br_ips/ips_patch.c index 03780cf72..506f23ad7 100644 --- a/tools/br_ips/ips_patch.c +++ b/tools/br_ips/ips_patch.c @@ -24,18 +24,36 @@ do { \ static const char SPLASH[] = "Small IPS patch utility\n" "Created by PikalaxALT on 23 June 2019 All Rights Reserved\n"; +static const char HELP[] = "ips_patch [-h] ROM PATCH OUT\n" + "\n" + " ROM - input ROM file\n" + " PATCH - IPS patch file to apply\n" + " OUT - path to write patched ROM\n" + "\n" + "Options:\n" + " -h - show this message and exit\n"; + int main(int argc, char ** argv) { + // Show a friendly message puts(SPLASH); - if (argc != 4) FATAL_ERROR("usage: %s ROM PATCH OUT\n", argv[0]); + // If requested, show help message + if (argc >= 2 && strcmp(argv[1], "-h") == 0) { + puts(HELP); + return 0; + } + // Enforce CLI syntax + if (argc != 4) FATAL_ERROR("usage: %s [-h] ROM PATCH OUT\n", argv[0]); FILE * rom = fopen(argv[1], "rb"); if (rom == NULL) FATAL_ERROR("failed to open file \"%s\" for reading\n", argv[1]); FILE * patch = fopen(argv[2], "rb"); if (patch == NULL) FATAL_ERROR("failed to open file \"%s\" for reading\n", argv[2]); FILE * out = fopen(argv[3], "wb"); if (patch == NULL) FATAL_ERROR("failed to open file \"%s\" for writing\n", argv[3]); + // IPS magic header char magic[5]; if (fread(magic, 1, 5, patch) != 5) FATAL_ERROR("read magic\n"); if (memcmp(magic, "PATCH", 5) != 0) FATAL_ERROR("malformed IPS patch\n"); + // Read the ROM into allocated memory. fseek(rom, 0, SEEK_END); size_t romsize = ftell(rom); fseek(rom, 0, SEEK_SET); @@ -46,16 +64,20 @@ int main(int argc, char ** argv) { while (1) { uint32_t offset; size_t size; - + // Read each hunk into the buffer, overwriting previous data. + // If two or more hunks overlap, the newest one is retained. + // A good IPS patch creator will avoid this. offset = (unsigned char)getc(patch) << 16; offset |= (unsigned char)getc(patch) << 8; offset |= (unsigned char)getc(patch); - if (offset == 0x454F46) break; + if (offset == 0x454F46) break; // end sentinel "EOF" size = (unsigned char)getc(patch) << 8; size |= (unsigned char)getc(patch); + if (offset + size > romsize) FATAL_ERROR("segment extends past end of ROM\n"); if (fread(buffer + offset, 1, size, patch) != size) FATAL_ERROR("read segment\n"); } fclose(patch); + // Write the patched ROM fwrite(buffer, 1, romsize, out); fclose(out); free(buffer); |