Add a new flag, -f, which allows independently fixing or trashing checksums.

This commit is contained in:
Anthony J. Bentley
2018-03-10 21:48:23 -07:00
parent f86dbafad0
commit 5a4bbe4985
2 changed files with 63 additions and 15 deletions

View File

@@ -20,9 +20,9 @@
static void print_usage(void) static void print_usage(void)
{ {
printf( printf(
"usage: rgbfix [-CcjsVv] [-i game_id] [-k licensee_str] [-l licensee_id]\n" "usage: rgbfix [-CcjsVv] [-f fix_spec] [-i game_id] [-k licensee_str]\n"
" [-m mbc_type] [-n rom_version] [-p pad_value] [-r ram_size]\n" " [-l licensee_id] [-m mbc_type] [-n rom_version] [-p pad_value]\n"
" [-t title_str] file\n"); " [-r ram_size] [-t title_str] file\n");
exit(1); exit(1);
} }
@@ -37,7 +37,12 @@ int main(int argc, char *argv[])
*/ */
/* all flags default to false unless options specify otherwise */ /* 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 settitle = false;
bool setid = false; bool setid = false;
bool colorcompatible = false; bool colorcompatible = false;
@@ -61,7 +66,7 @@ int main(int argc, char *argv[])
int version = 0; /* mask ROM version number */ int version = 0; /* mask ROM version number */
int padvalue = 0; /* to pad the rom with if it changes size */ 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) { switch (ch) {
case 'C': case 'C':
coloronly = true; coloronly = true;
@@ -69,6 +74,14 @@ int main(int argc, char *argv[])
case 'c': case 'c':
colorcompatible = true; colorcompatible = true;
break; 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': case 'i':
setid = true; setid = true;
@@ -168,7 +181,9 @@ int main(int argc, char *argv[])
printf("rgbfix %s\n", get_package_version_string()); printf("rgbfix %s\n", get_package_version_string());
exit(0); exit(0);
case 'v': case 'v':
validate = true; fixlogo = true;
fixheadsum = true;
fixglobalsum = true;
break; break;
default: default:
print_usage(); print_usage();
@@ -195,7 +210,7 @@ int main(int argc, char *argv[])
* Write changes to ROM * Write changes to ROM
*/ */
if (validate) { if (fixlogo || trashlogo) {
/* /*
* Offset 0x1040x133: Nintendo Logo * Offset 0x1040x133: Nintendo Logo
* This is a bitmap image that displays when the Game Boy is * 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 0x14D0x14F, They must * See also: global checksums at 0x14D0x14F, They must
* also be correct for the game to boot, so we fix them * 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] = { uint8_t ninlogo[48] = {
@@ -217,6 +232,10 @@ int main(int argc, char *argv[])
0xDD, 0xDC, 0x99, 0x9F, 0xBB, 0xB9, 0x33, 0x3E 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); fseek(rom, 0x104, SEEK_SET);
fwrite(ninlogo, 1, 48, rom); fwrite(ninlogo, 1, 48, rom);
} }
@@ -415,7 +434,7 @@ int main(int argc, char *argv[])
fputc(version, rom); fputc(version, rom);
} }
if (validate) { if (fixheadsum || trashheadsum) {
/* /*
* Offset 0x14D: Header Checksum * Offset 0x14D: Header Checksum
*/ */
@@ -426,9 +445,14 @@ int main(int argc, char *argv[])
for (int i = 0; i < (0x14D - 0x134); ++i) for (int i = 0; i < (0x14D - 0x134); ++i)
headcksum = headcksum - fgetc(rom) - 1; headcksum = headcksum - fgetc(rom) - 1;
if (trashheadsum)
headcksum = ~headcksum;
fseek(rom, 0x14D, SEEK_SET); fseek(rom, 0x14D, SEEK_SET);
fputc(headcksum, rom); fputc(headcksum, rom);
}
if (fixglobalsum || trashglobalsum) {
/* /*
* Offset 0x14E0x14F: Global Checksum * Offset 0x14E0x14F: Global Checksum
*/ */
@@ -445,6 +469,9 @@ int main(int argc, char *argv[])
while ((byte = fgetc(rom)) != EOF) while ((byte = fgetc(rom)) != EOF)
globalcksum += byte; globalcksum += byte;
if (trashglobalsum)
globalcksum = ~globalcksum;
fseek(rom, 0x14E, SEEK_SET); fseek(rom, 0x14E, SEEK_SET);
fputc(globalcksum >> 8, rom); fputc(globalcksum >> 8, rom);
fputc(globalcksum & 0xFF, rom); fputc(globalcksum & 0xFF, rom);

View File

@@ -14,6 +14,7 @@
.Sh SYNOPSIS .Sh SYNOPSIS
.Nm rgbfix .Nm rgbfix
.Op Fl CcjsVv .Op Fl CcjsVv
.Op Fl f Ar fix_spec
.Op Fl i Ar game_id .Op Fl i Ar game_id
.Op Fl k Ar licensee_str .Op Fl k Ar licensee_str
.Op Fl l Ar licensee_id .Op Fl l Ar licensee_id
@@ -46,6 +47,30 @@ If both this and the
flag are set, flag are set,
.Fl C .Fl C
takes precedence. 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 .It Fl i Ar game_id
Set the game ID string Set the game ID string
.Pq Ad 0x13F Ns \(en Ns Ad 0x142 .Pq Ad 0x13F Ns \(en Ns Ad 0x142
@@ -104,12 +129,8 @@ overlapping portion of the title.
.It Fl V .It Fl V
Print the version of the program and exit. Print the version of the program and exit.
.It Fl v .It Fl v
Validate the header and fix checksums: the Nintendo character area Equivalent to
.Pq Ad 0x104 Ns \(en Ns Ad 0x133 , .Fl f Cm lhg .
the header checksum
.Pq Ad 0x14D ,
and the global checksum
.Pq Ad 0x14E Ns \(en Ns Ad 0x14F .
.El .El
.Sh EXAMPLES .Sh EXAMPLES
Most values in the ROM header are only cosmetic. Most values in the ROM header are only cosmetic.