VDC 8563

Dieser Grafikchip war ein Überbleibsel aus dem CBM900-Projekt. Er wurde modifiziert im C128 eingesetzt, um den 80-Zeichen-Schirm realisieren zu können.

Die Entwicklungsgeschichte des Chips ist recht abenteuerlich. Frühe Modelle hatten eine Fehlerrate von drei Fehlern pro Sekunde statt alle drei Jahre. Das Blockverschiebefeature konnte nur maximal 256 Bytes verschieben (3,5 Bildschirmzeilen...) und selbst dann vergaß es gelegentlich ein paar Zeichen. Um das zu umgehen, musste man den Verschiebebefehl ZWEIMAL geben. Dummerweise vergaß man, dies dem armen Kerl zu sagen, der CP/M für den C128 entwickelt hatte. In der Nacht vor der Präsentation auf der CES bekam er es dann mit und setzte sich hin, um alle Schreibzugriffe auf die entsprechenden Register anzupassen. Da er die zum neuassemblieren benötigten Gerätschaften nicht dabei hatte, musste dies direkt mit einem Diskettenmonitor geschehen. Ach ja, bei CP/M sind die Bytes auf den Disketten rückwärts in ebenfalls rückwärts orientierten Sektoren abgespeichert. Außerdem konnte er die Zahl der Instruktionen weder erhöhen noch verringern, sondern bloß vorhandene Instruktionen auswechseln. Dazu kam das Sektorprüfsummenberechnen von Hand. All das mit einem Diskettenmonitor...

Da der Chip keinerlei Interrupts abgibt, wenn er mit einer Aufgabe fertig ist, musste er permanent abgefragt werden (der Running Gag bei Commodore wurde daraufhin, man braucht ja keine Klingel im Telefon, man kann ja jederzeit abheben um zu schauen ob einer dran ist). Dazu kamen noch Synchronisationsprobleme, da der Chip mit 16 MHz getaktet wurde, der Rest des Systems aber mit 14,31818 MHz, dadurch wurden Speicherzugriffe ein reines Glücksspiel. Die Fertigungsausbeute des Chips lag etwa bei 0.001 % (kein Witz!!!), für jeden Chip musste das Netzteil anders eingestellt werden und das laden der Fonts dauerte bei jedem Einschalten etwa 10 Sekunden, vorausgesetzt, es funktionierte überhaupt. Die meisten dieser Probleme wurden erst kurz vor der Präsentation des C128 "behoben", das meiste waren "dirty hacks", um überhaupt etwas zeigen zu können.

Eigenschaften des VDC

Im Gegensatz zu beispielsweise dem VIC hatte der VDC seinen eigenen Grafikspeicher, der beim alten C128 16 KByte, beim neueren C128 DCR 64 KByte groß war. Dieser Speicher war nicht direkt für die CPU des Rechners ansprechbar, und die Register des Chips waren auch nicht wie die der anderen im I/O-Bereich des Rechners zu finden. Um den VDC zu steuern, wurde auf eine etwas seltsame Methode zurückgegriffen. Der Chip war nur mit zwei Speicherstellen im Adressbereich der CPU vertreten, eine davon repräsentierte die Registernummer, die andere den Registerwert. Wenn man nun etwas in ein Register schreiben wollte, dann schrieb man zuerst die Registernummer in die eine Speicherzelle, und dann den gewünschten Wert in die andere. Das lesen funktionierte analog, indem man erst die Registernummer angab, und den Wert dann aus dem zweiten Speicherbereich las. Dies machte direkte Zugriffe auf den Bildschirmspeicher zwar nicht unmöglich (es gab spezielle VDC-Register zum Ansprechen des Speichers) aber äußerst umständlich.

Dafür bekam man einen CGA-ähnlichen Grafikchip, der Texte in 16 Farben in einer 80x25 Matrix anzeigen konnte (mittels eines Interlace-Tricks waren 80x50 Zeichen möglich, aber leider nur mit dem typischen geflimmere) und Grafik in 640 x 200 Bildpunkten und mit Programmiertricks sogar noch viel höherer Auflösung auf den Schirm brachte.

Darstellungsmodi

Art Auflösung Farben
Text 80 x 25 1 aus 16
Grafik 640 x 200 1 aus 16

Register

Verwendet in
Register 0 / $0: Anzahl der Zeichen zwischen Synchronimpulsen
76543210 RW Anzahl der Zeichen zwischen Synchronimpulsen
Register 1 / $1: Anzahl der Zeichen pro Zeile
76543210 RW Anzahl der Zeichen pro Zeile
Register 2 / $2: Linker Bildschirmrand
76543210 RW Linker Bildschirmrand
Register 3 / $3: Breite des horizontalen und vertikalen Synchronimpulses
7654.... RW Breite des vertikalen Synchronimpulses
....3210 RW Breite des horizontalen Synchronimpulses
Register 4 / $4: Wie Register 0, aber für Anzahl der Zeilen.
76543210 RW Gesamtzahl Zeichenzeilen minus 1
Register 5 / $5: Feineinstellung zu Register 4
765..... RW Ungenutzt
...43210 RW Feinabgleich für Register 4
Register 6 / $6: Anzahl der Textzeilen
76543210 RW Anzahl der Textzeilen
Register 7 / $7: Oberer Bildschirmrand
76543210 RW Beginn des Oberen Bildschirmrandes
Register 8 / $8: Anzeigeform
765432.. RW Ungenutzt
......10 RW Anzeigeform: 00 und 10 = Kein Zeilensprung, 01 = Zeilensprung, 11 = Zeilensprung doppelte Dichte
Register 9 / $9: Zeichenlänge
765..... RW Ungenutzt
...43210 RW Anzahl der der Bildschirmzeilen pro Zeichenzeile minus 1
Register 10 / $a: Cursor-Darstellung
7....... RW Ungenutzt
.65..... RW Cursor-Modus: 00 = Cursor blinkt nicht, 01 = kein Cursor sichtbar, 10 = Cursor blinkt mit 1/16 der Bildwiederholfrequenz, 11 = Cursor blinkt mit 1/32 der Bildwiederholfrequenz
...43210 RW Cursor-Startzeile
Register 11 / $b: Cursorende
765..... RW Ungenutzt
...43210 RW Cursor-Endzeile
Register 12 / $c: Start des Bildschirmspeichers
76543210 RW Startadresse des Bildschirmspeichers (High Byte)
Register 13 / $d: Start des Bildschirmspeichers
76543210 RW Startadresse des Bildschirmspeichers (Low Byte)
Register 14 / $e: Cursorposition im Video RAM
76543210 RW Cursor-Position im Bildschirmspeicher (High Byte)
Register 15 / $f: Cursorposition im Video RAM
76543210 RW Cursor-Position im Bildschirmspeicher (Low Byte)
Register 16 / $10: Lightpen-Position
76543210 RW Vertikale Light-Pen Position in Zeichen-Zeilen plus 1
Register 17 / $11: Lightpen-Position
76543210 RW Horizontale Light-Pen Position in Zeichen-Zeilen plus 8
Register 18 / $12: Adresse im VDC-RAM
76543210 RW Speicheradresse für direkten Bildschirmspeicherzugriff (High Byte)
Register 19 / $13: Adresse im VDC-RAM
76543210 RW Speicheradresse für direkten Bildschirmspeicherzugriff (Low Byte)
Register 20 / $14: Startadresse des Attribut-RAM
76543210 RW Startadresse des Attributspeichers (High Byte)
Register 21 / $15: Startadresse des Attribut-RAM
76543210 RW Startadresse des Attributspeichers (Low Byte)
Register 22 / $16: Zeichenformat
7654.... RW Zeichenbreite in Pixel minus 1 (Mit Zeichenzwischenraum)
....3210 RW Zeichenbreite in Pixel minus 1 (Ohne Zeichenzwischenraum)
Register 23 / $17: Zeichenformat
765..... RW Ungenutzt
...43210 RW Anzahl der Bildschirmzeilen pro Zeichenzeile minus 1 ohne vertikalen Zeilenabstand
Register 24 / $18: Zeichenbreite und Flags
7....... RW Block-Copy: 0 = Block wird geschrieben nach einem Schreibzugriff auf Register 30, 1 = Block wird kopiert nach einem Schreibzugriff in Register 30
.6...... RW Darstellung: 0 = Normaldarstellung, 1 = Inversdarstellung
..5..... RW Blinkfrequenz der Buchstaben: 0 = Blinkfrequenz ist 1/16 der Bildwiederholfrequenz, 1 = Blinkfrequenz ist 1/32 der Bildwiederholfrequenz
...43210 RW Anzahl der Bildschirmzeilen, die der Bildschirm nach oben geschoben wird
Register 25 / $19: Diverse Steuerzwecke
7....... RW Betriebsart: 0 = Textdarstellung, 1 = Grafikdarstellung
.6...... RW Attribute: 0 = Aus, 1 = An
..5..... RW Semigrafik Betriebsart: 0 = Der Horizontale Zwischenraum zwischen zwei Zeichen wird in der Hintergrundfarbe dargestellt, 1 = Der horizontale Zwischenraum zweier Zeichen wird in der gleichen Farbe dargestellt, wie das letzte normal dargestellte Zeichen
...4.... RW Pixelgröße: 0 = 1 DOT-Takt, 1 = 2 DOT-Takte
....3210 RW Anzahl der Pixel, um die der Bildschirm nach links geschoben wird
Register 26 / $1a: Farbregister
7654.... RW Vordergrundfarbe wenn Bit 6 von Register 25 = 0
....3210 RW Hintergrund und Rahmenfarbe
Register 27 / $1b: Adressen-Inkrement pro Zeile
76543210 RW Wert, der zum Bildschirm- und Attributzeiger nach jeder Zeile aufaddiert wird, um die nachste Zeile zu erhalten
Register 28 / $1c: Startadresse des Zeichensatzes
765..... RW Adresse des Zeichengenerators (Bits 13 - 15)
...4.... RW DRAM-Typ: 0 = 4416, 1 = 4164
Register 29 / $1d: Position der Unterstreichung
...43210 RW Bildschirmzeilenzähler für Untersteichen
Register 30 / $1e: Zählregister
76543210 RW Anzahl der Block-Write oder Block-Copy-Zyklen. Eine 0 entspricht 256 Zyklen. Das verändern dieses Registers startet den Block-Zyklus
Register 31 / $1f: Datenregister
76543210 RW Daten für Block-Write und normales Write. Beim Lesen des Registers wird die durch Register 18/19 bestimmte Bildschirmposition übergeben
Register 32 / $20: Startadresse des Blocks
76543210 RW Block-Copy Quelladresse (High-Byte). Die Zieladresse wird in Register 18/19 erwartet
Register 33 / $21: Startadresse des Blocks
76543210 RW Block-Copy Quelladresse (Low-Byte)
Register 34 / $22: technische Werte
76543210 RW Anzahl der Zeichen vom Beginn der dargestellten Zeile bis zur positiven Flanke des Display-Enable-Pins
Register 35 / $23: technische Werte
76543210 RW Anzahl der Zeichen vom Beginn der dargestellten Zeile bis zur negativen Flanke des Display-Enable-Pins
Register 36 / $24: technische Werte
7654.... RW Ungenutzt
....3210 RW Anzahl der Refresh-Zyklen pro Bildschirmzeile