ref: 5a4bbe4985fe9d73eafabd78a6a305aff8cff1dd
parent: f86dbafad0525a74ae048ecc6d4f15392930a3cf
author: Anthony J. Bentley <anthony@anjbe.name>
date: Sat Mar 10 16:48:23 EST 2018
Add a new flag, -f, which allows independently fixing or trashing checksums.
--- 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 @@
*/
/* 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 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 @@
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 @@
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 @@
* 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 @@
/*
* 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 @@
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 @@
fputc(version, rom);
}
- if (validate) {
+ if (fixheadsum || trashheadsum) {
/*
* Offset 0x14D: Header Checksum
*/
@@ -426,9 +445,14 @@
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
*/
@@ -444,6 +468,9 @@
fseek(rom, 0x150, SEEK_SET);
while ((byte = fgetc(rom)) != EOF)
globalcksum += byte;
+
+ if (trashglobalsum)
+ globalcksum = ~globalcksum;
fseek(rom, 0x14E, SEEK_SET);
fputc(globalcksum >> 8, rom);
--- 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 @@
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 @@
.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.