1541-Emul

Aus
Version vom 30. September 2019, 10:31 Uhr von Tw (Diskussion | Beiträge) (WEB Links)
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)
Wechseln zu: Navigation, Suche


Emulation eines 1541 Disketten Laufwerk

Die Idee, ein Floppy Laufwerk zu emulieren, ist nicht neu. Das gibt es bereits in Form des **[[1]]**, verbessert als **[[2]]** und in vollendeter Perfektion als **[[3]]** ([[c64wiki>1541_Ultimate|1541 Ultimate]]).

Das MMC2IEC und das [[c64wiki>SD2IEC]] basieren auf einen [[wpde>Atmel]] [[wpde>Atmel_AVR|AVR Controller]]. Diese Module emulieren aber nur das [[c64wiki>Commodore DOS]] und nicht die Floppy Hardware an sich.

Das **[[c64wiki>1541_Ultimate|1541u]]** ist eine FPGA Lösung und ersetzt die 1541 Hardware durch eine moderne (programmierbare) Hardware. Das Ultimate ist der perfekte Ersatz für eine richtige 1541 Floppy, daher funktionieren damit auch sehr spezielle Programme die sehr hardwarenah designed sind. Der Nachteil der 1541u ist der relativ hohe Preis der Karte, der von dem teuren FPGA verursacht wird.

Wie der eindrucksvolle [[4]] Emulator beweist, kann man eine 1541 auch perfekt per Software emulieren. Allerdings ist dazu eine beträchtliche Rechenleistung erforderlich. Selbst moderne Spielkonsolen wie der WIZ mit 533MHz tun sich sehr schwer, die 1541 in Echtzeit perfekt zu emulieren.

Das Ziel wäre eine perfekte Emulation der 1541 zu einem günstigeren Preis im Vergleich zu einer 1541u.

Voraussetzungen

Um die 1541 per Software zu emulieren, muss zunächst der Prozessor, Speicher und IO emuliert werden. Eine 1541 ist recht simpel aufgebaut:

 * Eine 6502 CPU, getaktet mit 1MHz
 * Ein 16KB großes ROM für die Firmware (DOS) (Adressraum $C000-$FFFF)
 * Ein 2KB großes RAM (Adressraum $0000-$07FF)
 * Zwei VIA (Adressraum $1800 und $1C00)
 * Laufwerk Eigenschaften

Diese Anforderungen klingen nicht spektakulär. Allerdings existiert gerade bei der 1541 einiges an hochoptimierter Software (**Speeder**), wo die Hardware ziemlich ausgereizt wird. Deshalb ist es notwendig, dass die Emulation **taktgenau** und präzise erfolgt, damit alle gängigen Speeder auch auf der Emulation laufen.


Untersuchung Durchführbarkeit

Am schönsten wäre natürlich, eine vorhandene Hardware wie das [[c64wiki>SD2IEC|SD2IEC]] verwenden zu können. Deshalb geht die Suche nach passender Hardware für den **1541-Emul** in Richtung AVR Controller. Der Atmega-644 kann mit bis zu 20MHz getaktet werden und sollte genug Leistung haben, eine 8-Bit CPU wie den 6502 mit 1MHz emulieren zu können.

Bezüglich **6502 Emulation** gibt es genügend Vorlagen im Netz, allerdings meist Monsterlösungen die einen kleinen Atmega rasch überfordern würden. Ich suche nach einer reinen C Lösung die extrem simpel im Aufbau ist. Fündig wurde ich [Domain]. Da gibt es einen sehr einfachen, statisch aufgebauten Emulator Source von Neil Bradley ([[5]]). Der zweiten Emu Source ist von Marat Fayzullin und ist sehr aktuell, modular programmiert (Emu arbeitet mit Zeiger auf CPU Struktur) und enthält zudem einen Debugger mit Disassembler: ([[6]])

Ich habe beide Emulatoren an die AVR spezifischen Dinge angepasst. Das Speichermodell der 1541 wurde implementiert (2K RAM, 16KB ROM Code im Flash und die VIA Adressen als Funktion für später zum an programmieren). Der Debugger mit 6502 Disassembler wurde angepasst (Tabellen im Flash). Die Emulation läuft tadellos in einem Atmega644 auf dem Standard XS-1541 Modul. Nach einem Reset durchläuft die Emulation die gesamte Initialisierung der Floppy samt Speichertest und Prüfsummen Check des ROM. Danach geht die Emulation in die Warteschleife ...

Die beiden Ansätze in reinem C erweisen sich aber trotz Optimierungen als zu langsam. Selbst bei 20MHz erreicht man nur 50% der Geschwindigkeit einer 6502 CPU bei 1MHz. Ein leistungsstarker Prozessor ist erforderlich für eine Taktgenaue Emulation des 6502 . Will man bei der AVR Architektur bleiben, dann muss man sich was einfallen lassen.

Nach monatelangen Stillstand bin ich auf das geniale Projekt von **Tom Gowing** und **Brian Pescatore** gestoßen: [Emulation]

Mit dem NES Emulator auf der Basis von zwei Atmega644 wurde sehr viel Vorarbeit für den 1541-Emul geleistet. Der Nintendo NES läuft nämlich ebenfalls mit einem 6502, der sogar mit 1,77 MHz getaktet ist. Angeblich soll der AVR den NES mit voller Geschwindigkeit emulieren können.

Das NES Projekt war zwar nicht erfolgreich, der 6502 Teil jedoch schon. Der NES hat ja auch einen Video Teil, den die Jungs mit dem zweiten AVR emulieren wollten. Dieser Teil scheint nicht geglückt zu sein.

Der 6502 Emulator aus dem NES Projekt ist an den kritischen Stellen in Assembler implementiert. Die Speicherzugriffe sind teilweise nicht virtuell sondern als echte Hardware realisiert: Der AVR gibt die Adresse an zwei seiner IO Ports aus und liest oder schreibt Daten über ein drittes Port.


Ergebnis

Es hat sich gezeigt, dass eine reine C Implementierung an einem AVR zu langsam arbeitet. Aber wenn kritische Teile der Software in Assembler geschrieben werden, dann kommt man so gerade auf Emulation in Echtzeit hin.

Ein Problem stellt die Adressdekodierung dar. Bei jedem Lese- und Schreibvorgang muss die Adresse untersucht und die Zielhardware (RAM, ROM, IO) ermittelt werden. Eine taktgenaue Emulation lässt sich nicht machen, aber im Schnitt kommt man auf ein gutes Ergebnis. Und die für **Speeder** relevanten Teile (VIA Zugriff für Bustransfer) schafft man taktgenau.

\\ __Was die restliche Hardware der Floppy anbelangt__:

Es gibt eine Reihe von IO die irrelevant für den Datentransfer sind (zb. Spindelmotor, Lichtschranke/Schreibschutz, Gerätenummer ...). Bedingt durch die Anlaufzeit, Spurwechselzeit etc. muss hier maximal eine Zeitverzögerung emuliert werden.

Aus Sicht der 6502 CPU (und damit aus Sicht der Emulation) stellt sich das Lesen von Diskette einfach dar: Man stellt den Kopf auf eine Spur von 0 bis 34 und bekommt kontinuierlich einen Datenstrom. Durch Sync Impulse (V Flag) weiss die CPU wenn ein Byte gelesen werden kann. In bestimmten Zeitabständen kommt jeweils ein neues Byte an, unabhängig ob das Byte gelesen wurde oder nicht. Jeder Block hat zwei Bereiche, einen Kopfteil (header) und einen Datenteil.

Die Daten selbst sind kodiert (GCR Kodierung) auf der Diskette gespeichert, dabei werden beim Schreiben jeweils 4 Bit in 5 Bit verwandelt. Beim Lesen werden entsprechend jeweils 5 Bit zurückgewandelt in 4 Bit.

Um eine perfekte Emulation zu erreichen, muss man diese Serialisierung der Daten beibehalten. Man könnte dazu einen zweiten Controller benutzen oder einen CPLD mit RAM. Denselben Controller zu verwenden ist keine perfekte, dafür aber die preisgünstigste Lösung. Wenn der emulierte 6502 die virtuelle Leseelektronik zugreift, dann wird aufgrund eines Timerwert das aktuelle Byte gelesen aus dem Spurdaten Buffer. Da eine Spur immer wiederholend übertragen wird, sollte der RAM des Controller eine ganze Spur fassen können (~8KB). Bei einem Spurwechsel liest der Controller die entsprechende Spur der virtuellen Diskette (D64 Image Datei) in den Spur Buffer.




Technische Lösung


WEB Links