Magic Disk 64

home to index to html: MD9104-KURSE-CIA-KURS_TEIL_6-3.html
Dritter Teil:                           
Als Nächstes wird die absolute Anfangsa-
dresse eines Textes, den ich im Speicher
abgelegt habe, in  LO/HI-Darstellung  in
A/Y  geladen  und  der  Wert 0 in das X-
Register. Dies dient der  Parameterüber-
gabe  für  die  Routine "SETIT", die an-
schließend aufgerufen wird. Sie gibt den
Text, dessen Anfangsadresse in A/Y steht
aus und liest anschließend eine  Uhrzeit
ein,  die  sie  in  den Uhrregistern von
CIA1 speichert. Zuvor schreibt  sie  den
übergebenen  Wert des X-Registers in CRB
und setzt somit den Alarm- oder  Uhzeit-
Setzen-Modus. Der erste Aufruf von SETIT
setzt  die  aktuelle Uhrzeit, der zweite
die Alarmzeit.                          
Anschließend  wird  der  neue  Interrupt
eingestellt - alle IRQs werden  gesperrt
und  der  IRQ-Zeiger  des Betriebssysems
wird auf  unsere  neue  Interruptroutine
mit Namen "NEWIRQ" verbogen.            
Nun folgen zwei Schleifen, die die Spri-
tes, die wir benutzen wollen um die Uhr-
zeit auszugeben vorbereiten.  Die  erste
Schleife  kopiert  eine  Liste,  die ich
etwas weiter hinten im Source-Code abge-
legt  habe  in den Bereich von $D000 bis
$D00F. Diese Register des VIC  sind  für
die  Koordinaten  der Sprites verantwor-
lich, die nun entsprechend gesetzt sind.
Die zweite Schleife schreibt in die VIC-
Register 39 bis 46 den Wert 1, und setzt
somit  die  Farbe  für  alle Sprites auf
Weiß.                                   
Nun müssen wir die CIA1 noch darauf vor-
bereiten,   daß   Echtzeituhr-Alarm-IRQs
ausgelöst werden sollen. Dies geschieht,
indem  wir den Wert $85 in das ICR (Reg.
13) von CIA schreiben. Damit lassen  wir
zum Einen die immer noch gültigen Timer-
IRQs zu die von Timer A  erzeugt  werden
zu  (für  den  System-IRQ),  zum Anderen
haben wir mit dem Wert $85 auch noch das
2. Bit gesetzt, das Alarm-IRQs als   In-
terruptquelle  festlegt.  Bit  7 muß wie
immer gesetzt sein,  damit  die  übrigen
Bits als IRQ-Quelle übernommen werden.  
Nun müssen wir noch den SID darauf  vor-
bereiten, einen Piepton auszugeben, wenn
ein  IRQ  auftritt. Deshalb wird das HI-
Frequenzregister von  Stimme1  (Reg.  1)
mit  dem Wert $C0 geladen und eine Hüll-
kurve in Reg.  5  des  SID  geschrieben.
Register  6,  das ja ebenfalls Attribute
der Hüllkurve  angibt,  wird  nicht  neu
beschrieben, da es in der Regel den Wert
0  enthalten  sollte,  den ich dort auch
haben wollte.                           
Zum  Abschluß folgen nun noch 5 Befehle,
die den Anfang des  BASIC-Speichers  hö-
hersetzen. Dies ist erforderlich, da ich
nämlich  am  normalen Anfang die Sprites
und den  Code  von  CLOCK  untergebracht
habe.  Würden Sie nun ein BASIC-Programm
eingeben,  so  würden  Sie  CLOCK  über-
schreiben, was nicht sein sollte. In den
Adressen  $2B  und $2C hat das Betriebs-
system die Adresse des BASIC-Starts  ge-
speichert. Wir setzen diese Adressen nun
einfach auf die Endadresse von CLOCK und
rufen anschließend die Routine bei $A642
auf.  Dort  steht  die BASIC-Routine für
den Befehl "NEW".  Dies  ist  notwendig,
damit  die  neue  Anfangsadresse des BA-
SIC-Speichers  auch  vom  Betriebssystem
angenommen wird.                        
Die Initialisierungsroutine gibt nun die
IRQs wieder frei und springt zurück.    
Kommen wir zu der neuen IRQ-Routine, die
die Uhr steuert. Sie muß  zunächst  prü-
fen,  ob  der  ausgelöste  Interrupt ein
Timer-, oder ein Alarm-IRQ war  und  de-
mentsprechend  reagieren. Bei Alarm gibt
sie einen Piepton aus, bei einem  Timer-
IRQ  wird nur die aktuelle Zeit aus CIA1
ausgelesen und mit Sprites auf dem Bild-
schirm  dargestellt. Hierbei muß sie un-
terscheiden, ob die  Zeit  nun  in  24h-
oder  AM/PM-Darstellung  auf  dem  Bild-
schirm erscheinen soll. Werfen wir  doch
einfach  einmal  einen  Blick  auf diese
Routine:                                
========================================
NEWIRQ ist die IRQ-Routine von CLOCK.   
Hier wird zunächst einmal die vom Dar-  
stellungsmodus abhängige Spriteanzahl   
eingeschaltet.                          
========================================
newirq  lda #$7f       Wert für Sprites 
                       0-6 einschalten  
                       (für 24h)        
        ldx mode       Uhr-Modus prüfen.
        bne l5         ungleich 0, also 
                       24h              
        lda #$ff       Sonst AM/PM, des-
                       halb Wert für    
                       "Sprites 0-7 ein-
                       schalten" laden  
l5      sta v+21       und einschalten  
===                                     
Hier wird geprüft ob ein Alarm-IRQ (Bit2
von ICR=1) Auslöser war. Wenn ja, so wir
ein Piepton ausgegeben.                 
===                                     
        lda cia1+13    ICR auslesen     
        and #$04       Bit2 isolieren   
        beq timeref    Wenn =0, dann kei
                       Alarm und weiter 
        lda #15        Sonst Lautstärke 
        sta sid+24     einschalten      
        lda #33        Stimme 1 als "Sä-
                       gezahn"          
        sta sid+4      einschalten      
        ldx #$ff       Und warten...    
loop5   dey            (dies...         
        bne loop5      ...ist...        
        dex            ...eine...       
        bne loop5      ...Warteschleife)
        lda #00        Ton gespielt,    
                       deshalb          
        sta sid+4      Stimme1 aus      
        sta sid+24     Lautstärke aus   
========================================
Dies ist der Teil von NEWIRQ, der die   
Zeit neu ausgibt.                       
========================================
timeref ldx #43        Spriteblock "AM" 
                       in X laden       
        lda cia1+11    Stunden in Akku  
        bmi l6         Wenn 7.Bit=1 habe
                       wir "PM", dehalb 
                       weiter           
        cmp #$12       Akku=12 (in BCD)?
        bne l2         Nein, also weiter
        lda #00        12 Uhr AM gibts  
                       nicht, deshalb   
                       00 Uhr AM        
        beq l2         Unbedingter Sprun
===                                     
Hier wird hinverzweigt, wenn PM ist.    
===                                     
l6      inx            X-Reg enthält    
                       Spriteblock für  
                       "AM" - jetzt für 
                       "PM"             
        and #$7f       Bit7 (=PM) der   
                       Stunden löschen  
        ldy mode       Modus prüfen     
        beq l2         Wenn AM/PM dann  
                       weiter           
        cmp #$12       Akku = 12?       
        beq l3         Ja, dann nicht 12
                       addieren         
        sed            BCD-Mode an      
        clc            Weil PM, 12 ad-  
        adc #$12       dieren (für 24h) 
        cld            BCD-Mode aus     
l2      stx sprpoi+7   AM/PM-Sprite     
                       schalten         
========================================
Nun folgt der Teil von NEWIRQ der die   
aktuelle Zeit ausgibt.                  
========================================
l3      jsr getnum     Akkuinhalt in    
                       Spritepointer um-
                       wandeln          
        stx sprpoi+0   Sprites für Stun-
        sta sprpoi+1   den setzen       
        lda cia1+10    Minuten laden    
        jsr getnum     ...wandeln       
        stx sprpoi+2   ...und           
        sta sprpoi+3   ...setzen        
        lda cia1+9     Sekunden laden   
        jsr getnum     ...wandeln       
        stx sprpoi+4   ...und           
        sta sprpoi+5   ...setzen        
        lda cia1+8     Zehtelsek. laden 
        clc            Spritepointer der
        adc #sprbas    Ziffer 0 addiern 
        sta sprpoi+6   und setzen       
        jmp $ea31      IRQ beenden      
========================================
Zunächst  einmal möchte ich Ihnen die In
halte  und  die  Bedeutung  verschiedene
Labels in diesem Teil des Listings erläu
tern:                                   
* MODE  enthält  den Wert 3 und steht fü
  die Speicherzelle  3,  in  der  wir  j
  festgelegt  hatten  in welchem Darstel
  lungsmodus CLOCK arbeiten soll.       
* SPRPOI enthält den Wert 2040, die Basi
  sadresse der Spritepointer.  In  diese
  Pointern  wird angegeben, welcher Spri
  teblock  in  einem  Sprite  dargestell
  werden soll.                          
* SPRBAS enthät den Wert 33 und steht fü
  den ersten Spriteblock, den wir verwen
  den.  In  ihm  steht  die  Ziffer 0 al
  Sprite. Addieren wir zu einem  Wert  i
  Akku (zwischen 0 und 9) den Wert SPRBA
  hinzu,  so  erhalten wir den Zeiger au
  den Spriteblock mit der  entsprechende
  Ziffer des Wertes, den wir im Akku ste
  hen hatten.                           
* GETNUM  ist eine Routine, die eine BCD
  Zahl im Akku in die  zwei  Ziffernwert
  aufspaltet  und  SPRBAS  zu diesem Wer
  hinzuaddiert. In  X-Register  und  Akk
  werden  die  Spritepointer  der  beide
  Ziffern zurückgegeben.                
(Endgültig Schluß ist erst bei Teil     
 vier...)                               
Valid HTML 4.0 Transitional Valid CSS!