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)