IRQ-KURS "Die Hardware ausgetrickst..." (Teil 17)
Herzlich Willkommen zum 17 . und letzten
Teil unseres IRQ-Kurses. In dieser Ausgabe möchten wir Ihre Ausbildung abschließen und Ihnen die letzten Geheimnisse der AGSP-Routine erläutern, mit
deren Besprechung wir ja schon im letzten 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 Bildschirms. Zudem hatten wir noch einen
einfachen Sprite-Multiplexer mit integriert. 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 beliebigen Offset in Xund Y-Richtung zu
verschieben ( in X-Richtung um 0-319, in
Y-Richtung um 0-255 Pixel) . Damit wir
jedoch eine SPEZIELLE Verschiebung umsetzen können, muß die AGSP-Routine
natürlich auch mit speziellen Parametern
gefüttert werden, die von einer anderen
Routine in der Hauptschleife des Prozessors 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, welche 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 Zeropageadressen oder sogar direkt im Code
der IRQ-Routine eingetragen werden. Insgesamt 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 durchzuführen. Die Verschiebungen in Xund
Y-Richtungen werden wir im folenden mit
XPos und YPos bezeichnen. Unsere Beispielprogramme verwalten auch gleichnamige Variablen in der Zeropage. Sie werden 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 aufnehmen muß, benötigen wir für den Wert
XPos also zwei Speicherstellen, die von
unserem Beispielprogramm in den Zeropageadressen $02/$03 in Lo/ Hi-Byte-
Darstellung verwaltet werden. Für YPos
genügt uns ein Byte, das in der Zeropageadresse $04 zu finden ist.
Wollen wir nun jedoch zunächst herausstellen, 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 durchzulaufen 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 vorinitialisiert wird. Dieser Wert ergibt
sich aus der Anzahl Rasterzeilen, die
für das VSP-Timing benötigt werden. Normalerweise sollten dies 25 Rasterzeilen
sein. Da wir jedoch ein Spritescoreboard
mit einer Gesamthöhe von 42(=$2 a) 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, solange, bis er dem Wert in FLDCNT entspricht, womit die FLD-Schleife verlassen 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 berechnet 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 kommen. Dies sind keine Parameter im eigentlichen Sinne, sondern Änderungen im
Code der HSP-Routine, die eine Verzögerung 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 Taktzyklen verzögern müssen, um die gewünschte
Verschiebung zu erzielen. Auch hier zeige ich Ihnen wieder einen Auszug aus der
HSP-Routine, der der besseren Erläuterung 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 vorzugaukeln, er befände sich noch nicht in einer Rasterzeile. Anschließend wird mit
dem JSR-, dem DEX-, und den BEQ-/ BNE-Befehlen auf den Anfang des linken Bildschirmrandes gewartet, wobei die letzen
beiden Befehle ausschließlich für das
taktgenaue HSP-Timing herangezogen werden. 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 extremfall alle Zeichen übersprungen werden können. Der anschließende STX-Befehl
setzt dann die Darstellung wieder auf
Charakterzeilenbeginn, womit der VIC
dazu gezwungen wird, sofort eine Charakterzeile 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 umzusetzen 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 Bedingung 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 verbraucht 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. Dadurch 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 unserem 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 umgesetzt. Beachten Sie nur bitte noch folgenden 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 Parameterumrechnungsroutine 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 Parameterberechnungen, die Raster-IRQ- Effekte betreffend, abgehandelt. Da HSPund VSP-Routine den Bildschirm jedoch immer nur
in 8- Pixel-Schritten verschieben, müssen
wir diesen nun noch mit den ganz normalen 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 jeweils 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 lediglich das Softscrolling des Bildschirms zu setzen, müssen auch zur korrekten Bildschirmdarstellung notwendige
Bits in diesen Registern mitgesetzt werden. Auch dies wird unsere Parameterberechnungsroutine übernehmen.
2) DIE AGSP-PARAMETER- ROUTINE " CONTROLL" Kommen wir nun endlich zu der Unterroutine, die die benötigten Parameter in
umgerechneter Form in die AGSP-Routine
einbettet, und letztere zu einer korrekten Anzeige des Bildschirms bewegt.
Nachdem wir die Funktionprinzipien der
Parameterübergabe nun ausführlich besprochen haben, besteht die Controll-Routine nur noch aus ein paar " Rechenaufgaben" . 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 Border- 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 Drehund Angelpunkt 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ücksichtigt 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
Hiresund 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 Grafikdarstellung nicht!
( Anm. d. Red. : Bitte wählen Sie nun den 2 . Teil der IRQ-Routine aus dem Menu)