CPU
Lieutenant
- Registriert
- Jan. 2006
- Beiträge
- 704
Hallo liebe Community,
vor gut dreieinhalb Jahren habe ich hier im Forum nachgefragt, wie man einen C64-Emulator schreibt - ziehmlich blauäugig wie ich heute finde . Nun habe ich letztens das Projekt wiederbelebt bzw. richtig begonnen nebenbei zu basteln. Noch kurz zum Sinn: ich finde es interessant mal so ganz tief in eine Maschine hereinzuschauen und diese nachzubauen. Allerdings ist mein Ziel nicht einen vollkommenen Emulator zu schreiben (die gibt es ja bereits alle schon), sondern einfach aus Spaß ein bisschen zu basteln und hoffentlich mal z.B. den typischen Startbildschirm mit der interaktiven Prompt hin zu bekommen.
Bisher habe ich einen Emulator für die MOS6510 CPU geschrieben und einen Speicher über ein simples Array nachgebildet. Ein kleiner Testlauf:
Wird ausgeführt als:
Nun, das Ergebnis finde ich recht zufriedenstellend. Allerdings habe ich bisher noch keine Interrupts implementiert. Da wäre meine Frage wie ich das mache. Interrputs (und Exceptions) kenne ich von der Theorie her so, dass es irgendwo eine ISR gibt (Interrupt Service Routine) die dann abgearbeitet wird. Aber wie sieht das hier (MOS6510) aus?
Und als nächste Frage: wie mache ich weiter?
Nun die CPU + Speicher habe ich. Den VIC muss ich - meines Erachtens nach - nicht implementieren, d.h. die GUI greift sich einfach die 1000 Bytes "Bildschirminhalt" (von $0400 - $07e7) aus dem Speicher ab und setzt jeweils an die Stelle das entsprechende Zeichen mit entsprechender Farbe (von $d800 - $dbff). So müsste ich doch den VIC komplett umgehen können, oder?
Fraglich finde ich nur dieses Konzept mit den Sprites. In dieser Beschreibung steht, dass es 8 Spriteblock-Register gibt und dass man daraus 320x200 Pixel Vollgrafik erzeugen kann. Allerdings ist jedes Register nur 1 Byte groß und da kann man doch kein solches Sprite drin ablegen. Es ist sicher nur ein Verweis ... aber da bin ich noch nicht so hinter gekommen.
Weiterhin ist die Frage, ob ich einfach die "originalen Dateien" (also aus einem Emulator) für den KERNAL, BASIC-ROM & Co. in mein Array-Speicher laden kann und dann die CPU einfach starten lassen kann. Dies scheint mir aber etwas zu einfach zu sein.
Außerdem noch ein Frage: wie man dem Speicherbelegungsplan entnehmen kann gibt es verschiedene "Overlays" von ROM über RAM usw. Betrachten wir z.B. mal das BASIC-ROM. Das wird beim Lesen verwendet und beim Schreiben der zugeordnete Speicherbereich im RAM. Ist das wirklich so, oder wird beim Start das ROM ins RAM geladen und dann kann ich eben die Inhalte modifizieren bis zum nächsten Abschalten und diese werden auch solange als der modifizierte Wert gelesen?
Von Adresse $c000 bis $cfff stehen 4 KB freies RAM zur Verfügung, um eigene Assembler-Programme reinzuladen. Das scheint mir doch ein bisschen wenig für z.B. ein Spiel. Wo wird denn z.B. ein Spiel hingeladen?
Ich hoffe, Ihr könnt mir in einigen Bereichen ein bisschen Licht in's Dunkle bringen :-) das würde mich freuen ...
Viele Grüße,
CPU
Gute Quellen zum Recherchieren sind:
http://www.c64-wiki.de/index.php/Speicherbelegungsplan
http://www.c64-wiki.de/index.php/Bildschirmspeicher#Speicheradressen
http://www2.informatik.hu-berlin.de/~kunert/oldpages/cbm/64cpu/64cpu.html
http://unusedino.de/ec64/technical/aay/c64/bmain.htm
vor gut dreieinhalb Jahren habe ich hier im Forum nachgefragt, wie man einen C64-Emulator schreibt - ziehmlich blauäugig wie ich heute finde . Nun habe ich letztens das Projekt wiederbelebt bzw. richtig begonnen nebenbei zu basteln. Noch kurz zum Sinn: ich finde es interessant mal so ganz tief in eine Maschine hereinzuschauen und diese nachzubauen. Allerdings ist mein Ziel nicht einen vollkommenen Emulator zu schreiben (die gibt es ja bereits alle schon), sondern einfach aus Spaß ein bisschen zu basteln und hoffentlich mal z.B. den typischen Startbildschirm mit der interaktiven Prompt hin zu bekommen.
Bisher habe ich einen Emulator für die MOS6510 CPU geschrieben und einen Speicher über ein simples Array nachgebildet. Ein kleiner Testlauf:
Code:
LDX #$08
DEX
BRK
Wird ausgeführt als:
Code:
> Instruction: 0xa2 / LDX (imm)
> Exec
MOS6510[pc=0x2, accu=0x0, x=0x8, y=0x0, sp=0x0, p=0x0, isRunning=true]
> Instruction: 0xca / DEX (sngl)
> Exec
MOS6510[pc=0x3, accu=0x0, x=0x7, y=0x0, sp=0x0, p=0x0, isRunning=true]
> Instruction: 0x0 / BRK (sngl)
> Exec
MOS6510[pc=0x4, accu=0x0, x=0x7, y=0x0, sp=0x0, p=0x0, isRunning=false]
Nun, das Ergebnis finde ich recht zufriedenstellend. Allerdings habe ich bisher noch keine Interrupts implementiert. Da wäre meine Frage wie ich das mache. Interrputs (und Exceptions) kenne ich von der Theorie her so, dass es irgendwo eine ISR gibt (Interrupt Service Routine) die dann abgearbeitet wird. Aber wie sieht das hier (MOS6510) aus?
Und als nächste Frage: wie mache ich weiter?
Nun die CPU + Speicher habe ich. Den VIC muss ich - meines Erachtens nach - nicht implementieren, d.h. die GUI greift sich einfach die 1000 Bytes "Bildschirminhalt" (von $0400 - $07e7) aus dem Speicher ab und setzt jeweils an die Stelle das entsprechende Zeichen mit entsprechender Farbe (von $d800 - $dbff). So müsste ich doch den VIC komplett umgehen können, oder?
Fraglich finde ich nur dieses Konzept mit den Sprites. In dieser Beschreibung steht, dass es 8 Spriteblock-Register gibt und dass man daraus 320x200 Pixel Vollgrafik erzeugen kann. Allerdings ist jedes Register nur 1 Byte groß und da kann man doch kein solches Sprite drin ablegen. Es ist sicher nur ein Verweis ... aber da bin ich noch nicht so hinter gekommen.
Weiterhin ist die Frage, ob ich einfach die "originalen Dateien" (also aus einem Emulator) für den KERNAL, BASIC-ROM & Co. in mein Array-Speicher laden kann und dann die CPU einfach starten lassen kann. Dies scheint mir aber etwas zu einfach zu sein.
Außerdem noch ein Frage: wie man dem Speicherbelegungsplan entnehmen kann gibt es verschiedene "Overlays" von ROM über RAM usw. Betrachten wir z.B. mal das BASIC-ROM. Das wird beim Lesen verwendet und beim Schreiben der zugeordnete Speicherbereich im RAM. Ist das wirklich so, oder wird beim Start das ROM ins RAM geladen und dann kann ich eben die Inhalte modifizieren bis zum nächsten Abschalten und diese werden auch solange als der modifizierte Wert gelesen?
Von Adresse $c000 bis $cfff stehen 4 KB freies RAM zur Verfügung, um eigene Assembler-Programme reinzuladen. Das scheint mir doch ein bisschen wenig für z.B. ein Spiel. Wo wird denn z.B. ein Spiel hingeladen?
Ich hoffe, Ihr könnt mir in einigen Bereichen ein bisschen Licht in's Dunkle bringen :-) das würde mich freuen ...
Viele Grüße,
CPU
Gute Quellen zum Recherchieren sind:
http://www.c64-wiki.de/index.php/Speicherbelegungsplan
http://www.c64-wiki.de/index.php/Bildschirmspeicher#Speicheradressen
http://www2.informatik.hu-berlin.de/~kunert/oldpages/cbm/64cpu/64cpu.html
http://unusedino.de/ec64/technical/aay/c64/bmain.htm
Zuletzt bearbeitet:
(Quellen hinzugefügt)