Magic Disk 64

home to index to text: MD9502-KURSE-IRQ-KURS_16.1.txt
                IRQ-KURS                
     "Die Hardware ausgetrickst..."     
                (Teil 16)               

Herzlich Willkommen zum 16 . Teil unseres Kurses über die Rasterstrahlprogrammierung. In den letzten beiden Kursteilen hatten wir uns mit zwei IRQ-Routinen beschäftigt, die das hardwaremässige Scrollen des Bildschirms jeweils in der Horizontalen ( HSP-Routine) und Vertikalen ( VSP-Routine) ermöglichten. Der Clou an diesen beiden Routinen war, daß des GESAMTE Bildschirm vom VIC verschoben wurde, und wir keinen einzigen Taktzyklus zum Kopieren von Bildschirmdaten verschwenden mussten. In diesem Kursteil wollen wir nun das " Sahnestückchen" der Raster-IRQ- Programmierung besprechen:
die Kombinattion aus HSPund VSP-Routine, genannt " AGSP" . Diese Abkürzung steht für " Any Given Screen Position" und bedeutet, daß der Bildschirm in jede Richtung verschoben werden kann, und das natürlich HARDWAREMÄSSIG, also wie schon bei HSP und VSP ohne auch nur einen Zyklus zum Kopieren von Bildschirmdaten zu verschwenden!
Stellen Sie sich vor, was für Möglichkeiten sich hierdurch für Spiele ergeben: so kann man z. B. problemlos Spiele programmieren, die sich über einer beliebig großen Oberfläche abspielen, die in alle Richtungen flüssig gescrollt werden kann, ohne dabei mehr als 30 Rasterzeilen pro Frame zu verbrauchen.25 Rasterzeilen lang ist der Prozessor eigentlich nur mit dem Abpassen der optimalen Rasterstrahlpostion für den HSP-Effekt beschäftigt, der, wie wir schon im 14 . Kursteil sehen konnten, pro Charakterzeile, die der Bildschirm horizontal gescrollt werden soll, eine Rasterzeile für das Timing verbraucht.
Damit Sie sehen, was mit der AGSP-Routine alles möglich ist, haben wir Ihnen natürlich wieder zwei Beispielpro- gramme vorbereitet. Sie heissen " AGSP1" und " AGSP2" und werden wie immer mit ",8,1" geladen und durch ein " SYS4096" gestartet. Desweiteren finden Sie auf dieser MD eine Demo mit Namen " AGSP-Demo", in der am eindrucksvollsten die Möglichkeiten der AGSP-Routine demonstriert werden. Sie sehen hier einige Hiresgrafiken, die in Sinuswellenform aufund abschwingen und gleichzeitig von links nach rechts scrollen. Hierbei werden jeweils neue Grafiken in die Grafik einkopiert, so daß der Eindruck entsteht, daß der Bildschirm weitaus größer sei, als eigentlich sichtbar. Das Demo laden Sie mit LOAD" AGSP-DEMO",8 und starten es durch " RUN" .
1) DAS AGSP-PRINZIP Kommen wir nun also zum Arbeitsprinzip von AGSP, das eigentlich recht schnell erläutert ist: Zunächst einmal passen wir die erste Rasterzeile des Bild- schirms ab, an der die erste Charakterzeile gelesen werden muß. Hier nun lassen wir eine VSP-Routine, so wie wir Sie im letzten Kurteil schon kennenlernten, zunächst dem VIC vorgaugeln, daß er auf den Beginn der Charakterzeile noch zu warten hat, indem wir eine horizontale Bildschirmverschiebung um 1 Pixel in $ D011 angeben. Inmitten dieser Zeit soll nun die VSP-Routine diese Verschiebung wieder Aufheben, um so den VIC sofort die Charakterdaten lesen zu lassen, und ihn somit dazu zu zwingen, den Bildschirm nach rechts versetzt darzustellen. Die Anzahl Taktzyklen, die bis zum Zurückschalten verzögert werden müssen, muß dabei der Anzahl Zeichen entsprechen, die der Bildschirm verschoben werden soll. Hieran anschließend lasen wir eine HSP-Routine folgen, die den Beginn der nächsten Charakterzeilen vor dem VIC herdrückt, um so auch die zeilenweise Verschiebung des Bildschirmanfangs zu erreichen. Da diese Routine maximal 25 Rasterzeilen benötigt ( nämlich dann, wenn die Darstellung erst 25 Charakterzeilen später beginnen soll, müssen die ersten 25 Rasterzeilen des sichtbaren Bildschirms immer für das Timing der AGSP-Routine verwendet werden, auch wenn stellenweise weniger Rasterzeilen dazu benötigt werden ( z. B. wenn nur eine Zeile Verschiebung erzeugt werden muß) . Für diese Fälle müssen wir mit Hilfe einer normalen FLD-Routine den Bildschirm um die fehlende Anzahl Rasterzeilen nach unten drücken, damit der Bildschirm auch immer in ein und derselben Rasterzeile beginnt. Diese FLD-Routine wird in unserem Programmbeispiel den VSPund HSP-Routinen vorgeschaltet. Sie sorgt also gleichzeitig für immer gleiches Timing und zudem für die richtige Positionierung in der Horzontalen. Aus diesem Grund sind dann die ersten 25 Rasterzeilen des Bildschirms auch nicht zum Darstellen von Bildschirmdaten verwendbar.
In unserem Programmbeispielen haben wir hier jedoch Sprites untergebracht, in denen die Scrollrichtung angezeigt wird.
In einem Spiel könnte sich hier z. B.
auch eine Score-Anzeige befinden.
2) DAS PROGRAMM Wollen wir uns nun die Funktionsweise von AGSP anhand des Programmbeispiels " AGSP1" anschauen. Die Routinen zur Joystickabfrage und Scrollgeschwindigkeitsverzögerung sollen hier nicht Thema unseres Kurses sein, sondern lediglich die Routine, die uns den Bildschirm beliebig im sichtbaren Fenster positioniert. Zur angesprochenen Scrollgeschwindigkeitsverzögerung sei erwähnt, daß wir hier beim Drücken und Loslassen des Joysticks die Scrollrichtung verzögern, bzw. nachlaufen lassen, so daß der Scrolleffekt zunächst träge anfängt und beschleunigt und beim Loslassen erst abgebremst werden muß, bis er zum Stillstand kommt.
Die Initialisierungsroutine zu AGSP1 bei$1000 legt nun zunächst einen Border-IRQ in Zeile $ FB fest, wobei, wie schon so oft in unseren Beispielen, der Hard-IRQ- Vektor bei $ FFFE/$ FFFF benutzt wird.
Diese Border-Routine ( bei $1400) schaltet nun den oberen und unteren Bildschirmrand ab und initialisiert einen Raster-IRQ für Rasterzeile $18, wobei dann unsere eigentliche IRQ-Routine " AGSP" angesprungen wird. Sie befindet sich an Adresse $1200 und soll im nun Folgenden ausführlich beschrieben werden. Die AGSP-Routine soll nun der Reihe nach folgende Arbeiten verrichten:

* Verwaltung des Sprite-Scoreboards, das aus zwei Spritereihen zu je acht Sprites bestehen soll.

* Glätten des IRQs, um ein möglichst exaktes Timing zu bewirken.

* FLD-Routine benutzen, um die fehlenden Rasterzeilen, die von VSP ggf. nicht benötigt werden, auszugleichen
* VSP-Routine charakterweisen zum hoch- und runterscrollen des Bildschirms einsetzen
* HSP-Routine zum charakterweisen linksund rechtsscrollen des Bildschirms einsetzen
* horizontales und vertikales Softscrolling zur exakten Bildschirmverschiebung durchführen a) DIE SPRITELEISTE Kommen wir nun also zum ersten Teil der AGSP-Routine, die zunächst das Sprite-Scoreboard verwaltet. Wir verwenden hier zwei Sätze zu je acht Sprites, deren Spritedaten in den Adressen von $0 C00-$1000 zu finden sein sollen ( Sprite-Pointer $30-$3 f) . Um die Pointer zwischen beiden leichter umschalten zu können benutzen wir zwei Video-RAM- Adressen. Für die erste Zeile, die eh in einem unsichtbaren Bildbereich liegt, wird das Video-RAM an Adresse $0000 verschoben, so daß wir die Spritepointer in den Adressen $03 F8-$03 FF liegen haben.
Für die zweite Spritezeile wird das Video- RAM an die ( normale) Adresse $0400 gelegt, womit wir die Spritepointer an den Adressen $07 F8-$07 FF vorfinden. Dadurch, daß durch den VSP-Effekt auch diese Spritepointer als einzelne Zeichen auf dem Bildschirm auftauchen können, müssen wir die Pointer in jedem Rasterdurchlauf ( Frame) wieder neu setzen, da die Pointer auf dem Bildschirm ja durchaus auch Bildschirmzeichen enthalten können. Doch kommen wir nun endlich zum Source-Code der AGSP-Routine, der in seinem ersten Teil zunächst einmal die Spriteinitialisierungen vornimmt und eigentlich einfach zu verstehen sein sollte:

agsp:    pha       ;IRQ-Beginn -> also  
         txa       ; Prozessorregs.     
         pha       ; retten             
         tya                            
         pha                            
         lda #$1e  ;Y-Position aller    
         sta $d001 ; Sprites auf Raster-
         sta $d003 ; zeile $1E (dez. 30)
         sta $d005 ; setzen             
         sta $d007                      
         sta $d009                      
         sta $d00b                      
         sta $d00d                      
         sta $d00f                      
         lda #$01  ;Die Farbe aller     
         sta $d027 ; Sprites auf 1, also
         sta $d028 ; 'weiß' setzen      
         sta $d029                      
         sta $d02a                      
         sta $d02b                      
         sta $d02c                      
         sta $d02d                      
         sta $d02e                      

lda #$ ff ; Alle Sprites einsta $ d015 ; schalten lda #$80 ; Hi-Bit d. X-Pos. von sta $ d010 ; Sprite 8 setzen lda #$00 ; Sprite-Multicolor sta $ d01 c ; ausschalten

         clc       ;C-Bit f.Add. löschen
         lda #$58  ;XPos Sprite 0       
         sta $d000 ; setzen             
         adc #$18  ;$18 (dez.24) add.   
         sta $d002 ; u. XPos Spr.1 setz.
         adc #$18  ;$18 (dez.24) add.   
         sta $d004 ; u. XPos Spr.2 setz.
         adc #$18  ;usw.                
         sta $d006                      
         adc #$18                       
         sta $d008                      
         adc #$18                       
         sta $d00a                      
         adc #$18                       
         sta $d00c                      
         adc #$18  ;$18 (dez.24) add.   
         sta $d00e ; u. XPos Spr7 setz. 

Bis hierhin hätten wir nun die wichtigsten Spritedaten initialisiert. Dadurch, daß diese in jedem Frame neu gesetzt werden, können Sie im AGSP-Bereich problemlos auch noch acht weitere Sprites sich bewegen lassen. Sie müssen deren Spritedaten dann nur am Ende der AGSP-Routine wieder in die VIC-Register einkopieren. Nun folgt noch die Initialisierung der Spritepointer. Zunächst die für die Sprites der ersten Spritezeile, deren Pointer ja im Video-RAM ab Adresse $0000 untergebracht sind, und sich somit in den Adressen von $03 f8-$03 ff befinden. Anschließend werden die Spritepointer für die zweite Spritereihe eingetragen, die sich im normalen Bildschirmspeicher bei $0400, in den Adressen $07 f8-$07 ff befinden. Das abschließende schreiben des Wertes 3 in Register $ DD00 stellt sicher, daß der 16 K-Adressbereich des VICs auf den unteren Bereich, von $0000 bis $3 FFF, gelegt ist:

         ldx #$30  ;Spr.Pointer Spr0=$30
         stx $03f8 ; bis Spr7=$37 in    
         inx       ; die Pointeradressen
         stx $03f9 ; $03F8-$03FF ein-   
         inx       ; tragen             
         stx $03fa                      
         inx                            
         stx $03fb                      
         inx                            
         stx $03fc                      
         inx                            
         stx $03fd                      
         inx                            
         stx $03fe                      
         inx                            
         stx $03ff                      
         inx       ;Spr.Pointer Spr0=$38
         stx $07f8 ; bis Spr8=$3F in    
         inx       ; die Pointeradressen
         stx $07f9 ; $07F8-$07FF ein-   
         inx       ; tragen             
         stx $07fa                      
         inx                            
         stx $07fb                      
         inx                            
         stx $07fc                      
         inx                            
         stx $07fd                      
         inx                            
         stx $07fe                      
         inx                            
         stx $07ff                      

lda #$03 ; VIC-Adressraum auf sta $ dd00 ;$0000-$3 FFF schalt.
b) DAS GLÄTTEN DES IRQS Der nun folgende Teil der AGSP-Routine ist für das Glätten des IRQs verantwortlich. Ausserdem wird hier der Border-IRQ wieder als nächste IRQ-Quelle festgelegt, womit diese Arbeit nun auch erledigt wäre:

     dec $d019   ;IRQ-ICR freigeben     
     lda #$1d    ;Nächster Raster-IRQ   
     sta $d012   ; bei Zeile $1D        
     lda #<irq2  ;Adresse Glättungs-    
     sta $fffe   ; IRQ in $FFFE/$FFFF   
     lda #>irq2  ; eintragen            
     sta $ffff                          
     cli         ;IRQs erlauben         

ch: nop ; Insgesamt 23 NOPs, in

     ...         ; denen der Glättungs- 
     nop         ; IRQ ausgelöst wird   
     bne ch                             

Beachten Sie bitte, daß das Programm hier nicht mehr normal fortgesetzt wird, sondern daß innerhalb der 23 NOPs auf den Glättungs-IRQ bei " IRQ2" gewartet wird. Selbiger folgt gleich diesem Stückchen Source-Code, wobei ihm ein RTS-Befehl vorangestellt ist, der mit dem Label " Cycles" assoziiert wird. Dieser RTS-Befehl wird später im AGSP-IRQ desöfteren zum Verzögern angesprungen.
Zusammen mit dem aufrufenden JSR-Befehl werden so 12 Taktzyklen verbraucht ( je Befehl 6 Zyklen) :
cycles:
rts ; Verzög.- Unterroutine

irq2:pla         ;(IRQ-) Prozessorstatus
     pla         ; und Rücksprungadresse
     pla         ; vom Stapel werfen    
     dec $d019   ;VIC-ICR freigeben     
     lda #$f8    ;Nächster Raster-IRQ   
     sta $d012   ;bei Zeile $F8         
     lda #<border;Adresse der Border-IRQ
     sta $fffe   ; -Routine in Vektor   
     lda #>border; bei $FFFE/$FFFF ein- 
     sta $ffff   ; tragen               
     lda #$c8    ;40-Zeichen-Darst.     
     sta $d016   ; einschalten          
     lda #$06    ;Video-RAM nach $0000  
     sta $d018   ; verschieben (für Spr.
                   Pointer 1.Spr.Zeile, 
                   sh. oberste 4 Bits!) 
     nop         ;verzögern             

lda $ d012 ; Und den letzten Taktcmp #$1 d ; Zyklus korrigieren beq line ;( IRQ-Glättung) line: lda #$00 . . .
c) DIE FLD-ROUTINE Nun folgt der wichtige Teil der AGSP-Routine. Zunächst einmal noch ein wenig Verwaltungsarbeit. Wir setzen hier den Bildschirmbereich, in dem das VSP-Timing unergebracht ist auf schwarz und setzen schon einmal die Y-Positionen der Sprites für die zweite Spritezeile des Scoreboards ( wie Sie aus unseren Kursteilen über die Spriteprogrammierung wissen, so wird die neue Y-Koordinate erst dann vom VIC übernommen, wenn die ersten Sprites fertig gezeichnet sind - somit können wir die neuen Koordinaten irgendwann setzen, wenn der VIC die alten Sprites noch zeichnet - was hier der Fall ist) :
line lda #$00 ; Bildschirm und Rahsta $ d020 ; mein auf ' schwarz' sta $ d021 ; schalten

         jsr cycles ;3*12=36 Zyklen     
         jsr cycles ; verzögern         
         jsr cycles                     
         bit $ea    ;3 Zyklen verz.     
         ldy #$1e+21;YPos=YPos+21       
         sty $d001  ; und für die Spr0- 
         sty $d003  ; Spr7 setzen       
         sty $d005                      
         sty $d007                      
         sty $d009                      
         sty $d00b                      
         sty $d00d                      
         sty $d00f                      

Nach diesen mehr organisatorisch wichtigen Aufgaben folgt nun die FLD-Routine, die das Timing zur VSP-Routine ausgleichen soll:
fld: ldx #$27 ; Max. Anz. FLD-Durchl.
ldy #$01 ; Index d011/ d018- Tab.
fldlp: jsr cycles ;12 Zyklen verz.

      lda field1,y;Wert für $d011 holen 
      sta $d011   ; und setzen          
      lda field2,y;Wert für $d018 holen 
      sta $d018   ; und setzen          
      nop         ;6 Zyklen verz.       
      nop                               
      nop                               
      iny         ;Tab-Index+1          
      dex         ;FLD-Durchläufe-1     
      cpx <fldcnt ;=erforderliche Anz.  
      bne fldlp   ; Durchl.?Nein->Weiter
      nop         ;Sonst 14 Zyklen      
      jsr cycles  ; verzögern           
      lda field2,y;und letzten Wert für 
      iny         ; $d018 setzen        
      sta $d018                         

( Anm. d. Red. : Bitte wählen Sie nun den 2 . Teil des Kurses aus dem Textmenu)

Valid HTML 4.0 Transitional Valid CSS!