Assembler...
Ich hab vorgestern mal wieder damit begonnen meinen Gameboy-Emulator weiterzubauen. Vor zwei Jahren habe ich mich ein paar Tage damit beschaeftigt, Informationen ueber das System gesucht (es gibt einige gute Docs im Netz) -- mir gehts dabei primaer um den Lerneffekt. Habe noch nie einen Konsolen-Emulator geschrieben, und der Gedanke ein Computersystem komplett zu verstehen ist recht verlockend. Es gibt im Low-Level-Bereich durchaus noch mehr Dinge die ich noch lernen kann und auch lernen will.
Ich dachte mir Gameboy wird schon nicht so komplex sein... spaeter musste ich dann feststellen, dass das Instruction-Set der Gameboy-CPU doch nicht ganz ohne ist, es sind wohl um die 500 Befehle...
Das erste was ich vor zwei Jahren gemacht habe ist die Grafikausgabe... also noch keine Emulation der CPU etc... ich habe einfach mal geschaut wie im Speicher die Grafiken hinterlegt sind, die ROM-Datei in den Speicher geladen und mit etwas C-Code und OpenGL angezeigt... das Ergebnis ist recht motivierend, weil ich so recht schnell die Tiles aus Zelda anzeigen konnte...
Aber ein Emulator ist das natuerlich noch nicht. Also habe ich damit begonnen die CPU nachzubauen. Mein Ziel war es den Startscreen von Tetris anzeigen zu koennen... nach und nach habe ich immer mehr Instruktionen eingebaut, aber von der Anzeige war ich noch weit entfernt. Gameboy-Spiele machen am Anfang viel Initialisierung, Speicher rumkopieren, VRAM befuellen, etc.
Auch kam ich schnell an die Grenzen meines C-Programms: Jede Instruktion war eine eigene C-Funktion die ueber eine Listenstruktur mit den jeweiligen Befehls-Infos verknuepft war... sehr simpel... aber mit der Zeit sehr umstaendlich. Wenn man genau schaut, machen (wie in Assembler ueblich) die meisten Befehle eigentlich das gleiche... nur die Register und Speicheradressen unterscheiden sich. Also muss ein anderer Ansatz her.
Vor zwei Jahren habe ich dann damit angefangen das Programm auf C++ umzuschreiben... ueber Templates und Referenz-Objekte kann ich so eine Instruktion wie z.B. "LD" 1x programmieren und der Template-Code kann mir das jeweils als 8bit und 16bit-Version erstellen jeweils dann von und zu beliebigen Registern oder Adressen im Speicher. Nach einiger Zeit ist das Projekt leider eingeschlaffen...
Vorgestern habe ich es wieder weitergemacht. Inzwischen habe ich etwa 40 Befehle realisiert und im Grunde ist mein Emulator sogar ein echter kleiner Debugger und Disassembler mit Breakpoints etc...
Das ist auch notwendig, weil ich ohne solche Debugging-Moeglichkeiten eigentlich keine Moeglichkeit haette zu pruefen, ob der Emulator richtig emuliert.
Jetzt habe ich den ersten grossen Schritt geschafft: Er emuliert ein Hello-World Gameboy-ROM:
Mal schauen ob ich im naechsten Schritt den Tetris-Startscreen angehen kann... aber es ist nicht so einfach. Es ist doch relativ komplex und es fehlt noch extrem viel: Mapped Memory, Spezialregister (IO/LCD-Bildschirm etc), Interrupts, Eingabe, Scrolling, Korrektes Timing, etc...
Aber ich glaube wenn man den Befehlssatz einigermassen komplett hat und ein gescheites Speichersystem, dann ist der Rest nicht mehr so schwer...