Die Grafikeinheit
Die Grafikeinheit des Gameboys war lange etwas mysteriös. Zwar war bekannt, wie sie prinzipiell funktioniert. Die letzten Details wurden allerdings erst vor wenigen Jahren entschlüsselt, der weiter unten eingebettete Ultimate Gameboy Talk auf dem 33c3 erläutert sie. Auch ich habe versucht, mir einen Reim auf das Bekannte zu machen - wohl wissend, dass meine Lösung niemals in Hardware funktionieren würde.
Wie der Großteil der auf 2D-Grafik beschränkten Konsolen basiert die Grafik des Gameboys auf Tiles (Kacheln) und Sprites (wörtlich: Geist, Gespenst oder Kobold). Aus den Tiles wird der Bildhintergrund aufgebaut, darüber dürfen sich die Sprites frei bewegen. So lassen sich komplexe Szenerien mit geringem Speicherbedarf aufbauen. Nintendo benutzt statt Sprites den Begriff Objects. Beim Gameboy sind Tiles und Sprites normalerweise 8 x 8 Pixel groß. Für Sprites können allerdings auch zwei solcher Blöcke zusammengefasst werden. Da sie dann 8 x 16 Pixel groß sind, kann mehr Bildschirmfläche mit Sprites bedeckt werden.
Die Bilddaten für Sprites und Tiles werden im Grafikspeicher abgelegt, bis zu 384 Blöcke von 8 x 8 Pixeln sind möglich. Dabei sind Teile des Speichers zwischen Sprites und Tiles geteilt. Insgesamt 40 Sprites kann der Gameboy gleichzeitig darstellen, allerdings dürfen es nicht mehr als zehn pro Bildschirmzeile sein. Ihre Position und andere Parameter werden über den bereits erwähnten OAM konfiguriert.
Der Hintergrund einer Szene wird anhand eines 32-x-32-Rasters aus Tiles aufgebaut. Sie befinden sich also immer an festen Positionen. Damit ist der Hintergrund 256 x 256 Pixel groß, das Display des Gameboys kann allerdings nur 160 x 144 Pixel darstellen. Daher kann über zwei Register der darzustellende Teil des Hintergrunds ausgewählt werden. So kann im unsichtbaren Teil bereits ein neuer Hintergrund vorbereitet werden und die Welt bewegt sich flüssig.
So kommt das Bild auf den Bildschirm
Im Gegensatz zu moderneren Grafikkarten nutzt die Hardware des Gameboys keinen Speicher, in dem das ausgegebene Bild aufgebaut wird (Frame Buffer). Es wird direkt pixelweise auf dem Flüssigkristallbildschirm aufgebaut. Das klingt erst einmal unwichtig, hat allerdings konkrete Auswirkungen auf den Emulator: Die Funktionalität der Hardware muss eins zu eins nachgebaut werden. Ein Spiel kann nämlich zwischen zwei Bildschirmzeilen Parameter der Grafikhardware ändern, wodurch Effekte erzeugt werden. Sie funktionieren nicht, wenn beispielsweise die gesamten Bilddaten einmal pro Bild in einen Anzeigepuffer kopiert werden.
Die Grafikhardware liest beim Aufbau des Bildes aus OAM und Grafikspeicher. In letzterem befindet sich neben den Daten für Tiles und Sprites das Raster für den Hintergrund. Zusätzlich kann auch noch ein Fenster definiert werden, das über dem Hintergrund angezeigt wird. Es wird gern für Textausgaben genutzt, greift ebenfalls auf die Tiles zurück und wird mit einem 32-x-32-Raster aufgebaut.
Bevor Pixeldaten ausgegeben werden, sucht die Grafikhardware sich zuerst die in der aktuellen Zeile aktiven Sprites aus dem OAM. Danach erzeugt sie pixelweise das Bild, für jedes Pixel wird entschieden, ob es die Farbe des Hintergrunds, des Fensters oder eines Sprites bekommt. Die Auswahl des Farbwerts geschieht anhand fester Prioritäten. Die vier möglichen Graustufen sind übrigens nicht in den jeweiligen Bilddaten festgelegt. Sie werden anhand von Farbpaletten ausgewählt, die Werte in den Bilddaten sind Indizes in die aktuelle Palette.
Für Sprites und Tiles existieren unabhängige Paletten. Die Sprites haben sogar zwei, die anzuwendende wird im OAM-Eintrag des Sprites ausgewählt. Über die Paletten lassen sich wieder leicht Effekte realisieren. So kann beispielsweise das Bild ausgeblendet werden, ohne dass die zugrundeliegenden Bilddaten verändert werden müssen. Genauer wird das alles im folgenden Video erklärt.
Und so habe ich es für moderne Computer emuliert
Der Software-Renderer, den ich für meinen Emulator programmiert habe, setzt den oben beschriebenen Ablauf um. Dabei gibt es noch ein paar Kleinigkeiten zu beachten, beispielsweise die Prioritäten von Hintergrund, Fenster und Sprites. Auch untereinander haben die Sprites noch einmal Prioritäten. Sie hängen von der Position im OAM ab und bestimmen, welches Sprite gezeichnet wird, wenn zwei sich überlappen. Das wird für jedes Pixel entschieden.
Damit wird ein Bild mit vier Graustufen erzeugt - das gefällt mir besser als die Grüntöne des originalen Gameboy. Es wird mit Javas Swing-Bibliothek für graphische Oberflächen in ein Fenster kopiert und dabei skaliert. So füllt es das Fenster vollständig aus und die Emulatorfunktion muss nur ein Format erzeugen können - die 160 x 144 Pixel des Gameboy-Bildschirms. Kommen wir als nächstes zum Sound, denn auch den möchte ich bei den meisten Spielen nicht vermissen. Dem Taltal-Gebirge würde etwas fehlen!
Oder nutzen Sie das Golem-pur-Angebot
und lesen Golem.de
- ohne Werbung
- mit ausgeschaltetem Javascript
- mit RSS-Volltext-Feed
Der Speicher | Das Soundmodul |
+1 Bin schon auf den Folgeartikel zur Umsetzung der parallel stattfindenden HW-Abläufe...
Sheep It Up ist für mich ein Musterbeispiel eines Homebrewspiels für den GB. Simpel...
Ich finde es daher umso erstaunlicher, wie die Leute Cores für den Mister erstellen. Ich...
Zuerst noch einmal vielen Dank für den Artikel. Bei aller Abkürzung hätte ich mir aber...
Kommentieren