Im Grunde kann man sagen, dass einen fortgeschrittenen und einen anfangenden Übersetzer nur eine Sache unterscheidet - das Anwenden und das Nutzen eines Debuggers.
Jahrelang habe ich alles durch simples versuchen gemacht, “Was passiert wenn ich das hier ändere?”, und es war teilweise eine frustrierende Zeit. Besonders als es später an die Komprimierungen ging wurde es nur frustrierender. Bei solchen Sachen (und anderen natürlich auch) ist der Debugger des Rom-Hackers bester Freund. Ich kann mir einfach nicht mehr vorstellen, ohne einen Debugger zu arbeiten. Hier einige der Aspekt, die den Debugger so unerlässlich machen:
Das einfachste und zugleich effektivste was ein Debugger zu bieten hat sind Breakpoints. Das heißt, dass das Programm (in diesem Fall das emulierte Spiel) angehalten wird, wenn bestimmte Kriterien getroffen werden. Meistens ist das eines der Folgenden:
- Execute. Die Ausführung wird angehalten, wenn ein bestimmter Codeabschnitt ausgeführt wird
- Write. Es wird dann angehalten, wenn an eine bestimmte Stelle im Speicher geschrieben wird
- Read. Wenn von einer bestimmten Stelle gelesen wird, wird die Ausführung unterbrochen
Fortgeschrittene Debugger haben noch mehr, aber das sind die Grundlegendsten. Alle drei Kriterien sind unerlässlich, und alle drei werden sehr häufig gebraucht. Man nutzt sie etwa, um zu erfahren von wo etwas geladen wird (Read), welcher Codeabschnitt an eine bestimmte Stelle schreibt (Write) oder welchen Wert eine Variable hat, wenn ein Abschnitt durchlaufen wird (Execute).
Und das bringt uns auch gleich zum nächsten Feature. In fast allen Debuggern ist es möglich, den Code Schritt für Schritt auszuführen, und jeweils das Verhalten und die Werte der Register zu beobachten. Dieses Feature ist vital, wenn man zum Beispiel eine Komprimierungsroutine verstehen will, oder einfach wissen möchte, wie das Spiel bestimmte Werte berechnet.
Ein weiteres fortgeschrittenes Feature ist das direkte Bearbeiten des Codes innerhalb des Debuggers. Es gibt einfach keinen besseren Weg etwas zu verstehen, als es gezielt zu zerstören. Wenn man etwas ändert, und das Spiel dadurch sein Verhalten auch ändert, dann hat man eine richtige Stelle gefunden. Das innerhalb des Debuggers zu machen ist unglaublich nützlich, aber bei weitem nicht alle Debugger erlauben es. Zu diesem Feature zählt auch, dass man die Werte der Register frei ändern kann - ebenfalls unglaublich nützlich, nur auf tieferer Ebene.
Wenige Debugger erlauben das ändern des Codes beim Ausführen - aber fast alle erlauben das Loggen (”Tracen”) des Codes in eine Textdatei. Es wird jede ausgeführte Anweisung geschrieben, so dass man schrittweise alles nachvollziehen kann.
Vorausgesetzt, dass man mit dem jeweiligen Assembler-Dialekt vertraut ist, kann man mit Debuggern so unendlich viel erreichen. Man mag es anfangs nicht glauben, aber die Möglichkeiten sind schier unbegrenzt. Ein besonders nennenswerter Debugger ist no$gba, der einen wundervollen Einstieg bietet, und mit zu den besten Debuggern überhaupt zählt.