#240 – Patching GB Roms feat. IR Remote

Gegen Ende von Artikel 215 haben wir ja unsere selbstgebastelte Game Boy Flashkarte mit der „Remote Control“-ROM aus Artikel 93 beschrieben:

Zur Erinnerung: Im Zusammenspiel mit einem Game Boy Color lassen sich mit der Software Infrarotsignale erlernen und über den Infrarotsensor des GBC verschicken. Das Teil funktioniert (sofern die Batterien des Game Boy Colors noch gut voll sind) prima und ich habe damit schon verschiedenste Geräte fernsteuern können. Aktuell nutze ich das Modul zur Bedienung des Fernsehers im Spielezimmer über meinen Game Boy Color. Ich weiß – mega nerdy! 😛

Eine Sache, die mich an der Software allerdings schon immer etwas gestört hat, ist die recht allgemein gehaltene Beschriftung der einzelnen Felder zur Auswahl eines IR-Signals. Besser wäre es, wenn anstatt „A“, „B“, oder „C“ eine etwas eindeutigere Beschriftung wie z.B. „P“ (für Power), „M“ (für Mute) oder „+“ und „-“ für die Lautstärke stehen würden!

Die Preisfrage ist: Wie können wir das ändern? Die Software komplett neu zu schreiben, kommt für mich nicht in Frage. Ich habe vor Jahren damit schon mal etwas herumexperimentiert, bin aber an den Entwicklungswerkzeugen sowie deren (größtenteils nicht vorhandenen) Support für die Ansteuerung der Infrarotdioden gescheitert.

Fun Fact: Zwar ließe sich das Grundgerüst sicher in C realisieren, aber für die Infrarot-Ansteuerung gibt es kaum Beispiele und wenn dann nur irgendwelche kryptischen Assembler-Schnipsel, welche ich nicht mal kompiliert, bzw. assembliert bekommen habe. Seht es mir nach, dass ich mich nicht noch weiter in das Thema vergraben möchte – #Lebenszeit und so! 😉

Hm, wenn man den Quellcode der Remote Control ROM hätte, könnte man versuchen die entsprechenden Änderungen im Programm vorzunehmen und es dann (z.B. mit dem Development-Kit GBDK-2020) neu zu kompilieren. Blöd nur, dass wir den Quellcode nicht haben! 😀 Dementsprechend müssen wir einen anderen Weg finden. Ich glaube, ich habe da auch schon so eine Idee…

Als erstes sollten wir uns mal die ROM-Datei vom Modul sichern. Dafür habe ich die „Billigversion“ des Cart Readers (aus den Artikeln 221 und 222) verwendet:

Schön ist, dass wir beim Sicherungsvorgang gleich die aus dem ROM-Header ausgelesenen Informationen angezeigt bekommen. Wie wir in Artikel 215 gelernt haben, besteht jedes Game Boy Modul aus einem ROM-Baustein sowie optional weiteren Komponenten (z.B. einem Memory Bank Controller oder RAM-Bausteinen). In unserem Fall ist das Programm (also die Daten auf dem ROM-Baustein) 64kB groß und verwendet zusätzlich einen MBC1-Chip. Meine Vermutung ist, dass der MB-Controller verbaut wurde, um auf den 32kB großen RAM-Chip zuzugreifen.

Fun Fact: Das Programm selbst (also die Remote Control Anwendung) ist so klein, dass es vermutlich auch mit einem 32kB großen ROM-Baustein (ohne Memory Bank Controller und RAM-Chip) auskommen würde. Allerdings wäre es dann ziemlich nutzlos, denn ohne den Zugriff auf RAM-Speicher könnte man keine Infrarotsignale einspeichern und anschließend abspielen! 😉

Um zu überprüfen, ob die ROM-Datei korrekt ausgelesen wurde, laden wir das Programm in einen Game Boy Emulator auf dem PC. Ich nehme hierfür immer sehr gerne „BGB“, da die Software sehr akkurat (damit meine ich nah an der originalen Hardware) arbeitet.

Läuft! Der Lesevorgang scheint also geklappt zu haben. Jetzt wird es Zeit, dass wir uns die ROM-Datei etwas genauer zu Gemüte führen. Hierfür öffnen wir das gute Stück mit einem Hex-Editor (z.B. HxD):

Im Adressbereich „0100-014F“ residiert der Cartridge Header. Darin findet man die gleichen Informationen, welche uns der Cart Reader beim Auslesevorgang angezeigt hat. Beispielsweise steht an der Adresse „0147“ der MBC-Typ (in einem Byte kodiert). Der Wert „02“ steht hierbei für „MBC1+RAM“. Im direkt darauffolgenden Byte ist die ROM-Größe angegeben. Der Wert „01“ steht hierbei für 64kB – passt!

Wie ich vermutet hatte, ist das eigentliche Programm deutlich kleiner als 64kB, denn ab der Adresse „40A4“ (16.548 Bytes) finden sich nur noch Füll-Bytes („FF“). Gut für uns, denn so gibt es weniger Zeug, was wir analysieren müssen! 😀

Fun Fact: Es sieht so aus, als nutze die Anwendung größtenteils nur die erste ROM-Bank (Adressbereich 0000-3FFF) und einen winzigen Teil der zweiten (4000-7FFF).

Beim Durchschauen der ROM-Datei ist mir aufgefallen, dass die Entwickler wohl auch die Daten sauber vom eigentlich Programmcode getrennt und auf irgendwelche „Schweinereien“, also irgendwelche technischen Tricks zur Verschlüsselung oder Komprimierung der Daten (wie bei der EB-EXE-Datei in den Artikeln 168 und 169) verzichtet haben. Das ist sehr schön, denn so können wir auf einen Blick erkennen, was binärer Programmcode ist (oben Bild) und was Programmdaten (z.B. Fehlermeldungen, Texte und Beschreibungen) sind (unten im Bild):

So finden sich an einigen Stellen tatsächlich Klartextwerte, welche die Menüstruktur repräsentieren könnten. Ich vermute, dass sich ab den Adressen „38BA“ und „3A22“ die Beschreibungen des PLAY- sowie des RECORD-Menüs befinden:

Probieren geht über Studieren. Ich denke, wir sollten die entsprechenden Werte einfach mal nach unserem Gusto ersetzen und schauen, ob das Programm noch läuft! 😉

Hm, zumindest der Emulator kann die ROM noch öffnen. Warum der Emulator einige der Speicherplätze als „gefüllt“ (mit gespeichertem Infrarotsignal bestückt) anzeigt, obwohl gar keine „SAVE-Datei“ (mit dem RAM-Inhalt) angelegt ist, ist mir schleierhaft! 😀

Um ganz sicher zu gehen, dass unser angepasstes Programm auch auf einem echten Game Boy Color funktioniert, sollten wir die ROM-Datei mal auf das Modul schreiben. Theoretisch könnten wir das auch mit dem Cart Reader machen, aber um etwas Abwechslung reinzubringen verwende ich diesmal den Cart Flasher aus Artikel 93. Wenn man schon geeignetes Werkzeug hat, dann sollte man es auch ab und an verwenden! 😉

Es ist wichtig, dass man dem Tool die korrekten Flash- und RAM-Größen des Hardware-Moduls verrät und vorab den Flashspeicher (also vor dem Beschreiben mit der neuen Programmversion) erstmal löscht, sonst treten nur irgendwelche merkwürdigen Fehler auf. Und ja, ich spreche aus Erfahrung! 😀

Scheint prinzipiell zu funktionieren – die geänderten Menüelemente fallen sofort auf!

Not so fun Fact: Leider habe ich beim Beschreiben des Flashspeichers auch versehentlich den RAM-Speicher (welcher die Infrarotsignale enthält) gelöscht. Dementsprechend sind alle gespeicherten Infrarotcodes zur Bedienung des Fernsehers verloren gegangen. Shit happens! xD

Um die Software zu testen, müssen wir also noch die einzelnen Speicherplätze wieder mit den entsprechenden Remote-Codes befüllen. Das geht über das „REC“-Menü sowie mit Hilfe einer IR-Eingangsquelle – so wie z.B. der Fernbedienung des LG-TVs (siehe Artikel 229):

Die Beschriftung macht nun meiner Meinung nach deutlich mehr Sinn:

Bleibt nur zu hoffen, dass auch die „Technik“ (also das Abspielen der Infrarotcodes) noch funktioniert. Scheinbar haben wir – obwohl wir auf gut Glück irgendwelche Hexwerte in der ROM-Datei angepasst haben – nichts zerstört, denn das Modul lässt sich tatsächlich immer noch einwandfrei als Fernbedienung verwenden – cool! 🙂

Um ehrlich zu sein, bin ich erstaunt, dass das alles auf Anhieb geklappt hat! 😀 Ok – letztendlich haben wir ja auch nur ein paar Buchstaben ausgetauscht, aber selbst das ist leider nicht immer ganz trivial. Möchte man größere Änderungen an der Programmlogik (Menüstruktur, Speicherzugriffe, etc.) vornehmen, müsste man die ROM-Datei viel intensiver mit speziellen Werkzeugen (Disassembler oder Code-Debugger zur Untersuchung der Maschinenbefehle mit Breakpoints zur Laufzeit) unter die Lupe nehmen. Ich bin nicht böse, dass wir uns das heute erspart haben! 😀

Soweit so gut, damit sind wir fertig, oder? Nicht ganz, denn tatsächlich ist das „direkte Ändern im Binärcode des Moduls“ alles andere als sicher und auch recht fehleranfällig. Normalerweise werden solche Änderungen an einer ROM-Datei in sogenannte „Rom-Patches“ (eigene Datei mit der Beschreibung der Änderung) ausgelagert, welche dann mit Hilfe einer Patch-Software auf die originale ROM-Datei angewandt werden.

Fun Fact: Das Prinzip ist das gleiche, wie bei einem Patch, den man für ein PC-Spiel (z.B. zur Korrektur von Fehlern oder zur Ergänzung neuer Spielelemente) installiert. Letztendlich wird dabei auch nur das bestehende Programm modifiziert oder um weitere Daten erweitert.

Mit dem Tool „Lunar IPS“ funktioniert sogar der umgekehrte Weg und wir können uns aus der von uns modifizierten ROM-Datei sowie dem originalen ROM-File einen Patch, welcher alle Änderungen die wir gemacht haben beinhaltet, erstellen:

Fun Fact: Das Dateiformat solcher Patches ist für gewöhnlich „.IPS“.

Betrachten wir den generierten Patch in einem Hexeditor, kann man erkennen, dass die Struktur dieser Binärpatches relativ einfach gehalten ist. Zu Beginn der Datei findet sich der String „PATCH“ (50 41 54 43 48) und am Ende die Abschlusskennung „EOF“ (45 4F 46). Die Änderungen werden in Blöcken zusammengefasst und sind nach folgendem Schema aufgebaut: Adresse, an der die Änderung durchgeführt werden soll (3 Byte), Länge der zu ändernden Daten (2 Byte), zu ändernde Daten (variabel). Hier ein Beispiel der Änderung von „F“ und „G“ zu „U“ und „P“.

Fun Fact: Neben IPS gibt es auch noch einige weitere Dateiformate für binäre Patches wie z.B. „UPS“ oder „BPS“. Letztendlich sind das aber alles Weiterentwicklungen, welche auf dem IPS-Format basieren. Ein Nachteil von IPS-Patchen ist, dass die zu patchende Datei max. 16 MB groß sein kann.

Die Software arbeitet clever und fasst gleich mehrere Änderungen (Bytes), welche im Binärfile hintereinanderkommen, zusammen. Tatsächlich ist das Format aber relativ flexibel und lässt auch das Modifizieren von einzelnen Bytes zu. Das ist gut, denn so kann man auch als dummer Mensch manuell nach einem ganz einfachen Muster solche Patches erstellen. Zugegeben – richtig viel Spaß macht das nicht, aber es funktioniert! 😀 So sieht z.B. ein händisch zusammengebastelter Patch aus:

Fun Fact: Ich habe es ausprobiert – tatsächlich erzeugen beide Patch-Files (das automatisch generierte und das von mir händisch zusammengebastelte) das gleiche Ergebnis! 🙂

Hm, noch besser wäre es natürlich, wenn man den Patch nicht händisch zusammenbasteln müsste, sondern einfach mit Hilfe einer grafischen Oberfläche generieren und im Idealfall sogar bearbeiten könnte. Durch den logischen und strukturierten Aufbau des IPS-Formats (samt Möglichkeit zum Tausch von nur einem Byte pro Block) steht einer Automatisierung mit einem kleinen Programm eigentlich nichts im Wege. Na, ich denke da sollte sich doch was entwickeln lassen! 😉

Auf der Suche nach einer geeigneten Programmiersprache und Entwicklungsumgebung für eine Oberflächenanwendung habe ich mich wieder an die Software „wxDev-C++“ erinnert, welche ich bereits bei ein paar älteren Projekten verwendet habe. Damit lassen sich sehr einfache C++-Konsolen- oder Windows-Dialoganwendungen (.EXE) mit Schaltflächen und Eingabefeldern erstellen.

Die Umsetzung war dann leider trotzdem nicht so einfach, wie ich es mir vorgestellt hatte. Man merkt richtig, wie schnell man einrostet, wenn man eine Zeit lang nichts programmiert! Ich kann euch gar nicht sagen wie oft ich im Internet nach Befehlen und Beispielen suchen musste… 😀

Not so fun Fact: Um einen Fehler beim Schreiben der Hex- und Binärwerte in die Patchdatei aufzuspüren, habe ich letztendlich doch noch einen recht störrischen Code-Debugger verwenden müssen. Bitte kein Mitleid – selbst schuld, wenn man sich so alberne Ideen in den Kopf setzt! 😀

Passend zum Infrarot-Fernbedienungsprogramm habe ich die Anwendung „RemConEdit“ getauft. Zugegeben – das Ergebnis ist sehr simpel, tut aber genau das was es soll. Mit der Funktion „Patch erzeugen“ werden die Werte der einzelnen Felder in einen IPS-Patch für die ROM-Datei geschrieben und mit „Patch einlesen“ lassen sich bestehende Patchfiles öffnen, bearbeiten und neu abspeichern.

Klar, noch besser wäre es, wenn man die Beschriftung der einzelnen Felder gleich direkt auf dem Game Boy anpassen könnte. Um so etwas zu realisieren müsste man aber deutlich mehr ändern (einen Editor implementieren) und vermutlich die Software komplett neu schreiben. Und ja, ihr Klugscheißer – klar kann man die paar Buchstaben auch einfach direkt in der ROM-Datei abändern, aber ich finde den Weg über so eine Oberfläche hat schon was. Außerdem haben wir dadurch gleich noch einen Blick auf das Patchen von Game Boy ROM-Dateien geworfen und das war ja schließlich der eigentliche Sinn vom heutigen Artikel, oder? 😛

In diesem Sinne – bis die Tage, ciao!

Write a comment