Emulator programmieren: Mit Software das Verhalten von Hardware nachbilden

In Hardware läuft alles parallel, in Software nicht. Wie kann man das emulieren? Und wie bremst man einen schnellen Prozessor zum langsamen Gameboy?

Artikel von Johannes Hiltscher veröffentlicht am
Ein Emulator muss nicht nur dasselbe tun wie der Original-Gameboy, er muss es auch in derselben Reihenfolge tun.
Ein Emulator muss nicht nur dasselbe tun wie der Original-Gameboy, er muss es auch in derselben Reihenfolge tun. (Bild: Johannes Hiltscher/Golem.de)

Die Programmteile zur Emulation von Hardwarekomponenten sind mehr oder weniger schnell programmiert. Wie kommt dann aber alles zusammen? Gar nicht so leicht, denn in einem Chip arbeiten alle Komponenten parallel. Gelegentlich beeinflussen sie einander, die meiste Zeit arbeiten sie aber unabhängig voneinander. Während sie unabhängig arbeiten, erledigen sie eine gewisse Menge ihrer jeweiligen Aufgaben.

Inhalt:
  1. Emulator programmieren: Mit Software das Verhalten von Hardware nachbilden
  2. Eigene Prozessverwaltung
  3. Zeitsynchronisation
  4. Bild und Ton müssen stimmen
  5. Letzte Schritte und Fazit

Ein Emulator muss die zeitlichen Abhängigkeiten zwischen den Komponenten nachbilden, um die Funktion des Originalsystems überzeugend zu imitieren. Ein weiteres Problem ist, dass das emulierende System meist wesentlich leistungsfähiger ist als das emulierte. Wir nehmen hier wieder den Gameboy als Beispiel, der führt maximal einen Befehl pro Prozessortakt aus. Superskalare Prozessoren, wie sie seit Jahrzehnten in Computern und seit Jahren auch Smartphones üblich sind, können mehrere Befehle pro Takt ausführen. Zudem takten sie um ein Mehrtausendfaches höher.

Ein Spiel, das mehrere hundert Mal schneller läuft, als es sollte, macht aber wenig Spaß. Wir benötigen eine Lösung für die beiden zuvor genannten Probleme - und werden uns damit andere, neue Probleme einhandeln. Aber auch die lassen sich lösen.

Parallelität der Hardware

Ein Emulator muss zuerst einmal dafür sorgen, dass die zeitlichen Zusammenhänge zwischen den einzelnen Komponenten erhalten bleiben. Am besten verstehen lässt sich das an einem konkreten Beispiel. Die Grafikeinheit erzeugt zeilenweise das dargestellte Bild. Während des Großteils dieser Zeit hat die CPU keinen Zugriff auf den Grafikspeicher und kann entsprechend auch keine Änderungen vornehmen. Das ist erst am Ende der Zeile während des horizontalen Strahlrücklaufs (horizontal blank) möglich.

Stellenmarkt
  1. Mitarbeiterin bzw. Mitarbeiter (m/w/d) IT-Change- und Releasemanagement
    Finanzbehörde Steuerverwaltung, Hamburg
  2. Facheinkäufer*in (IT/TK und Consulting)
    GASAG AG, Berlin
Detailsuche

Dann kann das ausgeführte Programm Änderungen vornehmen, die sich auf die Grafik auswirken. Viele Spiele nutzen das für Effekte. Der Emulator muss sicherstellen, dass in beiden Phasen der Zeilenausgabe - während der Pixelausgabe und des Strahlrücklaufs - die CPU genauso viele Befehle ausführen kann, wie sie es auf einem Gameboy könnte. Problematischer als zu viele ausgeführte Befehle ist es, wenn der emulierte Prozessor weniger Befehle ausführen kann als die echte Hardware. Denn dann können Berechnungen noch nicht abgeschlossen sein und sich anders auswirken als beim Original.

Genau dafür haben wir doch viele Prozessorkerne! Oder?

Es mag intuitiv erscheinen, die Parallelität der Hardware zu erreichen, indem jede Komponente mittels Thread auf einem eigenen Prozessorkern emuliert wird. Threads zerlegen ein Programm in mehrere, parallel abzuarbeitende Teile auf, die allerdings noch immer im selben Adressraum liegen und so mit wenig Aufwand kommunizieren und Daten austauschen können. Theoretisch wäre es also denkbar, einfach jede Hardwarekomponente durch einen Prozessorkern abarbeiten zu lassen. Der Ansatz hat allerdings ein Problem: Die einzelnen Threads müssen sehr oft aktiviert werden und führen teils nur wenige Befehle aus.

Das funktioniert zwar, ist aber ziemlich ineffizient. Denn die Prozessverwaltung (Scheduling) eines Betriebssystems verteilt die Prozessorzeit aus Effizienzgründen nicht in beliebig kleinen Teilen (Zeitscheiben). Hierfür gibt es eine Untergrenze, bei Linux ist sie variabel und liegt im Bereich einiger Millisekunden. Keiner der Abläufe in der Gameboy-Hardware dauert so lang. Da zudem die emulierende Hardware wesentlich leistungsfähiger ist als die originale, benötigen die entsprechenden Programmteile weniger Zeit, als sie es in der Hardware täten.

Nintendo Switch (OLED-Modell) Weiss

Die einzelnen Threads warten also viel, und wenn ein Thread für einen kürzeren Zeitraum warten muss, als das Betriebssystem ihn anbietet, geschieht das mit busy waiting. Dabei verbringt der Prozess die Zeit bis zur nächsten Aktivierung in einer Warteschleife und belegt weiterhin die von ihm genutzten Ressourcen. Schlimmer noch: Da ihm vom Betriebssystem irgendwann der Prozessor weggenommen wird, läuft er dann eine ganze Weile gar nicht.

Die Synchronisation eines solchen Systems wäre der reinste Horror. Abgesehen davon nutzt es mehr Rechenzeit als benötigt wird und verhindert, dass Prozessorkerne heruntertakten oder in einen Stromsparmodus versetzt werden. Die Lösung des Problems ist eine eigene Prozessverwaltung für die sehr kurzen Ausführungsintervalle von teils wenigen Dutzend Mikrosekunden.

Bitte aktivieren Sie Javascript.
Oder nutzen Sie das Golem-pur-Angebot
und lesen Golem.de
  • ohne Werbung
  • mit ausgeschaltetem Javascript
  • mit RSS-Volltext-Feed
Eigene Prozessverwaltung 
  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6.  


jhi (Golem.de) 14. Jun 2022 / Themenstart

Ja, das ist richtig, aber auf der Ebene dessen, was ich an Code schreibe, findet er nicht...

Kommentieren



Aktuell auf der Startseite von Golem.de
Franziska Giffey
Deepfake von Klitschko täuscht Berlins Bürgermeisterin

Berlins Regierende Bürgermeisterin Franziska Giffey (SPD) hat per Videokonferenz mit einem Deepfake von Vitali Klitschko gesprochen. Der Betrug flog auf.

Franziska Giffey: Deepfake von Klitschko täuscht Berlins Bürgermeisterin
Artikel
  1. Datenpanne: IT-Mitarbeiter verliert USB-Stick mit Meldedaten einer Stadt
    Datenpanne
    IT-Mitarbeiter verliert USB-Stick mit Meldedaten einer Stadt

    Die Tasche mit dem USB-Stick wurde über ein in ihr ebenfalls enthaltenes Smartphone geortet und gefunden.

  2. Logistik: Post will mit Solarschiff Pakete in Berlin verteilen
    Logistik
    Post will mit Solarschiff Pakete in Berlin verteilen

    Die Post will Pakettransporte von der Straße aufs Wasser verlagern. Das erste der Schiffe wird mit Solarstrom betrieben. In Zukunft sollen sie autonom fahren.

  3. Qualitätsprobleme: VW muss ID.Buzz-Produktion wegen Akkufehlern stoppen
    Qualitätsprobleme
    VW muss ID.Buzz-Produktion wegen Akkufehlern stoppen

    Qualitätsprobleme mit dem Akku des Volkswagen ID. Buzz sorgen für einen Produktionsstopp. Schuld soll eine Akkuzelle eines neuen Lieferanten sein.

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 • MSI 323CQRDE (WQHD, 165 Hz) 399€ • LG OLED 48C17LB 919€ • Samsung 980 PRO (PS5-komp.) 2 TB 234,45€ • Apple HomePod Mini 84€ • 16.000 Artikel günstiger bei Media Markt • MindStar (u. a. AMD Ryzen 7 5700G 239€, Samsung 970 EVO Plus 250 GB 39€ und Corsair Crystal 680X RGB 159€) [Werbung]
    •  /