Magic Disk 64

home to index to text: MD9412-KURSE-IRQ-KURS_14.txt
                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 diesem und den nächsten beiden ( letzten) Kursteilen werden wir uns mit Raster-Tricks beschäftigen, die es uns ermöglichen, 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 Scollzeilen/- spalten den gesamten Bildschirm um 8 Pixel ( oder einen Charakter) weiterkopieren, 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 vertikalen Scrollen," HSP", zum horizontalen Scrollen, sowie " AGSP", die eine Kombination Kombination aus den beiden ersteren dartsellt. Mit ihnen können wir den gesamten Bildschirm ganz problemlos ( auch Hires-Grafiken!) in alle Richtungen 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" Routinen, 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 kompexeren Rastertricks, und leistete uns auch schon manchen guten Dienst um Timingprobleme 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 identisch sind." VSP" steht für " Vertical Screen Position", was der einfach Ausdruck für das ist, was die Routine bewirkt: 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 funktionstüchtige VSP-Routine, die gleichzeitig noch einen FLD-Effekt miteingebaut 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 Beginn 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ächsten 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 richtigen Rasterzeile zu befinden, in der er die nächste Charakterzeile zu lesen hatte," 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 durfte. 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 konnte man auch problemlos den Bildschirm erst in der Mitte oder am unteren Bildschirmrand beginnen lassen ( so arbeitet übrigens auch der Effekt, mit dem Sie die Seiten, die Sie gerade lesen umblättern) .
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 identisch 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 Bildrandes 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 Softscroll- Werte für Register $ D011( nur die untersten 3 Bit sind genutzt), die die vertikale Verschiebung immer um eine Rasterzeile vor dem Rasterstrahl herschieben, so daß der FLD-Effekt entstehen 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" nebenbei 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 Grafikchip 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 rechtzeitig 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 seinen 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 einen einzigen NOP mehr, der hinter der IRQ-Glättung eingefügt wurde. Das bedeutet, daß der FLD-Schreibzugriff auf Register $ D011, mit dem der vertikale Verschiebeoffset 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 Charakterzeile) erhöht.

* Da der VIC beim Erreichen der nächsten Rasterzeile wieder glaubt, er müsse sich auf die Charakterzeile vorbereiten, zählt er den internen Adresszeiger 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 Erreichen der ersten Charakterzeile einsetzen 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 erste Charakterzeile wurde somit ÖBER-SPRUNGEN!
Im Klartext bedeutet das: für jede Rasterzeile, 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 Anfang des Bildschirms anzeigen lassen.
Der VIC liest nun aber pro Rasterdurchlauf 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 $07 E8 bis $07 FF dar ( wenn wir von der Stanard-Basisadresse des Video-RAMs bei $0400 ausgehen) . Dies sind 24 Zeichen, die somit am Anfang der letzten Bildschirmzeile 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 1 KB) 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 16 KB der 64 KB des C64 adresssieren, wobei die Lage dieses Bereichs allerdings auch verschoben werden kann. Das heißt also, daß der VIC insgesamt zwar Adressen in einem 64 KB-Raum (16 Adressbits sind hierzu notwendig) adressieren, aber gleichzeitig immer nur auf 16 KB für Grafikdaten zugrei- fen kann. Möchte man diesen 16 KB-Bereich verschieben, so kann das mit den untersten zwei Bits von Adresse $ DD00 getan werden. Im Normalfall stehen beide auf 0 und lassen den VIC deshalb im Bereich von $0000 bis $3 FFF 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) erscheinen. Die Bits 10-13 dieser Adresse bestimmen 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 Basisadresse für das Video-RAM ist. Die restlichen, zur Adressierung benötigten 10 Bits kommen aus dem oben schon erwähnten, VICinternen Adresszähler. Er ist exakt 10 Bits lang, womit maximal 1 KB-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 ungenutzten Zeichen des Video-RAMs darstellt: Da der 10- Bit-Zähler nun auf den Offset $03 E8 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 $07 E8-$07 FF 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 Charakterzeilen- 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 Charakterverschiebung entstehen, sollten auch nicht unerwähnt bleiben:
Durch die Verschiebung der Video-RAM- Daten am Ende des Bildschirms um 24 Zeichen 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 Zeichen ungenutzt. Durch einen stinknormalen Rasterinterrupt können wir dann problemlos vor Beginn der Charakterzeile, an der der VIC-Adresszeiger überläuft, auf das zweite Video-RAM umschalten, wobei dieses dann zwar an der überlaufenden Adresse ausgelesen wird, was jedoch durch unsere Verschiebung wieder ausgeglichen wird.
Ein weiterer Nachteil, der bei VSP entsteht, 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 Anzeigen von Grafikzeichen in diesen acht Bytes mit der Spriteanzeige Probleme bekomen. Jedoch auch dies ist zu bewältigen. Entweder, indem man so geschickt arbeitet, daß in diesen Bereichen auf dem Bildschirm nur Zeichen in der Hintergrundfarbe zu sehen sind ( bei schwarzem 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 ansonsten die Spritepointer hineinschreiben. Da der VIC schon 42 Taktzyklen nach Beginn der Rasterzeile, in der die Charakterzeile beginnen soll, die Video-RAM- Daten gelesen hat, können wir also getrost wieder die Spritepointer zurückschreiben und haben so lediglich eine einzige Rasterzeile, in der die Sprites garnicht ( oder nur verstümmelt) dargestellt 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 unterbracht werden muß. Da pro Rasterzeile der interne Adresspointer um eine Charakterzeile weitergezählt wird, muß also im Maximalfall in 25 Rasterzeilen der VSP-Effekt eingesetzt werden. Will man den Bildschirm nun konstant an eine bestimmten Position beginnen lassen, so muß nach der Anzahl der zu überspringenden Charakterzeilen wieder eine normale FLD-Routine ( ohne das zusätzlich NOP) benutzt werden, um bis zur 25 . Rasterzeile nach Bildschirmanfang zu verzögern, OHNE daß gleich alle 25 Charakterzeilen ü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 unteren drei Bits von $ D011 zum Softscrollen 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 durchgefü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 Hardwarescroller " HSP" anschauen, bei dem das VSP-Prinzip auf die Horizontale Bildschirmposition umgesetzt wurde.( ih/ ub)

Valid HTML 4.0 Transitional Valid CSS!