3. Kernal-Funktionen
aufrufen
Nun können Sie eigene
Unterprogramme in Maschinensprache erstellen, und diese auch in BASIC benutzen.
Mit dem „Saver“ oder DATAGEN ist dies auch
ganz einfach zu bewerkstelligen. Leider müssen Sie auf die bereits bekannte
Weise das Rad immer wieder neu erfinden. Wenn Sie zum Beispiel ein Zeichen an
einer ganz bestimmten Position auf dem Bildschirm ausgeben wollen, müssen Sie
dafür immer wieder ein eigenes Unterprogramm erstellen. Und wenn Sie bedenken,
dass Sie Ihre Daten ja auch aus einer Datei holen können, dann streichen Sie
spätestens hier die Segel.
Es gibt aber noch ganz
andere Unterprogramme, nämlich die, die im Kernal-ROM
stehen. Diese können Sie genau so aufrufen, wie Ihre eigenen Unterprogramme,
nämlich mit JSR. Der Vorteil dieser fest verdrahteten Unterprogramme ist
nun, dass diese Ihnen das Leben sehr erleichtern können. So können Sie z.B.
nach dem Öffnen einer Datei eine Kernal-Funktion
aufrufen, die die Daten, die in der Datei stehen, automatisch in den Speicher
einliest, zur Not auch so, dass Ihr laufendes BASIC-Programm dadurch unberührt
bleibt. Ferner können Sie mit den Kernal-Funktionen
auch in einer einfachen Weise Zeichen von der Tastatur einlesen, oder aber auf
dem Bildschirm ausgeben. Auf diese Weise müssen Sie z.B. keine eigene CHAROUT-Routine
programmieren, sondern können einfach vorgefertigte Standardfunktionen
benutzen. Auch für das Auslesen der Tastatur gilt diese Aussage. Dies spart
nicht nur Zeit, sondern verringert auch die Wahrscheinlichkeit, dass Sie in
wichtige Funktionen Fehler einbauen, die Sie dann später aufwendig suchen müssen.
3.1 Kernal-Routinen
in eigenen Programmen einsetzen
Der Kernal,
also das Betriebssystem des C64, enthält sehr viele Subroutinen. Diese werden
sehr ausgiebig benutzt, sogar vom BASIC-Interpreter und dem Texteditor. Hierbei
liegen die Sprungadressen der Kernal-Routinen ab der
Adresse $E000 ziemlich verstreut im Speicher. Da dies sehr benutzerunfreundlich
ist, gibt es zusätzlich eine Tabelle im Speicher, die die jeweiligen JSR-Befehle
zur eigentlichen Kernal-Routine enthält, die Sie
aufrufen wollen. Der Vorteil dieser doppelt indirekten Adressierung ist,
dass Sie sich die Aufrufadressen dieser zusätzlichen Sprungtabelle besser
merken können, als die verstreut im Speicher liegenden realen Positionen der Kernal-Routinen.
Die Sprungtabelle, die
Sie sich besser merken können, als die verstreut im Speicher liegenden realen
Adressen der Kernal-Routinen beginnt an Adresse
$FF81. Da JSR-Befehle zusammen mit dem Parameter für das Sprungziel
(absolute 16-Bit-Adressen) 3 Bytes im Speicher belegen, belegt auch jede Kernal-Funktion 3 Bytes Speicher. Kommen wir nun zu einem
einfachen Programmbeispiel, das die Funktion GETIN benutzt, um eine
Taste von der Tastatur einzulesen. Wenn eine Taste gedrückt wird, dann soll das
entsprechende Zeichen an die Adresse geschrieben werden, auf die der
16-Bit-Zeiger in den Adressen 1000 und 1001 zeigt (Lo-Byte in Adresse 1000,
Hi-Byte in Adresse 1001). Damit Sie auch Zeichenketten einlesen können, wird
der Zeiger in den Adressen 1000 und 1001 immer dann um den Wert erhöht, der in
der Adresse 1003 steht, wenn der Wert in der Adresse 1002 nicht 0 ist.
06-GETCH
10
- .BA 49152
20
- .EQ GETIN=$FFE4
30
-READKEY JSR GETIN
40
- CMP #0
50
- BEQ READKEY
60
- LDX 1000
70
- STX 248
80
- LDX 1001
90
- STX 249
100
- LDY #0
110
- STA (248),Y
120
- LDA 1002
130
- CMP #0
140
- BEQ EXIT
150
- CLC
160
- LDA 1000
170 - ADC 1003
180 - STA 1000
190 - LDA 1001
200 - ADC #0
210 - STA 1001
220 -EXIT RTS
Das Assemblerprogramm GETCH
beginnt an Adresse 49152. Um den Umgang mit GETIN noch mehr zu
vereinfachen, wird in Zeile 20 ein Equate
definiert, damit Sie GETIN (dies ist die Abkürzung von „get input“) tatsächlich über den
Namen aufrufen können. So wird das eigentliche Warten auf einen Tastendruck
sehr vereinfacht, und kann in einer kurzen Warteschleife realisiert werden (Zeile
30 - 50). Diese Warteschleife ruft eigentlich nur GETIN auf. Wenn GETIN
zurückkehrt, dann befindet sich im Akkumulator immer dann der Wert 0, wenn
keine Taste gedrückt wurde. Dieser Sachverhalt wird in Zeile 40 und 50
geprüft, und wenn der bedingte Sprung (BEQ) in Zeile 50 zutrifft,
dann wurde keine Taste gedrückt, und Ihr Programm springt zurück zu Zeile 30.
Wenn allerdings eine Taste gedrückt wurde, dann landen Sie in Zeile 60.
Nun haben Sie das folgende Problem: Ihr Zeiger in Adresse 1000 und 1001 kann
nicht auf die folgende Weise benutzt werden:
STA
(1000),Y
Sie erinnern Sich?
Zeiger für die indirekte, Y-indizierte Adressierung können nur in der Zeropage stehen. Aber auch im Akkumulator steht schon ein
Wert, den Sie nicht mehr benutzen können, nämlich der Wert der gerade
gedrückten Taste (genauer: Der zu dem entsprechenden Zeichen gehörende
PETSCII-Code). Deshalb müssen Sie in Zeile 60 - 90 das X-Register
und einen Hilfszeiger benutzen, der im Zero-Page-Bereich steht (im Endeffekt
kopieren Sie die Inhalte der Adressen 1000 und 1001 in die Adressen 248 und
249). Nun können Sie in Zeile 100 und 110 die korrekte Adressierungsform
benutzen, um den Wert, den Ihnen GETIN zurückgeliefert hat, an die
richtige Zeigeradresse zu schreiben.
Nun müssen Sie
feststellen, ob in Adresse 1002 der Wert 0 steht. Wenn dies der Fall ist, dann
setzt der CMP-Befehl in Zeile 130 das Zero-Flag
auf 1, und der bedingte Sprung in Zeile 140 springt zum Label EXIT.
EXIT beendet dann Ihr Programm mit RTS. Wenn allerdings an
Adresse 1002 nicht der Wert 0 steht, dann wird Ihr Zeiger in der Adresse 1000
und 1001 um den Wert erhöht, der in Adresse 1003 steht. Hierfür müssen Sie in
den Zeilen 150 - 210 eine 16-Bit-Addition durchführen: Zunächst löschen
Sie das Carry-Flag. Anschließend addieren Sie den
Wert in Adresse 1003 zum Wert in Adresse 1000. Wenn dort ein Übertrag
geschieht, dann wird dieser bei der anschließenden Addition von 0 zu dem Wert
in Adresse 1001 mitberücksichtigt, weil Sie das Carry-Flag
hier „stehen lassen“. Nur auf diese Weise kann Ihr Zeiger in den Adressen 1000
und 1001 auch Seitengrenzen überschreiten.
Im Endeffekt haben Sie
nun schon alles beisammen, was Sie zum Umgang mit dem Kernal
benötigen. Sie wissen nun, wie man eine Kernal-Funktion
aufruft, und wie man die entsprechenden Rückgabewerte verarbeitet. Was nun noch
fehlt, ist eine Übersicht über sämtliche Kernal-Funktionen,
die entsprechenden Aufrufadressen und verwendeten Register.
3.2 Kernal-ROM-Referenz
Kommen wir nun zu den Kernal-Funktionen selbst Die Kernal-Routinen
werden durch eine Sprungtabelle verwaltet, die an der Adresse $FF81 beginnt,
und an der Adresse $FFF5 endet. Für jede Kernal-Routine
gibt es nun einen 3 Byte großen Eintrag, der einen JSR-Befehl für
jeweils eine bestimmte Routine enthält. Wenn Sie also z.B. die Funktion, die an
der Adresse $FF81 steht, mit SYS 65409 aufrufen, dann wird ein indirekter
Sprung zu der eigentlichen Routine an Adresse $FF5B ausgeführt. Zum Glück
brauchen Sie sich nicht darum zu kümmern, wo die Original-Routine steht, Sie
müssen sich aber dennoch darum kümmern, die Parameter in der richtigen Weise zu
übergeben. In Assembler brauchen Sie nur die entsprechenden Register mit den
richtigen Werten zu füllen und anschließend den richtigen JSR-Befehl
ausführen. In BASIC ist die Sache dagegen ein klein wenig komplizierter, weil
BASIC die Register A, X und Y in den Adressen 780, 781 und
782 spiegelt (in genau dieser Reihenfolge), und im Fall eines SYS-Befehls
automatisch an die entsprechende Kernal-Funktion
übergibt. Sie müssen also in diesem Fall die Adressen 780, 781 und 782 durch POKE-Anweisungen
mit den richtigen Werten füllen, bevor Sie die entsprechende Kernal-Routine mit SYS aufrufen. Die nachfolgende
Referenz erklärt nun sämtliche Kernal-Funktionen.
(Quelle: http://sta.c64.org/cbm64krnfunc.html)
3.2.1 SCINIT-Funktion
SYS-Adresse: $FF81 (65409)
Reale Adresse(n) der aufgerufenen Funktion(en):
$FF5B
Eingabeparameter: Keine
Ausgabeparameter: Keine
Veränderte Register: A, X, Y
SCINIT initialisiert
sämtliche VIC-Register mit Standardwerten und setzt sämtliche Ein- und Ausgaben
wieder auf die Standardwerte zurück. Dies bedeutet, dass wenn Sie Ihre Ein-
oder Ausgaben in eine Datei oder auf den Drucker umgeleitet haben, diese
Umleitungen auf die Tastatur und auf den Bildschirm zurückgesetzt werden. SCINIT
löscht auch den Bildschirm und reaktiviert den Timer-Interrupt, wenn dieser zuvor deaktiviert
wurde.
3.2.2 IOINIT-Funktion
SYS-Adresse: $FF84
(65412)
Reale Adresse(n) der
aufgerufenen Funktion(en): $FDA3
Eingabeparameter: Keine
Ausgabeparameter: Keine
Veränderte Register: A,
X
IOINIT initialisiert die
CIA-Chips mit Standardwerten und setzt die Lautstärke des SID auf den Wert 0
zurück. Auch der Speicher wird neu mit Standardwerten initialisiert, und der Timer-Interrupt wird wieder
eingeschaltet, wenn dieser vorher deaktiviert war. Wenn Sie zuvor die
Speicherkonfiguration geändert haben (z.B. das BASIC-ROM ausgeblendet haben,
oder eine andere Bank für den Bildschirmspeicher gewählt haben), dann werden
diese Einstellung rückgängig gemacht. Auch die Tastatur wird wieder
reaktiviert, wenn diese vorher ausgeschaltet war.
3.2.3 RAMTAS-Funktion
SYS-Adresse: $FF87 (65415)
Reale Adresse(n) der aufgerufenen Funktion(en):
$FD50
Eingabeparameter: Keine
Ausgabeparameter: Keine
Veränderte Register: A, X, Y
RAMTAS löscht die Adressen
$0002-$0101 und $0200-$03FF und führt einen internen Speichertest aus.
Ebenfalls werden die Zeiger für den Start und das Ende des BASIC-Programms neu
berechnet, und es wird dafür gesorgt, dass wieder 38.911 BASIC-Bytes frei sind. Die Startadresse des Bildschirmspeichers wird
allerdings ebenfalls auf 1024 zurückgesetzt, das heißt, wenn Sie die Lage des
Bildschirmspeichers zuvor geändert haben, wird auch diese Änderung rückgängig
gemacht.
3.2.4 RESTOR-Funktion
SYS-Adresse: $FF8A (65418)
Reale Adresse(n) der aufgerufenen Funktion(en):
$FD15
Eingabeparameter: Keine
Ausgabeparameter: Keine
Veränderte Register: Keine
RESTOR verhält sich so, als
ob Sie die RESTORE-Taste gedrückt hätten: Die Timer-Interrupt-Routine
wird zurückgesetzt, und die Adressen $0314-$0333 werden mit Standardwerten
gefüllt. Anschließend wird der Bildschirm gelöscht, und es erscheint READY.
3.2.5 VECTOR-Funktion
SYS-Adresse: $FF8D (65421)
Reale Adresse(n) der aufgerufenen Funktion(en):
$FD1A
Eingabeparameter: Start einer Vektortabelle in
Form von Lo/Hi in Register X/Y
Ausgabeparameter: Keine
Veränderte Register: A, Y
Mit VECTOR
können Sie die Zeiger in den Adressen $0314-$0333 auslesen oder neu setzten.
Dazu muss in die Indexregister die Startadresse der eigenen Vektortabelle
eingetragen werden (X=Lo-Byte, Y=Hi-Byte). Das Carry-Flag entscheidet dabei darüber, was die Routine tut. Wird
das Carry-Flag zuvor mit CLC gelöscht, wird
die benutzerdefinierte Tabelle an die Adressen $0314-$0333 geschrieben, wird
das Carry-Flag zuvor mit SEC gesetzt, werden
die Werte an den Adressen $0314-$0333 ausgelesen und in die benutzerdefinierte
Tabelle übertragen. Da Sie von BASIC aus das Carry-Flag
nicht beeinflussen können, können Sie diese Routine nicht mit SYS
aufrufen.
3.2.6 SETMSG-Funktion
SYS-Adresse: $FF90 (65424)
Reale Adresse(n) der aufgerufenen Funktion(en):
$FE18
Eingabeparameter: Switch Value im Akkumulator
SETMSG setzt den System Error
Display Switch an der Adresse $009D auf einen bestimmten Wert. Dieser Wert hat
jedoch keinen Einfluss auf BASIC, und es werden stets alle Fehlermeldungen
angezeigt, egal, was hier eintragen wird. SETMSG taucht auch in keinem
Beispiel auf, das Sie im Internet finden können, und es wird auch nicht
erklärt, welcher Wert z.B. zum Abschalten bzw. Einschalten von
System-Fehlermeldungen benutzt werden kann.
3.2.7 LSTNSA-Funktion
SYS-Adresse: $FF93 (65427)
Reale Adresse(n) der aufgerufenen Funktion(en):
$EDB9
Eingabeparameter: Sekundär-Geräte-Adresse für
den seriellen Bus
Ausgabeparameter: Keine
Veränderte Register: A
LSTNSA setzt voraus, dass Sie
zuvor ein Gerät mit LISTEN in den Empfangs-Bereitschaftsmodus versetzt
haben (das Gerät hört Ihnen nun quasi zu und wartet auf Daten). Meistens müssen
Sie dafür zunächst eine Primäradresse (das ist die Geräteadresse), aber auch
zusätzlich eine Sekundäradresse (das ist eine Art Empfangskanal) angeben. LSTNSA
legt hierbei die Sekundäradresse fest und teilt diese anschließend auch dem
Gerät mit, damit dieses weiß, auf welchem Kanal Sie Daten senden. Die
Sekundäradresse ist allerdings vom Gerät abhängig, und Sie können z.B. für
einen Drucker mit der Geräteadresse 3 nicht den gleichen Fehlerkanal mit der
Sekundäradresse 15 benutzen, wie bei Ihrer Floppy.
3.2.8 TALKSA-Funktion
SYS-Adresse: $FF96 (65430)
Reale Adresse(n) der aufgerufenen Funktion(en):
$EDC7
Eingabeparameter: Sekundär-Geräte-Adresse für
den seriellen Bus
Ausgabeparameter: Keine
Veränderte Register: A
TALKSA setzt voraus, dass Sie
zuvor ein Gerät mit TALK in den Sendemodus versetzt haben (das Gerät
sendet nun Daten, wenn es welche im Puffer hat). Meistens müssen Sie dafür
zunächst eine Primäradresse (das ist die Geräteadresse), aber auch zusätzlich
eine Sekundäradresse (das ist eine Art Empfangskanal) angeben. TALKSA
legt nun die Sekundäradresse fest und teilt diese anschließend diese auch dem
Gerät mit, damit dieses weiß, auf welchem Kanal es senden soll. Die
Sekundäradresse ist allerdings auch bei TALK vom Gerät abhängig. Beim Commodore-Bus kann übrigens nur ein Gerät senden, während
alle anderen Geräte, die nicht senden, zuhören müssen. Alle Geräte hängen hier
am gleichen Buskabel, weshalb man hier auch von einem Feldbus sprechen
kann.
3.2.9 MEMBOT-Funktion
SYS-Adresse: $FF99 (65433)
Reale Adresse(n) der aufgerufenen Funktion(en):
$FE25
Eingabeparameter: Zeiger auf den Beginn des
BASIC-Arbeitsbereichs in den Index-Registern X/Y
Ausgabeparameter: Beginn des
BASIC-Arbeitsbereichs in den Index-Registern X/Y
Veränderte Register: X, Y
BOT hat nichts mit einem
Bot wie Chatbot zu tun, sondern BOT ist die Abkürzung von „bottom“. Der BASIC-Arbeitsbereich enthält die Variablen,
Strings und Array-Elemente, die während des Programmbetriebs angelegt werden. MEMBOT
(memory bottom) setzt den
Start dieses Bereiches neu, wenn Sie vorher das Carry-Flag
mit SEC auf 1 setzen, und liest den aktuellen MEMBOT-Zeiger in
die Index-Register ein, wenn Sie vorher das Carry-Flag
mit CLC löschen. MEMBOT kann dazu benutzt werden, die Größe des
verfügbaren Speichers zu ändern. MEMBOT sollte (wie auch MEMTOP)
mit Bedacht eingesetzt werden, denn Sie können mit dieser Funktion viel Schaden
anrichten. Da Sie von BASIC aus das Carry-Flag nicht
beeinflussen können, können Sie diese Routine nicht mit SYS aufrufen.
3.2.10 MEMTOP-Funktion
SYS-Adresse: $FF9C (65436)
Reale Adresse(n) der aufgerufenen Funktion(en):
$FE34
Eingabeparameter: Zeiger auf den Beginn des
BASIC-Arbeitsbereichs in den Index-Registern X/Y
Ausgabeparameter: Beginn des
BASIC-Arbeitsbereichs in den Index-Registern X/Y
Veränderte Register: X, Y
Der
BASIC-Arbeitsbereich enthält die Variablen, Strings und Array-Elemente, die
während des Programmbetriebs angelegt werden. MEMTOP (memory top) setzt das Ende dieses Bereiches neu, wenn Sie
vorher das Carry-Flag mit SEC auf 1 setzen,
und liest den aktuellen MEMTOP-Zeiger in die Index-Register ein, wenn
Sie das Carry-Flag vorher mit CLC löschen. MEMTOP
kann dazu benutzt werden, die Größe des verfügbaren Speichers zu ändern. MEMTOP
sollte mit Bedacht eingesetzt werden, denn Sie können mit dieser Funktion viel
Schaden anrichten. Da Sie von BASIC aus das Carry-Flag
nicht beeinflussen können, können Sie diese Routine nicht mit SYS aufrufen.
3.2.11 SCNKEY-Funktion
SYS-Adresse: $FF9F (65439)
Reale Adresse(n) der aufgerufenen Funktion(en):
$EA87
Eingabeparameter: Keine
Ausgabeparameter: Keine
Veränderte Register: A, X, Y
Diese Funktion an
Adresse $EA87 wird auch immer aufgerufen, wenn ein Timer-Interrupt
auftritt, deshalb müssen Sie sich eigentlich normalerweise nicht um die Abfrage
des Keyboards kümmern. Allerdings gibt es auch Fälle, in denen Sie z.B. bei
abgeschalteten Interrupts auf eine bestimmte Taste warten müssen, und in diesem
Fall müssen Sie dann SCNKEY per Hand aufrufen. SCNKEY schreibt
nun einen eindeutigen Matrix-Code, der jeder Taste zugeordnet ist, in die
Adresse $00CB, und den aktuellen Status der beiden SHIFT-Tasten als
Flags in die Adresse $028D (ist Bit 0 gesetzt, ist die linke SHIFT-Taste
gedrückt, ist Bit 1 gesetzt, ist die rechte SHIFT-Taste gedrückt). Der
Code, den Sie benutzen müssen, um das entsprechende Zeichen auf der Tastatur in
den Bildschirmspeicher zu schreiben, landet anschließend im Tastaturpuffer, der
an der Adresse $0280 beginnt, und bis zu 10 Tasten aufnehmen kann. Beachten Sie
hier unbedingt, dass SCNKEY im Tastaturpuffer keine ASCII-Codes ablegt,
und erst BASIC dafür sorgt, dass der PETSCII-Code durch einen ASCII-Code
ersetzt wird. Wenn BASIC jedoch nicht aktiv ist, weil Sie z.B. vorher das
BASIC-ROM abgeschaltet haben, dann müssen Sie sich selbst um solche Dinge
kümmern. Viele Spiele tun genau dies, da dieses Vorgehen 100-mal schneller sein
kann, als die Standardroutinen.
3.2.12 SETTMO-Funktion
SYS-Adresse: $FFA2 (65442)
Reale Adresse(n) der aufgerufenen Funktion(en):
$FE21
Eingabeparameter: Timeout-Wert für die serielle
Schnittstelle im Akkumulator
Ausgabeparameter: Keine
Veränderte Register: Keine
SETTMO (set
timeout) legt den Timeout-Wert für die serielle
Schnittstelle in 1/60 Sekunden-Schritten fest. Das heißt, ein Timeout von 60
bedeutet, dass wenn die serielle Schnittstelle nach einer Sekunde nicht
antwortet, bzw. eine Sekunde lang kein Zeichen mehr sendet, ein Timeout-Fehler
ausgelöst wird. Normalerweise behandelt BASIC dann diesen Zustand und versucht
z.B. festzustellen, ob überhaupt noch Daten erwartet werden. Wenn dies der Fall
ist, wird von BASIC aus die Fehlermeldung DEVICE NOT PRESENT ausgegeben,
unabhängig davon, ob das entsprechende Gerät vorher schon einmal erreichbar
war.
3.2.13 IECIN-Funktion
SYS-Adresse: $FFA5 (65445)
Reale Adresse(n) der aufgerufenen Funktion(en):
$EE13
Eingabeparameter: Keine
Ausgabeparameter: Byte von der seriellen
Schnittstelle im Akkumulator
Veränderte Register: A
IECIN liest ein Byte von der
seriellen Schnittstelle und schreibt den Byte-Wert in den Akkumulator. Alle
Geräte, die an der seriellen Schnittstelle hängen, müssen vorher mit TALK
in den Sendemodus versetzt werden, und müssen auch eine sekundäre Geräteadresse
erhalten. IECIN ist eine blockierende Funktion, das heißt, sie wartet
auf jedes Byte, und muss deshalb so lange in einer Schleife aufgerufen
werden, bis alle Bytes eingelesen wurden. Erst dann kann ein eventueller
Datenpuffer an die Zieladresse kopiert werden. IECIN gibt leider keinen
Fehlerstatus zurück, und kann auch nicht feststellen, ob wirklich ein Byte
verfügbar ist. Erst, wenn ein Timeout an der seriellen Schnittstelle auftritt,
wird ein Interrupt ausgelöst, und BASIC kann dieses Timeout dann mit der
Meldung DEVICE NOT PRESENT quittieren. Leider sagt DEVICE NOT PRESENT
nichts darüber aus, woran es gelegen hat, dass kein Byte mehr empfangen werden
kann.
3.2.14 IECOUT-Funktion
SYS-Adresse: $FFA8 (65448)
Reale Adresse(n) der aufgerufenen Funktion(en):
$EDDD
Eingabeparameter: Byte-Wert im Akkumulator
Ausgabeparameter: Keine
Veränderte Register: A
IECOUT sendet ein Byte an die
serielle Schnittstelle, der Byte-Wert steht im Akkumulator. Alle Geräte, die an
der seriellen Schnittstelle hängen, müssen vorher mit LISTEN in den
Empfangsmodus versetzt werden, und müssen auch eine sekundäre Geräteadresse
erhalten. IECIN ist eine blockierende Funktion, das heißt sie wartet
bei jedem Byte darauf, dass es korrekt gesendet wurde. Manche Geräte führen
jedoch kein Handshake aus. Handshake bedeutet: Sie müssen den korrekten
Empfang eines Bytes stets bestätigen. Ein fehlendes Handshake bei vielen
Geräten ist sicherlich ein Manko, aber es gab früher viele solche Geräte, bei
denen man sich nicht sicher sein konnte, dass auch alle Bytes korrekt gesendet
wurden. Auch IECOUT selbst gibt leider keinen Fehlerstatus zurück. Erst,
wenn ein Timeout an der seriellen Schnittstelle auftritt, weil z.B. das
Handshake ausbleibt, wird ein Interrupt ausgelöst, und BASIC kann dieses
Timeout dann mit der Meldung DEVICE NOT PRESENT quittieren. Leider sagt DEVICE
NOT PRESENT nichts darüber aus, woran es gelegen hat, dass kein Byte mehr
gesendet werden kann.
3.2.15 UNTALK-Funktion
SYS-Adresse: $FFAB (65451)
Reale Adresse(n) der aufgerufenen Funktion(en):
$EDEF
Eingabeparameter: Keine
Ausgabeparameter: Keine
Veränderte Register: A
UNTALK sendet ein UNTALK-Kommando
über den Bus. Da hier der Commodore-Bus benutzt wird,
bei dem sämtliche Geräte an einer einzigen Leitung hängen, kann auch immer nur
ein einziges Gerät senden. Es ist also immer klar, welches Gerät gemeint ist,
wenn Sie UNTALK senden, Sie müssen deshalb hier keine Geräteadressen
angeben. UNTALK führt nun dazu, dass sämtliche Geräte wieder in den LISTEN-Modus
wechseln und auf die Übermittlung einer Geräteadresse warten. Wenn Sie also nun
ein anderes Gerät zum Senden von Daten auffordern wollen, müssen Sie zunächst
wieder die Kommandos TALK und TALKSA verwenden, um ein neues
Gerät auszuwählen und auch eine Sekundäradresse mitzuteilen.
3.2.16 UNLSTN-Funktion
SYS-Adresse: $FFAE (65454)
Reale Adresse(n) der aufgerufenen Funktion(en):
$EDFE
Eingabeparameter: Keine
Ausgabeparameter: Keine
Veränderte Register: A
UNLSTN sendet ein UNLISTEN-Kommando
über den Bus. Da hier der Commodore-Bus benutzt wird,
bei dem sämtliche Geräte an einer einzigen Leitung hängen, kann auch immer nur
ein einziges Gerät senden - in diesem Fall ist es der C64. Es ist also immer
klar, dass Sie selbst keine Daten mehr senden wollen, wenn Sie UNLISTEN
übermitteln, Sie müssen deshalb hier keine Geräteadressen angeben.
3.2.17 LISTEN-Funktion
SYS-Adresse: $FFB1 (65457)
Reale Adresse(n) der aufgerufenen Funktion(en):
$ED0C
Eingabeparameter: Gerätenummer
Ausgabeparameter: Keine
Veränderte Register: A
LISTEN versetzt ein Gerät,
für das Sie die Gerätenummer im Akkumulator angeben, in den LISTEN-Modus.
Dies bedeutet, dass das Gerät nun zuhört und auf die Übermittlung von Daten
wartet. Das erste Byte, dass Sie nun senden müssen, ist die Sekundäradresse,
die quasi ein spezieller Kanal ist, auf dem Sie später Daten übertragen wollen.
Deshalb müssen Sie auch direkt nach LISTEN mit LSTNSA eine
Sekundäradresse übermitteln, bevor Sie die eigentlichen Daten übertragen
können. Die Sekundäradresse, die Sie verwenden müssen, ist vom Gerät abhängig,
und muss eventuell dem Handbuch zu dem entsprechenden Gerät entnommen werden.
Bei der Floppy ist dies der Kanal 1 für Maschinenprogramme, 8 für
BASIC-Programme oder 15 für den Kommandokanal.
3.2.18 TALK-Funktion
SYS-Adresse: $FFB4 (65460)
Reale Adresse(n) der aufgerufenen Funktion(en):
$ED09
Eingabeparameter: Gerätenummer
Ausgabeparameter: Keine
Veränderte Register: A
TALK versetzt ein Gerät,
für das Sie die Gerätenummer im Akkumulator angeben, in den TALK-Modus.
Dies bedeutet, dass das Gerät nun bereit ist, Daten zu senden. Bevor dies aber
geschehen kann, müssen Sie noch zusätzlich die Sekundäradresse mit TALKSA
übermitteln. Die Sekundäradresse ist quasi ein spezieller Kanal, auf dem Sie
später die Daten abholen wollen. Die Sekundäradresse, die Sie verwenden müssen,
ist vom Gerät abhängig, und muss eventuell dem Handbuch zu dem entsprechenden
Gerät entnommen werden. Meistens ist es auch nötig, mehrmals zwischen LISTEN
und TALK hin und her zu wechseln, weil die meisten Geräte (z.B. die Floppystation) erst Daten senden, wenn Sie das
entsprechende Kommando hierfür übertragen haben.
3.2.19 READST-Funktion
SYS-Adresse: $FFB7 (65463)
Reale Adresse(n) der aufgerufenen Funktion(en):
$FE07
Eingabeparameter: Keine
Ausgabeparameter: Gerätestatus-Byte im
Akkumulator
Veränderte Register: A
READST ist eigentlich eine
Funktion, die nur das Kommando GETST (get status) über den Bus sendet - und zwar an das Gerät, dass
Sie zuletzt adressiert haben. Jedes Gerät muss in jedem Modus das GETST-Byte
(Byte-Wert $FF) akzeptieren, egal, ob dies gerade im LISTEN-Modus
oder im TALK-Modus arbeitet. Wenn ein Gerät GETST empfängt, muss
dieses sofort ein Status-Byte zurücksenden, das READST danach im
Akkumulator ablegt. Einige Geräte, wie z.B. Modems, die das RS232-Protokoll
verwenden, unterstützen keine Geräte-Status-Bytes, deshalb wird in diesem Fall
der Wert $00 in den Akkumulator geladen. Der Wert $00 bedeutet stets, dass
alles okay ist, selbst bei der Floppy-Station, die Status-Bytes unterstützt,
ist dies so. Allerdings ist die Bedeutung der Status-Byte auch teilweise
geräteabhängig, weshalb hier unbedingt das entsprechende Handbuch zu Rate
gezogen werden sollte.
3.2.20 SETLFS-Funktion
SYS-Adresse: $FFBA (65466)
Reale Adresse(n) der aufgerufenen Funktion(en):
$FE07
Eingabeparameter: A=logische Dateinummer,
X=Gerätenummer, Y=Sekundäradresse
Ausgabeparameter: Keine
Veränderte Register: A, X, Y
SETLFS legt die Parameter
einer Datei fest, die Sie später mit OPEN öffnen wollen. SETLFS
arbeitet nur zusammen mit Kassettenlaufwerken (Geräteadresse 1) und Floppy-Stationen
(Geräteadressen 8, 9, 10, 11), und nicht mit Druckern oder Modems. Auch manche
Festplattenlaufwerke werden unterstützt, aber nur die, die auch
Standard-Floppy-Kommandos verstehen. SETLFS wird auch zuerst von BASIC
aus aufgerufen, wenn Sie OPEN verwenden. Z.B. wird bei dem Befehl
OPEN
1,8,1,"TEST"
SETLFS mit den Parametern A=1
(logische Dateinummer 1), X=8 (Gerätenummer 8), Y=1
(Sekundäradresse 1) aufgerufen. Dies führt dann dazu, dass die Floppy mit der
Geräteadresse 8 an die Sekundäradresse 1 gebunden wird. Der Dateiname wird
allerdings separat durch SETNAM festgelegt, erst danach können Sie OPEN
aufrufen.
3.2.21 SETNAM-Funktion
SYS-Adresse: $FFBD (65469)
Reale Adresse(n) der aufgerufenen Funktion(en):
$FDF9
Eingabeparameter: A=Länge des Dateinamens,
X/Y=Zeiger auf den Dateiname-String
Ausgabeparameter: Keine
Veränderte Register: A, X, Y
SETNAM legt für die Datei
einen Dateinamen fest, für die Sie die Parameter vorher mit SETLFS
festgelegt haben. Die Länge des Dateinamens müssen Sie im Akkumulator angeben,
und den Zeiger auf die Adresse, an der der String mit dem Dateinamen beginnt,
müssen Sie in der Form X=Lo-Byte, Y=Hi-Byte angeben. Sie dürfen
hier allerdings keine PETSCII-Zeichen in Ihrem Dateinamen verwenden, sondern
müssen ASCII-Codes benutzen. Dies ist der einzige Code, den Floppys und
Kassettenlaufwerke verstehen.
3.2.22 OPEN-Funktion
SYS-Adresse: $FFC0 (65472)
Reale Adresse(n) der aufgerufenen Funktion(en):
$031A, $F34A
Eingabeparameter: Keine
Ausgabeparameter: Keine
Veränderte Register: A, X, Y
OPEN öffnet die Datei, die
Sie vorher durch SETLFS und SETNAM definiert haben. OPEN
gibt keine Parameter zurück, und nimmt auch keine entgegen, da vorher
detailliert festgelegt wurde, welches Gerät nun die Kommandos bzw. Daten
empfangen soll. Allerdings legt OPEN einen internen Puffer für sämtliche
Dateiparameter an, und ordnet diesen Parametern auch die logische Dateinummer
zu, die Sie bei SETLFS angegeben haben.
3.2.23 CLOSE-Funktion
SYS-Adresse: $FFC3 (65475)
Reale Adresse(n) der aufgerufenen Funktion(en):
$031C, $F291
Eingabeparameter: Logische Dateinummer im
Akkumulator
Ausgabeparameter: Keine
Veränderte Register: A, X, Y
CLOSE schließt die Datei,
die Sie durch die logische Dateinummer im Akkumulator angeben. OPEN legt
einen internen Puffer für sämtliche Dateiparameter an, und ordnet diesen
Parametern auch die logische Dateinummer zu, die Sie vorher mittels SETLFS
angegeben haben. CLOSE gibt die Dateiparameter für eine geschlossene
Datei wieder frei. Das bedeutet, dass die freigewordene logische Dateinummer
wieder für andere Dateien benutzt werden kann. Da die Anzahl der verfügbaren
Dateinummern begrenzt ist, sollten Dateien stets wieder geschlossen werden,
nachdem die Arbeit an ihnen beendet wurde.
3.2.24 CHKIN-Funktion
SYS-Adresse: $FFC6 (65478)
Reale Adresse(n) der aufgerufenen Funktion(en):
$031E, $F20E
Eingabeparameter: Logische Dateinummer im
X-Register
Ausgabeparameter: Keine
Veränderte Register: A, X
CHKIN (change
keyboard input) leitet
sämtliche Tastatureingaben in eine Datei um. Die logische Dateinummer, in die
die Eingaben umgeleitet werden, befindet sich vorher im X-Register.
Diese Datei wird dann als das sogenannte Default Input File ausgewählt,
und sämtliche Bytes, die Sie anschließend mit CHRIN (siehe auch dort)
einlesen, werden in das Default Input File umgeleitet.
3.2.25 CHKOUT-Funktion
SYS-Adresse: $FFC9
(65481)
Reale Adresse(n) der
aufgerufenen Funktion(en): $0320, $F250
Eingabeparameter:
Logische Dateinummer im X-Register
Ausgabeparameter: Keine
Veränderte Register: A,
X
CHKOUT (change
output) leitet sämtliche Bildschirmausgaben in eine
Datei um, die logische Dateinummer, in die die Ausgaben umgeleitet werden,
befindet sich vorher im X-Register. Diese Datei wird dann als das
sogenannte Default Output File ausgewählt, und sämtliche Bytes, die Sie
anschließend mit CHROUT (siehe auch dort) ausgeben, werden in das
Default Output File umgeleitet. So können Sie z.B. in einfacher Weise ein Screenshoot als Datei speichern, Sie müssen nur die Zeichen
auf dem Bildschirm auslesen und per CHROUT in eine vorher mit CHKOUT
ausgewählte Datei schreiben.
3.2.26 CLRCHN-Funktion
SYS-Adresse: $FFCC (65484)
Reale Adresse(n) der aufgerufenen Funktion(en):
$0322, $F333
Eingabeparameter: Keine
Ausgabeparameter: Keine
Veränderte Register: A, X
CLRCHN (clear
channels) setzt die umgeleitete Ein- und Ausgabe auf
die Standardwerte zurück, deshalb benötigt CLRCHN keine zusätzlichen
Parameter. Die Standardeingabe ist nach Aufruf von CLRCHN die Tastatur,
die Standardausgabe der Bildschirm.
3.2.27 CHRIN-Funktion
SYS-Adresse: $FFCF (65487)
Reale Adresse(n) der aufgerufenen Funktion(en):
$0324, $F157
Eingabeparameter: Keine
Ausgabeparameter: Zeichen von der Tastatur im
Akkumulator
Veränderte Register: A, Y
CHRIN (character
input) liest ein Zeichen von der Standard-Eingabe ein
und speichert dies im Akkumulator. Für den Fall, dass die Standard-Eingabe die
Tastatur ist, wird jedoch eine ganze Zeile eingelesen, bis Sie RETURN
drücken (nur das letzte Zeichen in der Zeile landet in diesem Fall im
Akkumulator).
3.2.28 CHROUT-Funktion
SYS-Adresse: $FFD2 (65490)
Reale Adresse(n) der aufgerufenen Funktion(en):
$0324, $F157
Eingabeparameter: Zu schreibendes Zeichen
Ausgabeparameter: Keine
Veränderte Register: Keine
CHROUT (character
output) schreibt ein Zeichen als Byte auf die
Standard-Ausgabe, der Byte-Wert befindet sich im Akkumulator. Für den Fall,
dass die Standard-Ausgabe der Bildschirm ist, wird das entsprechende Zeichen,
das dem Zeichen mit dem ASCII-Code im Akkumulator entspricht, an der
aktuellen Cursorposition ausgegeben. Wenn die Standard-Ausgabe umgeleitet
wurde, wird das Byte in die entsprechende Datei geschrieben (siehe auch CHKOUT).
3.2.29 LOAD-Funktion
SYS-Adresse: $FFD5 (65493)
Reale Adresse(n) der aufgerufenen Funktion(en):
$F49E
Eingabeparameter: A=Flags, X/Y=Ladeadresse in
Form von Lo- und Hi-Byte
Ausgabeparameter: Fehlerstatus im Carry-Flag
Veränderte Register: A, X, Y
LOAD lädt eine Datei in den
Speicher und setzt das Carry-Flag auf 1, wenn ein
Fehler aufgetreten ist (natürlich muss diese Datei vorher mit OPEN
geöffnet werden). Nur, wenn im Akkumulator der Wert 0 übergeben wird, wird eine
Datei auch geladen, ein anderer Wert als 0 bedeutet, dass ein Verify ausgeführt wird. Verify
heißt, dass der Inhalt der Datei mit dem Puffer verglichen wird, auf die der
Zeiger in den Registern X und Y zeigt (X=Lo-Byte, Y=Hi-Byte).
Wenn der Inhalt der Datei mit dem Puffer übereinstimmt, dann wird das Carry-Flag gesetzt, und der Zeiger in den Registern X und Y
zeigt danach auf das letzte Byte, das korrekt ist. Im Fehlerfall wird stets
eine Fehlernummer im Akkumulator übergeben (siehe auch Abschnitt Kernal-Fehler).
Wenn im Akkumulator 0
übergeben wird, dann wird die Datei in den Speicher geladen. Normalerweise geben
hier die ersten 2 Bytes in der Datei die Startadresse in Form eines Lo- und
Hi-Bytes an, es sei denn, die Sekundäradresse wird auf 0 gesetzt. In diesem
Fall können Sie selbst entscheiden (durch einen Zeiger in den Registern X
und Y), an welche Stelle Ihr Programm geladen wird. BASIC benutzt diese
Konstruktion immer dann, wenn Sie eine Datei mit ,8 und nicht mit ,8,1
laden. In diesem Fall wird ein neues BASIC-Programm an die Adresse 2049
geladen.
3.2.30 SAVE-Funktion
SYS-Adresse: $FFD8 (65496)
Reale Adresse(n) der aufgerufenen Funktion(en):
$F5DD
Eingabeparameter: A=Zeropage-Zeiger,
X/Y=Endadresse in Form von Lo- und Hi-Byte
Ausgabeparameter: Fehlerstatus im Carry-Flag
Veränderte Register: A, X, Y
SAVE speichert einen
Speicherbereich in einer Datei (natürlich muss die Datei vorher mit OPEN
geöffnet worden sein). Anders, als bei LOAD, müssen hier zwei Zeiger
angegeben werden. Deshalb befindet sich nur der Zeiger auf das letzte Byte des
Speicherblocks in den Index-Registern, und Sie müssen im Akkumulator zusätzlich
einen Zeropage-Zeiger übergeben, der auf die Startadresse des Speicherblocks
zeigt. Dieser Zeropage-Zeiger wird dann später mittels Y-indizierter indirekter
Adressierung dazu benutzt, das aktuelle Byte, das Sie in die Datei schreiben
wollen, auszulesen. Im Fehlerfall wird das Carry-Flag
gesetzt, und im Akkumulator befindet sich eine Fehlernummer (siehe auch
Abschnitt Kernal-Fehler).
3.2.31 SETTIM-Funktion
SYS-Adresse: $FFDB (65499)
Reale Adresse(n) der aufgerufenen Funktion(en):
$F6E4
Eingabeparameter: A/X/Y=Neuer Wert der Uhr
(Time of day)
Ausgabeparameter: Keine
Veränderte Register: A, X, Y
SETTIM schreibt einen
Zeitwert in die Adressen 160-162 ($00A0-$00A2), die die BASIC-Uhr dann in der
Variablen TI ablegt. In Adresse 160 wird der Wert aus dem Akkumulator,
in Adresse 161 der Wert aus dem X-Register, und in Adresse 162 der Wert
aus dem Y-Register eingetragen. Zusammengenommen hat die Uhr also einen
Wert von 3 Bytes, dieser wird jedoch nicht etwa jede 1/100 Sekunde oder jede
Sekunde erhöht, sondern in Einheiten von 1/60 Sekunden. Auch ist der Zeitzähler
ein einfacher Zähler, deshalb läuft auch der Wert in der Adresse 160 nicht nach
60 Zählerschritten über, sondern erst nach 256. Sie müssen also, wenn Sie eine
bestimmte Uhrzeit hier eintragen wollen, diese in 1/60 Sekunden-Intervalle
umrechnen.
3.2.32 RDTIM-Funktion
SYS-Adresse: $FFDE (65502)
Reale Adresse(n) der aufgerufenen Funktion(en):
$F6DD
Eingabeparameter: Keine
Ausgabeparameter: Neuer Wert der Uhr (Time of day) in A/X/Y
Veränderte Register: A, X, Y
RDTIM liest den aktuellen
Zeitwert der Uhr in die Adressen 160-162 ($00A0-$00A2) ein, die die BASIC-Uhr
auch so in der Variablen TI ablegt. Im Akkumulator wird der Wert aus der
Adresse 160 eingetragen, in das X-Register wird der Wert aus der Adresse
161 eingetragen, und in das Y-Register der Wert aus der Adresse 162.
Zusammengenommen hat die Uhr also einen Wert von 3 Bytes, dieser wird jedoch
nicht etwa jede 1/100 Sekunde oder jede Sekunde erhöht, sondern in Einheiten
von 1/60 Sekunden. Auch ist der Zeitzähler ein einfacher Zähler, deshalb läuft
auch der Wert in der Adresse 160 nicht nach 60 Zählerschritten über, sondern
erst nach 256. Sie müssen also, wenn Sie den Zählerstand auslesen und die
aktuelle Uhrzeit erhalten wollen, diese von 1/60 Sekunden-Intervallen in eine
reale Uhrzeit umrechnen. Allerdings benötigen Sie Zusatzhardware mit einem
batteriegetriebenen Pufferspeicher, wenn Ihre Uhr auch bei ausgeschaltetem
Computer weiterlaufen soll.
3.2.33 STOP-Funktion
SYS-Adresse: $FFE1 (65505)
Reale Adresse(n) der aufgerufenen Funktion(en):
$0328, $F6ED
Eingabeparameter: Keine
Ausgabeparameter: Zero-Flag
mit dem Status der STOP-Taste
Veränderte Register: A, X
STOP fragt ab, ob die RUN/STOP-Taste
gedrückt ist, und wenn dies der Fall ist, dann wird das Zero-Flag gesetzt und der Keyboard-Puffer gelöscht. Natürlich
werden auf diese Weise auch sämtliche eventuellen Umleitungen von Eingaben in
eine Datei zurückgesetzt. Von BASIC aus können Sie diese Funktion allerdings
nicht verwenden, weil dort die RUN/STOP-Taste die Funktion hat, ein
laufendes Programm zu unterbrechen. In vielen Spielen wird jedoch die RUN/STOP-Taste
umprogrammiert bzw. deaktiviert, damit Sie z.B. nachdem das Spiel gestartet
wurde, kein Speicherabbild mehr auf Diskette erstellen können (dies ist eine
der Methoden, mit denen sich einige alten Spiele knacken lassen). Zusammen mit
der Deaktivierung der RUN/STOP-Taste wird bei moderneren Spielen auch
zusätzlich der Reset-Interrupt
umgebogen, was dann dazu führt, dass das Spiel nach Betätigung des Reset-Schalters einfach neu startet, und Sie auch in diesem
Fall kein Speicherabbild mehr erstellen können. Viele modernen Spiele führen
auch direkt nach dem Start aufwendige Initialisierungen des Speichers durch,
ohne die Sie das Spiel nicht starten können. Die Verhinderung, nach dem Start
ein Speicherabbild erstellen zu können, ist deswegen ein essentieller
Bestandteil von Kopierschützen.
3.2.34 GETIN-Funktion
SYS-Adresse: $FFE4 (65508)
Reale Adresse(n) der aufgerufenen Funktion(en):
$032A, $F13E
Eingabeparameter: Keine
Ausgabeparameter: Gelesenes Byte von der
Standardeingabe im Akkumulator
Veränderte Register: A, X, Y
Normalerweise ist die
Standardeingabe die Tastatur, es sei denn, es wurde vorher OPEN (siehe
auch dort) und anschließend CHKIN (siehe auch dort) aufgerufen, um die
Standardeingabe z.B. in eine Datei umzuleiten. GETIN (get
input) liest immer einzelne Bytes in den Akkumulator
ein, bei Dateien können auch Kernal-Fehler (siehe
auch dort) auftreten, z.B. wenn das Dateiende erreicht ist. Eingaben von der
Tastatur liefern den Wert 0 zurück, wenn keine Taste gedrückt wurde. Leider
liefert GETIN für die Tastatur keine ASCII-Werte zurück, diese Wandlung
von PET in ASCII ist eine interne Funktion, die BASIC im Falle der GET-Funktion
ausführt.
3.2.35 CLALL-Funktion
SYS-Adresse: $FFE7 (65511)
Reale Adresse(n) der aufgerufenen Funktion(en):
$032C, $F32F
Eingabeparameter: Keine
Ausgabeparameter: Keine
Veränderte Register: A, X
CLALL (clear
all files) schließt sämtliche Dateien, und stellt
anschließend die Standardeingabe wieder auf die Tastatur um. Sämtliche
Umleitungen werden also durch CLALL ungültig, und sämtliche vorher
geöffneten Dateien werden geschlossen, sodass Sie auch keine Daten mehr aus den
entsprechenden Dateien lesen können.
3.2.36 UDTIM-Funktion
SYS-Adresse: FFEA
(65514)
Reale Adresse(n) der
aufgerufenen Funktion(en): $F69B
Eingabeparameter: Keine
Ausgabeparameter: Keine
Veränderte Register: A,
X
UDTIM aktualisiert den
Zeitwert in den Adressen 160-162 ($00A0-$00A2), die die BASIC-Uhr dann in der
Variablen TI ablegt. Zusammengenommen hat die Uhr einen Wert von 3
Bytes, dieser wird jedoch nicht etwa jede 1/100 Sekunde oder jede Sekunde
erhöht, sondern in Einheiten von 1/60 Sekunden. Auch ist der Zeitzähler ein
einfacher Zähler, deshalb läuft auch der Wert in der Adresse 160 nicht nach 60
Zählerschritten über, sondern erst nach 256. UDTIM aktualisiert nun
diesen Zeitzähler, und muss deshalb periodisch aufgerufen werden. Normalerweise
erledigen dies die Timer-Interrupt-Routinen
automatisch. Wenn Sie aber z.B. das BASIC-ROM abgeschaltet oder die
Interrupt-Routinen verändert haben, dann müssen Sie UDTIM manuell
aufrufen, um die Uhr zu aktualisieren.
3.2.37 SCREEN-Funktion
SYS-Adresse: FFED (65517)
Reale Adresse(n) der aufgerufenen Funktion(en):
$E505
Eingabeparameter: Keine
Ausgabeparameter: X=Anzahl der
Bildschirmspalten, Y=Anzahl der Bildschirmzeilen
Veränderte Register: X, Y
SCREEN gibt beim C64 stets
den Wert 40 im X-Register, und den Wert 25 im Y-Register zurück.
Andere Commodore-Systeme tragen dort jedoch auch
andere Werte ein. So gibt es z.B. beim Plus 4 oder beim C128 einen Grafikmodus
mit 40 und einen Grafikmodus mit 80 Spalten.
3.2.38 PLOT-Funktion
SYS-Adresse: FFF0 (65520)
Reale Adresse(n) der aufgerufenen Funktion(en):
$E50A
Eingabeparameter: Auszuführende Operation im
Carry-Flag
Ausgabeparameter: Je nach Operation
Veränderte Register: X, Y
PLOT ist wohl die Funktion,
die die meisten Benutzer verwirrt, weil PLOT keine Pixel auf dem
Bildschirm ausgibt, wie dies manche PLOT-Varianten auf anderen Systemen
(z.B. dem Atari ST) tun. Auf dem C64 ist PLOT dafür da, den Cursor zu
positionieren. Hierzu wird das Carry-Flag mit SEC
auf 1 gesetzt, und anschließend wird PLOT aufgerufen. Die zu setzende
Cursor-Spalte befindet sich hierbei im X-Register, die zu setzende
Cursor-Spalte im Y-Register. Wenn dagegen mit PLOT die aktuelle
Cursorposition bestimmt werden soll, muss vor dem Aufruf das Carry-Flag mit CLC auf 0 gesetzt werden. In diesem Fall
wird dann die aktuelle Cursor-Position in die Register X und Y
übertragen. Bedenken Sie an dieser Stelle, dass Sie in BASIC keinen Einfluss
auf das Carry-Flag haben, und deswegen auch dort PLOT
nicht verwenden können.
3.2.39 IOBASE-Funktion
SYS-Adresse: FFF3 (65523)
Reale Adresse(n) der aufgerufenen Funktion(en):
$E500
Eingabeparameter: Keine
Ausgabeparameter: Zeiger auf die Basisadresse
von CIA-Chip 1 in Register X/Y
Veränderte Register: X, Y
IOBAE liefert auf dem C64
stets die Adresse $DC00 zurück, weil die Basisadresse der CIA-Chips nicht auf
die Art und Weise verändert werden kann, wie z.B. die Lage des
Bildschirmspeichers oder der Zeichentabelle. Es gibt jedoch Nachfolger des CIA,
bei denen die Basisadresse durchaus verändert werden kann, z.B. beim Commodore Plus 4 oder auch beim Amiga.