Magic Disk 64

home to index to text: MD9410-KURSE-IRQ-KURS_12.1.txt
                IRQ-KURS                
     "Die Hardware ausgetrickst..."     
                (Teil 12)               

Herzlich Willkommen zu einer neuen Folge unseres IRQ-Kurses. In dieser Ausgabe werden wir uns weiter mit der ESCOS-Routine des letzten Kursteils beschäftigen. Wir werden hierbei die Routine mit einem Movie-Scroller verbinden, um so einen bildschirmübergreifenden Text scrollen zu lassen. Dies gestaltet sich ohne einen speziellen Trick gar nicht mal so einfach. . .
1) EINLEITUNG Wie Sie sich vielleicht noch erinnern, so hatten wir in der letzten Folge des IRQ-Kurses zuletzt das Beispielprogramm " ESCOS2" besprochen. Diese Raster-IRQ- Routine öffnete uns den linken und rechten, sowie den oberen und unteren Bild- schirmrand und stellte dann alle 21 Rasterzeilen eine neue Reihe mit je acht Sprites auf dem Bildschirm dar. Dadurch hatten wir insgesamt vierzehn Zeilen zu je acht Sprites auf dem Bildschirm, die alle nahtlos aneinandergereiht fast den gesamten Bildschirm überdeckten. Der einzige ungenutzte Bereich war der von Rasterzeile 294 bis 312, der zu klein war um eine weitere Spritereihe darin unterzubringen, aber sowieso schon unterhalb der für normale Monitore darstellbaren Grenze liegt.
Der einzige Unterschied der Routine " ES-COS2" zu " ESCOS1" bestand nun darin, daß erstere Routine lediglich ein Zeilenoffset- Register für den ersten auszulösenden Raster-IRQ herunterzählte, um so einen Scroll-Effekt der Spritereihen zu erzielen." ESCOS2" ist also schon eine Art " Moviescroller" . Der Grund, warum sie es nicht wirklich ist, liegt darin, daß in jeder Spritezeile dieselben Sprites auf dem Bildschirm zu sehen waren.
Wie wir aber von den Moviescroll-Routinen wissen, müssen wir für einen Scrolltext das Aussehen einer Spritezeile ja individuell bestimmen können, damit auch wirklich ein Text, und nicht immer dieslbe Zeile, über den Bildschirm läuft.
2) DAS PROBLEM - DIE LÜSUNG " Kein Problem" werden Sie nun sagen," einfach die Textausgaberoutine der Moviescroller- Routinen vom IRQ-Kurs einbauen, und schon haben wir einen Scrolltext" . Diese Feststellung stimmt schon, wie sollte es auch anders gehen, jedoch stellt sich uns dabei noch ein kleines Problem in den Weg: dadurch nämlich, daß wir in den ESCOS-Routinen, keine Zwischenräume mehr zwischen den einzelnen Spritezeilen haben, gestaltet es sich als schwierig, die Sprite-Pointer zeitgenau zu setzen. Setzen wir diese nämlich auf die neu einzuscrollende Sprite- zeile, noch bevor die letzte Spritezeile abgearbeitet wurde, so erscheinen die alten Sprites schon im Aussehen der Neuen. Umgekehrt können die Spritepointer auch nicht nach Abarbeiten der letzten Spritezeile gesetzt werden da hier ja schon die neuen Sprites erscheinen müssen. Man könnte nun versuchen, ein megagenaues Timing zu programmieren, das innerhalb der ersten Rasterzeile einer neuen Spritezeile exakt vor Darstellen eines neuen Sprites dessen Pointer neu setzt. Dies gestaltet sich jedoch umso umständlicher, wenn wir beachten müssen, daß gleichzeitig auch noch der linke und rechte Rand geöffnet werden soll. Da dieser ebenfalls ein exaktes Timing verlangt, würden wir mit dem Doppeltiming in des Teufels Küche kommen. Aber keine Sorge: glücklicherweise können wir als IRQ-Magier wieder in die Raster-Trickkiste greifen, und eine weitaus einfachere Lösung des Problems anwenden.
Wie Sie z. B. schon von unseren FLI-Routinen wissen, hat man mit dem VIC die Möglichkeit, das Video-RAM innerhalb seines Adressbereiches von 16 KB zu verschieben. Der Speicherbereich, den der Grafikchip dazu verwendet, um den Inhalt des Textbildschirms aufzubauen muß also nicht zwingenderweise bei $0400 liegen, wo er sonst nach dem Einschalten des Rechners untergebracht ist. Durch die Bits 4-7 des Registers $ D018 können insgesamt 16 verschiedene Speicherbereiche gewählt werden, deren Basisadressen in $0400- Schritten von $0000-$3 C00 gehen.
Nun werden Sie fragen, was denn das Video- RAM mit unserer ESCOS-Routine zu tun hat, zumal wir die Bildschirmdarstellung doch sowieso abgeschaltet haben, und keinen Text auf dem Bildschirm haben?
Nun, ganz einfach: wo befinden sich denn die Register der Spritepointer normalerweise? Natürlich in den Adressen von $07 F8-$07 FF. Und genau diese Adresse liegen am Ende des Video-RAMs. Verschiebt man nun das Video-RAM an eine andere Adresse, so verschiebt man automatisch auch die Registeradressen der Spritepointer! Wird das Video-RAM also beispielsweise um $0400 Bytes nach $0800 verschoben, so bewegen sich die Spritepointer- Register ebenfalls um $0400- Bytes nach vorne. Um nun also das Aussehen der acht Sprites zu definieren, müssen die Adressen $0 BF8-$0 BFF beschrieben werden. Und genau das ist die Lösung unseres Problems. Da es während des Spriteaufbaus zu lange dauert, alle acht Spritepointer in den Akku zu laden und in die Register zu schreiben, soll das die Initialisierungsroutine des Moviescrollers übernehmen. Hierbei schreibt letztere die benötigten Werte für eine Spritezeile in die Pointerregister eines verschobenen Video-RAMs. Während der Darstellung brauchen wir nun nur noch durch Schreiben eines einzigen Bytes, nämlich des ensprechenden Wertes für ein neues Video-RAM in $ D018, auf selbiges umzuschalten. Dadurch, daß der VIC für die neue Spritezeile nun in einem ganz anderen Video-RAM arbeitet, holt er sich auch die Spritepointer aus den neuen Adressen, womit wir alle acht Spritepointer mit nur einem Schreibzugriff umgeschaltet hätten!
Die Umsetzung dieser Lösung in die Praxis gestaltet sich für uns sehr einfach.
Sinnigerweise haben wir nämlich in den Routinen " ESCOS1" und " ESCOS2" schon Platz für diese Änderung gelassen. Wie Sie sich vielleicht erinnern, hatten wir zur Darstellung der Sprites innerhalb der IRQ-Routine dieser beiden Beispielprogramme die Unterroutine " OPEN21" vierzehnmal aufgerufen. Sie wird immer in der ersten Rasterzeile einer neuen Spritezeile angesprungen, und übernimmt das Neusetzen der Y-Koordinaten aller Sprites, sowie das Üffnen des Sideborders in den folgenden 21 Rasterzeilen.
So sah der Aufruf in den beiden Bei- spielprogrammen aus:
nop ; Diese Befehlsfolge wird jsr open21 ; insgesamt 14 x aufgerufen

   ...       ; um je 21 Zeilen zu öffnen
   nop       ;Sprite Line 14            
   jsr open21                           

Die " NOP"- Befehle dienten dabei nur der Verzögerung um zwei Taktzyklen, damit die Änderung zum richtigen Zeitpunkt eintritt. Wir können diese Befehle mit jedem anderen Befehl ersetzen, der nur 2 Takte in Anspruch nimmt. Diese Tatsache machen wir uns für den Moviescroller zunutze. Wir ersetzen die NOPs mit LDA-Befehlen, wobei der Wert, der in den Akku geladen wird, dem Wert entspricht, der in Register $ D018 geschrieben werden muß, um auf das neue Video-RAM umzuschalten. Er dient quasi als Parameter für die " OPEN21"- Routine. Demnach sieht der Aufruf dieser Routine, aus dem Raster- IRQ heraus, nun folgendermaßen aus:
v00 : lda #$00*$10 ; Code für Scr0($0000) jsr open21 ;21 Rasterzeilen öffnen v01 : lda #$01*$10 ; Code für Scr0($0400) jsr open21 ;21 Rasterzeilen öffnen v02 : lda #$02*$10 ; Code für Scr0($0800) jsr open21 ;21 Rasterzeilen öffnen

    ...                                 
v0d:lda #$0d*$10 ;Code für Scr13 ($3400)
    jsr open21   ;21 Rasterzeilen öffnen

Wie schon in den ESCOS-Beispielen, so wiederholt sich auch hier die LDA-JSR- Befehlsfolge 14 Mal, wobei jeweils der nächste Video-RAM- Bereich als Parameter im Akku übergeben wird. Timingmässig hat sich nichts geändert, da der NOP-Befehl genausolange braucht wie der LDA-Befehl.
Eine ähnliche Modifikation haben wir nun für das Schreiben dieses Akku-Wertes in Register $ D018 vorgenommen. Diese Aufgabe soll von der Routine " OPEN21" durchgeführt werden. Hier ein Auszug der er- sten Zeilen dieser Routine aus dem Beispiel " ESCOS2" :
open21 :

   nop         ;Verzögern bis rechter   
   nop         ; Rand erreicht          
   dec $d016   ;38 Spalten (Rand        
   inc $d016   ;40 Spalten   öffnen)    
   lda $1500,y ;$D011-Wert aus Tabelle  
   sta $d011   ; lesen und eintragen    
   iny         ;Tabellen-Index+1        
   jsr cycles+5;24 Zyklen verzögern     

. . .
Wie Sie sehen, stehen hier ebenfalls zwei NOP-Befehle am Anfang der Routine.
Sie benötigen 4 Taktzyklen, was für einen " STA $ XXXX"- Befehl ebenfalls zutrifft. Die zwei NOPs wurden für den Moviescroller nun mit einem " STA $ D018" ersetzt:
open21 :
sta $ d018 ; VRAM f. SprPtrs. versch.

   dec $d016   ;38 Spalten (Rand        
   inc $d016   ;40 Spalten   öffnen)    
   lda $1500,y ;$D011-Wert aus Tabelle  
   sta $d011   ; lesen und eintragen    
   iny         ;Tabellen-Index+1        
   jsr cycles+5;24 Zyklen verzögern     

. . .
Damit hätten wir also die ESCOS-Routine so umprogrammiert, daß Sie uns in jeder der 14 Spritezeilen auch neue Spritepointer setzt. Es müssen nun noch zwei weitere Änderungen gemacht werden, damit der Moviescroller auch voll funktionstüchtig ist.
Zunächst einmal muß die Initialierungsroutine erweitert werden. Sie soll uns die Spritepointer der benutzten Video-RAM- Adressen auf bestimmte Sprites vorinitialisieren, so daß später zur Darstellung einer bestimmten Spritereihe nur noch die Nummer des zu benutzenden Video-RAMs in den Labeln " V00" bis " V0 D" der Raster-IRQ- Routine ( siehe oben) ein- getragen werden muß, und die Routine somit automatisch den richtigen Bildschirm zur korrekten Darstellung der entsprechenden Spritezeile wählt.
Zunächst einmal wollen wir vereinbaren, daß wir den 16 K-Adressbereich des VICs von $0000-$3 FFF um eins nach oben in den Bereich von $4000-$7 FFF verschieben.
Dadurch stört uns die Zeropage, die normalerweise ja auch im Bereich des VICs liegt, nicht mehr, und wir haben volle 16 KB zur Speicherung von Sprites und Spritepointer-Video- RAM zur Verfügung.
Die Verschiebung wird durch Schreiben des Wertes 2 in das Portregister A von CIA-B erreicht. Innerhalb der Initialsierung wurde also folgende Befehlssequenz hinzugefügt:

LDA #$02                                
STA $DD00                               

Damit befindet sich der Datenbereich für den VIC nun im Bereich von $4000-$7 FFF.
Beachten Sie bitte auch, daß nun der Bytewert, den der VIC in " ausgetricksten" Rasterzeilen darstellt, nicht mehr in $3 FFF, sondern in $7 FFF abgelegt werden muß ( im Beispielprogramm enthält er den Wert $81, womit vertikale Lininen hinter dem Scrolltext erscheinen) . Nun folgt der Teil, der die Spritepointer setzt. Hier treffen wir die Konvention, daß die Sprites, die durch die Pointer einer Video-RAM- Bereichs dargestellt werden auch innerhalb dieses Video-RAMs unterbracht werden sollen. Liegt dieses also Beispielsweise bei $4400, so soll Spritepointer 0 auf das Sprite bei $4400( Blocknr.16), Spritepointer 1 auf das Sprite bei $4440( Blocknr.17), usw., zeigen. Dies bewerkstelligt nun der folgende Teil der Init-Routine:

   lda #$f8       ;ZP-Zgr. $02/03 mit   
   sta $02        ; $43F8 init.         
   lda #$43                             
   sta $03                              

lda #($0000/64) ; Ptr. f. Sprite-Line01 jsr setpoint ; setzen lda #($0400/64) ; Ptr. f. Sprite-Line02 jsr setpoint ; setzen lda #($0800/64) ; Ptr. f. Sprite-Line03 jsr setpoint ; setzen . . .
lda #($3000/64) ; Ptr. f. Sprite Line13 jsr setpoint ; setzen lda #($3400/64) ; Ptr. f. Sprite Line14 jsr setpoint ; setzen Wie Sie sehen wird lediglich ein Adressierungszeiger in der Zeropage initialisiert, und dann 14 Mal die Unterroutine " SETPOINT" aufgerufen, wobei im Akku der Inhalt für den jeweils ersten Spritepointer übergeben wird. Hier nun die Routine " SETPOINT", die die eigentlichen Werte in die Pointerregister schreibt:
SETPOINT:
ldy #$00 ; Index-Reg. init.
sta ($02), y; SprPtr0 ablegen

   clc        ;Akku=Akku+1              
   adc #$01                             
   iny        ;Index=Index+1            
   sta ($02),y;SprPtr1 ablegen          
   clc        ;Akku=Akku+1              
   adc #$01                             
   iny        ;Index=Index+1            
   sta ($02),y;SprPtr2 ablegen          
   ...                                  
   clc        ;Akku=Akku+1              
   adc #$01                             
   iny        ;Index=Index+1            
   sta ($02),y;SprPtr7 ablegen          
   clc        ;Auf Hi-Byte des $02/$03  
   lda $03    ; Zeigers den Wert 4 add. 
   adc #$04   ; um auf nächstes VRAM zu 
   sta $03    ; positonieren            
   rts                                  

Wie Sie sehen, so wird vom Basiswert des ersten Spritepointers an, acht Mal jeweils um eins hochgezählt und das Ergebnis über den Vektor bei $02/$03 in die entsprechende Sprite-Pointer- Adresse geschrieben. Beim ersten Durchlauf zeigt dieser Vektor auf Adresse $43 F8, wo sich die Spritepointer des ersten Video-RAM- Bereichs befinden. Am Ende der Pointerinitialisierung wird die Vektoradresse nun um $0400 erhöht ( auf Hi-Byte wird $04 addiert), damit beim nächsten Durchlauf die Zeiger des nächsten Video-RAM- Bereichs gesetzt werden.
( Anm. d. Red. : Bitte wählen Sie jetzt den zweiten Teil des IRQ-Kurses aus dem Textmenu)

Valid HTML 4.0 Transitional Valid CSS!