Magic Disk 64

home to index to html: MD9503-KURSE-IRQ-KURS_17.1.html
                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)  
Valid HTML 4.0 Transitional Valid CSS!