Dritter Teil:
Als Nächstes wird die absolute Anfangsadresse 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übergabe für die Routine " SETIT", die anschließ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 Alarmoder 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 Uhrzeit auszugeben vorbereiten. Die erste
Schleife kopiert eine Liste, die ich
etwas weiter hinten im Source-Code abgelegt habe in den Bereich von $ D000 bis
$ D00 F. Diese Register des VIC sind für
die Koordinaten der Sprites verantworlich, 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 vorbereiten, 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 Interruptquelle 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 vorbereiten, einen Piepton auszugeben, wenn
ein IRQ auftritt. Deshalb wird das HI-Frequenzregister von Stimme1( Reg.1) mit dem Wert $ C0 geladen und eine Hüllkurve 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 überschreiben, was nicht sein sollte. In den
Adressen $2 B und $2 C hat das Betriebssystem die Adresse des BASIC-Starts gespeichert. 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 dementsprechend 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 Bildschirm dargestellt. Hierbei muß sie unterscheiden, ob die Zeit nun in 24 hoder AM/ PM-Darstellung auf dem Bildschirm 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 umwandeln stx sprpoi+0 Sprites für Stunsta 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. . .)