Ein kleiner Zwischenstatus. Die CPU Instruktionen sind vollständig und die Betriebssystem ROM Dateien können geladen werden.

Außerdem kann man beliebige Speicherbereiche betrachten.

Implementierung der CPU

Die Implementierung der CPU Instruktionen ging schneller als erwartet.

Das langwierigste war die Implementierung der Testfälle. Ich denke nicht, dass alles korrekt ist, aber das kann man später durch verfeinern der Testfälle korrigieren. Aktuell habe ich nur wenige Testfälle (aktuell 178) implementiert.

Eine Laderoutine für die Betriebssystem ROMs habe ich hinzugefügt, um den Arbeitsspeicher initial mit dem Basic und Kernal ROM zu befüllen.

Dazu werden die Dateien von der AssetLoader-Klasse per fetch geladen und bei Erfolg die initialize Methode der Controller-Klasse (index.ts) aufgerufen.

  new AssetLoader(
    [
      characterRom,
      basicRom,
      kernalRom
    ], (data) => { controller.initialize(data); })
 ;

Nachdem die ROMs erfolgreich geladen wurden, werden sie an die richtige Stelle im virtuellen Speicher kopiert und das virtuelle Reset-Signal aufgerufen.

/**
 * loads initial program into memory
 *
 * @param view
 */
public initialize(data : any) {
    this.memory.memcpy(0xa000, data.get(basicRom), 0, 0x2000);
    this.memory.memcpy(0xe000, data.get(kernalRom), 0, 0x2000);
    this.cpu.reset();
    this.view.setStartPosition(this.cpu.getRegister().pc);
    this.view.update();
}

Die oben verwendete Funktion memcpy aus der Memory-Klasse kopiert ein ArrayBuffer-Objekt an eine Stelle im virtuellen Speicher.

public memcpy(dstOffset: number, src: ArrayBuffer, srcOffset: number, length: number) : void {
    var dstU8 = new Uint8Array(this.memBuffer, dstOffset, length);
    var srcU8 = new Uint8Array(src, srcOffset, length);
    dstU8.set(srcU8);
};

Das Reset-Signal springt zur Reset-Routine des KERNAL ROMs. Die genaue Funktionalität ist unter http://www.pagetable.com/?p=410 beschrieben.

/**
 * handles cpu reset signal
 *
 * pc = ($fffc/$fffd)
 */
public reset() : void {
  this.reg.sp -= 3; // push pc & status register on stack (on reset only sp is decremented)
  this.reg.sp &= 0xff;

  this.reg.pc = this.mem.readByte(0xfffd) * 256 + this.mem.readByte(0xfffc);
}

CPU Statusanzeige

Die Anzeige des Speichers kann angepasst werden. Man kann entweder eine andere Startposition als Hex-Wert angeben, oder mit den Buttons BASIC und KERNAL zur Startposition des jeweiligen ROMs springen.

Das Ergebnis für diesen Teil befindet sich in meinem Gitlab-Projekt TSC64Emu. Die ausführbare Applikation ist hier erreichbar.

Ausblick

Im der nächsten Zeit gilt es weitere Testfälle zu implementieren und CPU Testprogramme verwenden, um die noch vorhandenen Fehler in der CPU Implementierung zu beheben.

Eine Übersicht von verschiedenen Testprogrammen findet sich unter http://visual6502.org/wiki/index.php?title=6502TestPrograms.

Ich habe zuerst die Testfälle von Mike Naberezny als Basis genommen und daraus Tests für Mocha und Chai geschrieben. Damit ist die Anzahl der Tests auf aktuell 667 Tests gewachsen.

Zusätzlich wurde die CPU mit der Testsuite von Klaus Dormann geprüft, um sämtliche Fehler im Code und evtl. bei den Testfällen zu beseitigen.

Nächster Beitrag Vorheriger Beitrag