Retro Gaming: Wie man einen Emulator programmiert

Warum nicht mal selbst einen Emulator programmieren? Das ist lehrreich und macht Spaß - wenn er funktioniert. Wie es geht, zeigen wir am Gameboy.

Artikel von Johannes Hiltscher veröffentlicht am
Ein Gameboy mit seinem digitalen Zwilling, einem Emulator
Ein Gameboy mit seinem digitalen Zwilling, einem Emulator (Bild: Johannes Hiltscher/Golem.de)

Hat die Welt nicht eigentlich schon genug Emulatoren? Für jede Plattform gibt es einen, man muss ihn nur herunterladen - im schlimmsten Fall steht davor noch die Entscheidung, welcher es genau sein soll. Oder man lädt sich gleich Retropie herunter und kann direkt Dutzende Retro-Computer und -Konsolen nutzen.

Wer gern tüftelt und sich für Hardware interessiert, wird sicher ein weitergehendes Interesse an dem Projekt Emulator entwickeln. Eine gute Umsetzung ist nämlich gar nicht so einfach, dafür umso lehrreicher. Man gewinnt nicht nur spannende Einblicke in den Aufbau der jeweiligen Hardware, ein Emulator ist auch eine hervorragende Programmierübung. Begnügt man sich mit der Emulation einer 8- oder 16-Bit-Konsole, ist nicht einmal Assembler-Code erforderlich.

Teile des Codes in Assembler zu implementieren, bietet zwar enormes Optimierungspotenzial, ein halbwegs aktueller Computer führt aber selbst nicht-optimierten Java-Code schnell genug aus. Für erste Versuche ist das ein großer Vorteil, da selbst ohne Optimierung und große Hirnakrobatik ein voll funktionsfähiger Emulator entsteht.

Wo fange ich an?

Am Anfang steht natürlich die Frage: Was möchte ich emulieren? Für mich stand die Antwort fest - den klassischen Gameboy. Er hat drei Vorteile: Er ist gut dokumentiert, die Hardware ist übersichtlich und einfach - und er ist die Konsole meiner Kindheit. Das Gameboy-CPU-Manual lag seit Jahren auf meiner Festplatte, im Internet Archive findet sich sogar das Programmierhandbuch von Nintendo.

Die nächste Frage: Welche Programmiersprache nutze ich? Grundsätzlich funktioniert jede Sprache, so lange sie nicht zur Laufzeit interpretiert wird. Ich habe für meine Implementierung Java genutzt, denn eigentlich wollte ich den Emulator ursprünglich auf Android-Geräten laufen lassen. Daraus wurde nie etwas, aus diesem Grund kommen aber in diesem Artikel Begriffe aus der Java-Welt vor. Generell fand ich einen objektorientierten Ansatz hilfreich. Verwendet man Templates und Interfaces, erspart man sich viele manuelle Prüfungen - das kann helfen, Fehler zu vermeiden.

Und das möchte man, denn einen Emulator zu debuggen ist kein Vergnügen, da das erwartete Verhalten nur teilweise bekannt ist. Was die emulierte Software tut, ist in der Regel unbekannt, weshalb man bei Fehlern schnell im Trüben fischt. Daher lege ich allen, die sich an einem Emulator versuchen wollen, sehr ans Herz, alle entwickelten Komponenten zu testen. Ich habe tagelang einen Fehler gesucht, der durch die fehlerhafte Implementierung eines Prozessorbefehls entstanden war.

Was macht eigentlich ein Emulator?

Damit der Emulator originalgetreu funktioniert, ist eine exakte Nachbildung des Prozessors und der Peripherie als Software erforderlich. Die Software tut am Ende das, was auch der originale Prozessor macht: Sie liest und verarbeitet Befehle, zusätzlich werden Komponenten benötigt, die Grafik und Sound erzeugen.

Beim Gameboy steckt all das in einem Chip, das Mainboard ist recht übersichtlich. Darauf finden sich neben dem Chip 16 KByte RAM, von denen jeweils 8 KByte als Arbeits- und Grafikspeicher dienen. Der Prozessor ist ein Derivat des beliebten Z80, allerdings wurde der Befehlssatz stark beschnitten. So fehlen fast alle Befehle für 16-Bit-Arithmetik, dafür kamen einige eigene hinzu. Neben Operationen für binär codierte Dezimalzahlen (BCD) finden sich Befehle zur Manipulation einzelner Bits.

  • Das Mainboard des Gameboys ist übersichtlich: in der Mitte der Prozessor mit Grafik- und Soundeinheit, rechts oben der Grafikspeicher, darunter der normale RAM. Unten befindet sich der Steckverbinder für die Module. (Bild: Johannes Hiltscher/Golem.de)
  • So sieht ein Spielemodul von innen aus: rechts unten der ROM, links unten der RAM. Über dem RAM ist der MBC aufgelötet (hier ein MBC5), rechts oben die Pufferbatterie für den RAM. Sie sorgt dafür, dass dessen Inhalt nach dem Ausschalten erhalten bleibt. (Bild: Johannes Hiltscher/Golem.de)
  • Link und der Gegner bestehen aus je vier 8 x 8 Pixel großen Sprites (rot umrandet), der Hintergrund aus ebenso großen Tiles (grün umrandet). (Bild: Johannes Hiltscher/Golem.de)
Das Mainboard des Gameboys ist übersichtlich: in der Mitte der Prozessor mit Grafik- und Soundeinheit, rechts oben der Grafikspeicher, darunter der normale RAM. Unten befindet sich der Steckverbinder für die Module. (Bild: Johannes Hiltscher/Golem.de)

Die meisten Befehle sind ein Byte lang, die Abarbeitung erfolgt in vier Stufen. Dabei handelt es sich um die klassische Zerlegung der Ausführung in

  1. Befehl aus dem Speicher holen (Instruction Fetch, IF)
  2. Befehl decodieren (Instruction Decode, ID)
  3. Befehl ausführen (Execute)
  4. Ergebnis schreiben (Write Back, WB)

Da der Prozessor kein Pipelining implementiert, benötigt jeder Befehl vier (oder ein ganzzahliges Vielfaches) Prozessortakte zur Ausführung. Befehle, die länger als vier Takte zur Ausführung benötigen, durchlaufen die einzelnen Schritte mehrfach. Dabei passiert gegebenenfalls in einzelnen Phasen nichts, sie können allerdings nicht ausgelassen werden. Damit arbeitet der Prozessor Befehle mit einer Frequenz von 1,05 MHz ab.

Bitte aktivieren Sie Javascript.
Oder nutzen Sie das Golem-pur-Angebot
und lesen Golem.de
  • ohne Werbung
  • mit ausgeschaltetem Javascript
  • mit RSS-Volltext-Feed
Einen Prozessor mit Software nachbauen 
  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8.  


mipi 06. Jun 2022

+1 Bin schon auf den Folgeartikel zur Umsetzung der parallel stattfindenden HW-Abläufe...

TarikVaineTree 05. Jun 2022

Sheep It Up ist für mich ein Musterbeispiel eines Homebrewspiels für den GB. Simpel...

Kakiss 29. Mai 2022

Ich finde es daher umso erstaunlicher, wie die Leute Cores für den Mister erstellen. Ich...

Olstyle 29. Mai 2022

Zuerst noch einmal vielen Dank für den Artikel. Bei aller Abkürzung hätte ich mir aber...



Aktuell auf der Startseite von Golem.de
KI-Bildgenerator
Diese Kamera generiert, statt zu fotografieren

Ein Bastler hat eine KI-Kamera ohne Objektiv gebaut. Paragraphica erzeugt Schnappschüsse mit einem Raspberry Pi und Stable Diffusion.

KI-Bildgenerator: Diese Kamera generiert, statt zu fotografieren
Artikel
  1. Blizzard: Diablo 4 benötigt für Singleplayer ein Abo auf Konsolen
    Blizzard
    Diablo 4 benötigt für Singleplayer ein Abo auf Konsolen

    Anders als gerade noch von Blizzard dargestellt ist in Deutschland auf Xbox und Playstation ein Abo für Diablo 4 nötig - auch im Solomodus.

  2. Magnetohydrodynamischer Antrieb: US-Militär lässt lautlosen U-Boot-Antrieb entwickeln
    Magnetohydrodynamischer Antrieb
    US-Militär lässt lautlosen U-Boot-Antrieb entwickeln

    Bislang war magnetohydrodynamischer Antrieb der Fiktion vorbehalten. Dank Fortschritten in der Akku- und Fusionstechnik soll sich das ändern.

  3. Disney und Videostreaming: Über 100 Eigenproduktionen aus Abo von Disney+ entfernt
    Disney und Videostreaming
    Über 100 Eigenproduktionen aus Abo von Disney+ entfernt

    Eigentlich wollte Disney nur etwas mehr als 50 Eigenproduktionen aus Disney+ verschwinden lassen. Nun fehlen deutlich mehr Filme und Serien.

Du willst dich mit Golem.de beruflich verändern oder weiterbilden?
Zum Stellenmarkt
Zur Akademie
Zum Coaching
  • Schnäppchen, Rabatte und Top-Angebote
    Die besten Deals des Tages
    • Daily Deals • Roccat bis -50% • AVM Modems & Repeater bis -36% • MindStar: 13 Grafikkarten im Sale • Logitech G Pro Wireless Maus 89€ • The A500 Mini 74,99€ • Logitech G213 Prodigy Tastatur 49,90€ • Crucial P5 Plus (PS5-komp.) 1TB 71,99€, 2TB 133,99€ [Werbung]
    •  /