CODINGLISTINGS ★ Teamwork im CPC: Der Videocontroller und das Gate-Array im CPC ★

Graphic - Elmar Krieger - Special Effects - Der Videocontroller Und Das Gate - Array Im CPC (CPC Amstrad International)Coding Listings
★ Ce texte vous est présenté dans sa version originale ★ 
 ★ This text is presented to you in its original version ★ 
 ★ Este texto se presenta en su versión original ★ 
 ★ Dieser Text wird in seiner Originalfassung präsentiert ★ 

Der Videocontroiler und das Gate-Array sind die Bauteile im CPC, von denen wenig bekannt ist. Durch Änderung von Werten in deren Registern sind aber äußerst interessante Effekte zu erzielen. So ist es beispielsweise möglich, Bilder über den gesamten Bildschirm hinweg darzustellen.

Der Videocontroller und das Gate-Array warten schon seit 1984 geduldig, daß man ihnen die Last ihrer großen Geheimnisse von den zarten Draht-füßchen nehme. Ersterer wurde höchstens einmal zum Umschalten in den 60-Hertz-Modus mit einem OUT-Befehl beehrt. Das Gate-Array dürfte bestenfalls als Zwischenhändler bei der schnellen BANK-Umschaltung gedient haben. Im Jahre 9 der CPC-Zeitrechnung ist eine Enthüllung dieser ungeahnten Fähigkeiten, denen ein Großteil der 16-Bit- und 32-Bit-Computer auch heute nichts Vergleichbares entgegenzusetzen hat, schon längst überfällig.

All jene, die bei Schlagworten wie "Hardwarenahe Assembler-Programmierung" lieber weiterblättern, sei hier gesagt: Verdrängt einmal für zehn Minuten Eure Ängste, und laßt Euch von den folgenden Seiten überraschen. Wer sich aktiv an der Reise durch den CPC beteiligen möchte, sollte über Grundkenntnisse der Maschinensprache verfügen. Doch auch für alle anderen werden sich viele effektvolle Tricks zum Einbau in BASIC-Programme finden.

Der Schwerpunkt der folgenden Seiten liegt auf dem Grundverständnis der Vorgänge im Videocontroller und im Gate-Array, denn für hardwarenahes Programmieren ist das Wissen um das Innenleben dieser CPC-Bausteine unerläßlich. Den, der sich tapfer durch die Theorie geschlagen hat, erwartet ein mundgerecht zubereiteter Happen Praxis.

Beginnen wir mit dem Videocontroller. Zur Einstimmung empfehlen wir einen Blick auf die Auflistung aller CRTC-Register. Nach dem Einschalten sind die Register leer, der Bildschirm ist also dunkel. Der Prozessor beginnt seine Arbeit im ROM, und eine seiner ersten Tätigkeiten ist das Füllen sämtlicher CRTC-Register. (Besitzereines Disassemblers können den Weg ab Adresse 0 im LOWER ROM verfolgen.) Vorher testet er noch das Vorhandensein einerLötbrücke, um den CRTC gegebenenfalls mil den Daten für den 60-Hertz-Modus zu füttern. Ein Listing zum Umschalten in den 60-Hertz-Modus finden Sie in der Listingbox. Der CRTC 6845(XX) von Motorola befindet sich schon seit Urzeiten am Markt und hat eine Verbreitung gefunden, die für einen Spezialchip einzigartig ist. So hat er zum Beispiel in den MDA-, Hercules- und CGA-Karten der PCs seinen festen Platz. Insgesamt bietet er vier Darstellungsmodi:

  1. Textmodus mit 80*25 Zeichen und freidefinierbarem Hardware-Cursor,
  2. Grafikmodus0 (160*200 Punkte, 16 Farben),
  3. Grafikmodus 1 (320*200 Punkte, vier Farben),
  4. Grafikmodus 2 (640*200 Punkte, zwei Farben).

Auf den PCs der ersten Tage fand nur der Textmodus Verwendung, vor allem wegen der damals noch sehr hohen Preise für RAM-Bausteine. Die PCs hatten damals, wie unser CPC, 64 kByte Speicher. Von MBytes wagte man noch nicht einmal zu träumen. Im Textmodus verbraucht jedes Zeichen gerade zwei Bytes (ASCII und Farbinformation), das sind bei 80*25 Zeichen nicht einmal 4 kByte Bildschirmspeicher. Da galten die Grafikmodi 0 bis 2 mit ihren satten 16 kByte Video-RAM als Luxus.

Grafik - früher einmal ein Luxus

Und eben dieser Textmodus wurde von den Entwicklern des CPC nicht berücksichtigt, so daß die Z80A-CPU weiterhin jedes Zeichen auf unserem Bildschirm pixelweise aulbauen muß. Da sich ein Hardware-Cursor aber nur im Textmodus darstellen läßt, kann man die Register 10, 11,14 und 15 als Relikt aus der PC-Welt getrost vergessen. Dank Amstrads Preisbewußtsein ist jetzt also der aufgrund seiner weiten Verbreitung billigste CRTC für den visuellen Kontakt mit dem CPC zuständig. Und weil Amstrads Einkäufer noch nie besonders wählerisch waren, haben sie auch gleich über zehn verschiedene Typen des CRTC 6845 für die CPCs besorgt. Deren kleine Unterschiede werden uns noch mit einigen zusätzlichen Problemen belasten. Glücklicherweise sind diese Differenzen oft so minimal, daß sich die zehn Typen auf drei Hauptvertreter zurückführen lassen. Im folgenden werden wir diese mit Typ 0 bis 2 bezeichnen, wobei Typ 0 am besten für Tricks jeder Art geeignet ist und Typ 2 oft ziemlich böse reagiert. Jetzt wäre es für jeden an der Zeit zu erfahren, welcher CRTC sich eigentlich in seinem eigenen CPC befindet. Lösung 1: Aufschrauben, Staub absaugen und Typenbezeichnung entziffern: 6845 SP = Typ 0,6845 R = Typ 1,6845 P=Typ2.

Lösung 2: Listing 2 abtippen und starten. Diesen CRTC-Test haben wir der französischen Demogruppe "LOGON SYSTEM" zu verdanken, die sich wohl einige Nächte mit öden Zeit- und Registervergleichen um die Ohren geschlagen haben muß.

Jetzt gilt es noch die Frage zu klären, wie man ein Register mit einem bestimmten Wert lädt. DerZ80-Prozessor tritt mit den Hardwarekomponenten über die 1/O-Kanäle (INPUT/OUTPUT-Kanäle) in Verbindung. Diese kann man sich als Schläuche von der CPU zum jeweiligen Gerät vorstellen, in die man mit OUT Daten hineinschicken und mit IN (INP in BASIC) herauslesen kann. Jetzt könnte man natürlich 18 Schläuche zu den einzelnen CRTC-Registern verlegen, was aber in einem teuren und komplizierten Schlauchsalat enden würde.


Portadressen: &BCXX (Auswahl), &BDXX (Schreiben),&BFXX (Lesen)

Reg.InhaltFunktion
063Gesamtbreite des Bildschirms inklusive Border und horizontaler Rücklauf
140Zahl der Zeichen/Zeile (Wortmodus, d.h. 40 für 80 Bytes)
246Beginn des horizontalen Rücklaufs (6 Zeichen nach rechtem Rand)
3142Feineinstellung des horizontalen Rücklaufs
438Gesamthöhe des Bildschirms inklusive Border und vertikaler Rücklauf
50Feineinstellung der Gesamthöhe in Pixelzeilen
625Zahl der angezeigten Textzeilen
730Beginn des vertikalen Rücklaufs (5 Textzeilen nach dem unteren Rand)
80Interlace-Modus(25 Hz Bild wiederholfrequenz, 2* Auflösung)
97Zahl der Pixelzeilen-1 pro Textzeile
100Aussehen des nichtexistenten Hardware-Cursors
110Aussehen des nichtexistenten Hardware-Cursors
1248Startadresse Bildsehirmspeicher (HIGH = Bit 8 - 13)
130Startadresse Bildschirmspeicher (LOW = Bit 0 - 7)
140Position des nichtexistenten Hardware-Cursors (HIGH)
150Position des nichtexistenten Hardware-Cursors (LOW)
16??Bildschirmadresse, bei der Lightpen-Impuls auftraf (HIGH)
17??Bildschirmadresse, bei der Lightpen-Impuls auftraf (LOW)

Die Register des CRTC 6845

I/O-Kanäle und Schlauchsalat

Man verwendet daher in der Praxis nur drei Leitungen, wobei man über Leitung 1 (&BC00) ein CRTC-Register auswählt, über Leitung 2 (&BD00) einen Wert hineinschreibt und über Leitung 3 (&BF00) den Inhalt eines Registers abfragt. Dieses Abfragen ist mit Vorsicht zu genießen. Bei CRTC-Typ 0 funktioniert es immerhin noch bei den Registern 12, 13, 16 und 17, während CRTC-Typ 2 nur bei 16 und 17 Werte ausspuckt. In der Praxis sieht das dann so aus:

10 OUT &BC00, zu ladendes Register 0-13)
20 OUT &BD00, Wert (0-255)

Wichtig ist, daß es sich bei &BC00 bis &BF00 um Pseudo-16-Bit-Adressen handelt, im Gegensatz zu echten 16-Bit-I/O-Adressen. Um Register 1 auf den Wert 9 zu setzen, gibt man ein:

OUT &BC00,1: OUT &BD00,9

Das gleiche Ergebnis erzielt man aber auch mit:

OUT &BC28,1 :OUT &BDAE,9

Es kommt also nur auf das HIGHBYTE (= &BC,&BD) an. In Assembler wird die Sache schon etwas komplizierter, gibt es doch drei verschiedene OUT-Befehle: "OUT (XX),A", "OUT (C),Reg" sowie die Blockbefehle "OU-TI", "OTIR", "OUTD" und "OTDR". Grundsätzlich steht in der Klammer die anzusprechende Portadresse und danach das CPU-Register, dessen Wert an eben diese I/O-Adresse geschickt werden soll.

Bei der Nutzung der IN- beziehungsweise OUT-Befehle sollte folgendes beachtet werden:

1) Der Befehl "OUT (XX),A" funktioniert nur bei 8-Bit-Portadressen zu denen &BCXX-&BFXX wohl nicht gehört. Fazit: In Verbindung mit dem CRTC schnellstens vergessen.

2) Der Befehl "OUT (C),Reg" krankt an seiner mißverständlichen Mnemo-nic (Name des Befehls), wird doch das C-Register nur bei "echten" 16-Bit-Adressen (beispielsweise Diskettencontroller &FB7E+&FB7F) zur Adressierung herangezogen. Sonst enthält es meistens sogar den Wert, der ausgegeben werden soll. Die komplette Verwirrung schafft da besonders der Befehl "OUT (C),C", unter dem sich Anfänger selten etwas Konkretes vorstellen können. Zum besseren Verständnis empfehlen wir, das C vor dem geistigen Auge durch ein BC zu ersetzen. Um wie oben Register 1 auf 9 zu setzen, könnte man schreiben:

ld a, 1 ld bc, &bcoo out (bc) ,a LD A, 9 LD bc, &BD00 out (bc) ,a

So wäre es wohl jedem verständlich, nur dem Assembler leider nicht. Der beharrt auf besagtem "(C)", und weil obige Methode langsam und speicherplatzfressend ist, benutzen wir eine kürzere und damit schnellere Methode. (Wie bei BASIC gesehen, ist der Wert des C-Registers oder LOWBYTES bei der Adressierung unerheblich.)

LD BC, &BC01
OUT (C),C
LD BC, &BD09
OUT (C),C

3) Die Blockout-Befehle OTIR und OTDR kann man wegen der bei Portadressen sinnlosen Wiederholung gleich abschreiben, bleiben noch OUTI und OUTD, mit denen absolute Geschwindigkeitsfanatiker noch ein paar Mikrosekunden bei längeren OUT-Ketten herausschinden können. Da wir sie aber in Verbindung mit dem Gate-Array brauchen, seien sie erwähnt. OUTI läßt sich am einfachsten so beschreiben:

LD A, (HL)
DEC B
OUT (C) ,A
INC HL

Für OUTD gilt analog:

LD A, (HL)
DEC B
OUT (C) ,A
DEC HL

Ihnen wird schon aufgefallen sein: Das "DEC B" steht vor dem eigentlichen Befehl OUT; ein Umstand, der vielen unbekannt sein dürfte. (Wer den Befehl OUTI schon einmal zusammen mit dem Gate-Array verwendete, hat seine Daten unbewußt über Adresse &7E geschickt, was glücklicherweise aber auch funktioniert.)

Auf das obige Beispiel angewandt:

LD HL, DATA
LD B, &BD
OUTI
LD B, &BE
OUTI
RET

DATA: DB 1, 9

Nun zurück zur CPU, die noch immer im ROM beschäftigt ist (Teile des Betriebssystems ins RAM kopieren', Einschaltmeldung ausgeben, Bildschirmmodus initialisieren und so weiter). Der CRTC wurde also endlich mit der oben besprochenen Methode "OUT (C),Reg" gefüttert und beginnt nun sofort mit der Darstellung des Bildes, dessen Daten er direkt aus dem standardmäßig 16 kByte großen Bildschirmspeicher holt. Dieser liegt beim CPC normalerweise im Bereich &C000 bis &FFFF. Intern verwaltet der CRTC mehrere Zähler, auf die man leider keinen Zugriff hat, die er aber ständig mit den Werten in seinen Registern vergleicht, wobei er bei Übereinstimmung eine bestimmte Aktion ausführt. Man kann also durch die Register indirekten Einfluß auf die Abläufe im CRTC nehmen.

Bitte "BORDER 26" eingeben, wir folgen jetzt dem Elektronenstrahl auf seinem Weg zum Monitor, wobei wir in der linken oberen Ecke des sichtbaren Bildschirmausschnittes beginnen (wo BORDER in PAPER übergeht.) Genau an diesem Punkt setzt der CRTC folgendeinterne Zähler auf 0:

  1. den Textzeilenzähler,
  2. den Pixelzeilenzähler und
  3. den Zeichenzähler.

Des weiteren kopiert er den Inhalt der Register 12 und 13, die ja die Startadresse des Bildschirmspeichers in leicht veränderter Form enthalten, in einen "Pointer", der ständig aktualisiert wird und so immer auf die Adresse zeigt, aus der der CRTC seine Daten nimmt. Warum Register 11 nicht &C0, sondern &30 enthält, obwohl der Bildschirmspeicher bei &C000 beginnt, ist aus der Abbildung ersichtlich. Der CRTC beginnt also mit der Darstellung der ersten Pixelzeile, wobei er im Wortmodus arbeitet, also immer zwei Bytes auf einmal aus dem Speicher liest (und den Pointer auch um 2 erhöht) und in die Bildinformation umwandelt. Dann vermindert er den Zeichenzähler um 1. Jetzt ist die Zeit für einen ersten Registervergleich gekommen. Ist der Stand des Zeichenzählers gleich dem Inhalt von

-Register 1 (Anzahl Zeichen/Zeile), so wird das Auslesen aus dem Video-RAM beendet und für den Rest der Zeile der BOR DER gezeichnet;

— Register 2 (Beginn des horizontalen Rücklaufs), wird der Elektronenstrahl dunkelgeschaltet und vom rechten Bildschirmrand an den Anfang der nächsten Pixelzeile am linken Rand geführt. Hat er diesen erreicht, wird wieder die Farbe des BORDERS erzeugt;

— Register 0 (Gesamtbreite des Bildschirms inklusive BORDER und horizontalem Strahlrücklauf), so ist die Ausgabe einer Pixelzeile beendet, und der CRTC führt folgende Aktionen aus:

  1. Der Zeichenzähler wird wieder auf 0 gesetzt.
  2. Der Pixelzeilenzähler wird um 1 erhöht und mit dem Inhalt von Register 9 (Pixelzeilen -I pro Textzeile) verglichen. Stimmen beide überein, wird der Pixelzeilenzähler mit 0 geladen, aber dafür der Textzeilenzähler um 1 erhöht .
  3. Die Änderung des Pixelzeilenzählers wird im "Pointer" berücksichtigt.

Register werden abgefragt

Die gleichen Abfragen wie oben für den horizontalen Zeichenzähler nun auch für den vertikalen Textzeilenzähler. Ist der Wert des Textzeilenzählers gleich dem Inhalt von

— Register 6 (Anzahl der dargestellten Textzeilen (25)), wird das Auslesen aus dem Video-RAM für diesen Bildaufbau beendet und nur noch der BORDER angezeigt;

— Register 7 (Start des vertikalen Rücklaufs), so wird der Elektronenstrahl wieder dunkelgeschaltet und von rechts unten nach links oben quer über den Bildschirm zurückbewegt;

— Register 4 (Gesamthöhe des Bildschirms inklusive BORDER und vertikalem Strahlrücklauf), beschäftigt sich der CRTC wieder mit dem Zurücksetzen sämtlicher Register und dem Neuladen des Pointers. Die unendliche Geschichte hat begonnen...

Zur Entspannung empfehlen wir, mit den gutmütigen Registern 1 und 6 zu experimentieren. Wer obiges Sezieren des CRTCs verstanden hat, sollte auch in der Lage sein, den Grund der verwirrenden Bildverschiebung bei Änderung von Register 1 zuerkennen. Von den Registern des CRTC nun zum Gate-Array, das den CRTC mit den für den Bildaufbau nötigen Farbdaten versorgt. Wie der Name schon andeutet: ein wichtiges Tor zur Hardwarewelt des CPC. Insgesamt verfügt das Gate-Ar-ray über vier Register, die über beliebige Portadressen von &40 bis &7F erreichbar sind. Bei Werten unter &7E fühlt sich der Floppycontroller angesprochen, deshalb sollte man trotzdem nach dem Befehl OUTI ein "INC B" setzen. Im Gegensatz zum CRTC schickt man aber nicht den Index (Regi-sterauswahl) und den eigentlichen Wert getrennt, sondern in einem einzigen Byte vereinigt. Bit 6 und 7 legen dabei das gewünschte der vier Register fest, Bit 0 bis 5 enthalten den zu sendenden Werl. Die einzelnen Funktionen sind aus der Abbildung der Gate-Array-Register ersichtlich.

Von Pixeln und Farben

Wir werden das Gate-Array zum schnellen Ändern von Bildschirm färben verwenden, da die Systemroutinen (&BC32 und so weiter) für komplexe Farbeffekte absolut ungeeignet sind. Um beispielsweise den BASIC-Befehl "INK 0,6" direkt Uber das Gate-Array auszuführen, benötigt man zwei OUT-Befehle.

Zuerst wird Register 0 mit der Pen-Nummer (= 0) geladen, dann Register 1 mit der Farbe (=6).

Nun nehmen wir die letzte Hürde: Das Betriebssystem versetzt uns vorsätzlich in die Scheinwelt einer nach der Helligkeit am Grünmonitor geordneten Farbpalette. Die Hardware verwendet allerdings ein anderes Codierungssystem. Ein Blick in die Tabelle offenbart: Der Farbe 6 (Hellrot) entspricht die Nummer 12. Man schreibt also:

OUT &7F00, 0

(Register 0, Wert 0)

OUT &7F00, &4C

(Register 1, das heißt Bit 6= 1, Wert 12) Ein kurzes Aufflackern von INK 0 bestätigt: Es hat funktioniert! Allerdings maximal nur 1/50 Sekunde, denn beim nächsten vertikalen Strahlrücklauf (VSR) setzt das Betriebssystem wieder die alten Farben. In Assembler geht man so vor:

DI ;Betriebssystem aus, Farbebleibt
LD BC,&7F00
OUT (C) ,C
LD C,&4C
OUT (C) , C ; Farbe setzen
LOOP: JP LOOP ;Endlosschleife

Zum Abschluß noch ein kurzer Blick auf den Portbaustein 8255, ähnlich wie das Gate-Array ein "Mädchen für alles" ist, ist er für Soundchip, Tastaturabfrage, Kassettenrekorder und Weiterleitung verschiedener Signale zuständig. Eine Übersicht der verwirrenden Funktionen würde diesen Rahmen sprengen, zumal wir nur an einem einzigen Bit interessiert sind: dem VSync-Signal. Der CRTC besitzt nämlich die angenehme Eigenschaft, bei jedem horizontalen und vertikalen Strahlrücklauf ein Synchronisationssignal auszugeben.. Ersteres ließen die CPC-Entwickler schamlos auf der Platine versickern, das VSync-Signal (vertikale Synchronisation) wurde aber dankenswerterweise an besagten Baustein 8255 weitergeleitet, wo es sich ständig über Bit 0 der Portadresse &F5 abfragen läßt.

Bildung der effektiven Video-RAM-A dresse (Pointer) >>

Das VSync-Signal am Parallelbaustein

Wegen der notwendigen Geschwindigkeit, bedingt durch die kurze Dauer des vertikalen Rücklaufs, funktioniert eine Abfrage nur in Assembler, unter BASIC verwendet man CALL &BD19 oder den Befehl FRAME (664/6128), die beide die nun folgende Routine im ROM aufrufen:

LD B,&F5 ;Portadresse laden
LOOP IN A, (C) ; Wie OUT (C) , A -nur INput statt OUTput über &F5
RRCA ; Bit 0 des empfangenen Wertes ins Carry-Flag
JR NC,LOOP ; War es 0,dann noch kein vertikaler Strahlrücklauf - weiter warten.

Und damit wäre sie auch endlich geschafft - die Theorie. Jetzt erwartet uns ein Sprung in die wogenden Gewässer der Praxis, was manchen rauchenden Köpfen vielleicht die ersehnte Abkühlungbringen wird.

Mittlerweile gibt es eine Vielzahl von "Special Effects", die wir hier unmöglich alle bis ins kleinste Detail durchleuchten können. Vielmehr sollte jeder,den der "Forscherdrang" gepackt hat, mit den nun folgenden Informationen gerüstet, in der Lage sein, die Feinheiten selbst zu entdecken. Beginnen wir mit den Rasterbalken. Eine der ältesten Errungenschaften der neuzeitlichen Demoprogrammierung wurde bereits um 1987 entdeckt. Fast allen dürften die wandernden Farbbalken bekannt sein, die auch Mode-2-Programme in ungeahnter Farbenpracht erstrahlen lassen. Der Name Raster geht auf den Begriff Rasterzeile zurück, was eigentlich Pixelzeile bedeutet. Die Idee: Während der Elektronenstrahl von oben nach unten über den Bildschirm rast, ändert man über das Gate-Array in dem Moment, wenn er von rechts nach links zurückgelenkt wird, ein bis zwei Farben. Im Speicher befindet sich dann eine Tabelle, die für jede Pixelzeile einen Farbwert enthält. Bei 200 Pixelzeilen wären so auch in Mode 2 200 Farben möglich. Der CPC kennt derer aber nur 27, womit die maximale Farbanzahl festgelegt ist.

Bedingt durch diverse Warlezyklen, sollten diese Schleifen rein rechnerisch trotzdem nur 62 ins (Millisekunden) dauern, was allerdings wieder von der Anzahl der OUT-Befehle abhängt. Es empfiehlt Sich,mit Werten von 61 bis 64 zu experimentieren.

LD HL,TTABELLE ; Farbdaten
LD A, 100 ; Anzahl Durchläufe
LD BC, &7F00 ; Postadresse Gate Array
OUT (C),C ;PEN 0 anwählen
LOP: LD C, (HL) ; 1:75 ms
OUT (C),C ; 4.00 ms (durch Wartezyklen)
INC HL ; 1.50 ms
LD R, A ;2.25 ms sinnlose Verzögerung
DS 49 ; 49.0 ms sinnlose Verzögerung (49 NOPs a 1 ms)
DEC ; 1.00 ms
JP NZ,. LOP ; 2 .50 ms

= 62 . 00 ms RET TABELLE: DB &54,&4B,&59,&5A,&53, . .......(100x)

Beispiel für eine typische 64-Millisekunden-Schleife

Volle Farbenpracht auch in Mode 2

Das Besondere besteht nun darin, daß man in besagter Tabelle nach jedem Bildschirmaufbau mit dem Befehl "LDIR" Bereiche verschiebt, neu aufbaut und so weiter. Hier sind nur durch die Phantasie des Programmierers Grenzen gesetzt.

Das Problem: Wie erkennen wir, daß der Elektronenstrahl gerade nach links zur nächsten Pixelzeile zurückgleitet wird und daß es daher an der Zeit wäre, wieder eine Farbänderung vorzunehmen?

Das vom CRTC zu diesem Zwecke generierte HSync-Signal (horizontale Synchronisation) fällt aus oben nachzulesendem Grunde aus. Die Antwort: Man agiert blind und vertraut darauf, daß eine Pixelzeile (auch Horizontalzyklus genannt), wie in Register 0 festgelegt, 64 (0bis 63) Zeichen (davon 24 Border) breit ist.

Der CRTC arbeitel mit einer Taktfrequenz von 1 MHz, ein Zyklus dauert also eine Mikrosekunde. Für den Aufbau einer Pixelzeile benötigt der CRTC 64 Taktzyklen (64 Mikrosekunden). Bedingt durch den Wortmodus liest er in dieser Zeit 128 Byte aus dem Bildschirmspeicher. Mit diesem Wissen gewappnet, geht man wie folgt vor:

  1. Man wartet auf den vertikalen Strahlrücklauf (mit obiger Routine) oder auf einen Interrupt (mit HALT).
  2. Warteschleife, um den Farbwechsel in die horizontaler Strahlrücklauf-Re-gion zu lenken.
  3. Man konstruiert eine Schleife, die für eine Farbänderung genau 64 Mikrose-kunden benötigt, und führt sie zum Beispiel 100 malaus.
  4. Jetzt wird die Farbdatentabelle verändert.
  5. Zurück zu Punkt 1.

Einen typischen Vertreter einer64-Mil-lisekunden-Schleife finden Sie in der Abbildung. Ein Beispiel für die Rasterbalkentechnik finden Sic in Listing 4. Direkter Nachfolger der Rasterbalken ist das Splitraster, aber mit einem kleinen Unterschied: Die Farbe wird nicht einmal, sondern mehrmals pro Pixel beziehungsweise Raslerzeile geändert. Beispielsweise lädt man die Register H, L, D, E, C und A mit beliebigen Farbwerten und gibt sie dann der Reihe nach aus, während sich der Elektronenstrahl im sichtbaren Bereich befindet:

OUT (C),H
OUT (C),L
OUT (C),D

und so weiter. Einziges Problem: Das VSync-Signal läßt sich nur noch unter großem Programmieraufwand zurSyn-chronisation verwenden, weil ein Durchlauf der Abfrageschleil'c über 7 ms dauert, wodurch man das Splitra-ster-Programm nur auf 7 ms genau mit dem Elektronen strahl gleichschalten kann, was schließlich ein flackerndes Hin- und Herrutschen der Splitraster verursacht. Der Geistesblitz: Man bedient sich des CPC-Interruptsystems: Jede 300stel Sekunde (auf die für uns so wichtige Millisekunde genau) unterbricht die CPU ihre Arbeit und springt (im Interruptmodus 0) zur Adresse &38, wo normalerweise ein Sprung zum Interrupt-Handler des Betriebssystems steht. An besagte Adresse schreibt man jetzt eine einfache Rtick-kehranweisung (El: RET) oder einen Sprung zur Splitraster-Routine. Das Hauptprogramm läßt man nun mit einem HALT-Befehl auf den Interrupt warten. Ein Beispiel finden Sie in Listing 5.

Nutzung des Interruptsystems

Ein zwar schon leicht angegrauter, aber oft sehr wirkungsvoller Trick: Man lädt das CRTC-Register 1 mit einem Wert größer als der in Register 0, meistens also &40. Dadurch muß der CRTC den Horizontalzyklus beenden, bevorerdie geforderte Zeichenanzahl (64,&40) geschrieben hat. Die Folge: Der Pointer bleibt hängen, und der CRTC gibt immer wieder dieselbe Textzeile aus. Eine auf diesem Trick aufgebaute Laufschrift wartet in Listing 6. Ein Problem ergibt sich aber bei CRTC-Typ 2: Der Pointer wird eingefroren, er wird auch am Beginn des Vertikalzyklus nicht mehr neu geladen. Es ist also die Textzeile sichtbar,in der sich der Elektronenstrahl im Moment der Register-1-Manipulation befand. Dieser Umstand wird von Listing 6 berücksichtigt. Dippel-, Trippel- oder Quadruppel-modus eignen sich gut für Leute, die wenig Bildschirmdaten schaufeln und trotzdem viel Bewegung sehen wollen. Die Lösung liegt im machtvollen Register 9: Lädt man es mit den Werten 15 (Dippel), 23 (Trippcl) oder 31 (Qua-druppel), so wird jede Textzeile zweimal, dreimal oder viermal hintereinander angezeigt. Der Pixelzeilenzähler durchläuft Werte bis 31. Es finden aber nurdie untersten drei Bits Verwendung, dadurch kommt es zur Wiederholung. Da aber eine Textzeile jetzt zweimal, dreimal oder viermal so groß ist, muß man auch die Werte in den Registern-4, 6 und 7 halbieren, dritteln oder vierteln.

Dippelmodus:

OUT &BC00, 4
OUT &BD00,19
OUT &BC00, 6
OUT &BD00,12
OUT &BC00, 7
OUT &BD00,15
OUT &BC00, 9
OUT &BD00,15

Die Gate-Array Register >>

Quadruppel:

OUT &BC00, 4
OUT &BD00, 9
OUT &BC00, 6
OUT &BD00, 6
OUT &BC00,7
OUT &BD00, 8
OUT &BC00, 9
OUT &BD00, 31

Versuchen Sic doch nun einmal selbst, den Tri ppe 1 mod u s austüfteln. Der Screen-Squasher läßt sich zum effektvollen Bildschirmauf- oder -abbau nutzen. Wie beim Rasterbalken wird hier in jeder Pixelzeile ein Register geändert, nur ist diesmal nicht das Gate-Array, sondern der CRTC das Opfer, genauer: Register 1. Es wird am Anfang einer Rasterzeile entweder mit 0 oder40 geladen. Im ersten Fall wird nur Border gezeichnet und der Rest des Bildes nach unten gedrückt, im zweiten Fall findet die Darstellung wie gewohnt statt. Der Effekt selbst läßt sich schwer beschreiben, Listing 7 bringt ihn aber aufden Monitor.

Der Horizontal-Waggler, in deutschen Landen auch "Schwabbier" genannt, funktioniert nach demselben Prinzip wieder Screen-Squasher. Allerdings ist Register 2 das Ziel. Man verändert kontinuierlich die Position des horizontalen Rücklaufs, der durch den Bildfang zwar an der gleichen Stelle bleibt, wodurch sich aber das Bild selbst verschiebt. Da der CRTC diesen Eingriff in den empfindlichen Horizontalzyklus schwer verdaut, kommt es zu einer weichen Bildverschiebung. Für Register 2 sind Werte von &2D bis &34 sinnvoll. CRTC-Typ-2-Besitzer müssen vorher Register 3 mit einer 8 laden, da er sonst Werte über &31 in Register 2 nicht verkraftet. Ein entsprechendes Beispiel hierfür ist der Effekt des Bildschirm-verzerrers, wie er als 1-kByte-Pro-gramm im Ausgabe 2/3'92 abgedruckt war.

Der Effekt des Vertikal-Wagglers zählt zu den neuesten Errungenschaften und ließ auch abgebrühte Demoschreiber beim Erstkonlakt erstaunen. Das Prinzip ist das gleiche wie bei den obigen Beispielen, diesmal wird aber Register 9 verändert. Je größer der Standardwert in Register 9 (normal 7) ist, desto unsauberer der Effekt. Listing 8 verwendet trotzdem den Wert 7. Die Routine kannn auch längst nicht alle Möglichkeiten ausschöpfen, die der Vertikal-Waggler bietet. Durch das ständige Abändern von Register 9 werden immer nur die ersten eins bis acht Pixelzeilen einer Textzeile angezeigt, bevor der CRTC zur nächsten Textzeile weitergeht. So entsteht der Staucheffekt, der aber nur bei reinen Grafiken besonders gut wirkt.

Tolle Effekte

Overscan ist einer der wenigen Effekte, der auch von Spieleprogrammierern verwendet wird. Man erinnere sich an die Titelbilder der französischen Firma Titus (Crazy Cars II, Wild Streets), die den ganzen Bildschirm mit Border einnehmen. Natürlich werden keine Pixel gedehnt, sondern der Bildausschnitt wird vergrößert.

Zuerst wird das Bild in die linke obere Ecke geschoben:

OUT &BC00, 3
OUT &3D00, 8 ; für CRTC-Typ-2-Kompatibilität,
OUT &3C00, 2
OUT &BD00, &32 ;Bild nach links schieben
OUT &BC00, 7
OUT &BD00, &23 ; Bild nach oben schieben
OUT &BC00,1
OUT &3D00, 48 ;Bild in X-Richtung dehnen (48 Zeichen)
OUT &BC00, 6
OUT &BD00, 34 ;Bild in Y-Richtung dehnen (34 Zeilen)

Statt 40x25 mißt der Bildschirm jetzt also 48x34 Zeichen. Der Nachteil liegt auf der Hand: Da der Bildschirmspeicher nur 16 kByte groß ist, 48x34 Zeichen aber (48x34x16=26112) fast 26 kByte benötigen, erscheint ein betrachtlicher Teil des Bildes doppelt. Als unser Retter aus dem Sumpf der Ratlosigkeit tritt diesmal Register 12 auf. Die Bits 2 und 3 sind für die Größe des Video-RAM verantwortlich, lädt man beide mit 1, adressiert der CRTC fortan 32 kByte Bildschirmspeicher. Man opfert also bereits die Hälfte des kostbaren Speicherplatzes:

OUT &BC00,12
OUT &BD00, &3C

Im unteren Bildbereich ist jetzt die Bank 0 (&0000-&3FFF) eingeblendet, man kann also sogar einem BASIC-Programm (ab & 170) bei der Arbeit zuschauen. Zum guten Schluß reißen wir die zwei kompliziertesten, dafür aber auch effektvollsten Speziaieffekte Screen-Splitting und Hardware-Scrol-ling kurz an. Kein modernes Demo wäre ohne diese beiden Alleskönner denkbar. Eine bitgenaue Erklärung würde wohl weitere acht Seiten verschlingen, deshalb konzentrieren wir uns am besten auf die Grundzüge: 1. Hardware-Scrolling: Dieser Trick wird immer dann verwendet, wenn ein bestimmter Bildbereich verschoben werden muß, die Software-Befehle wie LDIR oder LDI aber einfach zu langsam sind. Auch das Betriebssystem bedient sich dieser Technik, um den Bildschirm vertikal zu verschieben, wenn man ihn mit dem Cursor zu verlassen sucht. Es wird einfach die Bildschirmstartadresse in den Registern 12 und 13 um den Wert 40 erhöht oder vermindert. Will man ein horizontales Scrol-ling erreichen, genügt ein einfaches In-krementieren, zum Beispiel:

10 FOR A=0 to 255
20 CALL &BD19
30 OUT &BC00,13
40 OUT &BD00, A
50 NEXT

Programmiert man zum Beispiel eine Laufschrift, beschränkt sich die Arbeit der CPU auf Buchstabenschreiben am (weiterwandernden) rechten Rand. Durch Hardware-Scrolling verkompliziert sich allerdings auch die Berechnung von Video-RAM-Adressen: So folgt auf die Adresse &C7FF nicht &C800, sondern &C000. Wer das nicht glaubt, kannes überprüfen: "MODE 2" eingeben, mit dem Cursor 28 Zeilen hinunterfahren, "POKE &C7FF, 255" tippen und die folgende Adresse mit POKE-Befehlen suchen. Im Zweifelsfall helfen für den Anfang die Systemroutinen (&BC20 bis &BC29). Der Nachteil des Hardware-Scrollings zeigt sich deutlich: Will man mehr als eine Laufschrift, beispielsweise noch ein Bild darüber, wird auch dieses gnadenlos mitgescrollt. Hier eilt uns

2. Screen-Splitting zu Hilfe. Der Trick: Man ändert während des Bildaufbaus die Video-RAM-Adresse. Nach dem vertikalen Strahlrücklauf blendet man zum Beispiel mit

OUT &BC00,12
OUT &BD00,&10
OUT &BC00,13
OUT &BD00,0

die Speicherbank 1 (&4000-&7FFF) ein, die das Bild enthält. Hat der Elektronenstrahl den Bildschirm zur Hallte gezeichnet, lädt man die Adresse, die auf die Laufschrift zeigt, in die Register 12 und 13. Schön wäre es, ginge der CRTC jetzt gleich daran, die Laufschrift darzustellen. Doch die erscheint erst beim nächsten Bildaufbau. Der Grund: Der CRTC beachtet die Register 12 und 13 nur in dem Moment, wenn er daraus den Pointer neu lädt. Wie weiter oben beschrieben, geschieht das nur dann, wenn der interne Textzeilenzähler den Wert von Register 4 erreicht hat. Wenn man einfach den Inhalt von Register 4 halbiert, ist ein Bild nur noch halb so hoch, und der CRTC stellt derer zwei untereinander dar. Allerdings erreicht der Textzeilenzähler dadurch nie den in Register 7 festgelegten Wert, es kommt zu keinem vertikalen Strahlrücklauf, und das Bild läuft haltlos durch. Halbiert man jetzt aber auch noch Register 7, hat man es geschafft. Es gibt sogar zwei vertikale Strahlrückläufe, von denen einer den Bildschirm genau in der Mitte teilt. Hier ist nun die Screen-Splitting-Rou-tine in BASIC:

10 out &bc00, 4
20 out &bd00, 19
30 out &bc00, 7
40 out &bd00, 15

Listing 9 beinhaltet eine einfache Assembler-Routine, die den Bildschirm sechsmal teilt, die entsprechenden Bereiche scrollt und gleichzeitig die Verti-kalstrahl-Rücklaufbalken verdrängt. Ein Ende des Rüstungswettlaufs der Demoprogrammierer ist in Sicht. Galt es vor zwei Jahren noch als Kunst, den Bildschirm in jeder Textzeile zu split-ten (Register 4 = 0), und war vor einem Jahr das Screen-Splitting in jederPixel-zeile die letzte Errungenschaft (Register 4, 9 = 0), so schafft man heute bereits über drei Splits pro Pixelzeile, hat also endlich das horizontale Screen-Splitting erfunden. Doch hier zeigt sich: Die CPU verbrauchtdie ganze Rechenzeit, nur um die Video-RAM-Adresse jede Pixelzeile dreimal zu ändern, die dadurch erreichten Effekte sind auch wenig spektakulär, so daß man sich mit der Zeit mehr der Softwareseile zuwenden wird: Vektorgrafik und schnelle Sprite-Routinen (siehe ZAP'T'BALLS auf DATABOX 4/5'92) werden die Demos der Zukunft sein.

Die Assembler-Quelltexte zu den BASIC-Listings finden Sie auf der DATABOX zu dieser Ausgabe.

Elmar Krieger/jg, CPCAI

★ PUBLISHER: CPC Amstrad International
★ YEAR: 1992
★ AUTOR: Elmar Krieger
★ NOTE: Literatur
  • Multiface-II-Benutzerhandblatt
  • Programmierung der EGA - und VGA-Karten, Addison Wesley

 

★ AMSTRAD CPC ★ DOWNLOAD ★

Other platform tool:
» Elmar  Krieger-SPECIAL  EFFECTSDATE: 2018-08-17
DL: 311
TYPE: ZIP
SiZE: 18Ko
NOTE: 40 Cyls
.HFE: Χ

★ AMSTRAD CPC ★ A voir aussi sur CPCrulez , les sujets suivants pourront vous intéresser...

Lien(s):
» Coding Src's » Art and the Amstrad (Computing Today)
» Coding Src's » Skulls (Amstrad Computer User)
» Coding Src's » Circles
» Coding Src's » Random Lines
» Coding Src's » Steam Train Simulator
» Coding Src's » Graphic - Fuzzy (Amstrad Computer User)
Je participe au site:
» Vous avez des infos personnel ?
» Vous avez remarqué une erreur dans ce texte ?
» Aidez-nous à améliorer cette page : en nous contactant via le forum ou par email.

CPCrulez[Content Management System] v8.7-desktop/c
Page créée en 508 millisecondes et consultée 2309 fois

L'Amstrad CPC est une machine 8 bits à base d'un Z80 à 4MHz. Le premier de la gamme fut le CPC 464 en 1984, équipé d'un lecteur de cassettes intégré il se plaçait en concurrent  du Commodore C64 beaucoup plus compliqué à utiliser et plus cher. Ce fut un réel succès et sorti cette même années le CPC 664 équipé d'un lecteur de disquettes trois pouces intégré. Sa vie fut de courte durée puisqu'en 1985 il fut remplacé par le CPC 6128 qui était plus compact, plus soigné et surtout qui avait 128Ko de RAM au lieu de 64Ko.