IRQ-KURS "Die Hardware ausgetrickst..." (Teil 16) ----------------------------------------
Herzlich Willkommen zum 16. Teil unseres Kurses über die Rasterstrahlprogrammie- rung. 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 Vertika- len (VSP-Routine) ermöglichten. Der Clou an diesen beiden Routinen war, daß des GESAMTE Bildschirm vom VIC verschoben wurde, und wir keinen einzigen Taktzy- klus zum Kopieren von Bildschirmdaten verschwenden mussten. In diesem Kursteil wollen wir nun das "Sahnestückchen" der Raster-IRQ-Programmierung besprechen: die Kombinattion aus HSP- und 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 Zy- klus zum Kopieren von Bildschirmdaten zu verschwenden! Stellen Sie sich vor, was für Möglich- keiten sich hierdurch für Spiele erge- ben: so kann man z.B. problemlos Spiele programmieren, die sich über einer be- liebig großen Oberfläche abspielen, die in alle Richtungen flüssig gescrollt werden kann, ohne dabei mehr als 30 Ra- sterzeilen pro Frame zu verbrauchen. 25 Rasterzeilen lang ist der Prozessor ei- gentlich nur mit dem Abpassen der opti- malen Rasterstrahlpostion für den HSP- Effekt beschäftigt, der, wie wir schon im 14. Kursteil sehen konnten, pro Cha- rakterzeile, die der Bildschirm horizon- tal gescrollt werden soll, eine Raster- zeile 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 demon- striert werden. Sie sehen hier einige Hiresgrafiken, die in Sinuswellenform auf- und abschwingen und gleichzeitig von links nach rechts scrollen. Hierbei werden jeweils neue Grafiken in die Gra- fik einkopiert, so daß der Eindruck ent- steht, 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 Charakter- zeile gelesen werden muß. Hier nun las- sen 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 Bild- schirm nach rechts versetzt darzustel- len. Die Anzahl Taktzyklen, die bis zum Zurückschalten verzögert werden müssen, muß dabei der Anzahl Zeichen entspre- chen, die der Bildschirm verschoben wer- den 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 Charakter- zeilen 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 Zei- le 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 unse- rem Programmbeispiel den VSP- und HSP- Routinen vorgeschaltet. Sie sorgt also gleichzeitig für immer gleiches Timing und zudem für die richtige Positionie- rung in der Horzontalen. Aus diesem Grund sind dann die ersten 25 Rasterzei- len des Bildschirms auch nicht zum Dar- stellen 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 Joy- stickabfrage und Scrollgeschwindigkeits- verzögerung sollen hier nicht Thema un- seres Kurses sein, sondern lediglich die Routine, die uns den Bildschirm beliebig im sichtbaren Fenster positioniert. Zur angesprochenen Scrollgeschwindigkeits- verzögerung sei erwähnt, daß wir hier beim Drücken und Loslassen des Joysticks die Scrollrichtung verzögern, bzw. nach- laufen lassen, so daß der Scrolleffekt zunächst träge anfängt und beschleunigt und beim Loslassen erst abgebremst wer- den 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) schal- tet nun den oberen und unteren Bild- schirmrand 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 wer- den. 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 ein- setzen * HSP-Routine zum charakterweisen links- und rechtsscrollen des Bildschirms ein- setzen * horizontales und vertikales Softscrol- ling 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 $0C00- $1000 zu finden sein sollen (Sprite- Pointer $30-$3f). Um die Pointer zwi- schen beiden leichter umschalten zu kön- nen 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 ver- schoben, so daß wir die Spritepointer in den Adressen $03F8-$03FF liegen haben. Für die zweite Spritezeile wird das Vi- deo-RAM an die (normale) Adresse $0400 gelegt, womit wir die Spritepointer an den Adressen $07F8-$07FF vorfinden. Da- durch, daß durch den VSP-Effekt auch diese Spritepointer als einzelne Zeichen auf dem Bildschirm auftauchen können, müssen wir die Pointer in jedem Raster- durchlauf (Frame) wieder neu setzen, da die Pointer auf dem Bildschirm ja dur- chaus 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 ein- sta $d015 ; schalten lda #$80 ;Hi-Bit d. X-Pos. von sta $d010 ; Sprite 8 setzen lda #$00 ;Sprite-Multicolor sta $d01c ; 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 wichtig- sten Spritedaten initialisiert. Dadurch, daß diese in jedem Frame neu gesetzt werden, können Sie im AGSP-Bereich pro- blemlos 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 ein- kopieren. Nun folgt noch die Initiali- sierung 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 $03f8-$03ff befin- den. Anschließend werden die Spritepoin- ter für die zweite Spritereihe eingetra- gen, die sich im normalen Bildschirm- speicher bei $0400, in den Adressen $07f8-$07ff befinden. Das abschließende schreiben des Wertes 3 in Register $DD00 stellt sicher, daß der 16K-Adressbereich des VICs auf den unteren Bereich, von $0000 bis $3FFF, 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-$3FFF schalt. b) DAS GLÄTTEN DES IRQS Der nun folgende Teil der AGSP-Routine ist für das Glätten des IRQs verantwort- lich. Ausserdem wird hier der Border-IRQ wieder als nächste IRQ-Quelle festge- legt, womit diese Arbeit nun auch erle- digt 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. Die- ser 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 Takt- cmp #$1d ;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 Spri- tes für die zweite Spritezeile des Sco- reboards (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 Rah- sta $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 wichti- gen Aufgaben folgt nun die FLD-Routine, die das Timing zur VSP-Routine ausglei- chen 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)