Magic Disk 64

home to index to text: MD9503-KURSE-IRQ-KURS_17.1.txt
                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)

Valid HTML 4.0 Transitional Valid CSS!