IRQ-KURS "Die Hardware ausgetrickst..." (Teil 14) ----------------------------------------
Unser Kurs neigt sich langsam dem Ende zu, und als wahre "Raster-Feinschmecker" haben wir uns das beste Stückchen Code ganz für den Schluß aufgehoben. In die- sem und den nächsten beiden (letzten) Kursteilen werden wir uns mit Raster- Tricks beschäftigen, die es uns ermögli- chen, den Bildschirm des C64 HARDWA- REMÄSSIG in alle Richtungen zu scrollen. "Hardwaremässig" heißt, daß wir nicht etwa die Softscroll-Register des VICs beschreiben, und dann alle 8 Scollzei- len/-spalten den gesamten Bildschirm um 8 Pixel (oder einen Charakter) weiterko- pieren, sondern daß wir vielmehr den VIC derart austricksen, daß er uns diese Arbeit von alleine abnimmt, und zwar ohne, daß wir auch nur einen einzigen Taktzyklus zum Kopieren von Grafikdaten verschwenden müssen! Die hierzu notwen- digen Routinen heißen "VSP", zum verti- kalen Scrollen, "HSP", zum horizontalen Scrollen, sowie "AGSP", die eine Kombi- nation Kombination aus den beiden erste- ren dartsellt. Mit ihnen können wir den gesamten Bildschirm ganz problemlos (auch Hires-Grafiken!) in alle Richtun- gen verschieben. Im heutigen Kursteil wollen wir mit der VSP-Routine beginnen: 1) FLD UND VSP - DIE (UN)GLEICHEN BRÜDER Sie werden sich jetzt sicher wundern, warum hier der Begriff "FLD", auftaucht, war das doch eine der "einfacheren" Rou- tinen, die wir schon zu Anfang dieses Kurses besprochen hatten. Doch wie ich schon öfter erwähnte, ist die FLD- Routine meist der Schlüssel zu den kom- pexeren Rastertricks, und leistete uns auch schon manchen guten Dienst um Ti- mingprobleme extrem zu vereinfachen. Diesmal jedoch dreht sich alles direkt um unseren kleinen Helfershelfer, da die VSP-Routine sehr stark mit ihm verwandt ist, wenn die Beiden nicht sogar iden- tisch sind. "VSP" steht für "Vertical Screen Position", was der einfach Aus- druck für das ist, was die Routine be- wirkt: durch sie wird es uns ermöglicht, den gesamten Bildschirm ohne jeglichen Kopieraufwand vollkommen frei nach oben oder unten zu scrollen. Und jetzt der Clou an der ganzen Sache: FLD und VSP unterscheiden sich lediglich durch einen einzigen NOP-Befehl voneinander. Fügt man Letzterern den Verzögerungs-NOPs nach der IRQ-Glättung der FLD-Routine hinzu, so erhält man eine voll funk- tionstüchtige VSP-Routine, die gleich- zeitig noch einen FLD-Effekt miteinge- baut hat. Damit Sie genau wissen, wovon wir hier sprechen, sollten Sie sich auf dieser MD einmal die Programmbeispiele "FLD" und "VSP1" anschauen. Ersteres ist die FLD-Routine, so wie wir sie zu Be- ginn dieses Kurses kennengelernt hatten. Durch Bewegen des Joysticks nach oben und unten können wir mit ihr den Bild- schirm nach unten "wegdrücken". Das Prinzip, das dabei verfolgt wurde war, daß die FLD-Routine den Beginn der näch- sten Charakterzeile vor dem Rasterstrahl herschob, indem sie ihn ständig mit neuen vertikalen Verschiebeoffsets in Register $D011 fütterte. Da er deshalb glaubte, sich noch nicht in der richti- gen Rasterzeile zu befinden, in der er die nächste Charakterzeile zu lesen hat- te, "vergaß" er solange sie zu zeichnen, bis wir ihm durch Beenden der FLD- Schleife die Möglichkeit dazu gaben, endlich die Rasterzeile zu erreichen, in der er nun tatsächlich die versäumte Charakterzeile lesen und anzeigen durf- te. Egal, wieviele Rasterzeilen wir ihn dadurch "vertrödeln" ließen, er begann dann immer bei der Charakterzeile, die er eigentlich als nächstes aufzubauen gehabt hätte, so als wenn der FLD-Effekt nie aufgetreten wäre. War das die erste Charakterzeile des Bildschirms, so konn- te man auch problemlos den Bildschirm erst in der Mitte oder am unteren Bild- schirmrand beginnen lassen (so arbeitet übrigens auch der Effekt, mit dem Sie die Seiten, die Sie gerade lesen umblät- tern). 2) DAS PROGRAMMBEISPIEL VSP1 Wollen wir uns nun einmal die IRQ- Routine des Programmbeispiels "VSP1" anschauen. Im Prinzip nichts besonderes, da sie, wie schon erwähnt, fast iden- tisch mit der FLD-Routine ist. Sie ist ab Adresse $1100 zu finden und wird wie die meisten unserer IRQ-Routinen von der Border-IRQ-Routine, die wir immer zum Abschalten des unteren und oberen Bild- randes benutzen initialisiert:
fld pha ;Prozessorregs. txa ; auf Stapel retten pha tya pha dec $d019 ;VIC-ICR löschen inc $d012 ;Glättungs-IRQ lda #<irq2 ; vorbereitem sta $fffe cli ;IRQs freigeben ch nop ;Insgesamt 13 NOPs ... ; zum Verzögern bis nop ; zum nächsten jmp ch ; Raster-IRQ irq2 pla ;Statusreg. u. pla ; IRQ-Adr. vom pla ; Stapel werfen dec $d019 ;VIC-ICR freigeben lda #$f8 ;Rasterpos. f. Bor- sta $d012 ; der IRQ festlegen ldx #<bord ;IRQ-Vektoren ldy #>bord ; auf Border-IRQ stx $fffe ; zurücksetzen (für sty $ffff ; nächst. Durchlauf) nop ;Verzögern bis nop ; zum Raster- nop ; zeilenende nop nop nop nop lda $d012 ;den letzen Cyclus cmp $d012 ;korrigieren bne onecycle onecycle lda #$18 ;25-Zeilen-Bildschirm sta $d011; einschalten nop ;Insgesamt 16 NOPs zum ... ;Verzögern für FLD
Es folgt nun der alles entscheindende siebzehnte NOP-Befehl, der den VSP- Effekt auslöst:
nop ;NOP für VSP
Nun gehts weiter mit dem normalen FLD- Code. Entfernen Sie das obige NOP aus dem Code, so erhalten Sie wieder eine ganz normale FLD-Routine!
lda $02 ;Zeilenz. holen beq fldend ;Wenn 0 -> Ende ldx #$00 ;Zeiger init. fldloop lda rollvsp,x ;FLD-Offs. zum ora #$18 ;Verschieben d. sta $d011 ; Charakterz. lda colors1,x ;Blaue Raster sta $d020 ; im FLD-Be- sta $d021 ; reich darst. nop ;Bis Zeilen- nop ; mitte verzö- nop ; gern nop nop nop nop lda colors2,x ;Rote Raster sta $d020 ; Im FLD-Be- sta $d021 ; reich darst. nop ;Verzögern bis nop ; Zeilenende bit $ea inx ;Zeilenz.+1 cpx $02 ;Mit $02 vgl. bcc fldloop ;ungl.->weiter fldend nop ;Verz. bis nop ; Zeilenende nop nop nop lda #$0e ;Normale sta $d020 ; Bildschirm- lda #$06 ; farben ein- sta $d021 ; schalten pla ;Prozessorregs. tay ; zurückholen pla tax pla rti ; und ENDE
Die Tabelle "ROLLVSP" enthält Soft- scroll-Werte für Register $D011 (nur die untersten 3 Bit sind genutzt), die die vertikale Verschiebung immer um eine Rasterzeile vor dem Rasterstrahl her- schieben, so daß der FLD-Effekt entste- hen kann. Die Tabellen "Color1" und "Color2" geben die Farben an, die die FLD-Routine im weggedrückten FLD-Bereich darstellt. Dies ist nur als "Verschönerung" neben- bei gedacht. 3) DAS FUNKTIONPRINZIP VON VSP Intern kann man sich die Vorgehensweise des VIC beim Aufbauen des Bildschirms mit all seinen Rasterzeilen folgenderma- ßen vorstellen: Trifft unser armer Gra- fikchip auf eine Rasterzeile, in der eigentlich die nächste Charakterzeile erscheinen sollte, so bereitet er sich auf den gleich folgenden Zugriff auf das Video-RAM vor, und zählt schon einmal einen internen Adresszeiger auf die gewünschte Adresse um 40 Zeichen nach oben, um die folgenden 40 Bytes recht- zeitig lesen zu können. Nun vergleicht er die Rasterstrahlposition ständig mit seiner Startposition für den Lesevorgang und hält beim Erreichen von Selbiger den Prozessor für 42 Taktzyklen an, um sei- nen Lesezugriff durchzuführen. Durch die FLD-Routine wurde nun jedoch der Beginn der gesamten Charakterzeile ständig vor dem VIC hergeschoben, weswegen er sie auch schön brav erst später zeichnete. Unsere VSP-Routine verfügt nun über ei- nen einzigen NOP mehr, der hinter der IRQ-Glättung eingefügt wurde. Das bedeu- tet, daß der FLD-Schreibzugriff auf Re- gister $D011, mit dem der vertikale Ver- schiebeoffset um eins erhöht wird, exakt 2 Taktzyklen später eintritt als sonst. In genau diesen beiden Taktzyklen aber hat der VIC schon die interne Adresse auf das Video-RAM um 40 Zeichen erhöht und wartet jetzt auf das Erreichen der Startposition für den Lesevorgang. Da der in unserem Programm folgende Schreibzugriff auf $D011 diese Position für den VIC nun aber eine Rasterzeile weiterschiebt, kann er diese Position nie erreichen. Das Endergebnis, das wir dadurch erhalten ist Folgendes: * Der FLD-Effekt greift, und wir lassen den VIC die nächste Charakterzeile eine Rasterzeile später zeichnen. * Der interne Adresszeiger des VIC auf die Daten der nächsten Charakterzeile wurde um 40 Zeichen (also eine Charak- terzeile) erhöht. * Da der VIC beim Erreichen der nächsten Rasterzeile wieder glaubt, er müsse sich auf die Charakterzeile vorberei- ten, zählt er den internen Adresszei- ger um weitere 40 Bytes nach oben und wartet auf die richtige Startposition zum Lesen der nächsten 40 Bytes. * Lassen wir ihn nun tatsächlich die Charakterzeile lesen, indem wir die FLD(VSP)-Routine beenden, so stellt er zwar, wie beim normalen FLD-Effekt, wieder Charakterzeilen dar, jedoch wurde durch das zweimalige Erhöhen des Adresszeigers um 40 Bytes eine gesamte Charakterzeile übersprungen! Hatten wir den FLD-Effekt also z.B. vor Er- reichen der ersten Charakterzeile ein- setzen lassen, so zeichnet der VIC nun nicht die erste, sondern die ZWEITE Charakterzeile, da er sich ja 40 Bytes zu weit nach vorne bewegte!!! Die er- ste Charakterzeile wurde somit ÖBER- SPRUNGEN! Im Klartext bedeutet das: für jede Ra- sterzeile, die wir die FLD(VSP)-Routine länger laufen lassen, überspringt der VIC eine Charakterzeile. Auf diese Weise können wir also auch die Daten, die in der Mitte des Video-RAMs liegen am An- fang des Bildschirms anzeigen lassen. Der VIC liest nun aber pro Rasterdurch- lauf immer 25 Charakterzeilen. Lassen wir ihn also durch unseren VSP-Trick 40 Bytes zu spät auf die vermeintliche 1. Charakterzeile zugreifen (es handelt sich um die 1. Charakterzeile die auf dem Bildschirm zu sehen ist, jedoch mit den Daten, die eigentlich erst in der zweiten Charakterzeile des Bildschirms erscheinen sollten), so hört für ihn der Bildschirm auch 40 Bytes zu spät auf. Das Ergebnis: in der 25. Bildschirmzeile liest und stellt der VIC die Daten des sonst ungenutzten Bereichs des Video- RAMs im Adressbereich von $07E8 bis $07FF dar (wenn wir von der Stanard- Basisadresse des Video-RAMs bei $0400 ausgehen). Dies sind 24 Zeichen, die somit am Anfang der letzten Bildschirm- zeile zu sehen sind. Hieraufhin folgen 16 weitere Zeichen, die sich der VIC wieder aus der Anfangsadresse des Video- RAMs holt. Zum besseren Verständnis sollten wir vielleicht noch klären, wie der VIC auf das Video-RAM zugreift. Selbiges ist immer 1024 Bytes (also exakt 1KB) lang, obwohl der Bildschirm nur 1000 Bytes groß ist und somit die letzten 24 Bytes nie sichtbar werden. Wie Sie nun wissen, kann der VIC immer nur 16KB der 64KB des C64 adresssieren, wobei die Lage dieses Bereichs allerdings auch verschoben wer- den kann. Das heißt also, daß der VIC insgesamt zwar Adressen in einem 64KB- Raum (16 Adressbits sind hierzu notwen- dig) adressieren, aber gleichzeitig im- mer nur auf 16KB für Grafikdaten zugrei- fen kann. Möchte man diesen 16KB-Bereich verschieben, so kann das mit den unter- sten zwei Bits von Adresse $DD00 getan werden. Im Normalfall stehen beide auf 0 und lassen den VIC deshalb im Bereich von $0000 bis $3FFF arbeiten. Diese Adressen dienen als Basis für den VIC die ihm von der NMI-CIA in die obersten zwei Adressbits für seine RAM-Zugriffe eingeblendet werden. Die Zugriffsadresse ist also 16 Bit groß, wobei die beiden Bits 0 und 1 aus $DD00 immer in den obersten zwei Bits (14 und 15) erschei- nen. Die Bits 10-13 dieser Adresse be- stimmen die Basisadresse des Video-RAMs. Sie werden von den Bits 4-7 der VIC- Adresse $D018 geliefert. Steht hier der Bitcode $0001 (so wie nach Einschalten des Computers), so wird also zusammen mit den Bits aus $DD00 die Adresse $0400 angesprochen, die im Normalfall die Ba- sisadresse für das Video-RAM ist. Die restlichen, zur Adressierung benötigten 10 Bits kommen aus dem oben schon erwähnten, VIC-internen Adresszähler. Er ist exakt 10 Bits lang, womit maximal 1KB-Bereiche adressiert werden können. Dadurch erklärt sich auch, warum der VIC durch austricksen mit der VSP-Routine, in der letzten Zeile die 24 sonst unge- nutzten Zeichen des Video-RAMs dar- stellt: Da der 10-Bit-Zähler nun auf den Offset $03E8 zeigt, werden von dort auch die Daten gelesen. Hierbei findet dann aber nach dem 24. Byte ein Öberlauf des 10-Bit-Zählers statt, womit selbiger wieder auf 0 zurückspringt und wieder den Anfang des Video-RAMs adressiert. Dadurch erklärt sich auch, warum in der letzten Bildschirmzeile nach den Zeichen aus $07E8-$07FF wieder die Zeichen ab Adresse $0400 erscheinen. Bleibt noch zu erwähnen, daß dasselbe für das Color-RAM bei $D800 gilt. Dies ist immer an einer Fixadresse, wobei die untersten 10 Bit ebenfalls aus dem Cha- rakterzeilen-Adresszähler kommen. Das heißt also, daß die 24 sonst unsichtba- ren Zeichen ihre Farbe aus dem ebenfalls sonst ungenutzten Color-RAM-Bereich von $DBE8-$DBFF erhalten. 5) PROBLEME DIE BEI VSP ENTSTEHEN KÖNNEN Die Nachteile, die durch die Charakter- verschiebung entstehen, sollten auch nicht unerwähnt bleiben: Durch die Verschiebung der Video-RAM- Daten am Ende des Bildschirms um 24 Zei- chen nach rechts, ist natürlich auch die gesamte Grafik in zwei Teile zerlegt worden, weswegen ein Scroller nicht ganz so einfach durchzuführen ist. Um diesen Fehler auszugleichen müssen wir einen zweiten Video-RAM-Bereich verwalten, in dem die gesamte Grafik um 24 Zeichen versetzt abgelegt sein muß. In diesem Video-RAM sind dann die ersten 24 Zei- chen ungenutzt. Durch einen stinknorma- len Rasterinterrupt können wir dann pro- blemlos vor Beginn der Charakterzeile, an der der VIC-Adresszeiger überläuft, auf das zweite Video-RAM umschalten, wobei dieses dann zwar an der überlau- fenden Adresse ausgelesen wird, was je- doch durch unsere Verschiebung wieder ausgeglichen wird. Ein weiterer Nachteil, der bei VSP ent- steht, liegt auf der Hand: Die letzten acht Bytes des jetzt sichtbaren Video- RAMs sind die Adressen, in denen die Spritepointer abgelegt werden. Das heißt also, daß wir beim gleichzeitigen Anzei- gen von Grafikzeichen in diesen acht Bytes mit der Spriteanzeige Probleme bekomen. Jedoch auch dies ist zu bewäl- tigen. Entweder, indem man so geschickt arbeitet, daß in diesen Bereichen auf dem Bildschirm nur Zeichen in der Hin- tergrundfarbe zu sehen sind (bei schwar- zem Hintergrund einfach das Color-RAM in den Adressen von $DBF0-$DBFF ebenfalls auf schwarz setzen). Oder aber indem wir in diesen Zeichen immer nur dann die eigentlichen Video-RAM-Werte eintragen, wenn sie ausgerechnet vom VIC benötigt werden (also auch exakt vor dem Lesen der Öberlauf-Charakterzeile), und an- sonsten die Spritepointer hineinschrei- ben. Da der VIC schon 42 Taktzyklen nach Beginn der Rasterzeile, in der die Cha- rakterzeile beginnen soll, die Video- RAM-Daten gelesen hat, können wir also getrost wieder die Spritepointer zurück- schreiben und haben so lediglich eine einzige Rasterzeile, in der die Sprites garnicht (oder nur verstümmelt) darge- stellt werden können. Soll der gesamte Bildschirm einmal durchgescrollt werden können, so muß davon ausgegangen werden, daß maximal 25 Rasterzeilen am Beginn des Bildschirms ungenutzt bleiben müssen, da in Ihnen das Timing für den VSP-Effekt unter- bracht werden muß. Da pro Rasterzeile der interne Adresspointer um eine Cha- rakterzeile weitergezählt wird, muß also im Maximalfall in 25 Rasterzeilen der VSP-Effekt eingesetzt werden. Will man den Bildschirm nun konstant an eine be- stimmten Position beginnen lassen, so muß nach der Anzahl der zu überspringen- den Charakterzeilen wieder eine normale FLD-Routine (ohne das zusätzlich NOP) benutzt werden, um bis zur 25. Raster- zeile nach Bildschirmanfang zu verzö- gern, OHNE daß gleich alle 25 Charakter- zeilen übersprungen werden. 6) WEITERE PROGRAMMBEISPIELE Ausser der oben schon erwähnten "VSP1"- Routine finden Sie auf dieser MD auch noch zwei weitere Beispielprogramme, mit den Namen "VSP2" und "VSP3" (wie alle unserer Beispiele werden auch sie mit "SYS4096" startet). In Ersterem haben wir zusätzlich zum VSP-Effekt die unte- ren drei Bits von $D011 zum Soft- scrollen des Bildschirms verwendet, so daß der Bildschirm weich nach oben und unten geschoben werden kann. Die Routine "VSP3" scrollt das gesamte Video-RAM ununterbrochen durch, wodurch quasi ein unendlicher Horizontalscroller durch- geführt werden kann. Die 25 unbenutzten Rasterzeilen am Bildschirmanfang, die für das VSP-Timing benötigt werden, sind mit Sprites hinterlegt, in denen man z.B. in einem Spiel auch ein Scoreboard unterbringen kann. In der nächsten Folge des IRQ-Kurses werden wir uns den horizonalen Hardwa- rescroller "HSP" anschauen, bei dem das VSP-Prinzip auf die Horizontale Bild- schirmposition umgesetzt wurde. (ih/ub)