From 5a4bbe4985fe9d73eafabd78a6a305aff8cff1dd Mon Sep 17 00:00:00 2001 From: "Anthony J. Bentley" Date: Sat, 10 Mar 2018 21:48:23 -0700 Subject: [PATCH] Add a new flag, -f, which allows independently fixing or trashing checksums. --- src/fix/main.c | 45 ++++++++++++++++++++++++++++++++++++--------- src/fix/rgbfix.1 | 33 +++++++++++++++++++++++++++------ 2 files changed, 63 insertions(+), 15 deletions(-) diff --git a/src/fix/main.c b/src/fix/main.c index bb89b9ef..5877543c 100644 --- a/src/fix/main.c +++ b/src/fix/main.c @@ -20,9 +20,9 @@ static void print_usage(void) { printf( -"usage: rgbfix [-CcjsVv] [-i game_id] [-k licensee_str] [-l licensee_id]\n" -" [-m mbc_type] [-n rom_version] [-p pad_value] [-r ram_size]\n" -" [-t title_str] file\n"); +"usage: rgbfix [-CcjsVv] [-f fix_spec] [-i game_id] [-k licensee_str]\n" +" [-l licensee_id] [-m mbc_type] [-n rom_version] [-p pad_value]\n" +" [-r ram_size] [-t title_str] file\n"); exit(1); } @@ -37,7 +37,12 @@ int main(int argc, char *argv[]) */ /* all flags default to false unless options specify otherwise */ - bool validate = false; + bool fixlogo = false; + bool fixheadsum = false; + bool fixglobalsum = false; + bool trashlogo = false; + bool trashheadsum = false; + bool trashglobalsum = false; bool settitle = false; bool setid = false; bool colorcompatible = false; @@ -61,7 +66,7 @@ int main(int argc, char *argv[]) int version = 0; /* mask ROM version number */ int padvalue = 0; /* to pad the rom with if it changes size */ - while ((ch = getopt(argc, argv, "Cci:jk:l:m:n:p:sr:t:Vv")) != -1) { + while ((ch = getopt(argc, argv, "Ccf:i:jk:l:m:n:p:sr:t:Vv")) != -1) { switch (ch) { case 'C': coloronly = true; @@ -69,6 +74,14 @@ int main(int argc, char *argv[]) case 'c': colorcompatible = true; break; + case 'f': + fixlogo = strchr(optarg, 'l'); + fixheadsum = strchr(optarg, 'h'); + fixglobalsum = strchr(optarg, 'g'); + trashlogo = strchr(optarg, 'L'); + trashheadsum = strchr(optarg, 'H'); + trashglobalsum = strchr(optarg, 'G'); + break; case 'i': setid = true; @@ -168,7 +181,9 @@ int main(int argc, char *argv[]) printf("rgbfix %s\n", get_package_version_string()); exit(0); case 'v': - validate = true; + fixlogo = true; + fixheadsum = true; + fixglobalsum = true; break; default: print_usage(); @@ -195,7 +210,7 @@ int main(int argc, char *argv[]) * Write changes to ROM */ - if (validate) { + if (fixlogo || trashlogo) { /* * Offset 0x104–0x133: Nintendo Logo * This is a bitmap image that displays when the Game Boy is @@ -205,7 +220,7 @@ int main(int argc, char *argv[]) /* * See also: global checksums at 0x14D–0x14F, They must * also be correct for the game to boot, so we fix them - * as well when the -v flag is set. + * as well when requested with the -f flag. */ uint8_t ninlogo[48] = { @@ -217,6 +232,10 @@ int main(int argc, char *argv[]) 0xDD, 0xDC, 0x99, 0x9F, 0xBB, 0xB9, 0x33, 0x3E }; + if (trashlogo) + for (int i = 0; i < sizeof(ninlogo); i++) + ninlogo[i] = ~ninlogo[i]; + fseek(rom, 0x104, SEEK_SET); fwrite(ninlogo, 1, 48, rom); } @@ -415,7 +434,7 @@ int main(int argc, char *argv[]) fputc(version, rom); } - if (validate) { + if (fixheadsum || trashheadsum) { /* * Offset 0x14D: Header Checksum */ @@ -426,9 +445,14 @@ int main(int argc, char *argv[]) for (int i = 0; i < (0x14D - 0x134); ++i) headcksum = headcksum - fgetc(rom) - 1; + if (trashheadsum) + headcksum = ~headcksum; + fseek(rom, 0x14D, SEEK_SET); fputc(headcksum, rom); + } + if (fixglobalsum || trashglobalsum) { /* * Offset 0x14E–0x14F: Global Checksum */ @@ -445,6 +469,9 @@ int main(int argc, char *argv[]) while ((byte = fgetc(rom)) != EOF) globalcksum += byte; + if (trashglobalsum) + globalcksum = ~globalcksum; + fseek(rom, 0x14E, SEEK_SET); fputc(globalcksum >> 8, rom); fputc(globalcksum & 0xFF, rom); diff --git a/src/fix/rgbfix.1 b/src/fix/rgbfix.1 index f65a70d3..872499aa 100644 --- a/src/fix/rgbfix.1 +++ b/src/fix/rgbfix.1 @@ -14,6 +14,7 @@ .Sh SYNOPSIS .Nm rgbfix .Op Fl CcjsVv +.Op Fl f Ar fix_spec .Op Fl i Ar game_id .Op Fl k Ar licensee_str .Op Fl l Ar licensee_id @@ -46,6 +47,30 @@ If both this and the flag are set, .Fl C takes precedence. +.It Fl f Ar fix_spec +Fix certain header values that the Game Boy checks for correctness. +Alternatively, intentionally trash these values by writing their binary inverse +instead. +.Ar fix_spec +is a string containing any combination of the following characters: +.Pp +.Bl -tag -compact -width xx +.It Cm l +Fix the Nintendo logo +.Pq Ad 0x104 Ns \(en Ns Ad 0x133 . +.It Cm L +Trash the Nintendo logo. +.It Cm h +Fix the header checksum +.Pq Ad 0x14D . +.It Cm H +Trash the header checksum. +.It Cm g +Fix the global checksum +.Pq Ad 0x14E Ns \(en Ns Ad 0x14F . +.It Cm G +Trash the global checksum. +.El .It Fl i Ar game_id Set the game ID string .Pq Ad 0x13F Ns \(en Ns Ad 0x142 @@ -104,12 +129,8 @@ overlapping portion of the title. .It Fl V Print the version of the program and exit. .It Fl v -Validate the header and fix checksums: the Nintendo character area -.Pq Ad 0x104 Ns \(en Ns Ad 0x133 , -the header checksum -.Pq Ad 0x14D , -and the global checksum -.Pq Ad 0x14E Ns \(en Ns Ad 0x14F . +Equivalent to +.Fl f Cm lhg . .El .Sh EXAMPLES Most values in the ROM header are only cosmetic.