Magic Disk 64

home to index to html: MD9408-KURSE-IRQ-KURS_10.2.html
      Fortsetzung IRQ-Kurs, Teil 10     
----------------------------------------
Es  folgt  nun  der Programmteil mit dem
Label "CONTINUE",  der  von  der  obigen
Routine  angesprungen wird. Hier kümmern
wir uns wieder um den Scrolloffset, des-
sen  Wert ja noch negativ ist, da wir im
ersten Teil  der  MOVESPR-Routine  durch
die Subtraktion einen Unterlauf des Zäh-
lers erzeugt hatten. Damit Sie hier  nun
auch  Werte  größer  1 einsetzen können,
womit der Scroll  schneller  durchläuft,
wird  "SOFTROLL"  nicht  wieder  mit $17
vorinitialisiert, sondern  wir  addieren
auf  das  Ergebnis  der  Subtraktion den
Offset, der zwischen  zwei  Rasterinter-
rupts  liegt,  $18  (=dez. 24), auf. Der
resultierende Wert wird dann  wieder  in
Softroll  abgelegt. Auf diese Weise wer-
den  also  auch  Scrollwerte  größer   1
berücksichtigt.  War  das  Ergebnis  der
Subtraktion z.B. -2, so wird  "SOFTROLL"
auf 22 zurückgesetzt, womit der Öberlauf
abgefangen  wird,  und  der Scrolleffekt
flüssig weiterläuft:                    
CONTINUE:                               
   clc         ;C-Bit f.Add. löschen    
   lda softroll;SOFTROLL laden          
   adc #$18    ;24 addieren             
   sta softroll;und wieder ablegen      
   lda #$20    ;Op-Code für "JSR"       
   sta mt      ;in MT eintragen         
Besonders  trickreich  ist  die LDA-STA-
Folge am Ende dieses Programmteils.  Wir
tragen hier den Wert $20, der dem Assem-
bler-Opcode   des   "JSR"-Befehls   ent-
spricht,  in das Label "MT" ein. Letzte-
res   befindet   sich    innerhalb   der
MOVIEIRQ-Routine,  und  zwar vor dem Be-
fehl  "JSR  MAKETEXT".   Die   MAKETEXT-
Routine baut eine Spritezeile auf, indem
Sie  die  Zeichendaten  dieser Zeile von
dem Zeichensatz bei $0800 in die zu  be-
nutzenden  Sprites  einkopiert.  Da dies
nicht  direkt   zu   unserem   Kursthema
gehört, möchte ich auch nicht weiter auf
diese  Routine eingehen. Wichtig zu wis-
sen ist nur,  daß  die  MOVESPR-Routine,
nachdem  sie  erkannt hat, daß eine neue
Spritezeile aufgebaut  werden  muß,  die
MOVIEIRQ-Routine derart modifiziert, daß
im  nächsten  IRQ  die  MAKETEXT-Routine
angesprungen  wird.  Innerhalb  selbiger
existiert  dann eine weitere Befehlsfol-
ge, die den Wert $2C in das  Label  "MT"
schreibt.  Selbiger  Wert ist der Opcode
für den Assemlerbefehl "BIT".  In  allen
folgenden IRQs arbeitet der Prozessor an
diesem  Label also immer den Befehl "BIT
MAKETEXT" ab, der eigentlich keine Funk-
tion  beinhaltet, sondern lediglich ver-
hindern soll, daß  die  Maketext-Routine
angesprungen  wird.  Erst,  wenn MOVESPR
erkannt hat, daß eine  neue  Spritezeile
aufgebaut  werden  muß,  ändert  sie den
Befehl wieder in "JSR MAKETEXT"  um,  so
daß  die  Zeile  im  nächsten IRQ wieder
automatisch neu berechnet wird.  Dieser,
zugegebenermaßen etwas umständliche, Weg
des  Routinenaufrufs  wurde  gewählt, da
MAKETEXT  recht  lange  (insgesamt  etwa
einen  Rasterdurchlauf)  braucht, um die
Spritezeile  aufzubauen.  Damit  Sie  in
dieser  Zeit die Raster-IRQs nicht blok-
kiert, muß sie auf  diesem  Weg  benutzt
werden.  Während  ihres  Ablaufs erlaubt
sie auch weitere IRQs, so daß  Sie  wäh-
rend  der  Darstellung  des nächsten Ra-
sterdurchlaufs, immer zwischen den Spri-
tepositionierungen durch den IRQ, ablau-
fen kann.                               
Kommen  wir nun zum letzten Teil der MO-
VESPR-Routine, dem Label "ROLLON".  Sel-
biges wird ja ganz am Anfang der Routine
angesprungen,  wenn  kein  Unterlauf von
"SOFTROLL"  stattfand,  und  somit  ohne
jegliche  Änderung weitergescrollt wird.
Sie setzt den Spritepointerindex  "ISLI-
NE"  zurück  auf  den Wert in "SHOWLINE"
und bereitet den ersten Raster-IRQ  vor,
der  ja  immer in der Rasterzeile "SOFT-
ROLL" aufzutreten hat.                  
ROLLON:                                 
   lda showline;ISLINE mit Inhalt von   
   sta isline  ; SHOWLINE init.         
   lda softroll;Scroll-Offset holen     
   sta $d012   ;und als nächsten IRQ-   
   lda $d011   ;Auslöser setzen, dabei  
   and #$7f    ;Hi-Bit löschen u.       
   ora #$08    ;gleichz. 24-Zeilen-     
   sta $d011   ;Darst. einschalten      
   rts                                  
Beim Festlegen des Wertes "SOFTROLL" als
nächste IRQ-Rasterzeile, muß die Routine
auch das  High-Bit,  dieser  Rasterposi-
tion,  in  $D011  löschen.  Gleichzeitig
schaltet sie  die  25-Zeilen-Darstellung
durch  Setzen  des  3. Bits dieses Regi-
sters wieder ein.  Dies  ist  eigentlich
eine  Aufgabe,  die für das Beispielpro-
gramm  "MOVIE.1"  irrelevant  ist.  Wohl
aber  für  "MOVIE.2", in dem wir den Mo-
vie-Scroller über einen  Bildschirm  mit
abgeschaltetem  oberen  und unteren Rand
laufen lassen. Wie Sie wissen, muß  dazu
in  Rasterzeile  $FA die Darstellung von
25  auf  24  Zeichen-Zeilen  herunterge-
schaltet werden, und danach, vor nochma-
ligem Erreichen von $FA, wieder  auf  25
Zeilen  zurück, was hiermit durchgeführt
wird. Da MOVESPR immer im 13.  Interrupt
aufgerufen  wird,  und  dieser immer nur
innerhalb  der  Rasterzeilen   $10C-$126
auftreten   kann,   befinden   wir   uns
tatsächlich schon unterhalb der  Raster-
zeile  $FA,  womit die Änderung zum kor-
rekten Zeitpunkt durchgeführt wird.     
3) GLEICHZEITIGES ÜFFNEN DES BILDSCHIRMS
Wie schon angesprochen, öffnet das  Pro-
grammbeispiel  "MOVIE.2" zusätzlich noch
den oberen und  unteren  Bildschirmrand,
damit  die  Sprites  in  voller Bildhöhe
über den Bildschirm laufen. Vom  Prinzip
her  ist dies ein recht einfaches Unter-
fangen, das wir auch schon ausgiebig  in
diesem  Kurs  besprochen  und  angewandt
haben. Durch unsere Scrollroutine stellt
sich uns jedoch ein kleines  Problem  in
den Weg: da unsere Raster-IRQs durch den
Scrolleffekt  immer in verschiedenen Ra-
sterzeilen aufzutreten  haben,  und  wir
nicht  immer  genau sagen können, ob nun
der 11. oder 12. Rasterinterrupt  gerade
ausgelöst  wurde, bevor der Rasterstrahl
die Position $FA erreicht hat,  wird  es
schwierig  die Scroll-Routine so abzuti-
men, daß sie genau  an  dieser  Position
die  Bildschirmdarstellung ändert. Würde
man versuchen durch  Verzögerungsschlei-
fen  die richtige Position abzutimen, so
wäre das mit einem erheblichen  Program-
mieraufwand  verbunden.  Deshalb greifen
wir zu einem kleinen  Trick:  Die  INIT-
Routine  von  "MOVIE.2"  wurde  um  eine
kleine Änderung erweitert. Zunächst las-
sen  wir hier den Prozessor, durch stän-
diges Auslesen und Vergleichen  der  ak-
tuellen  Rasterposition, auf Rasterzeile
$FA warten. Ist diese erreicht, so  ini-
tialiseren wir Timer A von CIA-2 mit dem
Wert  $4CC7  und starten ihn. Da der Ra-
sterstrahl immer exakt so viele  Taktzy-
klen  braucht, um einmal über den ganzen
Bildschirm zu laufen, erzeugt diese  CIA
immer  genau  in Rasterzeile $FA, in der
sie gestartet  wurde,  einen  NMI.  Weil
dieser  Vorrang vor dem IRQ hat, wird er
selbst dann ausgelöst, wenn  gerade  ein
Raster-IRQ  auftritt oder in Bearbeitung
ist. Die NMI-Routine nimmt nun  die  er-
forderliche  Änderung  von $D011 vor, um
den Rand abzuschalten  (Bit  3  löschen)
und  kehrt  anschließend  sofort  wieder
zurück, ggf. sogar in einen vom NMI  un-
terbrochenen  Raster-IRQ,  der dann ganz
normal  zu  Ende  bearbeitet  wird.  Das
Zurücksetzen  von $D011 auf die alte 25-
Zeilen-Darstellung, wird dann wieder von
der  MOVESPR-Routine  durchgeführt,  wie
wir oben ja schon gesehen hatten.       
Um  die  NMIs  zu  erzeugen  springt die
INIT-Routine von "MOVIE.2" auf eine  Un-
terrountine  zum  Initialiseren  des Ti-
mer-NMIs. Wie  das  funktioniert  hatten
wir  schon ganz zu Anfang des Interrupt-
Kurses bespochen. Hier die  Routine,  um
Ihnen  den Vorgang wieder ins Gedächtnis
zu rufen. Wie auch  schon  für  den  IRQ
springen  wir  diesmal  nicht  über  den
Soft-NMI-Vektor bei $0318/$0319, sondern
über den Hardvektor bei  $FFFA/$FFFB  in
den NMI ein:                            
NMIINIT:                                
   lda #<nmi ;Startadresse NMI-Routine  
   sta $fffa ; in die Hardvektoren bei  
   lda #>nmi ;$FFFA/$FFFB eintragen     
   sta $fffb                            
   lda #$c7  ;Timer A mit dem Zählwert  
   sta $dd04 ; $4CC7 initialiseren      
   lda #$4c                             
   sta $dd05                            
   lda #$fa  ;Rasterz. $FA in Akku      
WAIT:                                   
   cmp $d012 ;m. akt. Raster vgl.       
   bne wait  ;ungl. also weiter         
   lda #$11  ;Gleich, also Timer A      
   sta $dd0e ; starten                  
   lda #$81  ;Timer-A-NMIs in ICR       
   sta $dd0d ; erlauben                 
   rts                                  
Das war eigentlich schon alles. Von  nun
an  löst  Timer  A  von CIA-B alle $4CC7
Taktzyklen einen NMI aus. Da der Raster-
strahl  immer  genau diese Anzahl Zyklen
benötigt, um ein  ganzes  Mal  über  den
Bildschirm zu laufen, tritt der NMI also
immer  in  Rasterzeile  $FA ein, auf die
wir vor Starten des Timers gewartet  ha-
ben.  Die  NMI-Routine  selbst ist recht
kurz und sieht folgendermaßen aus:      
NMI:  pha       ;Akku retten            
      lda $d011 ;$D011 holen            
HILO: ora #$00  ;7.Bit Rasterpos. setzen
      and #$F7  ;3.Bit löschen          
      sta $d011 ;$D011 zurückschreiben  
      bit $dd0d ;NMIs wieder erlauben   
      pla       ;Akku zurückholen       
      rti       ; und Ende              
Da die NMI-Routine  lediglich  den  Akku
benutzt,  brauchen  wir auch ausschliße-
lich nur diesen auf dem Stapel  zu  ret-
ten.  Danach  wird  der Inhalt von $D011
gelesen. Der nun folgende ORA-Befehl hat
die Aufgabe eine ggf. gesetztes High-Bit
der  Rasterstrahlposition  des  nächsten
Raster-IRQs  zu  setzen, damit wir durch
unsere Manipulation von $D011 nicht ver-
sehentlich  die, schon gesetzte, nächste
Raster-IRQ-Position  verändern.   Hierzu
wurde die MOVIEIRQ-Routine von "MOVIE.2"
derart  abgeändert,  daß  Sie  die High-
Position  für  den  nächsten  Raster-IRQ
nicht  nur  in  $D011  schreibt, sondern
auch im Label "HILO+1"  ablegt,  so  daß
das  Argument  des  ORA-Befehls zwischen
$00 und $80 variiert und immer den rich-
tigen  ODER-Wert  enthält.  Anschließend
folgt nun ein AND-Befehl zum Löschen des
3. Bits, womit wir mit dem  Ablegen  des
Wertes  die  24-Zeilen-Darstellung  ein-
schalten. Durch  den  BIT-Befehl  führen
wir   einen  Lesezugriff  auf  das  ICR-
Register von CIA-2 aus, womit wir selbi-
ges  Löschen,  und dadurch das Auftreten
und Melden des  nächsten  NMIs  ermögli-
chen.  Hiernach  wird  dann nur noch der
gerettete Akkuinhalt zurückgeholt, bevor
wir den NMI mittels  "RTI"  beenden.  Da
die  MOVESPR-Routine  nun automatisch zu
einer späteren Position Bit 3  in  $D011
wieder   setzt,  funktioniert  der  NMI-
Border-Trick also auch wieder im folgen-
den  Rasterdurchlauf! Mit Hilfe des hier
benutzen  NMI-Tricks  können  Sie  quasi
zwei   Raster-Intterrupts   gleichzeitig
ablaufen lassen,  was  auch  für  andere
Rasterroutinen sehr hilfreich sein kann.
                                 (ih/ub)



Valid HTML 4.0 Transitional Valid CSS!