shithub: rgbds

Download patch

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.