Magic Disk 64

home to index to html: MD9404-KURSE-IRQ-KURS_6.2.html
    Interruptkurs (Teil6 - 2.Hälfte)    
----------------------------------------
Kommen  wir  nun zur ersten FLD-Routine.
In ihr wird der Interrupt geglättet, was
eine besonders trickreiche Angelegenheit
ist. Sehen Sie sich  hierzu  einmal  den
Sourcecode an:                          
;*** FLD-Routine mit Glättung ($1100)   
FLD1  pha        ;Akku, X- u. Y-Reg.    
      txa        ; retten               
      pha                               
      tya                               
      pha                               
      dec $d019  ;neue IRQs erlauben    
      inc $d012  ;nächte Raster.=Ausl.  
      lda #<FLD2 ;Lo-Byte von FLD-IRQ2- 
      sta $fffe  ;Routine setzen        
      cli        ;IRQs erlauben         
WIRQ  nop        ;13 NOPs               
      nop        ; (innerhalb dieser    
      nop        ;  Schleife wird der   
      nop        ;  Interrupt ausge-    
      nop        ;  löst werden!!)      
      nop                               
      nop                               
      nop                               
      nop                               
      nop                               
      nop                               
      nop                               
      nop                               
      jmp QIRQ                          
FLD2  pla        ;Programmzähler und    
      pla        ; Statusreg. gleich    
      pla        ; wieder v. Stack holen
      nop        ;19 NOPs zum Verzögern 
      nop        ; bis zum tatsächlichen
      nop        ; Charakterzeilen-     
      nop        ; anfang               
      nop                               
      nop                               
      nop                               
      nop                               
      nop                               
      nop                               
      nop                               
      nop                               
      nop                               
      nop                               
      nop                               
      nop                               
      nop                               
      nop                               
      nop                               
      lda $d012  ;Den letzten Zyklus    
      cmp $d012  ; korrigieren          
      bne cycle                         
cycle ...        ;eigentlicher IRQ      
Hier  werden  Ihnen  einige  Dinge etwas
merkwürdig vorkommen (vor allem die vie-
len NOPs). Beginnen wir von Anfang an:  
In der Borderroutine hatten wir die  Ra-
sterzeile  festgelegt,  in der die FLD1-
Routine angesprungen werden  soll.  Dies
war  Zeile  61 ($3D), die genau zwei Ra-
sterzeilen  vor  der  eigentlichen  IRQ-
Rasterzeile  liegt.  In diesen zwei Zei-
len, die wir den  IRQ  früher  ausgelöst
haben, werden wir ihn jetzt glätten. Wie
in  jedem  Interrupt retten wir zunächst
die Prozessorregister.  Daran  anschlie-
ßend   wird  das  Low-Byte  der  Routine
"FLD2" in das Low-Byte  des  IRQ-Vektors
geschrieben, und die nächste Rasterzeile
(durch  den INC-Befehl) als nächster In-
terruptauslöser festgelegt. Beachten Sie
hierbei, daß die diese Routine  dasselbe
High-Byte  in der Adresse haben muß, wie
die erste FLD-Routine. Das kann man  da-
durch  erzielen,  daß  "FLD1"  an  einer
Adresse mit 0-Lowbyte  ablegt  wird  und
sofort  danach  die Routine "FLD2" folgt
(im Beispiel ist FLD1 an Adresse $1100).
Um einen neuen Interrupt zu ermöglichen,
müssen noch das ICR des VIC und das  In-
terrupt-Flag   des  Prozessors  gelöscht
werden (beachten Sie, daß letzteres  vom
Prozessor  automatisch bei Auftreten des
IRQs gesetzt wurde).                    
Es  folgt  nun  der  eigentliche  "Glät-
tungs-teil".  Hierzu lassen wir den Pro-
zessor  ständig   durch   eine   Endlos-
Schleife  mit  NOP-Befehlen  laufen. Da-
durch wird sichergestellt, daß  der  Ra-
ster-IRQ  der  nächsten  Rasterzeile  in
jedem Fall während der Ausführung  eines
NOP-Befehls  auftritt.  Da dieser Befehl
nur 2 Taktzyklen  verbraucht,  kann  die
Verzögerung  des  Interupts nur 0 oder 1
Taktzyklen lang sein. Diesen  einen  Zy-
klus  zu korrigieren ist nun die Aufgabe
des zweiten FLD-IRQs. Nachdem  er  ange-
sprungen  wurde  holen wir gleich wieder
die, vom Prozessor automatisch  gerette-
te,  Programmzähleradresse  und das Sta-
tusregister vom Stapel, da sie  nur  zum
ersten  FLD-Interrupt  gehören,  in  den
nicht mehr  zurückgekehrt  werden  soll.
Danach  folgen  19  NOP-Befehle, die nur
der Verzögerung dienen, um das Ende  der
Rasterzeile  zu  erreichen.  Die letzten
drei Befehle  sind  die  Trickreichsten!
Sie   korrigieren  den  einen  möglichen
Verzögerungs-Zyklus.    Zum     besseren
Verständnis sind sie hier nochmal aufge-
listet:                                 
      lda $d012  ;Den letzten Zyklus    
      cmp $d012  ; korrigieren          
      bne cycle                         
cycle ...        ;eigentlicher IRQ      
Obwohl  diese  Folge  recht unsinnig er-
scheint, hat sie es ganz schön in  sich:
Wir laden hier zunächst den Akku mit dem
Inhalt  von Register $D012, das die Num-
mer der aktuell bearbeiteten Rasterzeile
beinhaltet, und vergleichen  ihn  sofort
wieder  mit diesem Register. Danach wird
mit Hilfe des BNE-Befehls auf  die  Fol-
geadresse verzweigt, was noch unsinniger
erscheint.                              
Der  LDA-Befehl  befindet sich nun durch
die NOP-Verzögerung genau an  der  Kippe
zur  nächsten Rasterzeile, nämlich einen
Taktzyklus bevor  diese  Zeile  beginnt.
Sollte  nun  der FLD2-IRQ ohne den einen
Taktzyklus  Zeitverzögerung   ausgeführt
worden  sein,  so  enthält der Akku z.B.
den Wert 100. Der  CMP-Befehl  ist  dann
ein  Vergleich  mit dem Wert 101, da der
Rasterstahl nach dem LDA-Befehl schon in
die nächste Zeile  gesprungen  ist.  Da-
durch  sind  die  beiden Werte ungleich,
womit das Zero-Flag  gelöscht  ist,  und
der  Branch tatsächlich ausgeführt wird.
Beachten Sie nun, daß ein  Branch-Befehl
bei  zutreffender  Bedingung  durch  den
Sprung einen Taktzyklus mehr  Zeit  ver-
braucht,  als bei nicht zutreffender Be-
dingung (3 Zyklen!).  War  der  FLD2-IRQ
allerdings   mit  dem  einem  Taktzyklus
Verzögerung  aufgetreten,  so  wird  der
LDA-Befehl  genau  dann ausgeführt, wenn
Register  $D012  schon  die  Nummer  der
nächsten  Rasterzeile enthält, womit der
Akku den Wert 101 beinhaltet. Durch  den
Vergleich  mit  dem  Register,  das dann
immer noch den Wert  101  enthält,  wird
das  Zero-Flag  gesetzt,  da  die beiden
Werte identisch sind. Dadurch trifft die
Bedingung des BNE-Befehls nicht zu,  und
er  verbraucht  nur  2  Taktzyklen! Dies
gewährleistet, daß in beiden Fällen  im-
mer  die  gleiche  Zyklenzahl verbraucht
wird! War der FLD2-IRQ ohne Verzögerung,
so verbracht die  Routine  einen  Zyklus
mehr,  als  wenn  er  mit  einem  Zyklus
Verspätung auftrat!                     
Hiermit hätten wir den IRQ also  geglät-
tet  und können die eigentliche FLD- und
Farbsetz-Routine ausführen. Beachten Sie
für Folgebeispiele, daß wir  in  Zukunft
auf  diese  Weise die IRQs immer glätten
werden müssen, um saubere Ergebnisse  zu
erzielen. Hierzu wird immer wieder diese
Routine  verwandt, wobei das eigentliche
IRQ-Programm dann nach dem Branch-Befehl
eingesetzt wird. Gleichmäßiger kann  man
Raster-IRQ   nun   wirklich  nicht  mehr
ausführen!                              
Nach  dem  Glätten folgt die eigentliche
Interruptroutine, und zwar  direkt  nach
dem Label "Cycle". Sie setzt Rasterzeile
$F8  als Interruptauslöser fest und ver-
biegt den IRQ-Vektor wieder auf die Bor-
derroutine,   womit  der  Kreislauf  von
Neuem beginnt.  Gleichzeitig  setzt  Sie
die  Darstellung  auf  25 Zeilen zurück,
damit  der  Bordereffekt  auch  funktio-
niert.  Anschließend wird der FLD-Effekt
durchgeführt, indem der Zeilenanfang vor
dem Rasterstrahl hergeschoben wird. Wäh-
renddessen  werden  die Vorder- und Hin-
tergrundfarbe nach zwei Farbtabellen bei
$1200 und $1300 verändert.  Der  Raster-
split  wird  durch ausreichende Verzöge-
rung bis zur Mitte einer Rastezeile  er-
zeugt. Zum Schluß des IRQs wird noch bis
zum  Ende der Rasterzeile verzögert, und
die Standardfarben zurückgesetzt,  bevor
die  ursprünglichen  Inhalte der Prozes-
sorregister, wie sie vor  dem  Auftreten
des FLD1-IRQs vorhanden waren, zurückge-
holt werden und der IRQ beendet wird:   
Cycle dec $d019  ;VIC-ICR löschen       
      lda #$18   ;25-Zeilen-Darst. ein- 
      sta $d011  ; schlaten (Bordereff.)
      lda #$f8   ;Rasterz. $F8 ist näch-
      sta $d012  ; ster IRQ-Auslöser    
  ldx #<Bord ;IRQ-Vektor                
      ldy #>Bord ; auf                  
      stx $fffe  ; Border-Routine       
      sty $ffff  ; verbiegen            
      nop        ;Verzögern             
      lda $02    ;FLD-Zähler laden      
      beq FDEnd  ; Wenn 0, kein FLD!    
      ldx #$00   ;Zählreg.f.Farben init.
      clc                               
FDLop lda $d012  ;FLD-Sequenz (Zeilen-  
      adc #$02   ; anfang vor Raster-   
      and #$07   ; strahl herschieben   
      ora #$18                          
      sta $d011                         
      lda $1200,x;Farbe links holen     
      sta $d020  ; und setzen        sta
$d021                                   
      nop        ;Verzögern bis Mitte   
      nop                               
      nop                               
      nop                               
      nop                               
      nop                               
      nop                               
      lda $1300,x;Farbe rechts holen    
      sta $d020  ; und setzen           
      sta $d021                         
      bit $ea    ;Verzögern             
      inx        ;Farb-Zähler+1         
      cpx $02    ;Mit FLD-Zähler vgl.   
      bcc FDLop  ;ungl., also weiter    
FDEnd nop        ;Verz. bis Zeilenende  
      nop                               
      nop                               
      nop                               
      nop                               
      lda #$0e   ;Vorder-/Hintergrund-  
      sta $d020  ; farben auf           
      lda #$06   ; hellblau u. dunkel-  
      sta $d021  ; blau setzen          
      pla        ;Akku, X- und Y-Reg.   
      tay        ; zurückholen          
      pla                               
      tax                               
      pla                               
      rti        ;IRQ beenden           
Das war es dann wieder für diesen Monat.
Im  nächsten  Kursteil  werden  wir eine
weitere Anwendung besprechen,  die  eine
IRQ-Glättung  benötigt:  die Sideborder-
routinen zum Abschalten des  linken  und
rechten Bildschirmrands, nämlich.       
                                    (ub)



Valid HTML 4.0 Transitional Valid CSS!