Benutzer:Stephan64/Testseite1

Aus C64-Wiki
Zur Navigation springenZur Suche springen

Kommandos an den Emulator[Bearbeiten | Quelltext bearbeiten]

Speicherorganisation[Bearbeiten | Quelltext bearbeiten]

Zu den wichtigsten Fähigkeiten des Emulators Y64 gehört es, dass per Fernzugriff beliebige Speicherbereiche ausgelesen und — sofern technisch sinnvoll — auch geschrieben werden können. Der vom Emulator verwendete Speicher ist hierfür in virtuelle Segmente unterteilt, auf die mit einer 6 Bit langen Segmentnummer, einem 8 Bit-Index und ggf. einem 16 Bit-Offset zugegriffen werden kann. Die folgende Tabelle listet die Bedeutung der Segmentnummer und des zugehörigen Index auf:

Segment Inhalt des Segments Länge des Segments
(Bytes)
Index Interpretation des Index
$00 C64-Hauptspeicher 65536 0..255 Page (256 Byte-Speicherseite)
$01 Opcode-Statistik der 6510-CPU (5 Byte-Ganzzahlen, little endian) 1280 0..255 Opcode
$02 VGA-Ausschnitt horizontal 1..32000 0..11 Nummer des Ausschnitts
$03 VideoRAM-Ausschnitt 1..1000 0..11 Nummer des Ausschnitts
$04 FarbRAM-Ausschnitt 1..1000 0..11 Nummer des Ausschnitts
$05 Bitmap-Ausschnitt 1..8000 0..11 Nummer des Ausschnitts
$06 VGA-Bildschirm horizontal 32000 0..199 Nummer der Rasterzeile
$07 VideoRAM 1000 0..24 Nummer der Bildschirmzeile
$08 FarbRAM 1000 0..24 Nummer der Bildschirmzeile
$09 Bitmap 8000 0..24 Nummer der Bildschirmzeile
$0A Character Generator 2048 0..255 Nummer des Zeichens
$0B VIC 6569-Register 47 0..46 Nummer des Registers
$0C CIA 6526-Register (1) 16 0..15 Nummer des Registers
$0D CIA 6526-Register (2) 16 0..15 Nummer des Registers
$0E Aktuell verwendete Sprite-Definitionen 8× 64 0..7 Nummer des Sprite
$0F BASIC ROM 8192 0..31 Page (256 Byte-Speicherseite)
$10 Kernal ROM 8192 0..31 Page (256 Byte-Speicherseite)
$11 Zeichengenerator-ROM 4096 0..15 Page (256 Byte-Speicherseite)
$12 Spritedefinitionen 16384 0..255 Spritenummer
$13 Modul-Segment 20736 0..80 Page (256 Byte-Speicherseite)
$14 Stack 65536 0..255 Page (256 Byte-Speicherseite)
$15 Y64-Hauptprogramm 65264 0..254 Page (256 Byte-Speicherseite), nur für Debugging
$16 Y64-Initialisierungsroutinen 6064 0..23 Page (256 Byte-Speicherseite), nur für Debugging
$17 Y64-Grafikroutinen (16 Bit) 35200 0..137 Page (256 Byte-Speicherseite), nur für Debugging
$18 Y64-Grafikroutinen (32 Bit) 24304 0..94 Page (256 Byte-Speicherseite), nur für Debugging
$19 Y64-Dokumentation 13088 0..51 Page (256 Byte-Speicherseite), nur für Debugging
$1A Y64-USB-Treiber 13088 0..51 Page (256 Byte-Speicherseite), nur für Debugging
$1B Debug-Bildschirm Seite 1, Zeichen/Attribut 4000 0..24 Bildschirmzeile
$1C Debug-Bildschirm Seite 2, Zeichen/Attribut 4000 0..24 Bildschirmzeile
$1D Debug-Bildschirm Seite 1, Zeichen 2000 0..24 Bildschirmzeile
$1E Debug-Bildschirm Seite 2, Zeichen 2000 0..24 Bildschirmzeile
$1F Global Descriptor Table 304 0..37 Eintrag (Segmentbeschreibung)
$20 Virtuelles I/O-Segment 120 0..14 Slotnummer
$21 VGA-Bildschirm vertikal 16000 0..159 Nummer der Doppelspalte
$22 VGA-Fenster vertikal 0..11 Fensternummer
$23 DAQs 768 0..127 Nummer des Eintrags
+0..1: Länge-1
+2: Segment
+3: Index
+4..5: Offset
$24 Neu ausgewertete DAQs 0..127 Nummer des Eintrags
$25 Bereits ausgewertete DAQs 0..127 Nummer des Eintrags
$26 VGA-Cache 32000 0..199 Zeilennummer
$27 Ungenutzter Modul-Speicher 3584 0..13 Seitennummer
$28 Branch-Statistik 96 0..15 0/1: BPL/BMI forward taken/not taken
2/3: BPL/BMI backwards taken/not taken
4/5: BVC/BVS forward taken/not taken
6/7: BVC/BVS backwards taken/not taken
8/9: BCC/BCS forward taken/not taken
10/11: BCC/BCS backwards taken/not taken
12/13: BNE/BEQ forward taken/not taken
14/15: BNE/BEQ backwards taken/not taken

Virtuelles I/O-Segment[Bearbeiten | Quelltext bearbeiten]

Das virtuelle I/O-Segment ist unterteilt in Slots von jeweils 8 Bytes Länge, die abgeleitete Informationen über den Zustand des emulierten C64 bereitstellen:

Slot Inhalt des Slots Detaillierte Belegung
$00..$07 Attribute für Sprite 0..7 +0: X-Koordinate
+2: Y-Koordinate
+3: Farbe
+4: Definition
+5: Flags
... 0xxxxxbb: Sprite inaktiv, 1xxxxxbb: Sprite aktiv
... x0xxxxbb: Sprite monocolor, x1xxxxbb: Sprite multicolor
... xx0xxxbb: Sprite vor Hintergrund, xx1xxxbb: Hintergrund vor Sprite
... xxx0xxbb: Sprite Y normal, xxx1xxbb: Sprite Y vergrößert
... xxxx0xbb: Sprite X normal, xxxx1xbb: Sprite X vergrößert
... bb=VIC-Speicherbank (Bit 15-14)
+6: Multicolor-Farbe 1
+7: Multicolor-Farbe 2
$08 Attribute für SID-Stimme 1 +0..6: In SID-Register $D400..$D406 geschriebene Werte
$09 Attribute für SID-Stimme 2 +0..6: In SID-Register $D407..$D40D geschriebene Werte
$0A Attribute für SID-Stimme 3 +0..6: In SID-Register $D40E..$D414 geschriebene Werte
$0B Y64-Versionsnummer +0: Build
+1: Minor number
+2: Major number
$0C Hardware-Informationen +0: Typ des RS232-Interface
... $00: RS232
... $01: USB (Atmel MAX16U2)
... $02: USB (QinHeng CH340)
... $03: USB (Prolific PL2303)
... $04: USB (Silicon Labs CP2102)
... $05: USB (FTDI FT232)
$0D Instruktions-Statistik +0..1: Anzahl ausgeführter CPU-Instruktionen während des letzten Frame
+2..5: Anzahl bisher dargestellter Frames
$0E Masken für CIA1 +0..1: AND-Maske für $DC00/$DC01
+2..3: OR-Maske für $DC00/$DC01
$0F Leistungsdaten 80x86 +0..1: Startwert Timer
+2..3: Voriger Stand Timer nach Bildschirmaufbau
+4..5: Aktueller Stand Timer nach Bildschirmaufbau
+6: Anzahl Timerinterrupts seit letztem Bildschirmaufbau
+7: Drosselungsmaske (ungedrosselt: $00)
$10 Basisadressen VIC +0..1: Anfangsadresse Character-Generator
+2..3: Anfangsadresse Bitmap
+4..5: Anfangsadresse Video-RAM

DAQ-Listen[Bearbeiten | Quelltext bearbeiten]

Sollen eine größere Zahl von Werten gelesen werden, die nicht in aufeinanderfolgenden Speicherzellen eines Segments abgelegt sind oder sich gar in verschiedenen Segmenten befinden, so bietet sich die Nutzung von Data Acquisition-Listen (DAQ-Listen) an (siehe Segmente $23...$25). Hierbei werden nacheinander die Einträge einer zuvor definierten Liste von Speicherbereichen ausgelesen und anschließend in einem einzigen, gemeinsamen Datenblock übertragen.

Offset Inhalt
0-1 Länge des zu lesenden Speicherbereichs -1
2 %ecssssss
... e=0: Auswertung beim nächsten Eintrag fortsetzen, e=1: Auswertung stoppt nach diesem Eintrag
... c=0: Inhalt des Segments wird gelesen, c=1: Prüfsumme des Segments wird ermittelt
... ssssss: Segment des zu lesenden Speicherbereichs
3 Index des zu lesenden Speicherbereichs
4-5 Offset des zu lesenden Speicherbereichs

Speicherzugriffsbefehle[Bearbeiten | Quelltext bearbeiten]

Allen in den obigen Tabellen dokumentierten Speichersegmente lassen sich per Fernzugriff lesen und — sofern technisch möglich und sinnvoll — auch schreiben. Hierzu dienen die nachfolgend aufgeführten Befehle.

Beim Lesezugriff kann hierbei wahlweise ein im Befehl spezifizierter Speicherbereich übertragen werden, oder alternativ eine Prüfsumme über diesen Speicherbereich gebildet und übermittelt werden. Soll also beispielsweise periodisch der Bitmap-Speicher des emulierten C64 ausgelesen werden, so lässt sich jeweils zunächst anhand einer Prüfsumme feststellen, ob sich dieser Speicher überhaupt geändert hat und ob ein Transfer somit erforderlich ist.

Beim Schreibzugriff kann wahlweise ein Datenblock zum Emulator übertragen und in den spezifizierten Adressbereich geschrieben werden, oder ein einzelnes Datenbyte übertragen werden, mit dem der Adressbereich gefüllt werden soll. Auf diese Weise lässt sich insbesondere unkompliziert der Bildschirmspeicher oder ein Teil davon löschen.

Codierung für 1..32 Bytes Codierung für 1..2048 Bytes Funktion
%100xxxxx %00ssssss ii oh ol d0..dx %000xxxxx %xxxxxxxx %00ssssss ii oh ol d0..dx (x+1) Bytes d0..dx ab Offset (256*oh+ol) in Segment s, Index i schreiben
%100xxxxx %01ssssss ii oh ol dd %000xxxxx %xxxxxxxx %01ssssss ii oh ol dd (x+1) Bytes ab Offset (256*oh+ol) in Segment s, Index i mit Wert dd füllen
%100xxxxx %10ssssss ii d0..dx %000xxxxx %xxxxxxxx %10ssssss ii d0..dx (x+1) Bytes d0..dx ab Offset 0 in Segment s, Index i schreiben
%100xxxxx %11ssssss ii dd %000xxxxx %xxxxxxxx %11ssssss ii dd (x+1) Bytes ab Offset 0 in Segment s, Index i mit Wert dd füllen
%101xxxxx %00ssssss ii oh ol %001xxxxx %xxxxxxxx %00ssssss ii oh ol (x+1) Bytes ab Offset (256*oh+ol) in Segment s, Index i lesen
%101xxxxx %01ssssss ii oh ol %001xxxxx %xxxxxxxx %01ssssss ii oh ol Prüfsumme über (x+1) Bytes ab Offset (256*oh+ol) in Segment s, Index i bilden
%101xxxxx %10ssssss ii %001xxxxx %xxxxxxxx %10ssssss ii (x+1) Bytes ab Offset 0 in Segment s, Index i lesen
%101xxxxx %11ssssss ii %001xxxxx %xxxxxxxx %11ssssss ii Prüfsumme über (x+1) Bytes ab Offset 0 in Segment s, Index i bilden

Meldungen des Emulators[Bearbeiten | Quelltext bearbeiten]

Die folgenden, tabellarischen Darstellungen erläutern die vom Emulator Y64 verwendeten Codierungen für Informationen, die per Fernzugriff ausgelesen werden. Aus zwei Kleinbuchstaben bestehende Codes repräsentieren hierbei Bytes in Hexadezimaldarstellung, während achtstellige Codes mit einem vorangestellten Prozentzeichen für Bytes in Binärdarstellung stehen.

Codierung des CPU-Zustands[Bearbeiten | Quelltext bearbeiten]

Wird der Emulator per Fernzugriff dazu aufgefordert, für jeden im Debugger angezeigten und ausgeführten Befehl den aktuellen Status der CPU zu übermitteln, so geschieht dies in einem sehr kompakten Format. Ausgehend von einem zu Beginn mitgeteilten Ausgangszustand, codieren die Datenpakete jeweils nur die Veränderung gegenüber dem bisherigen Zustand. Hat beispielsweise ein Flag-Befehl keine Auswirkungen, weil das betreffende Flag bereits vor der Ausführung im gewünschten Zustand war, so wird dieser Befehl wie ein NOP codiert.

Codierung Alternative Codierung Veränderung des CPU-Zustands Beispiele für Einsatzzweck
$E0 $60 $00 PC=PC+1 NOP
$E1 $60 $01 PC=PC+2 STA/STX/STY zpg/ind
$E2 $60 $02 PC=PC+3 STA/STX/STY abs
$E3 dd $60 $03 dd PC=PC+(dd+2) Branch-Befehle
$E4 ml mh $60 $04 ml mh PC=256*mh+ml JMP
$E5 %ss00ssss $60 $05 %ss00ssss PC=PC+1, ST=%ss11ssss Flag-Befehle
$E5 %ss01ssss aa $60 $05 %ss01ssss aa PC=PC+1, ST=%ss11ssss, A=aa ASL/LSR/ROL/ROR A
$E5 %ss10ssss xx $60 $05 %ss10ssss xx PC=PC+1, ST=%ss11ssss, X=xx INX, DEX
$E5 %ss11ssss yy $60 $05 %ss11ssss yy PC=PC+1, ST=%ss11sss,s Y=yy INY, DEY
$E6 %ss00ssss $60 $06 %ss00ssss PC=PC+2, ST=%ss11ssss BIT zpg
$E6 %ss01ssss aa $60 $06 %ss01ssss aa PC=PC+2, ST=%ss11ssss, A=aa LDA imm/zpg/ind
$E6 %ss10ssss xx $60 $06 %ss10ssss xx PC=PC+2, ST=%ss11ssss, X=xx LDX imm/zpg/ind
$E6 %ss11ssss yy $60 $06 %ss11ssss yy PC=PC+2, ST=%ss11ssss, Y=yy LDY imm/zpg/ind
$E7 %ss00ssss $60 $07 %ss00ssss PC=PC+3, ST=%ss11ssss BIT abs
$E7 %ss01ssss aa $60 $07 %ss01ssss aa PC=PC+3, ST=%ss11ssss, A=aa LDA abs
$E7 %ss10ssss xx $60 $07 %ss10ssss xx PC=PC+3, ST=%ss11ssss, X=xx LDX abs
$E7 %ss11ssss yy $60 $07 %ss11ssss yy PC=PC+3, ST=%ss11ssss, Y=yy LDY abs
- $60 $08 PC=PC+1, SP=SP-1 PHA, PHP
- $60 $09 ss PC=PC+1, SP=SP+1, ST=ss PLP
- $60 $0A ss aa PC=PC+1, SP=SP+1, ST=ss, A=aa PLA
- $60 $0B ml mh PC=256*mh+ml, SP=SP-2 JSR
- $60 $0C ml mh PC=256*mh+ml, SP=SP+2 RTS
- $60 $0D ml mh ss PC=256*mh+ml, SP=SP-3, ST=ss IRQ, NMI
- $60 $0E ml mh ss PC=256*mh+ml, SP=SP+3, ST=ss RTI
- $60 $0F ml mh ss aa xx yy pp PC=256*mh+ml, ST=ss, A=aa, X=xx, Y=yy, SP=pp Neustart, LAX

Codierung von Zeitstempeln[Bearbeiten | Quelltext bearbeiten]

Zeitstempel, die im Rahmen des Fernzugriffs übermittelt werden, stellen keine fortlaufenden Zähler dar. Vielmehr liefert der Emulator die Zahl der CPU-Takte, die seit dem Beginn von Rasterzeile 0 vergangen sind (codiert in 2 Bytes, nachfolgend mit "tl" und "th" bezeichnet, Wertebereich 0..19655) und die Zahl der Bildschirmwiederholungen seit dem Start des Emulators (codiert in 4 Bytes, nachfolgend mit "bll", "blh", "bhl" und "bhh" bezeichnet, Wertebereich 0...4294967295). Haben sich ein oder mehrere höchstwertige Bytes seit der letzten Übermittlung nicht geändert, so werden diese nicht übertragen.

Codierung Alternative Codierung Interpretation
$C0 tl $40 $00 tl Low-Byte des Taktzählers=tl, High-Byte und Bildschirmzähler unverändert
$C1 tl th $40 $01 tl th Taktzähler=256*th+tl, Bildschirmzähler unverändert
$C2 tl th bll $40 $02 tl th bll Taktzähler=256*th+tl, niederwertigstes Byte des Bildschirmzählers=bll, Rest unverändert
$C3 tl th bll blh $40 $03 tl th bll blh Taktzähler=256*th+tl, niederwertigste 2 Bytes des Bildschirmzählers=bll/blh, Rest unverändert
$C4 tl th bll blh bhl $40 $04 tl th bll blh bhl Taktzähler=256*th+tl, niederwertigste 3 Bytes des Bildschirmzählers=bll/blh/bhl, Rest unverändert
$C5 tl th bll blh bhl bhh $40 $05 tl th bll blh bhl bhh Taktzähler=256*th+tl, Bildschirmzähler=bll/blh/bhl/bhh

Codierung von I/O-Zugriffen[Bearbeiten | Quelltext bearbeiten]

Die Übermittlung von I/O-Zugriffe lässt sich selektiv für ausgewählte Ein-/Ausgabebausteine und getrennt nach Lesen- und Schreibzugriffen aktivieren. Die Art des Zugriffs (lesend oder schreibend) und die Adresse des Registers wird gemeinsam in einem einzigen Byte codiert:

Codierung Interpretation/Register
%0xxxxxxx Lesezugriff
%1xxxxxxx Schreibzugriff
%d00xxxxx Zugriff auf Register $D400+%xxxxx des SID 6581
%d010xxxx Zugriff auf Register $DC00+%xxxx des ersten CIA 6522
%d011xxxx Zugriff auf Register $DD00+%xxxx des zweiten CIA 6522
%d1xxxxxx Zugriff auf Register $D000+%xxxxxx des VIC 6569
%d111111x Zugriff auf CPU-Port an Adresse $000x

Codierung von Inhalten des Debug-Bildschirms[Bearbeiten | Quelltext bearbeiten]

Wird der Emulator per Fernzugriff aufgefordert, den Inhalt des Debug-Bildschirms zu übertragen, so geschieht dies abschnittsweise, wobei Abschnitte mit variabler Länge in der jeweils optimalen Codierung übertragen werden. Sowohl Bereiche, die seit der letzten Übertragung unverändert geblieben sind, als auch Abschnitte mit einheitlichem Inhalt oder gleichem Attribut werden durch hierfür maßgeschneiderte Codierungen übermittelt.

Codierung Alternative Codierung Interpretation
%11111xxx %01111xxx xxxxxxxx Nächste (x+1) Zeichen/Attribut-Paare unverändert
%11110xxx zz %01110xxx xxxxxxxx zz Nächste (x+1) Zeichen auf Wert zz setzen, zugehörige Attribute unverändert
%11101xxx z0 ... zx %01101xxx xxxxxxxx z0 ... zx Nächste (x+1) Zeichen übertragen, zugehörige Attribute unverändert
%11011xxx aa %01011xxx xxxxxxxx aa Nächste (x+1) Zeichen unverändert, zugehörige Attribute auf Wert aa setzen
%11010xxx zz aa %01010xxx xxxxxxxx zz aa Nächste (x+1) Zeichen auf Wert zz setzen, zugehörige Attribute auf Wert aa setzen
%11001xxx aa z0 ... zx %01001xxx xxxxxxxx zz aa Nächste (x+1) Zeichen übertragen, zugehörige Attribute auf Wert aa setzen
%10111xxx a0 ... ax %00111xxx xxxxxxxx aa Nächste (x+1) Zeichen unverändert, zugehörige Attribute übertragen
%10110xxx zz a0 ... ax %00110xxx xxxxxxxx zz a0 ... ax Nächste (x+1) Zeichen auf Wert zz setzen, zugehörige Attribute übertragen
%10101xxx z0 a0 ... zx ax %00101xxx xxxxxxxx z0 a0 ... zx ax Nächste (x+1) Zeichen/Attribut-Paare übertragen

Eingeleitet wird die Übertragung jeweils mit einem Startzeichen ($A1 bzw. $20 $01 für die erste Seite, $A2 bzw. $20 $02 für die zweite Seite des Debug-Bildschirms). Anschließend folgt eine variable Anzahl von Abschnitten, deren Länge sich auf insgesamt 2000 Zeichen/Attribut-Paare summiert.