IRQ-KURS
"Die Hardware ausgetrickst..."
(Teil 17)
----------------------------------------
Herzlich Willkommen zum 17. und letzten
Teil unseres IRQ-Kurses. In dieser Aus-
gabe möchten wir Ihre Ausbildung ab-
schließen und Ihnen die letzten Geheim-
nisse der AGSP-Routine erläutern, mit
deren Besprechung wir ja schon im letz-
ten Monat begannen.
Dort hatten wir zunächst die IRQ-Routine
besprochen, die es uns ermöglicht, den
AGSP-Effekt durchzuführen. Sie bestand
aus einer geschickten Kombination der
Routinen FLD, VSP und HSP, sowie einigen
Befehlen zum Softscrollen des Bild-
schirms. Zudem hatten wir noch einen
einfachen Sprite-Multiplexer mit inte-
griert. Wie Sie also sehen, ist die
AGSP-Routine auch ein gutes Beispiel
dafür, wie die Raster-IRQ-Effekte in
Kombination miteinander ein perfektes
Zusammenspiel ergeben können.
Prinzipiell ist die im letzten Monat
besprochene AGSP-IRQ-Routine also in der
Lage, uns den Bildschirm um jeden belie-
bigen Offset in X- und Y-Richtung zu
verschieben (in X-Richtung um 0-319, in
Y-Richtung um 0-255 Pixel). Damit wir
jedoch eine SPEZIELLE Verschiebung um-
setzen können, muß die AGSP-Routine
natürlich auch mit speziellen Parametern
gefüttert werden, die von einer anderen
Routine in der Hauptschleife des Prozes-
sors vorberechnet werden müssen. Diese
Routine exisitiert natürlich auch in
unseren Programmbeispielen "AGSP1" und
"AGSP2", sie heißt "Controll" und soll
das Thema dieses Kursteils sein.
1) DIE PARAMETER DER AGSP-ROUTINE
Wollen wir zunächst einmal klären, wel-
che Parameter unsere AGSP-Routine benö-
tigt. Da es eine IRQ-Routine ist, können
wir selbige natürlich nicht so einfach
übergeben. Sie müssen teilweise in Zero-
pageadressen oder sogar direkt im Code
der IRQ-Routine eingetragen werden. Ins-
gesamt gibt es 5 Stellen, die wir ändern
müssen, damit die AGSP-Routine auch die
Parameter bekommt, die sie benötigt, um
eine ganz bestimmte Verschiebung durch-
zuführen. Die Verschiebungen in X- und
Y-Richtungen werden wir im folenden mit
XPos und YPos bezeichnen. Unsere Bei-
spielprogramme verwalten auch gleichna-
mige Variablen in der Zeropage. Sie wer-
den von der Joystickabfrage automatisch
auf die zwei benötigten Werte gesetzt,
um die die AGSP-Routine den Bildschirm
in beide Richtungen verschieben soll. Da
dies in jedem Frame erneut geschieht
wird so der Eindruck einer flüssigen
Verschiebung erzielt. Da die X-
Verschiebung Werte größer als 256 auf-
nehmen muß, benötigen wir für den Wert
XPos also zwei Speicherstellen, die von
unserem Beispielprogramm in den Zeropa-
geadressen $02/$03 in Lo/Hi-Byte-
Darstellung verwaltet werden. Für YPos
genügt uns ein Byte, das in der Zeropa-
geadresse $04 zu finden ist.
Wollen wir nun jedoch zunächst heraus-
stellen, welche Parameter aus diesen
beiden Werten berechnet werden müssen,
damit die AGSP-Routine die korrekte
Bildschirmverschiebung durchführt:
a) FLDCNT FÜR FLD UND VSP
Wie Sie sich sicherlich noch erinnern,
so benutzte unsere AGSP-Routine eine
FLD-Routine, um das Timing zur VSP-
Routine auszugleichen, für den Fall, daß
letztere weniger als 25 Charakterzeilen
vertikale Bildschirmverschiebung
durchführen sollte. Um nun die korrekte
Anzahl Zeilen zu verschieben, hatte sich
die FLD-Routine eines Zählers bedient,
der ihr angab, wieviel Mal sie durchzu-
laufen hatte. Zur besseren Erläuterung
des Zählers hier noch einmal der Kern
der FLD-Routine:
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
Der besagte FLD-Zähler befindet sich nun
im X-Register, das mit dem Wert $27 vor-
initialisiert wird. Dieser Wert ergibt
sich aus der Anzahl Rasterzeilen, die
für das VSP-Timing benötigt werden. Nor-
malerweise sollten dies 25 Rasterzeilen
sein. Da wir jedoch ein Spritescoreboard
mit einer Gesamthöhe von 42 (=$2a) Ra-
sterzeilen darstellen, muß auch diese
Anzahl Zeilen übersprungen werden. Der
FLD-Zähler enthält diesen Wert minus 3,
da ja auch schon durch die IRQ-Glättung
2 Rasterzeilen verbraucht wurden und
nach der FLD-Routine der Zähler wieder
für die VSP-Routine um 1 erhöht wird.
Dieser Zähler im X-Register wird nun pro
Rasterzeile einmal herabgezählt, solan-
ge, bis er dem Wert in FLDCNT ent-
spricht, womit die FLD-Schleife verlas-
sen wird. Aus dem verbleibenden Wert im
X-Register, der dann genau dem FLDCNT-
Wert entspricht, ergibt sich der VSPCNT,
der angibt, wie oft die VSP-Routine
durchlaufen werden muß. Dieser Zähler
muß nicht eigens berechnet werden. Somit
ist VSPCNT also einer der 5 Parameter,
die die AGSP-Routine benötigt. Er be-
rechnet sich aus YPos dividiert durch 8.
b) REDU1 UND REDU2 FÜR HSP
Nachdem also der Parameter für die VSP-
Routine und somit der Chrakterzeilen-
Verschiebung geklärt ist, wollen wir zu
den Parametern für die HSP-Routine kom-
men. Dies sind keine Parameter im ei-
gentlichen Sinne, sondern Änderungen im
Code der HSP-Routine, die eine Verzöge-
rung der gewünschten Dauer durchführen.
Wie Sie sich vielleicht erinnern, so
wird mit jedem Taktzyklus, den die HSP-
Routine das Zurücksetzen des Bildschirms
auf "Charakterzeile zeichnen" verzögert,
die Darstellung desselben um ein Zeichen
(also 8 Pixel) nach rechts verschoben.
Das heißt also, daß wir XPOS/8 Taktzy-
klen verzögern müssen, um die gewünschte
Verschiebung zu erzielen. Auch hier zei-
ge ich Ihnen wieder einen Auszug aus der
HSP-Routine, der der besseren Erläute-
rung dienen soll:
HSP: ldx field1+3,y;nächst. d011-Wert
stx $d011 ;schreiben
jsr cycles ;Anfang sichtb.
; Bildschirm abwart.
dex ;d011-Wert-1
redu1:beq redu2 ;Ausgleich für unge-
redu2:bne tt ; rade Zyklen
nop ;Insgesamt 20
... ; NOPs für das
nop ; HSP-Timing
tt stx $d011 ;akt.Z. einschalt.
Die HSP-Routine setzt die Y-Verschiebung
des Bildschirms nun zunächst hinter den
Rasterstrahl, um so dem VIC vorzugau-
keln, er befände sich noch nicht in ei-
ner Rasterzeile. Anschließend wird mit
dem JSR-, dem DEX-, und den BEQ-/BNE-
Befehlen auf den Anfang des linken Bild-
schirmrandes gewartet, wobei die letzen
beiden Befehle ausschließlich für das
taktgenaue HSP-Timing herangezogen wer-
den. An den Labels "REDU1" und "REDU2",
wird unsere Parameterberechnungsroutine
später den Code modifizieren, so daß das
Timing exakt dem gewünschten XPos/8-
Offset entspricht. Hierzu dienen auch
die 20 NOP-Befehle, die genau 40 Zyklen,
bzw. Zeichen verzögern, wodurch im ex-
tremfall alle Zeichen übersprungen wer-
den können. Der anschließende STX-Befehl
setzt dann die Darstellung wieder auf
Charakterzeilenbeginn, womit der VIC
dazu gezwungen wird, sofort eine Charak-
terzeile zu lesen und anzuzeigen. Also
erst hier wird der eigentliche Effekt
ausgeführt. Um nun das Einsetzen der
Charakterzeile genau abzutimen, müssen
wir also um XPOS/8 Taktzyklen verzögern.
Diese Verzögerung kann recht haarig um-
zusetzen sein, wenn es sich dabei um
eine ungerade Anzahl Zyklen handelt.
Diese Aufgabe soll der Branch-Befehl,
beim Label REDU1 lösen. Zunächst einmal
sollte erwähnt werden, daß das X-
Register nach dem DEX-Befehl IMMER einen
Wert ungleich null enthält, da dort ja
der benötigte Wert für $d011 steht, der
immer größer als 1 ist, womit durch den
DEX-Befehl nie auf 0 herabgezählt werden
kann. Das Zeroflag ist beim Erreichen
des Labels REDU1 also immer gelöscht.
Wie auch schon beim Glätten des IRQs
benutzen wir nun also den Trick mit den
Branch-Befehlen, um ggf. eine ungerade
Verzögerung zu erzielen. Wie Sie von
dort vielleicht noch wissen, benötigt
ein Branch-Befehl immer mindestens 2
Taktzyklen. Trifft die abgefragte Bedin-
gung nun zu, so dauert die Abarbeitung
des Branchbefehls immer einen Zyklus
mehr, also 3 Zyklen. Soll der Bildschirm
nun um eine gerade Anzahl Zeichen nach
rechts verschoben werden, so trägt die
Parameterberechnungsroutine bei REDU1
den Assembler-Opcode für einen BEQ-
Befehl ein. Da diese Bedingung nie
erfüllt ist, werden nur 2 Zyklen ver-
braucht und direkt mit dem folgenden
Befehl bei REDU2 fortgefahren. Muß eine
ungerade Anzahl Taktzyklen verzögert
werden, so setzt die Parameterberechnung
bei REDU1 den Opcode für einen BNE-
Befehl ein. Da diesmal die Bedingung
zutrifft, dauert die Abarbeitung des
Befehls 3 Taktzyklen, wobei jedoch eben-
falls mit REDU2 fortgefahren wird. Da-
durch dauert die Routine nun einen
Taktzyklus mehr, womit wir eine ungerade
Verzögerung erzielt haben.
Der Branch-Befehl bei REDU2 muß nun
ebenfalls modifiziert werden. Hierbei
bleibt der Opcode jedoch immer derselbe,
also ein BNE-Befehl, der immer wahr ist.
Es wird lediglich der Operand dieses
Befehls geändert, so daß nicht mehr auf
das Label "TT" gesprungen wird, sondern
auf einen der zuvor stehenden NOP-
Befehle, wodurch die entsprechende HSP-
Verzögerung sichergestellt wird. Der
Operand eines Branch-Befehles kann nun
ein Bytewert zwischen -127 und +128
sein, der den Offset angibt, um den der
Branch-Befehl den Programmzähler des
Prozessors erhöhen, bzw. erniedigen
soll. Steht hier also der Wert $05, so
werden die nächsten 5 Bytes im Code
übersprungen. Da ein NOP-Befehl immer
ein Byte lang ist, werden also in unse-
rem Fall exakt 5 NOPs übersprungen, wo-
mit noch 15 NOPs ausgeführt werden, die
15*2=30 Taktzyklen verzögern, und somit
den Bildschirm in der Horzontalen erst
ab dem dreißigsten Charakter beginnen
lassen. Der Sprungoffset für den BNE-
Befehl berechnet sich danach also aus
der Formel: 'Anzahl NOPs'-XPOS/8/2 =
20-XPOS/16.
Mit Hilfe dieser beiden Branch-Befehle
hätten wir nun also das entsprechende
Timing für die HSP-Routine korrekt umge-
setzt. Beachten Sie nur bitte noch fol-
genden Umstand: Dadurch, daß der
Branch-Befehl bei REDU2 immer ausgeführt
werden muß, also daß seine Bedingung
immer wahr sein muß, müssen wir hier
einen BNE-Befehl verwenden. Gerade aber
WEIL dessen Bedigung immer wahr ist,
benötigt er auch immer 3 Taktzyklen,
also eine ungerade Anzahl, womit er den
Ausgleich des Branch-Befehls bei REDU1
wieder zunichte machen würde. Damit dies
nicht geschieht, muß die Parameterum-
rechnungsroutine die Opcodes genau umge-
kehrt einsetzen, wie oben beschrieben:
also einen BNE-Befehl, wenn eine gerade
Anzahl Zyklen verzögert werden soll, und
einen BEQ-Befehl, wenn die Anzahl der zu
verzögernden Zyklen ungerade ist! Ich
erläuterte dies im obigen Fall zunächst
anders, um Sie nicht noch zusätzlich zu
verwirren!
c) PARAMETER FÜR DAS SOFTSCROLLING
Damit wären also alle Parameterberech-
nungen, die Raster-IRQ-Effekte betref-
fend, abgehandelt. Da HSP- und VSP-
Routine den Bildschirm jedoch immer nur
in 8-Pixel-Schritten verschieben, müssen
wir diesen nun noch mit den ganz norma-
len Softscroll-Registern um die fehlende
Anzahl Einzelpixel verschieben. Auch
dies wird noch innerhalb des AGSP-
Interrupts durchgeführt, nämlich genau
am Ende desselben. Hier hatten wir zwei
Labels mit den Namen "HORIZO" und "VER-
TIC" untergebracht, die jeweils auf eine
LDA-STA-Befehlsfolge zeigten, und den
entsprechenden Verschiebeoffset in die
VIC-Register $D011 und $D016 eintrugen.
Hier nochmal ein Codeauszug aus dem
AGSP-IRQ:
horizo: lda #$00 ;Versch. vom linken
sta $d016; Bildrand
vertic: lda #$00 ;Versch. vom oberen
sta $d011; Bildrand
Um nun die Werte dieser Verschiebungen
zu ermitteln, müssen wir lediglich je-
weils die untersten 3 Bits aus XPos und
YPos ausmaskieren und in die Oparanden-
Bytes der LDA-Opcodes eintragen. Da die
Register $D011 und $D016 jedoch auch
noch andere Aufgaben erfüllen, als le-
diglich das Softscrolling des Bild-
schirms zu setzen, müssen auch zur kor-
rekten Bildschirmdarstellung notwendige
Bits in diesen Registern mitgesetzt wer-
den. Auch dies wird unsere Parameterbe-
rechnungsroutine übernehmen.
2) DIE AGSP-PARAMETER-ROUTINE "CONTROLL"
Kommen wir nun endlich zu der Unterrou-
tine, die die benötigten Parameter in
umgerechneter Form in die AGSP-Routine
einbettet, und letztere zu einer korrek-
ten Anzeige des Bildschirms bewegt.
Nachdem wir die Funktionprinzipien der
Parameterübergabe nun ausführlich be-
sprochen haben, besteht die Controll-
Routine nur noch aus ein paar "Reche-
naufgaben". Sie wird von der Border-
IRQ-Routine aufgerufen und wertet die
Einträge in XPos sowie YPos aus. Diese
Werte werden, wie schon erwähnt, von der
Joystickabfrage in der Hauptschleife
unseres Programmbeispiels entsprechend
gesetzt und verwaltet.
Dadurch, daß Controll während des Bor-
der-IRQs aufgerufen wird, stellen wir
gleichzeitig auch sicher, daß die AGSP-
Routine zu einem Zeitpunkt modifiziert
wird, zu dem sie nicht ausgeführt wird,
und vermeiden so ihr Fehlverhalten.
Hier nun also die Controll-Routine, die
als erstes die erforderlichen Werte für
die Y-Verschiebung berechnet. Dies ist
zunächst der Wert für FLDCNT, gefolgt
von dem entsprechenden Eintrag für die
vertikale Softscrolling-Verschiebung,
die in VERTIC+1 eingetragen werden muß.
FLDCNT berechnet sich einfach aus
YPos/8. Der Softscrollwert entspricht
den untersten 3 Bits von YPos, also
(YPos AND $07). Hierbei muß jedoch durch
das HSP-Timing der benötigte Wert minus
1 ins Softscrollregister eingetragen
werden. Das hängt damit zusammen, daß
die Softscrollveränderung ja ebenfalls
in Register $D011 eingetragen werden
muß, was ja zugleich Dreh- und Angel-
punkt aller anderen Raster-IRQ-Routinen
ist. Die gewünschte Änderung führen wir
mit Hilfe einer speziellen Befehlsfolge
durch, um uns Überlaufsvergleiche zu
sparen. Zum Schluß steht in jedem Fall
der richtige Wert im Akku, in den wir
dann mittels ORA-Befehl noch die Bits 3
und 4 setzen, die den 25 Zeilen-Schirm,
sowie den Bildschirm selbst einschalten,
was bei $D011 ja ebenfalls noch berück-
sichtigt werden muß:
Controll:
lda <ypos ;YPOS holen
lsr ; durch 8
lsr ; dividieren
lsr
sta <fldcnt ;und in FLDCNT ablegen
clc ;C-Bit f. Add. löschen
lda <ypos ;YPos holen
and #$07 ;Unterste Bits ausmask.
eor #$07 ; umkehren
adc #$1a ; Ausgleichswert add.
and #$07 ; wieder maskieren
ora #$18 ; Bilschirmbits setzen
sta vertic+1 ; und in AGSP ablegen
Der ORA-Befehl am Ende ist übrigens von
wichtiger Bedeutung. Wie Sie ja wissen,
unterscheiden sich die beiden Beispiel
"AGSP1" und "AGSP2" nur darin, daß die
erste Version einen Textbildschirm, die
zweite Version einen Multicolor-Grafik-
Schirm scrollt. Der programmtechnische
Unterschied zwischen diesen beiden
Routinen besteht nun lediglich in der
Änderung des oben aufgeführten ORA-
Befehls. In AGSP2 wird hier mit dem Wert
$78 verknüft, womit zusätzlich auch noch
Hires- und Extended-Background-Color-
Mode eingeschaltet werden. Dies ist der
EINZIGE Unterschied zwischen den beiden
Beispielen, der eine große Auswirkung
auf das Erscheinen hat! Die AGSP-Routine
selbst ändert sich durch die Grafik-
darstellung nicht!
(Anm. d. Red.: Bitte wählen Sie nun den
2. Teil der IRQ-Routine aus dem Menu)