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)