C64-Emulator "fortsetzen"

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 :D. 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)
Uh, lang ists her das ich mich damit beschäftigt hab... aber n bissl was weiß ich noch:

- die Sprite-Adressen sind tatsächlich nur ein Verweis wo die Daten zum Sprite (Bitmap, Bildschirmposition) zu finden sind

- wenn deine Emulation vollständig ist kannst du einfach die original ROM Daten verwenden. Wie weit dir deine Abkürzung zum VIC da Ärger macht bleibt auszuprobieren. Da der VIC aber eigentlich nur Daten liest sollte das gehen, zumindest für die Einfachen Darstellungen. Der Rasterzeileninterrupt ist n anderes Thema ;-)

- Die Speicher werden tatsächlich überlagert und nicht kopiert. Gesteuert wird das ganze über die Adresse 0 oder 1 (bin mir nicht mehr ganz sicher). Prinzipiell kann man aber tatsächlich den ROM ins RAM kopieren (Schreibzugriffe erfolgen immer ins RAM, unabhängig davon ob der ROM für den Lesezugriff aktiv ist) und dann umschalten, wodurch man die Möglichkeit bekommt die Daten zu ändern.

- Assembler-Programme können auch in den "Basic"-Ram gelegt werden. Wenn man den Basic-Interpreter nicht braucht kann man diesen auch ausblenden und bekommt so einen recht großen Block.
 
Hallo,

asdfman schrieb:
Diesen Vortrag mal gesehen? Weiß nicht inwiefern er deine Probleme speziell behandelt, fand ihn damals als ich ihn das erste Mal sah allerdings recht umfassend:
ich habe ihn gleich als nächstes auf meiner Liste stehen und werde mal drüber schauen.

Jesterfox schrieb:
- die Sprite-Adressen sind tatsächlich nur ein Verweis wo die Daten zum Sprite (Bitmap, Bildschirmposition) zu finden sind
Beziehen sich also auf eine Speicherstelle im RAM.

Jesterfox schrieb:
- wenn deine Emulation vollständig ist kannst du einfach die original ROM Daten verwenden.
Was heißt "vollständig"? Ich habe eine CPU, die den MOS6510 Maschinencode ausführen kann und einen Speicher. Jetzt kann ich die originalen ROM-Daten in mein Array packen. Der Rest (vorbereiten der Zero-Page, Booten, etc.) sollte dann ja von "alleine" gehen. Aber wo setze ich den PC (Program Counter) initial an?

Jesterfox schrieb:
Wie weit dir deine Abkürzung zum VIC da Ärger macht bleibt auszuprobieren. Da der VIC aber eigentlich nur Daten liest sollte das gehen, zumindest für die Einfachen Darstellungen.
Das habe ich mir auch gedacht. Wenn man sich den Aufbau des VICs anschaut, dann ist er eigentlich doch nur damit beschäftigt das PAL/NTSC Ausgabesignal zu erzeugen. Unter [1] und [2] kann man das - meines Erachtens nach - schön sehen. Die Badlines sind für den Emulator uninteressant, weil wir das RAM nicht sperren müssen, d.h. nur von der CPU aus auf den PC drauf schauen.[/QUOTE]

Jesterfox schrieb:
Der Rasterzeileninterrupt ist n anderes Thema ;-)
Aber ein Thema, zudem man im Netz nicht soviel findet ...

Jesterfox schrieb:
- Die Speicher werden tatsächlich überlagert und nicht kopiert. Gesteuert wird das ganze über die Adresse 0 oder 1 (bin mir nicht mehr ganz sicher). Prinzipiell kann man aber tatsächlich den ROM ins RAM kopieren (Schreibzugriffe erfolgen immer ins RAM, unabhängig davon ob der ROM für den Lesezugriff aktiv ist) und dann umschalten, wodurch man die Möglichkeit bekommt die Daten zu ändern.
Ja, dafür ist der PLA [3] zuständig. Aber zu Beginn kann man das ja erstmal weglassen

Jesterfox schrieb:
- Assembler-Programme können auch in den "Basic"-Ram gelegt werden. Wenn man den Basic-Interpreter nicht braucht kann man diesen auch ausblenden und bekommt so einen recht großen Block.
Okay, das erklärt einiges. Also hat man rund 36 KB Speicher zur Verfügung für eine Anwendung.

Gruß,
CPU

[1] http://www.c64-wiki.de/index.php/Hardware-Aufbau_des_C64
[2] http://www.c64-wiki.de/index.php/VIC
[3] http://www.c64-wiki.de/index.php/PLA_(C64-Chip)
 
Als Ergänzung: I/O und Kernel-Rom können auch ausgeblendet werden.
 
Jepp, aber auf die wird man im Gegensatz zum Basic-Interpreter nicht dauerhaft verzichten können. Da muss man sich dann eine Logik überlegen wie man die nur kurzzeitig wegschaltet.

Mit "vollständiger" Emulation mein ich das zumindest alles was die ROMs benötigen wie erwartet funktioniert. Bin selber grad am überlegen was neben der CPU alles darunter fällt. Aber die Interrupts dürften wohl mit dazu gehören, zumindest wenn man auch etwas über die Tastatur eingeben können will. Der PLA wird aber wohl erst mal nicht benötigt. Was die Initialisierung des PCs angeht... da müsste man in der Doku vom 6510 nachschauen wo der anfängt und was der C64 dort zur Verfügung stellt.


Der Rasterzeilen-Interrupt ist an sich schnell erklärt. Er erzeugt einen IRQ wenn die Bildausgabe eine bestimmte Zeile erreicht (die Pixel werden ja im Prinzip seriell ausgegeben, genau so wie ein CRT das Bild per rasterstrahl aufbaut). Das zu emulieren wird aber wohl schwieriger ;-)

Die Interrupts sind ja Signale von außen die die CPU veranlassen die aktuelle "Umgebung" auf den Stack zu sichern und an eine im Speicher zur Verfügung gestellte Adresse zu springen.
 
Wollte nur darauf hinweisen, dass es geht, weil es Programme gibt, die das tun und der Emulator das erwartete Verhalten zeigen sollte.

Nachdem ich das von mir gepostete Video eben noch einmal gesehen habe, fiel mir noch auf, dass der VIC beim Zeichnen von bestimmten
Zeilen die CPU abschaltet. Das muss man im Hinterkopf haben, wenn man sich die Emulation des Chips sparen will und zu den Zeiten, wenn
das der Fall wäre, entsprechend kurz "pausieren". Wenn man aber keine perfekte Emulation anstrebt, kann man das unter Umständen
auch weglassen. So genau kann ich die Implikationen dieses Verhaltens jetzt nicht absehen.
 
Ich glaub das war alle 8 Zeilen für den Zugriff auf die Farbspeicher, da das zu lange dauert. Deswegen wird z.B. von den Fastloadern der Bildschirm abgeschalten um das zu unterbinden. Für einfache Programme und auch den Basic-Interpreter dürfte das egal sein, die bekommen das nicht wirklich mit.
 
Hallo,

Jesterfox schrieb:
Die Interrupts sind ja Signale von außen die die CPU veranlassen die aktuelle "Umgebung" auf den Stack zu sichern und an eine im Speicher zur Verfügung gestellte Adresse zu springen.

Ja, ja. Schon klar. In dieser Quelle hier wird unter 3.1 eine IRQ-Leitung aus dem VIC herausgeführt, die in den Prozessor geht. Von der Theorie sind mir Exception (softwareseitige Unterbrechung, z.B. Division by 2) und Interrupt (hardwareseitige Unterbrechung, z.B. Timer, Tastatureingabe) wohlbekannt. Ich habe schon ein wenig mit dem MIPS-Prozessor und diesen Geschichten "herumgespielt". Allerdings gibt es dort eine ISR. Die dürfte es allerdings auch bei dem MOS6510 geben.

Ich habe mal ein Blick in das Datenblatt geworfen und etwas zu der IRQ-Leitung gefunden:
irq.jpg

So verstehe ich das:
Code:
Laufende Instruktion abarbeiten
Lese 2. Bit im Statusregister

Wenn Bit NICHT gesetz Dann:
  PC & Statusregister sichern auf dem Stack
  2. Bit im Statusregister auf 1 setzen
  PC = ram[0xfffe] | (ram[0xffff] << 8)
  ???
Aber ich frage mich, wie es dann weiter geht (da wo die drei ??? stehen). Und ich denke, nebenbei, dass hier auch die Instruktion "RTI" (Return from Interrupt) am Schluss zum Einsatz kommt.

Und bei den Instruktion "CLI (Clear interrupt Disable Bit)" und "SEI (Set Interrupt Disable Status)" wird doch einfach nur das Bit im Statusregister gesetzt oder nicht gesetzt, oder? Es wird nichts Weiteres gemacht? Also eine Art "Softwareinterrupt" (was ja eine Exception wäre, z.B. Trap bei MIPS) ausgelöst, oder?

asdfman schrieb:
Wenn man aber keine perfekte Emulation anstrebt, kann man das unter Umständen
auch weglassen.
Genau so ist es: erstmal etwas lauffähiges hin bekommen und dann verbessern und erweitern :-)

Jesterfox schrieb:
Ich glaub das war alle 8 Zeilen für den Zugriff auf die Farbspeicher, da das zu lange dauert.
Ja so ungefähr. Der VIC braucht mehr BUS-Zyklen und hält daher die CPU an.

Viele Grüße,
CPU
 
An Stelle 7 der IRQ Abarbeitung geschieht ja ein impliziter Jump-Befehl (Edit: eigentlich ein JSR). Das was an Schritt 8 folgt hängt davon ab welcher Befehl an der Adresse steht auf dem nun der PC zeigt.

CLI und SEI setzen und löschen wirklich nur das Bit. Es wird auch kein Sofwareinterrupt ausgelöst oder ähnliches. Es hat nur zur Folge das wenn das Bit gesetzt ist kein IRQ mehr bearbeitet wird. Wird wie gesehen ja während eines IRQ benutzt um nicht nochmal unterbrochen zu werden, kann aber auch benutzt werden wenn man eine Routine hat die nicht unterbrochen werden soll. Der 2. Interrupt der CPU (NMI) ist davon aber nicht betroffen, der geht immer durch (und müsste eine 2. Speicherstelle für seinen Sprung in die Abarbeitungsroutine haben). Von daher hat der NMI auch eine höhere Priorität gegenüber dem IRQ. Allerdings frag ich mich gerade wie der NMI eine wiederholte Unterbrechung verhindert... irgendwie müsste der das eigentlich auch machen.
 
Also ich hatte mal eine 10-Themen lange Anleitung dazu gelesen, wie man für den NES Spiele entwickelt.
Bzgl. der Sprites war es da so, dass du 2 Begrenzungen hattest:
Einmal die Anzahl der Farben, die ein Sprite haben konnte.
Und einmal die Anzahl der Farben insgesamt auf dem Bildschirm.

Habe jetzt relativ viele Postings übersprungen, aber ich hoffe, dass dir das irgendwie helfen kann und diese Unterproblematik hier noch aktuell ist.
Ansonsten kann ich dir den Tipp geben evtl. von der anderen Seite an die Funktionen heranzugehen, nämlich zu sehen, wie man damals effektive Anwendungen für den C64 geschrieben hat.
 
Hallo,

Jesterfox schrieb:
An Stelle 7 der IRQ Abarbeitung geschieht ja ein impliziter Jump-Befehl (Edit: eigentlich ein JSR). Das was an Schritt 8 folgt hängt davon ab welcher Befehl an der Adresse steht auf dem nun der PC zeigt.
klar, wieso bin ich nicht darauf gekommen. Wenn man den PC hat kann man an die entsprechende Adresse springen und die Instruktionen dort abarbeiten. Vielleicht steht dann irgendwo ein RTI, um zur normalen Programmabarbeitung zurückzukehren.

Jesterfox schrieb:
CLI und SEI setzen und löschen wirklich nur das Bit. Es wird auch kein Sofwareinterrupt ausgelöst oder ähnliches. Es hat nur zur Folge das wenn das Bit gesetzt ist kein IRQ mehr bearbeitet wird. Wird wie gesehen ja während eines IRQ benutzt um nicht nochmal unterbrochen zu werden [...]
Okay.

Sehe ich das auch richtig, dass es gar keinen "Softwareinterrupt" gibt und auch keinen "Kernel-" und "User-"Modus, wie bei modernen CPUs? Das macht die Sache erheblich einfacher.

Falsch: es gibt einen Softwareinterrupt: BRK.

Wenn ich das mal zusammenfassen darf: Interrupts können nur ausgelöst werden, wenn die IRQ-Leitung auf High geht. D.h. von Seiten der Programme auf der CPU muss ich mir da keine Gedanken machen, oder?

Jesterfox schrieb:
Der 2. Interrupt der CPU (NMI) ist davon aber nicht betroffen, der geht immer durch (und müsste eine 2. Speicherstelle für seinen Sprung in die Abarbeitungsroutine haben). Von daher hat der NMI auch eine höhere Priorität gegenüber dem IRQ. Allerdings frag ich mich gerade wie der NMI eine wiederholte Unterbrechung verhindert... irgendwie müsste der das eigentlich auch machen.
Also hier ist eine Beschreibung zum NMI. Ich verstehe das so, dass man diese Interrupts nicht unterbinden kann und somit auch innerhalb eines NMIs ein weiteres passieren könnte. Aber etwas ganz Anderes hierzu: es wird dort aufgeführt, dass es eine NMI-Leitung gibt. Im Datenblatt des Prozessors steht aber nichts von einem solchen Pin.

Auf dieser Seite hier ist das Verhalten des KERNALs nach dem Einschalten aufgezeigt. Dazu folgende Fragen:

1. Oben habe ich ja bereits gefragt, wo man mit dem PC beginnt. Dort steht zu Beginn:
Code:
Aufruf der Routine $FFFC (springt nach $FCE2, RESET)
Also beginnt der PC an Adresse $fffc zu arbeiten.

2. Bei 4.3 wird ein Interrupt-Timer aktiviert. Klar ist, dass bei 60 Hz eben ein Interrupt 60 mal Pro Sekunde ausgeführt wird. Allerdings frage ich mich wie das technisch realisiert wird und was Speicherstelle $fddd damit zu tun haben. Weil irgendwie muss ja dann die IRQ-Leitung sich ändern. Oder hat der MOS6510 eine Interrupt-Logik eingebaut, die das Signal entsprechend immer wieder auslöst. Und warum finde ich dann davon nichts im Datenblatt?

3. Ich kümmere mich ja weder um Sound noch um I/O-Geräte. Könnte mir das vor die Füße fallen oder kann ich das einfach so weglassen?

Viele Grüße,
CPU
 
1. Soweit ich das seh wird der PC mit dem Inhalt von $FFFC und $FFFD geladen (Reset-Vektor) und ab dort erst mit der Ausführung von Befehlen begonnen.
2. $FDDD scheint einfach die Adresse des Programmcodes im Kernel zu sein die genau das macht. Den Timer-IRQ löst nicht die CPU selbst aus sondern irgend ein externer Chip. Bin mir nicht ganz sicher welcher, könnte der CIA1 sein.
3. solange nur Daten auf die I/O Chips ausgegeben werden ist es egal. Sobald aber eine Eingabe oder Reaktion erwartet wird gibt's Probleme. Der Timer-IRQ ist ein solcher Fall, bin noch am überlegen was es sonst noch gibt...

Der NMI liegt an Pin 4 der CPU, sieht man auch im Datenblatt. Da sind 3 Varianten der CPU abgebildet von denen die erste die im C64 sein müsste. Bei den anderen beiden ist der NMI und noch eine Leitung zu Gunsten von P6 und P7 (I/O Ports die über die Adressen 0000 und 0001 gesteuert werden). Die fehlen im C64, dort können nur 6 Bits dieses I/O Ports der CPU verwendet werden. 3 Bits steuern den PLA, die anderen 3 die Datasette. (Ok, hinten bei der Signal Description fehlt der NMI...)

Auslöser für einen IRQ ist die entsprechende Leitung an der CPU oder eben der BRK Befehl, der löst ja im Prinzip die selbe Interrupt-Routine aus. Der NMI kann nur extern ausgelöst werden.

Der NMI kann scheinbar nur über das auslösende Gerät elektrisch unterbunden werden indem die Leitung auf 0 gehalten wird, ansonsten sind mehrfache Aufrufe möglich. Ok, an sich spricht da auch nichts dagegen, außer das wenn es zu oft passiert der Stack überläuft ;-)

Eine Unterscheidung zwischen Kernel und Usermode hat der 6510 noch nicht.
 
Hallo,

Jesterfox schrieb:
1. Soweit ich das seh wird der PC mit dem Inhalt von $FFFC und $FFFD geladen (Reset-Vektor) und ab dort erst mit der Ausführung von Befehlen begonnen.
2. $FDDD scheint einfach die Adresse des Programmcodes im Kernel zu sein die genau das macht.
okay, das klingt logisch. Also weiß ich, worauf ich den PC initial stellen muss.

Jesterfox schrieb:
Den Timer-IRQ löst nicht die CPU selbst aus sondern irgend ein externer Chip. Bin mir nicht ganz sicher welcher, könnte der CIA1 sein.
Also nochmal zum gedanklichen Ordnen:

* mit BRK kann ich softwareseitig einen Interrupt auslösen und dann wird an entsprechende Stelle im KERNAL gesprungen und das Break-Flag gesetzt (für z.B. Debugging)

* mit NMI wird auch ein Interrupt, der allerdings unterbrochen werden kann, ausgelöst und von der Adresse im NMI-Vektor "behandelt"

* mit einem Interrupt über die IRQ-Leitung wird ein Interrupt ausgeführt, um z.B. Tastatureingaben zu sammeln. Auf dieser Seite hier ist der Quellcode an der Stelle $fddd aufgeführt, was ja die Stelle für "Enable Timer" ist. Der CIA1 hat definitiv etwas damit zu tun.

Allerdings verstehe ich immer noch nicht so recht, wie das jetzt funktioniert.

Jesterfox schrieb:
Der NMI liegt an Pin 4 der CPU, sieht man auch im Datenblatt. Da sind 3 Varianten der CPU abgebildet von denen die erste die im C64 sein müsste.
Okay, mein Datenblatt handelt zwar auch vom 6510, hat aber eine ganz andere Darstellung, als der Link, den ich gepostet habe ... Jetzt sehe ich es natürlich :-)

Jesterfox schrieb:
(I/O Ports die über die Adressen 0000 und 0001 gesteuert werden).
Ja, genau. Was hat es mit den zwei ersten Speicherstellen zu tun?

Jesterfox schrieb:
Eine Unterscheidung zwischen Kernel und Usermode hat der 6510 noch nicht.
Ein Glück ...

Viele Grüße,
CPU
 
* mit BRK kann ich softwareseitig einen Interrupt auslösen und dann wird an entsprechende Stelle im KERNAL gesprungen und das Break-Flag gesetzt (für z.B. Debugging)

Jepp. Das Break-Flag ist dabei vor allem die Anzeige das der Interrupt Softwareseitig ausgelöst wurde. Da die CPU nur 2 Interrupts hat muss "Sharing" betrieben werden und innerhalb der Interrupt-Routine geprüft werden wer jetzt eigentlich ausgelöst hat und was in dem Fall getan werden soll.

* mit NMI wird auch ein Interrupt, der allerdings unterbrochen werden kann, ausgelöst und von der Adresse im NMI-Vektor "behandelt"

Der NMI kann dabei auch den IRQ unterbrechen, hat also eine höhere Priorität hat.

* mit einem Interrupt über die IRQ-Leitung wird ein Interrupt ausgeführt, um z.B. Tastatureingaben zu sammeln. Auf dieser Seite hier ist der Quellcode an der Stelle $fddd aufgeführt, was ja die Stelle für "Enable Timer" ist. Der CIA1 hat definitiv etwas damit zu tun.

Die CIAs sind recht komplexe Biester, die können alles mögliche. Am CIA1 hängt vor allem die Tastatur und die Joystickports (auf den selben Leitungen, das zu trennen ist nicht immer sauber möglich ;-) und sein Timer wird wohl als IRQ-Timer mit 1/60 s verwendet (die Initialisierung des Timers erfolgt im Kernel eben an $FDDD ff., sind eigentlich nur ein paar Schreibzugriffe auf Register des CIA). Außerdem haben die noch Echtzeituhren eingebaut die interessanterweise aber nicht benutzt werden... die Uhr vom BASIC wird über den Zeitgeber IRQ gesteuert, weshalb sie mit jedem Diskzugriff anfängt hinterherzugehen...

Der CIA2 hängt am NMI und steuert vor allem den seriellen Port für die Floppy (weshalb die Disk-Zugriffe die Uhr ausbremsen da sie NMIs erzeugen) und ich denk auch den User-Port. Theoretisch könnte man damit auch einen "NMI-Timer" erzeugen, wird aber wohl vom Kernel nicht gemacht.

Am IRQ hängt noch der VIC (Rasterzeilen.-Interrupt), am NMI die Restore-Taste (löst direkt einen NMI aus). Weiß jetzt nicht ob ich noch Komponenten vergessen hab.

Ja, genau. Was hat es mit den zwei ersten Speicherstellen zu tun?

Die Adressen $0 und $1 steuern einen simplen Parallel-I/O Port an der CPU. In $0 wird für jedes Bit eingestellt ob es ein Ein- oder Ausgang sein soll und in $1 können die Werte gelesen oder geschrieben werden. Die ersten 3 Bits gehen wie gesagt in den PLA und steuern das Speicherlayout, Bits 3-5 sind für den Datasettenport, 6 und 7 sind nicht aus der CPU herausgeführt und somit nicht verwendbar (außer um Freezermodule auszutricksen, die 2 Speicherstellen stehen nicht im RAM und können deshalb nicht extern ausgelesen werden ;-)
 
Zurück
Oben