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...)