Ultimate Commodore 64 Reference

6502 KERNAL API ROM Disassembly Memory Map Charset · PETSCII · Keyboard pagetable.com

C64 KERNAL API

by Michael Steil, github.com/mist64/c64ref. Revision 6ce14d7, 2022-01-23

This allows you to view different commentaries side-by-side. You can enable/disable individual columns:

Programmer's Reference GuideCommodore 64 Programmer's Reference Guide, ISBN 0-672-22056-3
Tool KitCOMPUTE!'s VIC-20 and Commodore 64 Tool Kit: Kernal by Dan Heeb, ISBN 0942386337
Machine Language RoutinesMachine Language Routines for the Commodore 64 and 128 by Todd D Heimarck and Patrick Parrish, ISBN 0874550858
Mapping the Commodore 64Mapping the Commodore 64 by Sheldon Leemon, ISBN 0-942386-23-X
Commodore 128 intern [German]Commodore 128 intern by Jörg Schieb, Frank Thrun and Heinz Wrobel, ISBN 3-89011-098-3
Lee DavisonThe almost completely commented C64 ROM disassembly by Lee Davison
Cracking The KernalCracking The Kernal by Peter Marcotty in COMPUTE! #40, September 1983, pp. 268-274
Craig TaylorKernal 64 / 128 by Craig Taylor in C= Hacking, Volume 1, Issue 3; July 15, 1992
Joe Forster/STACommodore 64 standard KERNAL functions by Joe Forster/STA
Frank KontrosC64 KERNAL jump table by Frank Kontros
64 intern [German]Das neue Commodore-64-intern-Buch by Baloui, Brückmann, Englisch, Felt, Gelfand, Gerits and Krsnik, ISBN 3890113079


Address Symbol Category Decimal Programmer's Reference Guide Tool Kit Machine Language Routines Mapping the Commodore 64 Commodore 128 intern [German] Lee Davison Cracking The Kernal Craig Taylor Joe Forster/STA Frank Kontros 64 intern [German]
$FF81 CINT EDITOR1) 65409
Initialize screen editor & 6567 video chip
  • Communication registers: None
  • Preparatory routines: None
  • Error returns: None
  • Stack requirements: 4
  • Registers affected: A, X, Y

Description: This routine sets up the 6567 video controller chip in the Commodore 64 for normal operation. The KERNAL screen editor is also initialized. This routine should be called by a Commodore 64 program cartridge.

How to Use:

  1. Call this routine.

EXAMPLE:

     JSR CINT
     JMP RUN       ;BEGIN EXECUTION
Initialize screen editor

Called by: None.

JMP FF5B to initialize the VIC-II (6567) chip registers, clear the screen, set the cursor pointer, initialize the screen line link table, set the PAL/NTSC flag, set value for CIA #1 timer A, enable interrupts for CIA #1 timer A, and start timer A.

This Kernal jump instruction is only available on the 64. The nearest equivalent on the VIC is to JSR E518 to set the VIC (6560-6561) chip registers, clear the screen, set the cursor pointers, and initialize the screen line link table. The 6560 and 6561 chips are, respectively, the NTSC and PAL versions of the VIC's video chip. The VIC equivalent of CINT for enabling the IRQ timer interrupt is to JMP FE39 to enable VIA #2 timer 1 interrupts and to set a timer 1 value.

Thus, a VIC version might be something like this:

JMP 02A1 02A1 JSR E518 02A4 JSR FE39 02A7 RTS

CINT, or its VIC equivalent, is only needed if you write an autostart cartridge program and need to use the screen editor or IRQ timer A/timer 1 interrupts. If no autostart cartridge exists, the 64/VIC performs the actions in CINT during system reset.

CINT

This routine initializes all RAM locations used by the screen editor, returning screen memory to its default position and setting default screen and border colors. The routine also clears the screen and homes the cursor. All processor registers are affected.

For the 64 only, this routine initializes all VIC chip registers to their default values (that's done during the Kernal IOINIT routine in the 128). For the 128, CINT clears both displays and redirects printing to the display indicated by the position of the 40/80 DISPLAY key. The 128 routine also sets SID volume to zero and resets programmable function keys to their default definitions. It does not, however, reinitialize the 80-column character set. (That's also part of IOINIT.)

Initialize Screen Editor and VIC-II Chip

The start of the routine appears to be a patch that was added to later versions of the Kernal. It first calls the old routine at 58648 ($E518). This initializes the VIC-II chip to the default values, sets the keyboard as the input device and the screen as the output device, initializes the cursor flash variables, builds the screen line link table, clears the screen, and homes the cursor. The new code then checks the VIC Interrupt register to see if the conditions for a Raster Compare IRQ have been fulfilled. Since the Raster Register was initialized to 311, that can only occur when using a PAL system (NTSC screens do not have that many scan lines). The PAL/NTSC register at 678 ($2A6) is set on the basis of the outcome of this test. The CIA #1 Timer A is then set to cause an IRQ interrupt every sixtieth of a second, using the prescaler figures for a PAL or NTSC system, as appropriate.

Video-Controller und Editor initialisieren

Es werden die Funktionstasten auf Standard gelegt, beide Video-Controller initialisiert und der 40/80-Zeichen-Modus in Abhängigkeit der 40/80-Zeichen-Taste eingeschaltet. Weiterhin werden der Tastaturbuffer gelöscht sowie alle Flags rückgesetzt und ein CLRCH ausgeführt.

initialise VIC and screen editor
Initialize screen editor.

CINT resets the 6567 video controller chip and the screen editor.

;Reset the 6567 chip and the 6566 VIC chip.
     JSR CINT
     RTS
;Basically, just like pressing the STOP and RESTORE keys.
Setup VIC, screen values, (128: 8563)...
 Registers In  : None.
 Registers Out : None.
 Memory Changed: Screen Editor Locations.
Initialize VIC; restore default input/output to keyboard/screen; clear screen; set PAL/NTSC switch and interrupt timer.

Input: – Output: – Used registers: A, X, Y. Real address: $FF5B.

init VIC & screen editor
                                       - - -  - - -  A X Y
Video-Reset
$FF84 IOINIT SYS1) 65412
Initialize I/O devices
  • Communication registers: None
  • Preparatory routines: None
  • Error returns:
  • Stack requirements: None
  • Registers affected: A, X, Y

Description: This routine initializes all input/output devices and routines. It is normally called as part of the initialization procedure of a Commodore 64 program cartridge.

EXAMPLE:

     JSR IOINIT
Initialize I/O devices

Called by: None.

JMP FDA3 to initialize the CIA registers, the 6510 I/O data registers, the SID chip registers, start CIA #1 timer A, enable CIA #1 timer A interrupts, and set the serial clock output line high.

The closest equivalent to this routine on the VIC is JMP FDF9 to initialize the 6522 registers, set VIA #2 timer 1 value, start timer 1, and enable timer 1 interrupts.

Since these routines are called during system reset, the main use for IOINIT is for an autostart cartridge that wants to use the same I/O settings that the Kernal normally uses.

IOINIT

This routine initializes the CIA chips' registers to their default values, along with related RAM locations. All processor registers are affected. For the 128, the routine also initiatizes the VIC and VDC chip registers (a step which is part of the Kernal CINT routine on the 64). In addition, the 128 routine sets all SID chip registers to zero and calls the Kernal DLCHR routine to initiahze the character set for the 80-column chip.

Initialize CIA I/O Devices

This routine intializes the Complex Interface Adapter (CIA) devices, and turns the volume of the SID chip off. As part of this initialization, it sets CIA #1 Timer A to cause an IRQ interrupt every sixtieth of a second.

Initialisierung der Ein/Ausgabegeräte

Die Ein/Ausgabegeräte werden initialisiert, d.h. die RESET-Leitung auf dem IEC-Bus wird aktiviert. Angeschlossene Drucker werden in den Anfangszustand versetzt und die Floppy löscht ihre Kanäle - hört sich also an, als ob sie gerade eingeschaltet worden wäre.

initialise SID, CIA and IRQ, unused
Initialize input/output.

IOINIT initializes all I/O devices and routines. It is part of the system's powering-up routine.

;Initialize all I/O devices.
     JSR IOINIT
     RTS
;All registers are altered.
Initializes pertinant display and i/o devices
 Registers In  : C64: None. | C128: $0A04/bit 7
                            |          0 - Full Setup.
                            |          1 - Partial Setup. (no 8563 char)
 Registers Out : .A, .X, .Y destroyed.
 Memory Changed: CIA's, VIC, 8502 port, (C128: also optionally 8563).
 Note          : This routine automatically distinguishes a PAL system from a
                 NTSC system and sets PALCNT accordingly for use in the
                 time routines.
Initialize CIA's, SID volume; setup memory configuration; set and start interrupt timer.

Input: – Output: – Used registers: A, X. Real address: $FDA3.

initialize CIA & IRQ
                                       - - -  - - -  A X Y
CIAs initialisieren
$FF87 RAMTAS MEM1) 65415
Perform RAM test
  • Communication registers: A, X, Y
  • Preparatory routines: None
  • Error returns: None
  • Stack requirements: 2
  • Registers affected: A, X, Y

Description: This routine is used to test RAM and set the top and bottom of memory pointers accordingly. It also clears locations $00 to $0101 and $0200 to $03FF. It also allocates the cassette buffer, and sets the screen base to $0400. Normally, this routine is called as part of the initialization process of a Commodore 64 program cartridge.

EXAMPLE:

     JSR RAMTAS
Memory initialization

Called by: None.

JMP FD50 to the Initialize Memory Pointers routine on the 64.

At FD50 the routine stores $00 in locations 02-0101 and 0200-03FF; sets the pointer to the tape buffer, (B2), to 033C; sets the pointer to the end of RAM + 1 in (0283), sets the pointer to the start of RAM in (0281), sets the screen memory page to $04.

Although the VIC does not have a RAMTAS Kernal vector, the corresponding operation on the VIC is done by JMP FD8D. At FD8D the routine stores $00 in 00-FF and 0200-03FF; sets pointer to tape buffer, (B2), to 033C; sets the pointer to the end of RAM + 1 in (0283); sets the pointer to the start of RAM in (0281); sets the screen memory page to $1E or $10 depending on where RAM ends.

The RAMTAS routine would mainly be used by an autostart cartridge since the RAMTAS functions are normally executed during system reset.

RAMTAS

This routine clears zero-page RAM (locations $02-$FF) and initializes Kernal memory pointers in zero page. For the 64 only, the routine also clears pages 2 and 3 (locations $0200-$03FF), tests all RAM locations from $0400 upwards until ROM is encountered, and sets the top-of-memory pointer. For the 128, the routine sets the BASIC restart vector ($0A00) to point to BASIC's cold-start entry address, $4000.

Perform RAM Test and Set Pointers to the Top and Bottom of RAM

This routine performs a number of initialization tasks.

First, it clears Pages 0, 2, and 3 of memory to zeros. Next, it sets the tape buffer pointer to address 828 ($33C), and performs a nondestructive test of RAM from 1024 ($400) up. When it reaches a non-RAM address (presumably the BASIC ROM at 40960 ($A000)), that address is placed in the top of memory pointer at 643-4 ($283-4). The bottom of memory pointer at 641-2 ($281-2) is set to point to address 2048 ($800), which is the beginning of BASIC program text. Finally, the pointer to screen memory at 648 ($288) is set to 4, which lets the Operating System know that screen memory starts at 1024 ($400).

BASIC-Warmstart

Diese Routine initialisiert die Zeropage, setzt die Zeiger für SYSTOP und SYSBOT (also die Speicherunter- und obergrenze), setzt die Zeiger für die RS-232-Ein/Ausgabebuffer und den Kassettenbuffer zurück.

RAM test and find RAM end
Initialize RAM, reset tape buffer.

RAMTAS is used to test RAM, reset the top and bottom of memory pointers, clear $00 to $0101 and $0200 to $03FF, and set the screen memory to $0400.

;Do RAM test.
     JSR RAMTAS
     RTS
;All registers are altered.
Clears Z-Page, Sets RS-232 buffers, top/bot Ram.
 Registers In  : None.
 Registers Out : .A, .X, .Y destroyed.
 Memory Changed: Z-Page, Rs-232 buffers, top/bot Ram ptrs
Clear memory addresses $0002-$0101 and $0200-$03FF; run memory test and set start and end address of BASIC work area accordingly; set screen memory to $0400 and datasette buffer to $033C.

Input: – Output: – Used registers: A, X, Y. Real address: $FD50.

RAM test & search RAM end
                                       - - -  - - -  A X Y
RAM löschen/testen
$FF8A RESTOR SYS 65418
Restore default system and interrupt vectors
  • Preparatory routines: None
  • Error returns: None
  • Stack requirements: 2
  • Registers affected: A, X, Y

Description: This routine restores the default values of all system vectors used in KERNAL and BASIC routines and interrupts. (See the Memory Map for the default vector contents). The KERNAL VECTOR routine is used to read and alter individual system vectors.

How to Use:

  1. Call this routine.

EXAMPLE:

     JSR RESTOR
Reset RAM vectors to default

Called by: None.

JMP FD15/FD52 to execute the routine to initialize the Kernal RAM vectors. This RAM vector initialization is also done during system reset.

Calling this routine restores the vectors at (0314)-(0332) to their default values from the table at FD30/FD6D.

RESTOR

This routine resets the Kernal indirect vectors ($0314-$0333) to their default values. All processor registers are affected.

Restore RAM Vectors for Default I/O Routines

This routine sets the values for the 16 RAM vectors to the interrupt and important Kernal I/O routines in the table that starts at 788 ($314) to the standard values held in the ROM table at 64816 ($FD30).

Systemvektoren initialisieren

Es werden die Systemvektoren ab Adresse $0314 bis $0332 (inkl.) auf Normalwert gesetzt. Diese Routine sollte aufgerufen werden, wenn Sie zu viele Vektoren verbogen und die Übersicht verloren haben oder wenn Sie beispielsweise ein Erweiterungspaket ausschalten wollen. Diese Routine ruft die folgende VECTOR-Routine mit gelöschtem CARRY auf.

restore default I/O vectors

This routine restores the default values of all system vectors used in KERNAL and BASIC routines and interrupts.

Restore I/O default vectors.
Fill vector table at memory addresses $0314-$0333 with default values.

Input: – Output: – Used registers: – Real address: $FD15.

restore default I/O vectors
                                       - - -  - - -  A - Y
I/O initialisieren
$FF8D VECTOR SYS 65421
Manage RAM vectors
  • Communication registers: X, Y
  • Preparatory routines: None
  • Error returns: None
  • Stack requirements: 2
  • Registers affected: A, X, Y

Description: This routine manages all system vector jump addresses stored in RAM. Calling this routine with the the accumulator carry bit set stores the current contents of the RAM vectors in a list pointed to by the X and Y registers. When this routine is called with the carry clear, the user list pointed to by the X and Y registers is transferred to the system RAM vectors. The RAM vectors are listed in the memory map.

NOTE: This routine requires caution in its use. The best way to use it is to first read the entire vector contents into the user area, alter the desired vectors, and then copy the contents back to the system vectors.

How to Use:

READ THE SYSTEM RAM VECTORS

  1. Set the carry.
  2. Set the X and y registers to the address to put the vectors.
  3. Call this routine.

LOAD THE SYSTEM RAM VECTORS

  1. Clear the carry bit.
  2. Set the X and Y registers to the address of the vector list in RAM that must be loaded.
  3. Call this routine.

EXAMPLE:

;CHANGE THE INPUT ROUTINES TO NEW SYSTEM
     LDX #<USER
     LDY #>USER
     SEC
     JSR VECTOR      ;READ OLD VECTORS
     LDA #<MYINP     ;CHANGE INPUT
     STA USER+10
     LDA #>MYINP
     STA USER+11
     LDX #<USER
     LDY #>USER
     CLC
     JSR VECTOR      ;ALTER SYSTEM
     ...
USER *=*+26
Read or set RAM vectors

Called by: None.

Entry requirements: Carry should be set or clear, depending on the function desired:

Set the carry bit to store the RAM vectors at (0314)-(0332) at the location pointed to by the X and Y registers.

Clear the carry bit to load the RAM vectors at (0314)-(0332) from the location pointed to by X and Y.

JMP FD1A/FD57 (see chapter 2).

Store X and Y at (C3), the base address of where the vector table will be read from or stored to.

If the carry is set, store the RAM vectors at (0314)-(0332) to the location pointed to by the X and Y registers.

If the carry is clear, load the RAM vectors at (0314)-(0332) from the location pointed to by X and Y.

VECTOR

This routine can be used either to store the current values of Kernal indirect vectors at $0314-$0333 or to write new values to the vectors. When calling this routine, .X and .Y should be loaded with the address of a 32-byte table (low byte in .X, high byte in .Y). If the status-register carry bit is clear when the routine is called, the vectors will be loaded with the values from the table. If carry is set, the 16 two-byte address values currently in the vectors will be copied to the table.

Set the RAM Vector Table from the Table Pointed to by .X and .Y

This routine is used to read or change the values for the 16 RAM vectors to the interrupt and important Kernal I/O routines in the table that starts at 788 ($314). If the Carry flag is set when the routine is called, the current value of the 16 vectors will be stored at a table whose address is pointed to by the values in the .X and .Y registers. If the Carry flag is cleared, the RAM vectors will be loaded from the table whose address is pointed to by the .X and .Y registers. Since this routine can change the vectors for the IRQ and NMI interrupts, you might expect that the Interrupt disable flag would be set at its beginning. Such is not the case, however, and therefore it would be wise to execute an SEI before calling it and a CLI afterwards (as the power-on RESET routine does) just to be safe.

Systemvektoren kopieren oder rücksetzen

Diese Routine kopiert die 16 Vektoren ab $0314 in den durch das X- (Low) und Y-Register (High) definierten Speicher, sofern das CARRY-Flag gesetzt ist. Bei gelöschtem CARRY-Flag werden die Vektoren ab $0314 mit dem durch das X- und Y-Register angegebenen Bereich geladen.

Eingabeparameter: .X, .Y, CARRY

Beispiel:

        LDX #$00  ;Lo-Byte von $1000
        LDY #$10  ;Hi-Byte von $1000
        CLC       ;Lösche Carry zum Kopieren ($1000)->($0314)
        JSR $FF80 ;Belege Vektoren neu
read/set vectored I/O

This routine manages all system vector jump addresses stored in RAM. Calling this routine with the carry bit set will store the current contents of the RAM vectors in a list pointed to by the X and Y registers. When this routine is called with the carry bit clear, the user list pointed to by the X and Y registers is copied to the system RAM vectors.

NOTE: This routine requires caution in its use. The best way to use it is to first read the entire vector contents into the user area, alter the desired vectors and then copy the contents back to the system vectors.

Read/set vectored I/O.

VECTOR. If the carry bit of the accumulator is set, the start of a list of the current contents of the RAM vectors is returned in the X and Y registers. If the carry bit is clear, there the user list pointed to by the X and Y registers is transferred to the system RAM vectors.

;Change the input routines to new system.
     SEC
     JSR VECTOR
     LDA #L,MYINP
     STA USER+10
     LDA #H,MYINP
     STA USER+11
     LDX #L,USER
     LDY #H,USER
     CLC
     JSR VECTOR
     RTS
USER .DE 26
;The new input list can start anywhere. USER is the location for temporary strings, and 35-36 is the utility pointer area.
Copies / Stores KERNAL indirect RAM vectors.
 Registers In  : .C = 0 (Set KERNAL Vectors) | .C = 1 (Duplicate KERNAL vectors)
                 .XY = address of vectors    | .XY = address of user vectors
 Registers Out : .A, .Y destroyed            | .A, .Y destroyed.
 Memory Changed: KERNAL Vectors changed      | Vectors written to .XY
 Note          : This routine is rarely used, usually the vectors are directly
                 changed themselves. The vectors, in order, are :

                 C128: IRQ,BRK,NMI,OPEN,CLOSE,CHKIN,CHKOUT,CLRCH,BASIN,BSOUT
                       STOP,GETIN,CLALL,EXMON (monitor),LOAD,SAVE
                 C64 : IRQ,BRK,NMI,OPEN,CLOSE,CHKIN,CHKOUT,CLRCH,BASIN,BSOUT
                       STOP,GETIN,CLALL,USRCMD (not used),LOAD,SAVE
Copy vector table at memory addresses $0314-$0333 from or into user table.

Input: Carry: 0 = Copy user table into vector table, 1 = Copy vector table into user table; X/Y = Pointer to user table. Output: – Used registers: A, Y. Real address: $FD1A.

read/set I/O vectors
in: C=0 moves from Y/X to vectors      - X Y  - X -  A - Y
    C=1 moves vectors to Y/X           - X Y  - X -  A - Y
I/O Vektoren initialisieren
$FF90 SETMSG IO 65424
Control system message output
  • Communication registers: A
  • Preparatory routines: None
  • Error returns: None
  • Stack requirements: 2
  • Registers affected: A

Description: This routine controls the printing of error and control messages by the KERNAL. Either print error messages or print control messages can be selected by setting the accumulator when the routine is called. FILE NOT FOUND is an example of an error message. PRESS PLAY ON CASSETTE is an example of a control message.

Bits 6 and 7 of this value determine where the message will come from. If bit 7 is 1, one of the error messages from the KERNAL is printed. If bit 6 is set, control messages are printed.

How to Use:

  1. Set accumulator to desired value.
  2. Call this routine.

EXAMPLE:

     LDA #$40
     JSR SETMSG          ;TURN ON CONTROL MESSAGES
     LDA #$80
     JSR SETMSG          ;TURN ON ERROR MESSAGES
     LDA #0
     JSR SETMSG          ;TURN OFF ALL KERNAL MESSAGES
Set message control

Called by: JSR at A47D/C47D in BASIC's Enable Kernal Control Messages, JSR at A874/C874 in BASIC'S Disable Kernal Control Messages.

Entry requirements: Accumulator should contain the value used to set message control: $80 allows Kernal control messages; $40 allows Kernal error messages; $C0 allows both Kernal control and error messages; $00 disallows all Kernal messages.

JMP FE18/FE66. This routine is called to determine which messages will be displayed in response to control or error conditions. The accumulator value at entry determines the setting of the message control status.

Thanks to Russ Davies for pointing out that bits 6 and 7 are reversed in describing how to set message control in the 64 and VIC Programmer's Reference Guides.

SETMSG

SETMSG sets the value of the Kernal message flag (location $9D). Call the routine with the accumulator holding the desired flag value (.X and .Y are unaffected,) Valid flag values are 0 (no Kernal messages are displayed), 64 (only error messages are displayed), 128 (only control messages—PRESS PLAY ON TAPE, for example—are displayed), and 192 (both error and control messages are displayed).

Set the Message Control Flag

This routine controls the printing of error messages and control messages by the Kernal. It Bit 6 is seto to 1 (bit value of 64), Kernal control messages can be printed. These messages include SEARCHING FOR, LOADING, and the like. If Bit 6 is cleared to 0, these messages will not be printed (BASIC will clear this bit when a program is running so that the messages do not appear when I/O is performed from a program). Setting Bit 6 will not suppress the PRESS PLAY ON TAPE or PRESS PLAY & RECORD messages, however.

If Bit 7 is set to 1 (bit value of 128), Kernal error messages can be printed. If Bit 7 is set to 0, those error messages (for example, I/O ERROR #nn) will be suppressed. Note that BASIC has its own set of error messages (such as FILE NOT FOUND ERROR) which it uses in preference to the Kernal's message.

DOS-Meldungen ermöglichen/verhindern

Die Routine speichert den Wert des in der Zeropage-Adresse $9D. Sollen Systemmeldungen ausgegeben werden, so ist das Bit 7 des zu setzen. Ist $9D positiv, so werden Systemmeldungen verhindert.

Eingabeparameter: .A

control kernal messages

This routine controls the printing of error and control messages by the KERNAL. Either print error messages or print control messages can be selected by setting the accumulator when the routine is called.

FILE NOT FOUND is an example of an error message. PRESS PLAY ON CASSETTE is an example of a control message.

Bits 6 and 7 of this value determine where the message will come from. If bit 7 is set one of the error messages from the KERNAL will be printed. If bit 6 is set a control message will be printed.

Control Kernal messages.

SETMSG. Depending on the accumulator, either error messages, control messages, or neither is printed.

;Turn on control messages.
     LDA #$40
     JSR SETMSG
     RTS
;A 128 is for error messages; a zero, for turning both off.
Set control of KERNAL control and error messages.
 Registers In  : .A bit 7 = KERNAL Control Messages (1 = on)
                    bit 6 = KERNAL Error   Messages (1 = on)
 Registers Out : None.
 Note          : KERNAL Control messages are those defined as Loading, Found etc
                 ... KERNAL Error messages are I/O ERROR # messages which are
                 listed as follows:
Set system error display switch at memory address $009D.

Input: A = Switch value. Output: – Used registers: – Real address: $FE18.

enable/disable KERNAL messages
in: A bit7=1 error msgs on             A - -  - - -  A - -          bit6=1 control msgs on
Setzt Flag für Ausgabe von Systemmeldung
$FF93 SECOND IEEE 65427
Send secondary address for LISTEN
  • Communication registers: A
  • Preparatory routines: LISTEN
  • Error returns: See READST
  • Stack requirements: 8
  • Registers affected: A

Description: This routine is used to send a secondary address to an I/O device after a call to the LISTEN routine is made, and the device is commanded to LISTEN. The routine canNOT be used to send a secondary address after a call to the TALK routine.

A secondary address is usually used to give setup information to a device before I/O operations begin.

When a secondary address is to be sent to a device on the serial bus, the address must first be ORed with $60.

How to Use:

  1. Load the accumulator with the secondary address to be sent.
  2. Call this routine.

EXAMPLE:

;ADDRESS DEVICE #8 WITH COMMAND (SECONDARY ADDRESS) #15
     LDA #8
     JSR LISTEN
     LDA #15
     JSR SECOND
Send secondary address after listen to serial

Called by: None.

Setup routines: LISTEN

JMP EDB9/EEC0 to send the byte in the accumulator on the serial bus as a secondary address command with the serial attention output line set low. After this command is sent, the serial attention output line is brought high, the setting for transmitting normal data bytes.

You must ORA the secondary address with $60 before calling this routine to convert the secondary address to a recognized IEEE secondary address command. See page 378 of Raeto Collin West's Programming the PET/CBM for a detailed chart of the IEEE command groups.

SECOND

This low-level serial I/O routine sends a secondary address to a device which has been commanded to listen. The value in the serial status flag upon return will indicate whether the operation was successful.

Send a Secondary Address to a Device on the Serial Bus after LISTEN

This routine sends a secondary address from the Accumulator to the device on the serial bus that has just been commanded to LISTEN. This is usually done to give the device more particular instructions on how the I/O is to be carried out before information is sent.

Sekundäradresse nach LISTEN senden

Es wird die zu sendende Sekundäradresse im übergeben. Die Routine gibt den dann als Sekundäradresse auf dem IEC-Bus aus.

Eingabeparameter: .A

Beispiel:

        ;LISTEN wurde gesendet
        LDA #$F0  ;Sekadr. 0 bei CLOSE
        JSR $FF93 ;Sekundaradresse senden
send secondary address after LISTEN

This routine is used to send a secondary address to an I/O device after a call to the LISTEN routine is made and the device commanded to LISTEN. The routine cannot be used to send a secondary address after a call to the TALK routine.

A secondary address is usually used to give set-up information to a device before I/O operations begin.

When a secondary address is to be sent to a device on the serial bus the address must first be ORed with $60.

Send secondary address after LISTEN.

SECOND. After LISTEN has been called, a SECONDary address may be sent.

;Address device #8 with secondary address #15.
     LDA #8
     JSR LISTEN
     LDA #15
     JSR SECOND
;The accumulator designates the address number.
Sends secondary address to device after a LISTN
 Registers In  : .A = secondary address
 Registers Out : .A used.
 Memory Changed: None.
 Note          : Low level serial I/O - recommended use OPEN,CLOSE,CHROUT etc..
Send LISTEN secondary address to serial bus. (Must call LISTEN beforehands.)

Input: A = Secondary address. Output: – Used registers: A. Real address: $EDB9.

send secondary addr after listen
in: A=secondary address                A - -  - - -  A - -
schickt Sekundäradresse nach einem LISTEN-Befehl

auf den IEC-Bus

$FF96 TKSA IEEE 65430
Send a secondary address to a device commanded to TALK
  • Communication registers: A
  • Preparatory routines: TALK
  • Error returns: See READST
  • Stack requirements: 8
  • Registers affected: A

Description: This routine transmits a secondary address on the serial bus for a TALK device. This routine must be called with a number between 0 and 31 in the accumulator. The routine sends this number as a secondary address command over the serial bus. This routine can only be called after a call to the TALK routine. It will not work after a LISTEN.

How to Use:

  1. Use the TALK routine.
  2. Load the accumulator with the secondary address.
  3. Call this routine.

EXAMPLE:

;TELL DEVICE #4 TO TALK WITH COMMAND #7
     LDA #4
     JSR TALK
     LDA #7
     JSR TKSA
Send secondary address after talk to serial

Called by: None.

Setup routines: TALK.

Entry requirements: Accumulator should hold the secondary address 0-31 (decimal) ORed with $60.

JMP EDC7/EECE to send the secondary address after the TALK command and to do the TALK-LISTEN turnaround where the serial device becomes the talker and the 64/VIC (and other devices on the serial bus) become the listener.

The IEEE convention is that $6X and $7X represent secondary addresses. The 0-31(decimal) that you ORA with $60 before calling TKSA results in $6X if the accumulator holds 0-15 (decimal) and $7X if the accumulator holds 16-31 (decimal). The VIC-1541 User's Manual states that the secondary addresses can be 2-15 with 15 the command channel and 0 and 1 reserved for load and save.

TKSA

This low-level serial 1/0 routine sends a secondary address to a device which has previously been commanded to taLk. The success of the operation will be indicated by the value in the serial status flag upon return. (See READST for details.)

Send a Secondary Address to a Device on the Serial Bus after TALK

This routine sends a secondary address from the Accumulator to the device on the serial bus that has just been commanded to TALK. This is usually done to give the device more particular instructions on how the I/O is to be carried out before information is sent.

Sekundäradresse nach TALK senden

Adäquat zu der vorhergehenden Routine sendet diese Routine die Sekundäradresse - übergeben im nach erfolgtem TALK-Signal an den IEC-Bus.

Eingabeparameter: .A

send secondary address after TALK

This routine transmits a secondary address on the serial bus for a TALK device. This routine must be called with a number between 4 and 31 in the accumulator. The routine will send this number as a secondary address command over the serial bus. This routine can only be called after a call to the TALK routine. It will not work after a LISTEN.

Send secondary address after TALK.

TKSA is used to send a secondary address for a TALK device. TALK must be called first.

;Signal device #4 to talk with command #7.
     LDA #4
     JSR TALK
     LDA #7
     JSR TKSA
     RTS
;This example will tell the printer to print in uppercase.
Sends secondary address to device after TALK
 Registers In  : .A = secondary address.
 Registers Out : .A used.
 Memory Changed: None.
 Note          : Low level serial I/O - recommended use OPEN,CLOSE,CHROUT etc..
Send TALK secondary address to serial bus. (Must call TALK beforehands.)

Input: A = Secondary address. Output: – Used registers: A. Real address: $EDC7.

send secondary addr after talk
in: A=secondary address                A - -  - - -  A - -
schickt Sekundäradresse nach einem TALK-Befehl

auf den IEC-Bus

$FF99 MEMTOP MEM 65433
Set the top of RAM
  • Communication registers: X, Y
  • Preparatory routines: None
  • Error returns: None
  • Stack requirements: 2
  • Registers affected: X, Y

Description: This routine is used to set the top of RAM. When this routine is called with the carry bit of the accumulator set, the pointer to the top of RAM will be loaded into the X and Y registers. When this routine is called with the accumulator carry bit clear, the contents of the X and Y registers are loaded in the top of memory pointer, changing the top of memory.

EXAMPLE:

;DEALLOCATE THE RS-232 BUFFER
     SEC
     JSR MEMTOP   ;READ TOP OF MEMORY
     DEX
     CLC
JSR MEMTOP   ;SET NEW TOP OF MEMORY
Read or set the end-of-memory pointer

Called by: JSR at E40B/E3ED in BASIC's Cold Start.

Entry requirements: Carry should be set or clear, depending on function desired:

Set carry to read end of memory.

Clear carry to set end of memory. The X register contains the low byte of the address of the start of memory, and the Y register contains the high byte of the address of the start of memory.

JMP FE25/FE73.

If carry is clear at entry, set pointer to top of memory (0283) from X and Y registers.

If carry is set at entry, load X and Y registers from (0283), the pointer to the top of memory.

MEMTOP

These routines read or set the Kernal's bottom-of-memory pointer and top-of-memory pointer, respectively. (The bottomof-memory pointer is at locations $0281-$0282 for the 64 or $0A05-$0A06 for the 128; the top-of-memory pointer is at locations $0283-$0284 for the 64 or $0A07-$0A08 for the 128.) To read the pointer, call the routine with the carry flag set; the pointer value will be returned in .X (low byte) and .Y (high byte). To set the pointer, call the routine with the carry flag clear and with .X and .Y containing the low and high bytes, respectively, of the desired pointer value.

Read/Set Top of RAM Pointer

This routine can be used to either read or set the top of RAM pointer. If called with the Carry flag set, the address in the pointer will be loaded into the .X and .Y registers. If called with the Carry flag cleared, the pointer will be changed to the address found in the .X and .Y registers.

Setzen/Holen der Speicherobergrenze

Ist das CARRY-Flag gesetzt, so wird im X-Register (Lo) und Y-Register (Hi) die maximal verfügbare Speicherstelle übergeben. Wird die Routine mit gelöschtem CARRY angesprungen, so wird die Speicherobergrenze mit den beiden Registern belegt.

Eingabeparameter: .X, .Y (bei gelöschtem CARRY), CARRY

Ausgabeparameter: .X, .Y (bei gesetztem CARRY)

Beispiel:

        ;Auslesen der Speicherobergrenze
        SEC       ;Auslesen der Obergrenze
        JSR $FF99 ;Hole Obergrenze
        STX $FC   ;zwischenspeichern
        STY $FD   ;zwischenspeichern
        LDX #$00  ;Lo-Byte von $1000
        LDY #$10  ;Hi-Byte von $1000
        CLC       ;Flag zum Setzen des MEMTOP
        JSR $FF99 ;Setze Speicherobergrenze
read/set the top of memory

This routine is used to read and set the top of RAM. When this routine is called with the carry bit set the pointer to the top of RAM will be loaded into XY. When this routine is called with the carry bit clear XY will be saved as the top of memory pointer changing the top of memory.

Read/set top of memory.

MEMTOP. Same principle as MEMBOT, except the top of RAM is affected.

;Protect 1K of memory from BASIC.
     SEC
     JSR MEMTOP
     DEY
     CLC
     JSR MEMTOP
;The accumulator is left alone.
Read or Set top of System Ram
 Registers In  : .C = 1 (Read MemTop)     | .C = 0 (Set MemTop)
                                          | .XY = top of memory
 Registers Out : .XY = top of memory      | None.
 Memory Changed: None.                    | Top of memory changed.
 Note          : On the C=128, this routine refers to the top of BANK 0 RAM, not
                 BANK 1 RAM.
Save or restore start address of BASIC work area.

Input: Carry: 0 = Restore from input, 1 = Save to output; X/Y = Address (if Carry = 0). Output: X/Y = Address (if Carry = 1). Used registers: X, Y. Real address: $FE25.

read/set top of memory
in: C=0; Y/X address                   - X Y  - X Y  - - -    out:C=1; Y/X address                   - - -  - X Y  - X Y
holt bei gesetzem Carry-Flag die höchste RAM-

Adresse nach X und Y, bei gelöschtem Carry-Flag wird die Adresse von X und Y gesetzt.

$FF9C MEMBOT MEM 65436
Set bottom of memory
  • Communication registers: X, Y
  • Preparatory routines: None
  • Error returns: None
  • Stack requirements: None
  • Registers affected: X, Y

Description: This routine is used to set the bottom of the memory. If the accumulator carry bit is set when this routine is called, a pointer to the lowest byte of RAM is returned in the X and Y registers. On the unexpanded Commodore 64 the initial value of this pointer is $0800 (2048 in decimal). If the accumulator carry bit is clear (-O) when this routine is called, the values of the X and Y registers are transferred to the low and high bytes, respectively, of the pointer to the beginning of RAM.

How to Use:

TO READ THE BOTTOM OF RAM

  1. Set the carry.
  2. Call this routine.

TO SET THE BOTTOM OF MEMORY

  1. Clear the carry.
  2. Call this routine.

EXAMPLE:

;MOVE BOTTOM OF MEMORY UP 1 PAGE
     SEC         ;READ MEMORY BOTTOM
     JSR MEMBOT
     INY
     CLC         ;SET MEMORY BOTTOM TO NEW VALUE
     JSR MEMBOT
Read or set the start-of-memory pointer

Called by: JSR at E403/E3E5 in BASIC's Cold Start.

Entry requirements: Carry should be set or clear, depending on function desired:

Set carry to read bottom of memory.

Clear carry to set bottom of memory. The X register is the low byte of the address of the bottom of memory, and the Y register is the high byte of the address of the bottom of memory.

JMP FE34/FE82.

If the carry is clear at entry, set the pointer to bottom of memory (0281) from X and Y registers.

If the carry is set at entry, load X and Y registers from (0281), the pointer to the bottom of memory.

The initial values of (0281) are 1000 for an unexpanded VIC, 0400 for a VIC with 3K expansion, 1200 for a VIC with 8K or more expanded, and 0800 for the 64.

MEMBOT

See MEMTOP.

Read/Set Bottom of RAM Pointer

This routine can be used to either read or set the bottom of RAM pointer. If called with the Carry flag set, the address in the pointer willbe loaded into the .X and .Y registers. If called with the Carry flag cleared, the pointer will be changed to the address found in the .X and .Y registers.

Setzen/Holen der Speicheruntergrenze

Genauso wie bei der Routine MEMTOP wird bei gelöschtem CARRY-Flag die Untergrenze des verfügbaren Speichers mit den beiden Registern X ^Lo) und Y (Hi) belegt. Ist das CARRY-Flag gesetzt, so wird die Speicheruntergrenze ausgelesen und in den beiden Registern übergeben.

Eingabeparameter: .X, .Y (bei gelöschtem CARRY), CARRY

Ausgabeparameter: .X, .Y (bei gesetztem CARRY)

read/set the bottom of memory

This routine is used to read and set the bottom of RAM. When this routine is called with the carry bit set the pointer to the bottom of RAM will be loaded into XY. When this routine is called with the carry bit clear XY will be saved as the bottom of memory pointer changing the bottom of memory.

Read/set bottom of memory.

MEMBOT. If the carry bit is set, then the low byte and the high byte of RAM are returned in the X and Y registers. If the carry bit is clear, the bottom of RAM is set to the X and Y registers.

;Move bottom of memory up one page.
     SEC
     JSR MEMBOT
     INY
     CLC
     JSR MEMBOT
     RTS
;The accumulator is left alone.
Read or Set bottom of System Ram
 Registers In  : .C = 1 (Read MemBot)     | .C = 0 (Set MemBot)
                                          | .XY = bottom of memory.
 Registers Out : .XY = bottom of memory   | None.
 Memory Changed: None.                    | Bottom of Memory changed.
 Note          : On the C=128, this routine refers to the bottom of BANK 0 RAM,
                 not, BANK 1 RAM.
Save or restore end address of BASIC work area.

Input: Carry: 0 = Restore from input, 1 = Save to output; X/Y = Address (if Carry = 0). Output: X/Y = Address (if Carry = 1). Used registers: X, Y. Real address: $FE34.

read/set bottom of memory
in: C=0; Y/X address                   - X Y  - X Y  - - -    out:C=1; Y/X address                   - - -  - X Y  - X Y
dieselbe Funktion wie $FF99, jedoch für den

RAM-Anfang

$FF9F SCNKEY KBD2) 65439
Scan the keyboard
  • Communication registers: None
  • Preparatory routines: IOINIT
  • Error returns: None
  • Stack requirements: 5
  • Registers affected: A, X, Y

Description: This routine scans the Commodore 64 keyboard and checks for pressed keys. It is the same routine called by the interrupt handler. If a key is down, its ASCII value is placed in the keyboard queue. This routine is called only if the normal IRQ interrupt is bypassed.

How to Use:

  1. Call this routine.

EXAMPLE:

GET  JSR SCNKEY      ;SCAN KEYBOARD
     JSR GETIN       ;GET CHARACTER
     CMP #0          ;IS IT NULL?
     BEQ GET         ;YES... SCAN AGAIN
     JSR CHROUT      ;PRINT IT
Detect keyboard entry

Called by: None.

JMP EA87/EB1E to the Keyboard Scan routine (see chapter 4) to check for a keypress. If a valid key is found down and the keyboard buffer is not full, the ASCII code value for the key is placed in the buffer.

SCNKEY is useful if you have written a machine language program that runs with IRQ interrupts disabled, but you still want to scan the keyboard.

SCNKEY

This routine scans the keyboard matrix to determine which keys, if any, are currently pressed. The standard KQ service routine calls SCNKEY, so it's not usually necessary to call it explicitly to read the keyboard. The character code for the key currently pressed is loaded into the keyboard buffer, from where it can be retrieved using the Kernal GETIN routine. The matrix code of the keypress read during this routine can also be read in location $CB (64) or $D4 (128), and the status of the shift keys can be read in location $028D (64) or $D3 (128).

Read the Keyboard

This subroutine is called by the IRQ interrupt handler above to read the keyboard device which is connected to CIA #1 (see entry for 56320 ($DC00) for details on how to read the keyboard).

This routine returns the keycode of the key currently being pressed in 203 ($CB), sets the shift/control flag if appropriate, and jumps through the vector at 655 ($28F) to the routine that sets up the proper table to translate the keycode to PETASCII. It concludes with the next routine, which places the PETASCII value of the character in the keyboard buffer.

Ermitteln gedrückter Tasten

Diese Routine ist elementar zur Tastaturdekodierung. Die Tastatur wird auf eine gedrückte Taste anhand der Tastaturdekodiertabellen überprüft. Wird eine gedrückte Taste ermittelt, so wird der ASCII-Wert errechnet und dieser dem Tastaturbuffer (ab $034A) hinzugefügt.

scan the keyboard

This routine will scan the keyboard and check for pressed keys. It is the same routine called by the interrupt handler. If a key is down, its ASCII value is placed in the keyboard queue.

Scan keyboard.
Scans Keyboard
 Registers In  : None.
 Registers Out : None.
 Memory Changed: Relevant System Keyboard Values
Query keyboard; put current matrix code into memory address $00CB, current status of shift keys into memory address $028D and PETSCII code into keyboard buffer.

Input: – Output: – Used registers: A, X, Y. Real address: $EA87.

scan keyboard
                                       - - -  - - -  A X Y
fragt die Tastatur ab
$FFA2 SETTMO IEEE 65442
Set IEEE bus card timeout flag
  • Communication registers: A
  • Preparatory routines: None
  • Error returns: None
  • Stack requirements: 2
  • Registers affected: None
NOTE: This routine is used ONLY with an IEEE add-on card!

Description: This routine sets the timeout flag for the IEEE bus. When the timeout flag is set, the Commodore 64 will wait for a device on the IEEE port for 64 milliseconds. If the device does not respond to the Commodore 64's Data Address Valid (DAV) signal within that time the Commodore 64 will recognize an error condition and leave the handshake sequence. When this routine is called when the accumulator contains a 0 in bit 7, timeouts are enabled. A 1 in bit 7 will disable the timeouts.

NOTE: The Commodore 64 uses the timeout feature to communicate that a disk file is not found on an attempt to OPEN a file only with an IEEE card.

How to Use:

TO SET THE TIMEOUT FLAG

  1. Set bit 7 of the accumulator to 0.
  2. Call this routine.

TO RESET THE TIMEOUT FLAG

  1. Set bit 7 of the accumulator to 1.
  2. Call this routine.

EXAMPLE:

;DISABLE TIMEOUT
     LDA #0
     JSR SETTMO
Set IEEE time-out

Called by: None.

JMP FE21/FE6F to store accumulator in 0285. The VIC-20 Programmer's Reference Guide refers to this routine as setting a serial timeout flag and the Commodore 64 Programmer's Reference Guide refers to it as setting a flag for IEEE timeout. However, neither BASIC nor the Kernal refers to this vector. Since 0285 is not a register for an I/O chip and it is never referred to, it's hard to see how it can be used to enable or disable timeouts.

SETTMO

The SETTMO routine stores the contents of the accumulator in the IEEE timeout flag. (.X and .Y are unaffected.) This routine is superfluous, since the flag isn't used by any 64 or 128 ROM routine. It is present merely to maintain consistency with previous versions of the Kernal. For the 64, the flag location is $0285; for the 128, it's at $0A0E.

Set Time-Out Flag for IEEE Bus

This routine sets the time-out flag for the IEEE bus. When timeouts are enabled, the Commodore will wait for a device for 64 milliseconds, and if it does not receive a response to its signal it will issue a time-out error. Loading the Accumulator with a value less than 128 and calling this routine will enable time-outs, while using a value over 128 will disable time-outs.

This routine is for use only with the Commodore IEEE add-on card, which at the time of this writing was not yet available.

Setzen des Timeout-Flags für IEEE

Die Routine speichert den im übergebenen Wert als Timeout-Flag für die IEEE-Routinen an Adresse $0A0E. Um den Timeout in den IEEE-Routinen zu ermöglichen, muß das Bit 7 des gesetzt sein.

Eingabeparameter: .A

set timeout on serial bus

This routine sets the timeout flag for the serial bus. When the timeout flag is set, the computer will wait for a device on the serial port for 64 milliseconds. If the device does not respond to the computer's DAV signal within that time the computer will recognize an error condition and leave the handshake sequence. When this routine is called and the accumulator contains a 0 in bit 7, timeouts are enabled. A 1 in bit 7 will disable the timeouts.

NOTE: The the timeout feature is used to communicate that a disk file is not found on an attempt to OPEN a file.

Set time-out on serial bus.

SETTMO is used only with an IEEE add-on card to access the serial bus.

;Disable time-outs on serial bus.
     LDA #0
     JSR SETTMO
;To enable time-outs, set the accumulator to a 128 and call SETTMO.
 This is a routine who's code never made it into any versions
 of the KERNAL on the C64, Vic-20 and C128.  Thus it is of no
 pratical use.
Unknown. (Set serial bus timeout.)

Input: A = Timeout value. Output: – Used registers: – Real address: $FE21.

set IEEE timeout
in: A bit7=1 disable, bit7=0 enable    A - -  A - -  - - -
setzt das Time-out-Flag für den IEC-Bus
$FFA5 ACPTR IEEE 65445
Get data from the serial bus
  • Communication registers: A
  • Preparatory routines: TALK, TKSA
  • Error returns: See READST
  • Stack requirements: 13
  • Registers affected: A, X

Description: This is the routine to use when you want to get information from a device on the serial bus, like a disk. This routine gets a byte of data off the serial bus using full handshaking. The data is returned in the accumulator. To prepare for this routine the TALK routine must be called first to command the device on the serial bus to send data through the bus. If the input device needs a secondary command, it must be sent by using the TKSA KERNAL routine before calling this routine. Errors are returned in the status word. The READST routine is used to read the status word.

How to Use:

  1. Command a device on the serial bus to prepare to send data to the Commodore 64. (Use the TALK and TKSA KERNAL routines.)
  2. Call this routine (using JSR).
  3. Store or otherwise use the data.

EXAMPLE:

     ;GET A BYTE FROM THE BUS
     JSR ACPTR
     STA DATA
Get a byte from serial bus

Called by: None.

Setup routines: TALK, TKSA

The vector is JMP EE13/EF19. At EE13/EF19 the computer goes through a handshake sequence with the serial bus. During this sequence, the EOI handshake is performed if the serial clock input line does not go low within 250 microseconds as expected. If the EOI handshake sequence is performed, the routine sets the EOI status in the I/O status word, location 90. It can set the time-out status in the status word if serial clock in fails to go low within a certain time range.

If the preparation to receive handshaking signals detects no problems, and if the eight bits are received without handshaking error, the routine returns the byte received in the accumulator.

Exit conditions: The accumulator contains the byte received from the serial bus.

ACPTR

This low-level I/O routine retrieves a byte from a serial device without checking for a previous I/O error. If the operation is successful, the accumulator will hold the byte received from the device. The contents of .X and .Y are preserved. The success of the operation will be indicated by the value in the serial status flag upon return. (See READST for details.)

For the routine to function properly, the serial device must currently be a talker on the serial bus, which requires a number of setup steps. Generally, it's preferable to use the higher-level CHRFN routine instead.

Receive a Byte of Data from a Device on the Serial Bus

When called, this routine will get a byte of data from the current TALKer on the serial bus and store it in the Accumulator. In order to receive the data, the device must have previously been sent a command to TALK and a secondary address if it needs one.

Holt ein Byte vom seriellen Bus

Die Routine holt ein Byte vom seriellen IEC-Bus. Das geholte Zeichen wird im Akku übergeben. Das Statusbyte ST an $90 wird entsprechend der Aktion gesetzt.

Ausgabeparameter: .A

input byte from serial bus

This routine reads a byte of data from the serial bus using full handshaking. the data is returned in the accumulator. before using this routine the TALK routine, $FFB4, must have been called first to command the device on the serial bus to send data on the bus. if the input device needs a secondary command it must be sent by using the TKSA routine, $FF96, before calling this routine.

Errors are returned in the status word which can be read by calling the READST routine, $FFB7.

Input byte from serial port.

ACPTR is used to get data off the serial bus. TALK and TKSA must be called first.

;Get a byte from the serial bus.
     JSR ACPTR
     STA $0800
;This example only shows the end result; call TALK and TKSA first.
Get byte from current talker.
 Registers In  : None.
 Registers Out : .A = data byte.
 Memory Changed: None.
 Note          : Low level serial I/O - recommended use OPEN,CLOSE,CHROUT etc..
Read byte from serial bus. (Must call TALK and TALKSA beforehands.)

Input: – Output: A = Byte read. Used registers: A. Real address: $EE13.

input byte from SERIAL
out:A=byte, C=1 and ST=2 if timeout    - - -  A - -  A - -
holt ein Byte vom IEC-Bus in den Akku
$FFA8 CIOUT IEEE 65448
Transmit a byte over the serial bus
  • Communication registers: A
  • Preparatory routines: LISTEN, [SECOND]
  • Error returns: See READST
  • Stack requirements: 5
  • Registers affected: None

Description: This routine is used to send information to devices on the serial bus. A call to this routine will put a data byte onto the serial bus using full serial handshaking. Before this routine is called, the LISTEN KERNAL routine must be used to command a device on the serial bus to get ready to receive data. (If a device needs a secondary address, it must also be sent by using the SECOND KERNAL routine.) The accumulator is loaded with a byte to handshake as data on the serial bus. A device must be listening or the status word will return a timeout. This routine always buffers one character. (The routine holds the previous character to be sent back.) So when a call to the KERNAL UNLSN routine is made to end the data transmission, the buffered character is sent with an End Or Identify (EOI) set. Then the UNLSN command is sent to the device.

How to Use:

  1. Use the LISTEN KERNAL routine (and the SECOND routine if needed).
  2. Load the accumulator with a byte of data.
  3. Call this routine to send the data byte.

EXAMPLE:

     LDA #'X       ;SEND AN X TO THE SERIAL BUS
     JSR CIOUT
Send a byte to serial bus

Called by: None.

Setup routines: LISTEN, SECOND (if serial device requires a secondary address)

Entry requirements: Accumulator should contain character to output. JMP EDDD/ EEE4 to execute the Send Serial Byte Deferred routine.

When sending a character to a serial device, the routine maintains a one byte buffer at 95. If this buffer is empty, the character to be output is simply stored in the buffer. If the buffer already contains a character, the character from the buffer is sent onto the serial bus and the character to be output is stored in the buffer. When the serial file is closed or the serial device commanded to unlisten, the final byte in the buffer is sent. The character is sent to all open devices on the serial bus.

CIOUT

This low-level I/O routine sends a byte to a serial device. The accumulator should hold the byte to be sent. All register values are preserved. The success of the operation will be indicated by the value in the serial status flag. (See READST for details.)

For the routine to function properly, the target serial device must currently he a listener on the serial bus, which requires a number of setup steps. However, if you have already performed all the preparatory steps necessary for CHROUT to a serial device, then you can freely substitute CIOUT for CHROUT, since, for a serial device, CHROUT simply jumps to the CIOUT routine.

Send a Byte to an I/O Device over the Serial Bus

This routine's purpose is to send a byte of data over the serial bus. In order for the data to be received, the serial device must have first been commanded to LISTEN and been given a secondary address if necessary. This routine always buffers the current character, and defers sending it until the next byte is buffered. When the UNLISTEN command is sent, the last byte will be sent with an End or Identify (EOI).

Ausgabe eines Zeichens auf IEC-Bus

Diese Routine ist das Gegenstück zu ACPTR. Das im übergebene Zeichen wird auf dem lEC-Bus ausgegeben. Auch hier wird das Statusbyte ST an $90 entsprechend der Aktion geändert.

Eingabeparameter: .A

output a byte to serial bus

This routine is used to send information to devices on the serial bus. A call to this routine will put a data byte onto the serial bus using full handshaking. Before this routine is called the LISTEN routine, $FFB1, must be used to command a device on the serial bus to get ready to receive data.

The accumulator is loaded with a byte to output as data on the serial bus. A device must be listening or the status word will return a timeout. This routine always buffers one character. So when a call to the UNLISTEN routine, $FFAE, is made to end the data transmission, the buffered character is sent with EOI set. Then the UNLISTEN command is sent to the device.

Output byte to serial port.

CIOUT will send data to the serial bus. LISTEN and SECOND must be called first. Call UNLSN to finish up neatly.

;Send the letter X to the serial bus.
     LDA #'X
     JSR CIOUT
     RTS
;The accumulator is used to transfer the data.
Output byte to current listener.
 Registers In  : .A = byte.
 Registers Out : .A used.
 Memory Changed: None.
 Note          : Low level serial I/O - recommended use OPEN,CLOSE,CHROUT etc..
Write byte to serial bus. (Must call LISTEN and LSTNSA beforehands.)

Input: A = Byte to write. Output: – Used registers: – Real address: $EDDD.

output byte to SERIAL
in: A=byte, C=1 and ST=3 if timeout    A - -  A - -  - - -
gibt ein Byte aus dem Akku an den IEC-Bus aus
$FFAB UNTLK IEEE 65451
Send an UNTALK command
  • Communication registers: None
  • Preparatory routines: None
  • Error returns: See READST
  • Stack requirements: 8
  • Registers affected: A

Description: This routine transmits an UNTALK command on the serial bus. All devices previously set to TALK will stop sending data when this command is received.

How to Use:

  1. Call this routine.

EXAMPLE:

     JSR UNTALK
Send untalk to serial

Called by: None.

JMP EDEF/EEF6 to send $5F, the command for UNTALK, over the serial bus. Serial devices that are talking should quit talking and terminate their connection to the serial bus.

UNTLK

This low-level 1/0 routine sends an UNTALK command to all devices on the serial bus. Any devices which are currently talkers will cease sending data.

Send UNTALK to a Device on the Serial Bus

When called, this routine sends the UNTALK code (95, $5F) on the serial bus. This commands any TALKer on the bus to stop sending data.

UNTALK auf lEC-Bus senden

Diese Routine wird beim Schließen bzw. Umlegen eines Eingabekanals aufgerufen. Sie bringt das zum Reden (TALK) gebrachte Gerät zum Schweigen.

command serial bus to UNTALK

This routine will transmit an UNTALK command on the serial bus. All devices previously set to TALK will stop sending data when this command is received.

Command serial bus to UNTALK.

UNTLK. All devices previously set to TALK will stop sending data.

;Command serial bus to stop sending data.
     JSR UNTLK
     RTS
;Sending UNTLK commands all talking devices to get off the serial bus.
Commands current TALK device to stop TALKING.
 Registers In  : None.
 Registers Out : .A used.
 Memory Changed: None.
 Note          : Low level serial I/O - recommended use OPEN,CLOSE,CHROUT etc..
Send UNTALK command to serial bus.

Input: – Output: – Used registers: A. Real address: $EDEF.

untalk all SERIAL devices
                                       - - -  - - -  A - -
sendet UNTALK-Befehl auf den IEC-Bus
$FFAE UNLSN IEEE 65454
Send an UNLISTEN command
  • Communication registers: None
  • Preparatory routines: None
  • Error returns: See READST
  • Stack requirements: 8
  • Registers affected: A

Description: This routine commands all devices on the serial bus to stop receiving data from the Commodore 64 (i.e., UNLISTEN). Calling this routine results in an UNLISTEN command being transmitted on the serial bus. Only devices previously commanded to listen are affected. This routine is normally used after the Commodore 64 is finished sending data to external devices. Sending the UNLISTEN commands the listening devices to get off the serial bus so it can be used for other purposes.

How to Use:

  1. Call this routine.

EXAMPLE:

     JSR UNLSN
Send unlisten to serial

Called by: None.

JMP EDFE/EF04 to send $3F, the command for UNLISTEN, over the serial bus. Serial devices that are listening should recognize the command and terminate their connection to the serial bus.

UNLSN

This low-level I/O routine sends an UNLISTEN command to aH devices on the serial bus. Any devices which are currently listeners will cease accepting data.

Send UNLISTED to a Device on the Serial Bus

This routine sends the UNLISTEN code (63, $3F) on the serial bus. This commands any LISTENers to get off the serial bus, and frees up the bus for other users.

UNLISTEN auf IEC-Bus senden

Entsprechend zu UNTALK wird bei dieser Routine ein empfangendes Gerät vorerst abgeschaltet. Dies wird beim Schließen oder Umlegen eines Ausgabekanals gemacht.

command serial bus to UNLISTEN

This routine commands all devices on the serial bus to stop receiving data from the computer. Calling this routine results in an UNLISTEN command being transmitted on the serial bus. Only devices previously commanded to listen will be affected.

This routine is normally used after the computer is finished sending data to external devices. Sending the UNLISTEN will command the listening devices to get off the serial bus so it can be used for other purposes.

Command serial bus to UNLISTEN.

UNLSN commands all devices on the serial bus to stop receiving data.

;Command the serial bus to UNLiSteN.
     JSR UNLSN
     RTS
;The serial bus can now be used for other things.
Commands current listening device to stop listening.
 Registers In  : None.
 Registers Out : .A used.
 Memory Changed: None.
 Note          : Low level serial I/O - recommended use OPEN,CLOSE,CHROUT etc..
Send UNLISTEN command to serial bus.

Input: – Output: – Used registers: A. Real address: $EDFE.

unlisten all SERIAL devices
                                       - - -  - - -  A - -
sendet UNLISTEN-Befehl auf den IEC-Bus
$FFB1 LISTEN IEEE 65457
Command a device on the serial bus to listen
  • Communication registers: A
  • Preparatory routines: None
  • Error returns: See READST
  • Stack requirements: None
  • Registers affected: A

Description: This routine will command a device on the serial bus to receive data. The accumulator must be loaded with a device number between 0 and 31 before calling the routine. LISTEN will OR the number bit by bit to convert to a listen address, then transmits this data as a command on the serial bus. The specified device will then go into listen mode, and be ready to accept information.

How to Use:

  1. Load the accumulator with the number of the device to command to LISTEN.
  2. Call this routine using the JSR instruction.

EXAMPLE:

;COMMAND DEVICE #8 TO LISTEN
     LDA #8
     JSR LISTEN
Send listen with attention to serial devices

Called by: None.

JMP ED0C/EE17.

At ED0C/EE17 the accumulator, which contains the device number, is ORed with $20, turning on bit 5 to prepare to send a LISTEN command on the serial data output line. The device number should be 0-31 (decimal). (If you specify a value > 31, you mess up the high nybble which is used for sending commands on the serial bus.)

RS-232 interrupts are disabled.

Finally, the LISTEN command for this device is sent on the serial bus. To send the LISTEN, the 64/VIC brings the serial attention output line low to cause all devices on the serial bus to listen for a command coming on the bus.

LISTEN

This low-level serial I/O routine sends a LISTEN command to a specified serial device. Call the routine with the accumulator holding the device number (4-31) of the serial device to receive the command. The contents of .A and .X will be changed; .Y is unaffected. The success of the operation will be indicated by the value in the serial status flag upon return. (See READST for details.)

Send LISTEN to a Device on the Serial Bus

When called, this routine ORs the device number in the Accumulator with the LISTEN code (32, $20) and sends it on the serial bus. This commands the device to LISTEN.

Senden von LISTEN an ein Gerät

Es wird ein am IEC-Bus angeschlossenes Gerät zum Empfang aufgefordert. Dazu wird das Signal LISTEN über den IEC-Bus geschickt. Im wird die Geräteadresse des anzusprechenden Gerätes übergeben. Beispielsweise wird bei einem Drucker ein LISTEN gesendet, bevor die Zeichen zur Ausgabe über den IEC-Bus wandern. Wenn Sie LISTEN verwenden, so müssen Sie die auszugebenden Zeichen über die Routine CIOUT ausgeben (nicht über BSOUTÜ). Zum Schließen des Kanals verwenden Sie dann die Routine UNLISTEN. Es kann immer nur ein Gerät am IEC-Bus aktiv sein. Um diese komplizierten Arbeiten zu vereinfachen, können Sie im Betriebssystem Kanäle öffnen und schließen. BSOUT und BASIN übernehmen dann das Senden von LISTEN und UNLISTEN sowie TALK und UNTALK.

Eingabeparameter: .A

Beispiel:

        ;LISTEN an Drucker senden
        LDA #$24 ;Geräteadresse Drucker & LISTEN ein
        JSR $FFB1
command devices on the serial bus to LISTEN

This routine will command a device on the serial bus to receive data. The accumulator must be loaded with a device number between 4 and 31 before calling this routine. LISTEN convert this to a listen address then transmit this data as a command on the serial bus. The specified device will then go into listen mode and be ready to accept information.

Command devices on serial bus to LISTEN.

LISTEN will command any device on the serial bus to receive data.

;Command device #8 to listen.
     LDA #8
     JSR LISTEN
;The accumulator designates the device #.
Commands device to begin listening.
 Registers In  : .A = device #.
 Registers Out : .A used.
 Note          : Low level serial I/O - recommended use OPEN,CLOSE,CHROUT etc..
Send LISTEN command to serial bus.

Input: A = Device number. Output: – Used registers: A. Real address: $ED0C.

make SERIAL device listen
in: A=device number                    A - -  - - -  A - -
sendet LISTEN-Befehl auf den IEC-Bus
$FFB4 TALK IEEE 65460
Command a device on the serial bus to TALK
  • Communication registers: A
  • Preparatory routines: None
  • Error returns: See READST
  • Stack requirements: 8
  • Registers affected: A

Description: To use this routine the accumulator must first be loaded with a device number between 0 and 31. When called, this routine then ORs bit by bit to convert this device number to a talk address. Then this data is transmitted as a command on the serial bus.

How to Use:

  1. Load the accumulator with the device number.
  2. Call this routine.

EXAMPLE:

;COMMAND DEVICE #4 TO TALK
     LDA #4
     JSR TALK
Send talk with attention to serial devices

Called by: None.

Entry requirements: Accumulator should hold the serial device number (4-31 decimal).

JMP ED09/EE14 where the accumulator is ORed with $40 to set the value for a talk command to the device. Send this command over the serial data bus while the serial attention output line is held low.

TALK

This low-level 1/0 routine sends a TALK command to a serial device, Call the routine with the accumulator holding the number (4-31) of the device. The success of the operation will be indicated by the value in the serial status flag upon return, (See READST for details.)

Send TALK to a Device on the Serial Bus

When called, this routine ORs the device number in the Accumulator with the TALK code (64, $40) and sends it on the serial bus. This commands the device to TALK.

Senden von TALK an ein Gerät

Entsprechend der Routine LISTN sendet diese Routine das Kommando TALK an ein beliebiges Gerät. Die Geräteadresse ist im zu übergeben. Das Kommando TALK fordert ein am IEC-Bus angeschlossenes Gerät zum Reden, also zum Senden von Informationen auf.

Eingabeparameter: .A

command serial bus device to TALK

To use this routine the accumulator must first be loaded with a device number between 4 and 30. When called this routine converts this device number to a talk address. Then this data is transmitted as a command on the Serial bus.

Command serial bus device to TALK.

TALK. This routine will command a device on the serial bus to send data.

;Command device #8 to TALK.
     LDA #8
     JSR TALK
     RTS
;The accumulator designates the file number.
Commands device to begin talking.
 Registers In  : .A = device #.
 Registers Out : .A used.
 Memory Changed: None.
 Note          : Low level serial I/O - recommended use OPEN,CLOSE,CHROUT etc..
Send TALK command to serial bus.

Input: A = Device number. Output: – Used registers: A. Real address: $ED09.

make SERIAL device talk
in: A=device number                    A - -  - - -  A - -
sendet TALK-Befehl zum IEC-Bus
$FFB7 READST IO 65463
Read status word
  • Communication registers: A
  • Preparatory routines: None
  • Error returns: None
  • Stack requirements: 2
  • Registers affected: A

Description: This routine returns the current status of the I/O devices in the accumulator. The routine is usually called after new communication to an I/O device. The routine gives you information about device status, or errors that have occurred during the I/O operation.

The bits returned in the accumulator contain the following information: (see table below)

ST Bit Position ST Numeric Value Cassette Read Serial Bus R/W Tape Verify + Load
0 1 time out write
1 2 time out read
2 4 short block short block
3 8 long block long block
4 16 unrecoverable read error any mismatch
5 32 checksum error checksum error
6 64 end of file EOI line
7 -128 end of tape device not present end of tape

How to Use:

  1. Call this routine.
  2. Decode the information in the A register as it refers to your pro- gram.

EXAMPLE:

;CHECK FOR END OF FILE DURING READ
     JSR READST
     AND #64                       ;CHECK EOF BIT (EOF=END OF FILE)
     BNE EOF                       ;BRANCH ON EOF
Read or reset status

Called by: JSR at ABDD/CBDD in BASIC's INPUT, JSR at AF9A/CF9A in BASIC's STATUS, JSR at E180/E17D E195 in BASIC's LOAD/VERIFY.

JMP FE07/FE57 to read the I/O status word, 90, returning the value in the accumulator. This value reflects certain conditions during serial or tape I/O.

The 64/VIC Programmer's Reference Guides contain some errors:

First, when VERIFYing for a serial device, a VERIFY error can occur.

Second, for the VIC you cannot read the RS-232 status register, 0297, by calling this routine. READST for RS-232 always returns zero on the VIC. If you want to read the RS-232 status on the VIC, read 0297 directly; don't call this routine. This error in READST is corrected in the 64.

Third, detecting an end-of-tape header allows BASIC to display the DEVICE NOT PRESENT error message, but the Kernal routines for OPEN or LOAD/VERIFY do not set location 90. Thus, READST will not return the end-of-tape status condition following OPEN or LOAD/VERIFY. You can check end-of-tape status upon return from OPEN or LOAD/VERIFY by checking for the carry bit set and the accumulator set to 5, which are the conditions that indicate end-of-tape.

The table below shows the possible values returned by READST:

READST Values

Hex Value Bit Serial I/O Tape Read/LOAD/VERIFY RS-232 (64 only)
$80 7 Device not present Break detected
$40 6 EOI status End of file DSR signal missing
$20 5 Checksum error
$10 4 VERIFY error Unrecoverable read error CTS signal missing
$08 3 Long block Receive buffer empty
$04 2 Short block Receive buffer overrun
$02 1 Read timeout Framing error
$01 0 Write timeout Parity error

Status Terms

Long Block: Tape read is trying to read data bytes after the first block has already completed.

Short Block: Tape read is reading leader bits between blocks while the byte action routine is still expecting to be reading bytes from the block.

Unrecoverable Read Error: During tape read and LOAD/VERIFY, more than 31 errors were detected in block 1. This is also set if read or VERIFY errors for the same byte occurred in both blocks 1 and 2.

Checksum Error: Computed parity for the loaded area is not the same as the final byte of tape block 2 (the parity computed during the SAVE of the second block).

End of File: This status is set when doing CHRIN from tape for a sequential file and the read-ahead byte in the tape buffer

VERIFY Error: The byte retrieved from the serial device does not match the byte in memory.

EOI (End or Identify): This is set during the Receive Byte from Serial Device routine when the EOI handshake is performed. Set during serial read to indicate the last byte has been sent from the serial device. The unusual term EOI is a holdover from the IEEE-488 bus definitions used on older PET/CBM computers; you may find it simpler just to remember this as End of File for disk.

Device Not Present: Device does not respond with the proper handshake sequence during OPEN, LOAD, VERIFY, or SAVE operations.

Read Timeout, Write Timeout: Read or write timeouts are set when the serial device doesn't handshake within the allocated time.

Break Detected: This is set if the check for a stop bit finds a 0 rather than a 1, and the data bits received so far are all 0's.

Framing Error: This is set if the check for a stop bit finds a 0 and the data bits received so far included some bits set to 1.

DSR Signal Missing: The 64 can't detect the Data Set Ready signal from the RS-232 device during x-line handshaking.

CTS Signal Missing: The 64 can't detect the Clear To Send signal from the RS-232 device during x-line handshaking.

Parity Error: The parity bit indicates an error in transmission of this byte.

Receiver Buffer Empty: Nothing is in the RS-232 input buffer. This allows routines to test the status so they don't loop waiting for data.

Receiver Buffer Overun: The RS-232 input buffer is full and another byte has been received.

READST

This routine (some Commodore references call it READSS) returns the status of the most recent I/O operation. The status value will be in the accumulator upon return; the contents of .X and .Y are unaffected. If the current device number is 2 (indicating an RS-232 operation), the status value is retrieved from the RS-232 status flag (location $0297 for the 64 or $0A14 for the 128), and the flag is cleared. Otherwise, the status value is retrieved from the tape/serial status flag (location $90). That flag is not cleared after being read.

Bit Value Meaning if set Serial Meaning if set Tape Meaning if set RS-232
0 1/$01 write timeout parity error
1 2/$02 read timeout framing error
2 4/$04 short block receiver buffer overflow
3 8/$08 long block receiver buffet empty
4 16/$10 verify mismatch unrecoverable read or verify mismatch CTS missing
5 32/$20 checksum mismatch
6 64/$40 EOI (end of file) end of file DSR missing
7 128/$80 device nol present end of tape break
Read the I/O Status Word

Whenever an I/O error occurs, a bit of the Status Word is set to indicate what the problem was. This routine allows you to read the status word (it is returned in the Accumulator). If the device was the RS-232, its status register is read and cleared to zero. For the meanings of the various status codes, see the entry for location 144 ($90) or 663 ($297) for the RS-232 device.

Holen des I/O-Statusbytes

Es wird der aktuelle Systemstatus im zurückgegeben. Ist die RS232 aktiv, so wird das Statusbyte übergeben und direkt im Speicher gelöscht. Sollten Sie also das Statusbyte öfters benötigen, so speichern Sie es zwischen. Ist ein anderer als der RS232-Kanal geöffnet, so wird das Statusbyte von Adresse $90 übergeben.

Ausgabeparameter: .A

read I/O status word

This routine returns the current status of the I/O device in the accumulator. The routine is usually called after new communication to an I/O device. The routine will give information about device status, or errors that have occurred during the I/O operation.

Read I/O status word.

READST. When called, READST returns the status of the I/O devices. Any error code can be translated as operator error.

;Check for read error.
     JSR READST
     CMP #16
     BEQ ERROR
;In this case, if the accumulator is 16, a read error occurred.
Return I/O status byte.
 Registers In  : None.
 Registers Out : .A = status byte. (see section on ERROR messages).
 Memory Changed: None.
Fetch status of current input/output device, value of ST variable. (For RS232, status is cleared.)

Input: – Output: A = Device status. Used registers: A. Real address: $FE07.

read I/O status byte
out:A=status byte                      - - -  A - -  A - -
holt das Statuswort in den Akku
$FFBA SETLFS IO 65466
Set up a logical file
  • Communication registers: A, X, Y
  • Preparatory routines: None
  • Error returns: None
  • Stack requirements: 2
  • Registers affected: None

Description: This routine sets the logical file number, device address, and secondary address (command number) for other KERNAL routines.

The logical file number is used by the system as a key to the file table created by the OPEN file routine. Device addresses can range from 0 to 31. The following codes are used by the Commodore 64 to stand for the CBM devices listed below:

ADDRESS DEVICE
0 Keyboard
1 Datassette™
2 RS-232C device
3 CRT display
4 Serial bus printer
8 CBM serial bus disk drive

Device numbers 4 or greater automatically refer to devices on the serial bus.

A command to the device is sent as a secondary address on the serial bus after the device number is sent during the serial attention handshaking sequence. If no secondary address is to be sent, the Y index register should be set to 255.

How to Use:

  1. Load the accumulator with the logical file number.
  2. Load the X index register with the device number.
  3. Load the Y index register with the command.

EXAMPLE:

;FOR LOGICAL FILE 32, DEVICE #4, AND NO COMMAND:
     LDA #32
     LDX #4
     LDY #255
     JSR SETLFS
Set logical file number, device number, and secondary address

Called by: JSRs at E1DD/E1DA, E1F0/E1ED, and E1FD/E1FA in BA-SIC's Set LOAD/VERIFY/SAVE Parameters; JSRs at E22B/E228, E23F/E23C, and E24E/E24B in BASIC's Handle Parameters for OPEN and CLOSE.

Entry requirements: The accumulator should hold the logical file number, the X register should hold the device number, and the Y register should hold the secondary address.

JMP FE00/FE50 to set the logical file number, device number, and secondary address for a subsequent open, load, or save.

The logical file number can be 1-255.

The device numbers can be 0-31. Assigned device numbers include 0 for the keyboard, 1 for tape, 2 for RS-232, 3 for the screen, and 4-31 for serial bus devices. By convention, serial device numbers 4 and 5 are usually used for printers and 8-11 for disk drives.

See the comments in the paragraphs on SAVE and LOAD routines about secondary addresses. An even secondary address gives a identifier byte of 1 for a relocatable program tape header. An odd secondary address gives a tape identifier of 3 for a nonrelocatable program tape header. A secondary address that has bit 1 on (e.g., $02 or $03) produces an end-oftape header with an identifier byte of 5.

Secondary addresses >= 128 (decimal) will not be sent on the serial bus. For reading from serial, use an even secondary address. For writing to serial, use an odd secondary address. Valid secondary addresses for serial devices are 0-31 (decimal). If you specify a higher value, you may be sending a command other than what you intended, since secondary addresses greater than 31 are used to represent commands to serial devices.

SETLFS

This routine assigns the logical file number (location $B8), device number (location $BA), and secondary address location $B9) for the current I/O operation. Call the routine with the accumulator holding the logical file number, .X holding the device number, and .Y holding the secondary address. All register values are preserved during the routine. Refer to the LOAD and SAVE routines for the special significance of the secondary address in those cases. When OPENing files to serial devices, it's vital that each logical file have a unique secondary address, In the 128 Kernal, the LKUPLA and LKUPSA routines can be used to find unused logical file numbers and secondary addresses.

Set Logical File Number, Device Number, and Secondary Address

This routine stores the value in the Accumulator in the location which holds the current logical file number, the value in the .X register is put in the location that holds the current device number, and the value in the .Y register is stored in the location that holds the current secondary address. If no secondary address is used, the .Y register should be set to 255 ($FF). It is necessary to set the values of the current file number, device number, and secondary address before you OPEN a file, or LOAD or SAVE.

Fileparameter setzen

Diese Routine wird überall dort benötigt, wo man Files öffnen muß. Man übergibt die logische File-nummer im , die Geräteadresse im X-Register und die Sekundäradresse im Y-Register. Die Routine speichert diese Werte an den Zeropage-Adressen $B8 bis $BA ab.

Eingabeparameter: .A, .X, .Y

set logical, first and second addresses

This routine will set the logical file number, device address, and secondary address, command number, for other KERNAL routines.

the logical file number is used by the system as a key to the file table created by the OPEN file routine. Device addresses can range from 0 to 30. The following codes are used by the computer to stand for the following CBM devices:

ADDRESS DEVICE
0 Keyboard
1 Cassette #1
2 RS-232C device
3 CRT display
4 Serial bus printer
8 CBM Serial bus disk drive

Device numbers of four or greater automatically refer to devices on the serial bus.

A command to the device is sent as a secondary address on the serial bus after the device number is sent during the serial attention handshaking sequence. If no secondary address is to be sent Y should be set to $FF.

Set logical, first, and second address.

SETLFS stands for SET Logical address, File address, and Secondary address. After SETLFS is called, OPEN may be called.

;Set logical file #1, device #8, secondary address of 15.
     LDA #1
     LDX #8
     LDY #15
     JSR SETLFS
;If OPEN is called, the command will be OPEN 1,8,15.
Set logical file #, device #, secondary # for I/O.
 Registers In  : .A = logical file #, .X = device #, .Y = secondary #
 Registers Out : None.
 Memory Changed: None.
Set file parameters.

Input: A = Logical number; X = Device number; Y = Secondary address. Output: – Used registers: – Real address: $FE00.

set file parameters
in: A=logical file number              A X Y  A X Y  - - -        X=device number
    Y=secondary addr
setzt die Fileparameter, Akku muß logische

Filenummer enthalten, X = Gerätenummer und Y = Sekundäradresse

$FFBD SETNAM IO 65469
Set file name
  • Communication registers: A, X, Y
  • Preparatory routines:
  • Stack requirements: 2
  • Registers affected:

Description: This routine is used to set up the file name for the OPEN, SAVE, or LOAD routines. The accumulator must be loaded with the length of the file name. The X and Y registers must be loaded with the address of the file name, in standard 6502 low-byte/high-byte format. The address can be any valid memory address in the system where a string of characters for the file name is stored. If no file name is desired, the accumulator must be set to 0, representing a zero file length. The X and Y registers can be set to any memory address in that case.

How to Use:

  1. Load the accumulator with the length of the file name.
  2. Load the X index register with the low order address of the file name.
  3. Load the Y index register with the high order address.
  4. Call this routine.

EXAMPLE:

     LDA #NAME2-NAME     ;LOAD LENGTH OF FILE NAME
     LDX #<NAME          ;LOAD ADDRESS OF FILE NAME
     LDY #>NAME
     JSR SETNAM
Establish filename

Called by: JSR at E1D6/E1D3 in BASIC's Set LOAD /VERIFY /SAVE Parameters, JSRs at E21B/E218 and E261/E25E in BASIC's Handle Parameters for OPEN and CLOSE.

Entry requirements: Accumulator should contain the length of the filename. The X register should hold the low byte of the starting address of the filename. The Y register should hold the high byte of the filename address. The filename may be stored at any addressable memory location.

JMP FDF9/FE49 to prepare a filename for subsequent OPEN, LOAD/VERIFY, or SAVE processing. The accumulator value, the length of the filename, is stored in B7. The pointer to the filename from the X and Y registers is stored in (BB).

Although you could create a filename that is 255 (decimal) characters long (the accumulator can hold a maximum value of $FF or decimal 255), not all of this maximum filename size can be used.

For tape, the filename is stored in the tape buffer, which is 192 bytes long. Flowever, 5 bytes are taken for the identifier and the starting and ending addresses, which leaves 187 bytes that can be used for the filename.

One quirk with the serial devices is that if the secondary address you specify in SETLFS is larger than 128, the filename is not sent for OPEN, LOAD, or SAVE.

SETNAM

This routine assigns the length (location $B7) and address locations $BB-$BC) of the filename for the current I/O operation. Call the routine with the length of the filename in .A and the address of the first character of the name in .X (low byte) and .Y (high byte). If no name is used for the current operation, load the accumulator with 0; the values in .X and .Y are then irrelevant, All register values are preserved during this routine.

Set Filename Parameters

This routine puts the value in the Accumulator into the location which stores the number of characters in the filename, and sets the pointer to the address of the ASCII text of the filename from the .X and .Y registers. This sets up the filename for the OPEN, LOAD, or SAVE routine.

Setzen der Filenamenparameter

In der Routine werden die Informationen für den Filenamen in der Zeropage gespeichert. Diese Angaben sind alle vor dem Öffnen eines Kanales zu machen. Im wird die Länge des Filenamens übergeben, im X-Register das Lo-Byte der Adresse und im Y-Register das Hi-Byte der Adresse, an der der Filename gespeichert ist. Ferner müssen Sie mit der SETBNK-Routine die Konfigurationsindizes für den Filenamen und den zu bearbeitenden Speicherbereich übergeben.

Eingabeparameter: .A, .X, .Y

Beispiel:

        ;Eröffnen eines des Directory-Files auf Diskette
        LDA #$0C  ;Bereich im RAM-Bank 0
        TAX       ;Filename auch in RAM-Bank 0
        JSR $FF68 ;SETBNK aufrufen
        LDA #$01  ;Logische Filenummer
        LDX #$08  ;Geräteadresse
        LDY #$00  ;Sekundäradresse für Lesen
        JSR $FFBA ;SETLFS
        LDA #$01  ;Länge des Filenamens
        LDX #$00  ;Lo-Byte der Adresse, an der der
        LDY #$10  ;Filename gespeichert ist ($1000)
        JSR $FFBD ;SETNAM
        JSR $FFC0 ;OPEN - Öffnen des Kanals

und an Adresse $1000:

01000 24 ....
set the filename

This routine is used to set up the file name for the OPEN, SAVE, or LOAD routines. The accumulator must be loaded with the length of the file and XY with the pointer to file name, X being th low byte. The address can be any valid memory address in the system where a string of characters for the file name is stored. If no file name desired the accumulator must be set to 0, representing a zero file length, in that case XY may be set to any memory address.

Set filename.

SETNAM. In order to access the OPEN, LOAD, or SAVE routines, SETNAM must be called first.

;SETNAM will prepare the disk drive for'FILE#1'.
     LDA #6
     LDX #L,NAME
     LDY #H,NAME
     JSR SETNAM
NAME .BY 'FILE#1'
;Accumulator is file length, X is low byte, and Y is high byte.
Sets pointer to filename in preperation for OPEN.
 Registers In  : .A = string length, .XY = string address.
 Registers Out : None.
 Memory Changed: None.
 Note          : To specify _no_ filename specify a length of 0.
Set file name parameters.

Input: A = File name length; X/Y = Pointer to file name. Output: – Used registers: – Real address: $FDF9.

set file name
in: A=length of filename               A X Y  A X Y  - - -        Y/X=pointer to name addr
setzt Parameter des Filenamens, Akku muß

Länge des Namens enthalten, X und Y enthalten die Adresse des Filenamens (Low- und High-Byte)

$FFC0 OPEN IO 65472
Open a logical file
  • Communication registers: None
  • Preparatory routines: SETLFS, SETNAM
  • Error returns: 1,2,4,5,6,240, READST
  • Stack requirements: None
  • Registers affected: A, X, Y

Description: This routine is used to OPEN a logical file. Once the logical file is set up, it can be used for input/output operations. Most of the I/O KERNAL routines call on this routine to create the logical files to operate on. No arguments need to be set up to use this routine, but both the SETLFS and SETNAM KERNAL routines must be called before using this routine.

How to Use:

  1. Use the SETLFS routine.
  2. Use the SETNAM routine.
  3. Call this routine.

EXAMPLE:

This is an implementation of the BASIC statement: OPEN 15,8,15,"I/O"

     LDA #NAME2-NAME    ;LENGTH OF FILE NAME FOR SETLFS
     LDY #>NAME         ;ADDRESS OF FILE NAME
     LDX #<NAME
     JSR SETNAM
     LDA #15
     LDX #8
     LDY #15
     JSR SETLFS
     JSR OPEN
NAME .BYT 'I/O'
NAME2
Open logical file

Called by: JSR at E1C1/E1BE in BASIC's OPEN.

Setup routines: SETLFS, SETNAM

JMP(031A) with a default of F34A/F40A.

OPEN checks whether another logical file can be opened. Another logical file can be opened if the logical file number is not 0 and if fewer than ten logical files are already open. OPEN exits if trying to open to the screen or keyboard, as these devices do not use files.

For a serial device, OPEN commands the serial device to listen and then sends a secondary address for OPEN to this serial device.

For tape, OPEN checks for a tape header of a sequential file if reading, or writes a tape header for a sequential file if writing.

The RS-232 OPEN initializes various RS-232 lines and creates two 256-byte buffers at the top of memory. RS-232 OPEN handles the x-line handshaking opening sequence incorrectly on the VIC.

OPEN

This routine opens a logical file to a specified device in preparation for input or output. At least one preparatory step is required before the standard OPEN routine is called: SETLFS must be called to establish the logical file number, device number, and secondary address, For tape (device 1), RS-232 (device 2), or serial (device 4 or higher), SETNAM is also required to specify the length and address of the associated filename. Tor the 128, SETBNK must be called to establish the bank number where the filename can he found.

It is not necessary to load any registers before calling OPEN, and all processor register values may be changed during the routine. The carry will be clear if the file was successfully opened, or it will be set if it could not be opened. When carry is set upon return, the accumulator will hold an error code indicating the problem. Possible error-code values include 1 (ten files—the maximum allowed—are already open), 2 (a currently open file already uses the specified logical file number), and 5 (specified device did not respond). The RS-232 and tape/serial status flags will also reflect the success of the operation for those devices, (See READST for details.)

On the 128, there is an exception to the carry-bit rule. Because of a bug in the 128's RS-232 OPEN routine, carry will be set if the RS-232 device is present when x-line handshaking is used (if the DSR line is high), or clear if the device is absent—the opposite of the proper setting.

The JMP to the OPEN execution routine is by way of the IOPEN indirect vector $031A-$031B. You can modify the actions of the routine by changing the vector to point to a routine of your own,

Open a Logical I/O File

The routine jumps through a RAM vector at 794 ($31A). This routine assigns a logical file to a device, so that it can be used for Input/Output operations. In order to specify the logical file number, the device number, and the secondary address if any, the SETLFS routine must first be called. Likewise, in order to designate the filename, the SETNAM routine must be used first. After these two routines are called, OPEN is then called.

Öffnen einer Datei

Es wird die durch die Routinen SETNAM, SETLFS und SETBNK definierte Datei in die Liste der logischen Filenummern aufgenommen. Erst ab diesem Augenblick können die logischen Filenummern bei den Routinen CKOUT und CHKIN angegeben werden. Beachten Sie, daß Sie maximal neun Files auf einmal öffnen können.

open a logical file

This routine is used to open a logical file. Once the logical file is set up it can be used for input/output operations. Most of the I/O KERNAL routines call on this routine to create the logical files to operate on. No arguments need to be set up to use this routine, but both the SETLFS, $FFBA, and SETNAM, $FFBD, KERNAL routines must be called before using this routine.

Open a logical file.

OPEN. After SETLFS and SETNAM have been called, you can OPEN a logical file.

;Duplicate the command OPEN 15,8,15,'I/O'
     LDA #3
     LDX #L,NAME
     LDY #H,NAME
     JSR SETNAM
     LDA #15
     LDX #8
     LDY #15
     JSR SETLFS
     JSR OPEN
     RTS
NAME .BY 'I/O'
;OPEN opens the current name file with the current LFS.
Open up file that has been setup by SETNAM,SETLFS
 Registers In  : None.
 Registers Out : .A = error code, .X,.Y destroyed.
                 .C = 1 if error.
 Memory Changed: None.
Open file. (Must call SETLFS and SETNAM beforehands.)

Input: – Output: – Used registers: A, X, Y. Real address: ($031A), $F34A.

open log.file after SETLFS,SETNAM
out:A=error# if C=1                    - - -  - - -  A X Y
OPEN-Befehl, öffnet logische Datei
$FFC3 CLOSE IO 65475
Close a logical file
  • Communication registers: A
  • Preparatory routines: None
  • Error returns: 0,240 (See READST)
  • Stack requirements: 2+
  • Registers affected: A, X, Y

Description: This routine is used to close a logical file after all I/O operations have been completed on that file. This routine is called after the accumulator is loaded with the logical file number to be closed (the same number used when the file was opened using the OPEN routine).

How to Use:

  1. Load the accumulator with the number of the logical file to be closed.
  2. Call this routine.

EXAMPLE:

;CLOSE 15
     LDA #15
     JSR CLOSE
Close logical file

Called by: JSR at E1CC/E1C9 in BASIC's CLOSE

Entry requirements: Accumulator should contain the number of the logical file to be closed.

JMP(031C) with a default of F291/F34A.

If the logical file number in the accumulator is found in the logical file number table, also retrieve the current device number from the device number table and the secondary address from the secondary address table.

Then, execute the appropriate CLOSE routine for this current device.

If accessing a serial device, for secondary addresses < 128 (decimal), command the current device to LISTEN, send a CLOSE secondary address, and command the serial device to UNLISTEN. For secondary addresses > 128, this close sequence is omitted.

For an RS-232 device, bring the transmitted data line high, which is the idle state for RS-232 communications. Also, reset the pointers to the end of memory by reclaiming the space used for the RS-232 transmit and receive buffers.

When closing a logical tape file, determine whether writing to or reading from tape. If writing to tape then store a final byte of 0 in the tape buffer and write the buffer to tape.

For all types of devices, a common CLOSE exit is used. The number of open files, 98, is decremented, and the entry for this logical file is deleted from the logical file number table, the device number table, and the secondary address table.

CLOSE

This routine closes a specified logical file. Call the routine with the accumulator holding the number of the logical file to be closed. If no file with the specified logical file number is currently open, no action is taken and no error is indicated. If a file with the specified number is open, its entry in the logical file number, device number, and secondary address tables will be removed. For RS-232 files, the driving CLA #2 interrupts will also be disabled. For tape files, the final block of data will be written to tape (followed by an end-of-tape marker, if one was specified). For disk files, the EOI sequence will be performed.

The 128 version of the routine offers a special close function for disk files: Ff this routine is called with the statusregister carry bit set, and if the device number for the file is 8 or greater, and if the file was opened with a secondary address of 15, then the EOI sequence is skipped. (The table entries for the file are deleted, but that's all.) This solves a problem in earlier versions of the Kernal for disk files opened with a secondary address of 15, the command channel to the drive. An attempt to close the command channel will result in an EOI sequence that closes all files currently open to the drive, not just the command-channel file, This special mode allows the command-channel file to be closed without disturbing other files that may be open to the drive.

The JMP to the CLOSE execution routine is by way of the ICLOSE indirect vector at $031C-$031D. You can modify the actions of the routine by changing the vector to point to a routine of your own.

Close a Logical I/O File

The routine jumps through a RAM vector at 796 ($31C). It is used to close a logical file after all I/O operations involving that file have been completed. This is accomplished by loading the Accumulator with the logical file number of the file to be closed, and calling this routine.

Closing an RS-232 file will de-allocate space at the top of memory for the receiving and trasmit buffers. Closing a cassette file that was opened for writing will force the last block to be written to cassette, even if it is not a full 192 bytes. Closing a serial bus device will send an UNLISTEN command on the bus. Remember, it is necessary to properly CLOSE a cassette or disk data file in order to retrieve the file later.

For all types of files, CLOSE removes the file's entry from the tables of logical files, device, and secondary address at 601, 611, and 621 ($259, $263, $26D), and moves all higher entries in the table down one space.

Schließen einer logischen Datei

Es wird die im übergebene logische Datei geschlossen. Dabei werden alle gespeicherten Werte wie Geräteadresse, Sekundäradresse etc. in der dafür vorgesehenen Tabelle gelöscht. Ist die Aktion nicht problemlos verlaufen, so wird das CARRY-Flag gesetzt.

Eingabeparameter: .A

Ausgabeparameter: CARRY

Beispiel:

        ;Beispiel für CLOSE
        LDA #$01  ;Schließen der Beispieldatei von SETNAM
        JSR $FFC3 ;CLOSE ausführen
        BCS Error ;Fehler aufgetreten
close a specified logical file

This routine is used to close a logical file after all I/O operations have been completed on that file. This routine is called after the accumulator is loaded with the logical file number to be closed, the same number used when the file was opened using the OPEN routine.

Close a specified logical file.

CLOSE. This routine will CLOSE any logical file that has been OPENed.

;Close logical file #2.
     LDA #2
     JSR CLOSE
;The accumulator designates the file #.
Close a logical file.
 Registers In  : .A = logical file #.
 Registers Out : .A = error code, .X,.Y destroyed.
                 .C = 1 if error
 Memory Changed: None.
Close file.

Input: A = Logical number. Output: – Used registers: A, X, Y. Real address: ($031C), $F291.

close a logical file
in: A=logical file number              A - -  - - -  A X Y
CLOSE-Befehl, schließt logische Datei,

Akku muß logische Filenummer enthalten

$FFC6 CHKIN IO 65478
Open a channel for input
  • Communication registers: X
  • Preparatory routines: (OPEN)
  • Error returns: 0,3,5,6 (See READST)
  • Stack requirements: None
  • Registers affected: A, X

Description: Any logical file that has already been opened by the KERNAL OPEN routine can be defined as an input channel by this routine. Naturally, the device on the channel must be an input device. Otherwise an error will occur, and the routine will abort.

If you are getting data from anywhere other than the keyboard, this routine must be called before using either the CHRIN or the GETIN KERNAL routines for data input. If you want to use the input from the keyboard, and no other input channels are opened, then the calls to this routine, and to the OPEN routine are not needed.

When this routine is used with a device on the serial bus, it automatically sends the talk address (and the secondary address if one was specified by the OPEN routine) over the bus.

How to Use:

  1. OPEN the logical file (if necessary; see description above).
  2. Load the X register with number of the logical file to be used.
  3. Call this routine (using a JSR command).

EXAMPLE:

     ;PREPARE FOR INPUT FROM LOGICAL FILE 2
     LDX #2
     JSR CHKIN
Open channel for input

Called by: JSR at E11E/E11B in BASIC's Set Input Device.

Setup routines: OPEN

Entry requirements: The X register should contain the logical file number.

JMP (031E) with a default of F20E/F2C7. If the logical file is in the logical file number table, the routine obtains the device number and secondary address for this logical file from the corresponding entries in the device number and secondary address tables. If the logical file is not in the logical file number table, it displays FILE NOT OPEN, and returns with carry set and accumulator set to 3.

If the current device is the screen or the keyboard, the routine stores 0 for the keyboard or 3 for the screen in 99, the location holding the device number of the current input device. You don't have to use OPEN and CHRIN to input from the keyboard.

If the current device is the tape, the routine also checks the secondary address. If the current secondary address is not $60, the routine displays the NOT INPUT FILE message, and returns with carry set and accumulator set to 6. If the current secondary address is $60, then location 99 is set to 1 to make tape the current input device. OPEN does an ORA $60 of the secondary address.

If the current device is a serial device, it opens the input channel by sending a TALK command to the device, and sending the secondary address if the value for secondary address held in B9 is < 128 (decimal). If the serial device does not respond, it displays the DEVICE NOT PRESENT error message and returns with carry set and accumulator set to 5. Otherwise, it stores the serial device number in 99.

If the current device is RS-232, the routine opens an RS-232 input channel. This RS-232 routine sets the current input device, location 99, to 2 for RS-232, then handles either the 3line handshaking or the x-line handshaking opening sequence.

CHKIN

This routine specifies a logical file as the source of input in preparation for using the CHRIN or GETIN routines. The logical file should be opened before this routine is called. (See the OPEN routine.) The desired logical file number should be in .X when this routine is called. The contents of .Y are unaffected, but the accumulator value will be changed.

The routine sets the input channel (location $99) to the device number for the specified file. If the device is RS-232 (device number 2), the CIA #2 interrupts for RS-232 reception are enabled. Ef a serial device (device number 4 or greater) was specified, the device is made a talker on the serial bus,

If the file is successfully set for input, the status-register carry bit will be clear upon return. If carry is set, the operation was unsuccessful and the accumulator will contain a Kernal error-code value indicating which error occurred. Possible error codes include 3 (file was not open), 5 (device did not respond), and 6 (file was not opened for input). The RS-232 and serial status-flag locations also reflect the success of operations for those devices. (See READST for details.)

The JMP to the CEDGN execution routine is by way of the ICHKDN indirect vector at 798-799 ($031E-$031F). You can modify the actions of CHfQN by changing the vector to point to a routine of your own.

Designate a Logical File As the Current Input Channel

The routine jumps through a RAM vector at 798 ($31E). If you wish to get data from any device other than the keyboard, this routine must be called after OPENing the device, before you can get a data byte with the CHRIN or GETIN routine. When called, the routine will designate the logical file whose file number is in the .X register as the current file, its device as the current device, and its secondary address as the current secondary address. If the device on the channel is a serial device, which requires a TALK command and sometimes a secondary address, this routine will send them over the serial bus.

Logische Datei als Eingabekanal definieren

Im X-Register wird die logische Dateinummer übergeben, die als Eingabekanal benutzt werden soll. Die angegebene logische Dateinummer muß natürlich bereits mit dem OPEN-Kommando geöffnet worden sein. Wird nach dem Aufruf des CHKIN-Kommandos die BASIN-Routine aufgerufen, so erfolgt die Eingabe nicht von Tastatur, sondern von dem geöffneten Gerät; dies kann beispielsweise die Floppy sein. Zu beachten ist, daß zum Einlesen von Tastatur kein CHKIN notwendig ist, da die Tastatur Standard-Eingabegerät ist. Nach einem CLOSE oder CLRCH ist die Tastatur automatisch wieder das Eingabegerät. Auch bei dieser Routine wird das CARRY als OK-Flag benutzt.

Eingabeparameter: .X

Ausgabeparameter: CARRY

Beispiel:

        ;Einlesen der Directory
        JSR DIROP ;OPEN 1,8,0,"$" (selbstdefinierte Routine)
        LDX #$01  ;LFN der eröffneten Datei
        JSR $FFC6 ;CHKIN ausführen
        JSR $FFCF ;BASIN - Zeichen holen
open channel for input

Any logical file that has already been opened by the OPEN routine, $FFC0, can be defined as an input channel by this routine. the device on the channel must be an input device or an error will occur and the routine will abort.

If you are getting data from anywhere other than the keyboard, this routine must be called before using either the CHRIN routine, $FFCF, or the GETIN routine, $FFE4. if you are getting data from the keyboard and no other input channels are open then the calls to this routine and to the OPEN routine, $FFC0, are not needed.

When used with a device on the serial bus this routine will automatically send the listen address specified by the OPEN routine, $FFC0, and any secondary address.

Possible errors are:

  • 3 : file not open
  • 5 : device not present
  • 6 : file is not an input file
Open channel for input.

CHKIN is used to define any OPENed file as an input file. OPEN must be called first.

;Define logical file #2 as an input channel.
     LDX #2
     JSR CHKIN
;The X register designates which file #.
Sets input channel.
 Registers In  : .X = logical file #.
 Registers Out : .A = error code, .X,.Y destroyed.
                 .C = 1 if error
 Memory Changed: None.
Define file as default input. (Must call OPEN beforehands.)

Input: X = Logical number. Output: – Used registers: A, X. Real address: ($031E), $F20E.

open channel for input
in: X=logical file number              - X -  - - -  A X -
CHKIN setzt folgende Eingabe auf logische

Datei, die in X übergeben wird. Die logische Datei muß vorher mit der OPEN-Routine geöffnet werden.

$FFC9 CHKOUT IO 65481
Open a channel for output
  • Communication registers: X
  • Preparatory routines: (OPEN)
  • Error returns: 0,3,5,7 (See READST)
  • Stack requirements: 4+
  • Registers affected: A, X

Description: Any logical file number that has been created by the KERNAL routine OPEN can be defined as an output channel. Of course, the device you intend opening a channel to must be an output device. Otherwise an error will occur, and the routine will be aborted.

This routine must be called before any data is sent to any output device unless you want to use the Commodore 64 screen as your output device. If screen output is desired, and there are no other output channels already defined, then calls to this routine, and to the OPEN routine are not needed.

When used to open a channel to a device on the serial bus, this routine will automatically send the LISTEN address specified by the OPEN routine (and a secondary address if there was one).

How to Use:

REMEMBER: this routine is NOT NEEDED to send data to the screen.
  1. Use the KERNAL OPEN routine to specify a logical file number, a LISTEN address, and a secondary address (if needed).
  2. Load the X register with the logical file number used in the open statement.
  3. Call this routine (by using the JSR instruction).

EXAMPLE:

     LDX #3        ;DEFINE LOGICAL FILE 3 AS AN OUTPUT CHANNEL
     JSR CHKOUT
Open channel for output

Called by: JSR at E4AE/E115 in BASIC's Set Output Device.

Entry requirements: Set X register to logical file number.

JMP (0320) with default of F250/F309. If the logical file is in the logical file number table, obtain the device number and secondary address for this logical file from the corresponding entries in the device number and secondary address tables. If the logical file is not in the logical file number table, display the FILE NOT OPEN message, and return with carry set and accumulator set to 3.

If the current device is the keyboard, display the NOT OUTPUT FILE message, and return with carry set and accumulator set to 7.

If the current device is the screen, just set 9A, the current output device, to 3, and exit. You do not have to call OPEN and CHROUT to display on the screen.

If the current device is tape, also check the secondary address. If the secondary address is not $61, display the NOT OUTPUT FILE message, and return with carry set and accumulator set to 7. If the current secondary address is $61, set 9A to 1 for tape. Note: OPEN does an ORA $60 of the secondary address.

If the current device is a serial device, open the output channel for a serial device. Do this by commanding the current device to listen. Then for secondary addresses < 128, set the serial attention output line high. If the serial device does not handshake as expected, display DEVICE NOT PRESENT, and return with carry set and accumulator set to 5. Otherwise, set 9A to the serial device number.

If the current device is RS-232, then open an RS-232 output channel. This routine sets 9A to 2, and then it handles the 3-line or x-line handshaking sequence.

CHKOUT

This routine (some Commodore references call it CKOUT) specifies a logical file as the recipient of output in preparation for using the CHROUT routine. The logical file should be opened before this routine is called. (See the OPEN routine.) The desired logical file number should be in .X when this routine is called. The contents of .Y are unaffected, but the accumulator will be changed.

The routine sets the output channel (location $9A) to the device number for the specified file. If the device is RS-232 (device number 2), the routine also enables the CLA #2 interrupts for RS-232 transmission. fi a serial device (device number 4 or greater) is specified, the device is also made a listener on the serial bus.

If the file is successfully set for output, the status-register carry bit will be clear upon return. If the carry is set, the operation was unsuccessful, and the accumulator will contain a Kernal error-code value indicating which error occurred. Possible error codes include 3 (file was not open), 5 (device did not respond), and 7 (file was not opened for output). The RS-232 and serial status-flag locations also reflect the success of operations for those devices. (See READST for details.)

The JMP to the CHKOUT execution routine is by way of the ICKOUT indirect vector at $0320-$0321. You can modify the actions of the routine by changing the vector to point to a routine of your own.

Designate a Logical File As the Current Output Channel

The routine jumps through a RAM vector at 800 ($320). If you wish to output data to any device other than the screen, this routine must be called after OPENing the device, and before you output a data byte with the CHROUT routine. When called, the routine will designate the logical file whose file number is in the .X register as the current file, its device as the current device, and its secondary address as the current secondary address. If the device on the channel uses the serial bus, and therefore requires a LISTEN command and possibly a secondary address, this information will be sent on the bus.

Logische Datei als Ausgabedatei definieren

Entsprechend zu CHKIN definiert diese Routine ein im X-Register zu übergebene Datei als Ausgabedatei. Die Datei muß ordnungsgemäß geöffnet worden sein, beispielsweise würde eine Datei, die mit OPEN 1,8,0,"$" geöffnet wurde und mit CKOUT als Ausgabedatei definiert werden soll, einen Fehler hervorrufen, weil diese Datei zum Lesen und nicht zum Schreiben geöffnet wurde. Nach Definition einer Ausgabedatei ist nicht mehr der Bildschirm, sondern die definierte Datei Ausgabegerät. Alle über BSOUT auzugebenen Zeichen werden an dieses Gerät gesandt. Das CARRY-Flag dient als Fehlermelder. Ist es gelöscht, war die Aktion erfolgreich.

Eingabeparameter: .X

Ausgabeparameter: CARRY

open channel for output

Any logical file that has already been opened by the OPEN routine, $FFC0, can be defined as an output channel by this routine the device on the channel must be an output device or an error will occur and the routine will abort.

If you are sending data to anywhere other than the screen this routine must be called before using the CHROUT routine, $FFD2. if you are sending data to the screen and no other output channels are open then the calls to this routine and to the OPEN routine, $FFC0, are not needed.

When used with a device on the serial bus this routine will automatically send the listen address specified by the OPEN routine, $FFC0, and any secondary address.

Possible errors are:

  • 3 : file not open
  • 5 : device not present
  • 7 : file is not an output file
Open channel for output.

CHKOUT. Just like CHKIN, but it defines the file for output. OPEN must be called first.

;Define logical file #4 as an output file.
     LDX #4
     JSR CHKOUT
;Once again the X register defines the file #.
Sets output channel.
 Registers In  : .X = logical file #.
 Registers Out : .A = error code, .X,.Y destroyed.
                 .C = 1 if error
 Memory Changed: None.
Define file as default output. (Must call OPEN beforehands.)

Input: X = Logical number. Output: – Used registers: A, X. Real address: ($0320), $F250.

open channel for output
in: X=logical file number              - X -  - - -  A X -
CKOUT setzt folgende Ausgabe auf logische

Datei, die in X übergeben wird. Die logische Datei muß vorher mit der OPEN-Routine geöffnet werden.

$FFCC CLRCHN IO 65484
Clear I/O channels
  • Communication registers: None
  • Preparatory routines: None
  • Error returns:
  • Stack requirements: 9
  • Registers affected: A, X

Description: This routine is called to clear all open channels and restore the I/O channels to their original default values. It is usually called after opening other I/O channels (like a tape or disk drive) and using them for input/output operations. The default input device is 0 (keyboard). The default output device is 3 (the Commodore 64 screen).

If one of the channels to be closed is to the serial port, an UNTALK signal is sent first to clear the input channel or an UNLISTEN is sent to clear the output channel. By not calling this routine (and leaving listener(s) active on the serial bus) several devices can receive the same data from the Commodore 64 at the same time. One way to take advantage of this would be to command the printer to TALK and the disk to LISTEN. This would allow direct printing of a disk file.

This routine is automatically called when the KERNAL CLALL routine is executed.

How to Use:

  1. Call this routine using the JSR instruction.

EXAMPLE:

JSR CLRCHN
Reset I/O channels

Called by: JSR at A447/C447 in BASIC's Error Message Handler, JSR at ABB7/CBB7 in BASIC's INPUT#, JSR at E37B/E467 in BA-SIC's Warm Start, JSR at F6F4/F777 in Test for STOP Key, JSR at F716/F799 in Error Message Handler.

JMP(0322) with a default of F333/F3F3.

If the current output device is a serial device, send an UNLISTEN command on the serial bus. If the current input device is a serial device, send an UNTALK command on the serial bus.

Set 99, the current input device, to be the keyboard.

Set 9A, the current output device, to be the screen.

CLRCHN

This routine restores the default I/O sources for the operating system. The output channel (location $9A) is reset to device 3, the video display. (If the previous output channel was a serial device, it is sent an UNLISTEN command.) The input channel (location $99) is reset to device 0, the keyboard, (if the previous input channel was a serial device, it is sent an UNTALK command.) The contents of .X and .A are changed, but .Y is unaffected.

The JMP to the CLRCHN execution routine is by way of the lCLRCH indirect vector at $0322-$0323. You can modify the actions of the routine by changing the vector to point to a routine of your own.

Restore Current Input and Output Devices to the Default Devices

The routine jumps through a RAM vector at 802 ($322). It sets the current input device to the keyboard, and the current output device to the screen. Also, if the current input device was formerly a serial device, the routine sends it an UNTALK command on the serial bus, and if a serial device was formerly the current output device, the routine sends it an UNLISTEN command.

Ein/Ausgabekanäle schließen

Diese Routine löscht evtl, mit CHKIN und/oder CKOUT definierte Ein- und Ausgabedateien. Es wird an das Eingabegerät ein UNTALK und an das Ausgabegerät ein UNLISTEN gesendet. Der Bildschirm ist wieder Ausgabe - und die Tastatur Eingabegerät. Die Dateien werden nicht geschlossen, es erfolgt also kein CLOSE. Es werden weder Ein- noch Ausgabeparameter übergeben.

close input and output channels

This routine is called to clear all open channels and restore the I/O channels to their original default values. It is usually called after opening other I/O channels and using them for input/output operations. The default input device is 0, the keyboard. The default output device is 3, the screen.

If one of the channels to be closed is to the serial port, an UNTALK signal is sent first to clear the input channel or an UNLISTEN is sent to clear the output channel. By not calling this routine and leaving listener(s) active on the serial bus, several devices can receive the same data from the VIC at the same time. One way to take advantage of this would be to command the printer to TALK and the disk to LISTEN. This would allow direct printing of a disk file.

Close input and output channels.

CLRCHN resets all channels and I/O registers - the input to keyboard and the output to screen.

;Restore default values to I/O devices.
     JSR CLRCHN
     RTS
;The accumulator and the X register are altered.
Restore default input and output channels.
 Registers In  : None.
 Registers Out : .A, .X used.
 Memory Changed: None.
Close default input/output files (for serial bus, send UNTALK and/or UNLISTEN); restore default input/output to keyboard/screen.

Input: – Output: – Used registers: A, X. Real address: ($0322), $F333.

restore default devices
                                       - - -  - - -  A X -
CLRCH setzt die Ein- und Ausgabe wieder

auf Standard (Tastatur/Bildschirm)

$FFCF CHRIN IO 65487
Get a character from the input channel
  • Communication registers: A
  • Preparatory routines: (OPEN, CHKIN)
  • Error returns: 0 (See READST)
  • Stack requirements: 7+
  • Registers affected: A, X

Description: This routine gets a byte of data from a channel already set up as the input channel by the KERNAL routine CHKIN. If the CHKIN has NOT been used to define another input channel, then all your data is expected from the keyboard. The data byte is returned in the accumulator. The channel remains open after the call.

Input from the keyboard is handled in a special way. First, the cursor is turned on, and blinks until a carriage return is typed on the keyboard. All characters on the line can be retrieved one at a time by calling this routine once for each character. When the carriage return is retrieved, the entire line has been processed. The next time this routine is called, the whole process begins again, i.e., by flashing the cursor.

How to Use:

FROM THE KEYBOARD

  1. Retrieve a byte of data by calling this routine.
  2. Store the data byte.
  3. Check if it is the last data byte (is it a CR?)
  4. If not, go to step 1.

EXAMPLE:

     LDY $#00      ;PREPARE THE Y REGISTER TO STORE THE DATA
RD   JSR CHRIN
     STA DATA,Y    ;STORE THE YTH DATA BYTE IN THE YTH
                   ;LOCATION IN THE DATA AREA.
     INY
     CMP #CR       ;IS IT A CARRIAGE RETURN?
     BNE RD        ;NO, GET ANOTHER DATA BYTE

EXAMPLE:

     JSR CHRIN
     STA DATA

FROM OTHER DEVICES

  1. Use the KERNAL OPEN and CHKIN routines.
  2. Call this routine (using a JSR instruction).
  3. Store the data.

EXAMPLE:

     JSR CHRIN
     STA DATA
Get a byte from input channel

Called by: JSR at E112/E10F in BASIC's Input a Character.

Setup routines: OPEN, CHKIN (not required in retrieving from keyboard).

JMP (0324) with default of F157/F20E.

If the current input device, 99, is tape, then return the next byte from the tape buffer. Also, read one byte ahead to see if the next byte is zero, indicating end of file, and if true, set end-of-file status in 90.

If the current input device, 99, is a serial device, the accumulator returns the byte received over the serial bus. However, if there are any I/O status errors, return with accumulator set to $0D

If the current input device, 99, is RS-232, return with the next character from the RS-232 receive buffer. However, if the receive buffer is empty, the RS-232 routine on the VIC just loops until the receive buffer contains a character. The VIC can hang in an infinite loop if the RS-232 receive buffer never gets another character. If the receive buffer is empty on the 64, the routine returns with $0D in the accumulator.

If the current input device is the keyboard, each character typed (except for control characters such as the cursor keys) is displayed on the screen until the unshifted RETURN is entered. Once an unshifted RETURN is typed, reset the input routine to retrieve a character from this screen line. After each character is retrieved from the screen line, increment the pointer to the character being retrieved in this logical line. The screen POKE code is converted to the equivalent ASCII code, which is returned in the accumulator. If the end of the screen line has been reached, then return $0D, the ASCII code for a carriage return. The screen editor routines limit the size of a logical line to 80/88 characters. The way this CHRIN from the keyboard is typically used is to fill a buffer as BASIC does. BASIC calls the CHRIN routine to fill the BASIC input buffer at 0200. The BASIC routine keeps putting characters in the buffer until CHRIN retrieves a carriage return (ASCII $0D).

If the current input device, 99, is the screen, then return the ASCII code for the screen character in the current logical line pointed to by D3, the column the cursor is on. D3 is then incremented to point to the next character in the line. If D3 has reached the end of the line, return $0D signifying carriage return, and set D0 to 0 to force the next CHRIN to come from the keyboard.

When doing CHRIN from the keyboard, the keyboard routine uses this CHRIN from the screen once the carriage return has been entered. After processing the screen characters, the screen CHRIN then resets a flag at D0 to 0 to force input from the keyboard for the next CHRIN.

Exit conditions: Accumulator holds byte returned from channel.

CHRIN

This high-level I/O routine (some Commodore references may call it BASIN) receives a byte from the logical file currently specified for input (to change the default input device, see CHKIN above). Except to use the routine to retrieve input from the keyboard when the system is set for default I/O, you must open a logical file to the desired device and specify the file as the input source before calling this routine. (See the OPEN and CHKIN routines.)

For keyboard input (device 0), the routine accepts keypresses until RETURN is pressed, and then returns characters from the input string one at a time on each subsequent call. The character code for RETURN, 13, is returned when the end of an input string is reached. (The Kernal GETIN routine is better for retrieving individual keypresses.)

For tape (device 1), the routine retrieves the next character from the cassette buffer. If all characters have been read from the buffer, the next data block is read from tape into the buffer.

For RS-232 (device 2), the routine returns the next available character from the RS-232 input buffer. If the buffer is empty, the routine waits until a character is received—unless the RS-232 status flag indicates that the DSR signal from the external device is missing, in which case a RETURN character code, 13, is returned.

CHRIN from the screen (device 3) retrieves characters one at a time from the current screen line, ending with a RETURN character code when the last nonspace character on the logical line is reached. (Note that CHRIN from the screen does not work properly in the original version of the 128 Kernal.) For serial devices (device numbers 4 and higher), the routine returns the next available character from the serial bus, unless the serial status flag contains a nonzero value. In that case, the RETURN character code is returned.

For all input devices, the received byte will be in the accumulator upon return. The contents of .X and .Y are preserved during input from the keyboard, screen, or RS-232. For input from tape, only .X is preserved. For input from serial devices, only .Y is preserved. For input from the screen, keyboard, or serial devices, the status-register carry bit will always be clear upon return. For tape input, the carry bit will be clear unless the operation was aborted by pressing the RUN/STOP key. For tape, serial, or RS-232 input, the success of the operation will be indicated by the value in the status-flag location. (See the entry for READST.) The RS-232 portion of the original 128 version of CHRRsJ has a bug: The carry bit will be set if a byte was successfully received, and will be clear only if the DSR signal is missing—the opposite of the settings for the 64. It's better to judge the success of an RS-232 operation by the value in the status-flag location rather than by the carrybit setting. (See the READST routine.)

TheJMP to the CHREN execution routine is by way of the ICHRfN indirect vector at $0324-$0325. You can modify the actions of the routine by changing the vector to point to a routine of your own.

Input a Character from the Current Device

The routine jumps through a RAM vector at 804 ($324). Its function is to get a character from the current input device (whose device number is stored at 153 ($99)). This device must first have been OPENed and then designated as the input channel by the CHKIN routine.

When this routine is called, the next byte of data available from this device is returned in the Accumulator. The only exception is the routine for the keyboard device (which is the default input device). It the keyboard is the current input device, this routine blinks the cursor, fetches characters from the keyboard buffer, and echoes them to the screen until a carriage return is encountered. When a carriage return is round, the routine sets a flag to indicate the length of the last logical line before the return character, and reads the first character of this logical line from the screen.

Subsequent calls to this routine will cause the next character in the line to be read from the screen and returned in the Accumulator, until the carriage return character is returned to indicate the end of the line. Any call after this character is received will start the whole process over again.

Note that only the last logical line before the carriage return is used. Any time you type in more than 80 characters, a new logical line is started. This routine will ignore any characters on the old logical line, and process only the most recent 80-character group.

Ein Zeichen von Eingabekanal holen

Die eröffnete und mit CHKIN als Eingabedatei definierte Datei (sonst Tastatur) übergibt ein Zeichen im .

Ausgabeparameter: .A

input character from channel

This routine will get a byte of data from the channel already set up as the input channel by the CHKIN routine, $FFC6.

If CHKIN, $FFC6, has not been used to define another input channel the data is expected to be from the keyboard. the data byte is returned in the accumulator. the channel remains open after the call.

Input from the keyboard is handled in a special way. first, the cursor is turned on and it will blink until a carriage return is typed on the keyboard. all characters on the logical line, up to 80 characters, will be stored in the BASIC input buffer. then the characters can be returned one at a time by calling this routine once for each character. when the carriage return is returned the entire line has been processed. the next time this routine is called the whole process begins again.

Input character from channel.

CHRIN will get a character from the current input device. Calling OPEN and CHKIN can change the input device.

;Store a typed string to the screen.
     LDY #$00
LOOP JSR CHKIN
     STA $0800,Y
     INY
     CMP #$0D
     BNE LOOP
     RTS
;This example is like an INPUT statement. Try running it.
Read character from current input channel.
 Cassette - Returned one character a time from cassette buffer.
 Rs-232   - Return one character at a time, waiting until
            character is ready.
 Serial   - Returned one character at time, waiting if nessc.
 Screen   - Read from current cursor position.
 Keyboard - Read characters as a string, then return them
            individually upon each call until all characters
            have been passed ($0d is the EOL).

 Registers In  : None.
 Registers Out : .A = character or error code, .C = 1 if error.
 Memory Changed: None.
Read byte from default input (for keyboard, read a line from the screen). (If not keyboard, must call OPEN and CHKIN beforehands.)

Input: – Output: A = Byte read. Used registers: A, Y. Real address: ($0324), $F157.

input character
out:A=character, C=1 and ST=error      - - -  A - -  A - -
BASIN Eingabe, holt ein Zeichen in den Akku
$FFD2 CHROUT IO 65490
Output a character
  • Communication registers: A
  • Preparatory routines: (CHKOUT,OPEN)
  • Error returns: 0 (See READST)
  • Stack requirements: 8+
  • Registers affected: A

Description: This routine outputs a character to an already opened channel. Use the KERNAL OPEN and CHKOUT routines to set up the output channel before calling this routine, If this call is omitted, data is sent to the default output device (number 3, the screen). The data byte to be output is loaded into the accumulator, and this routine is called. The data is then sent to the specified output device. The channel is left open after the call.

NOTE: Care must be taken when using this routine to send data to a specific serial device since data will be sent to all open output channels on the bus. Unless this is desired, all open output channels on the serial bus other than the intended destination channel must be closed by a call to the KERNAL CLRCHN routine.

How to Use:

  1. Use the CHKOUT KERNAL routine if needed, (see description above).
  2. Load the data to be output into the accumulator.
  3. Call this routine.

EXAMPLE:

     ;DUPLICATE THE BASIC INSTRUCTION CMD 4,"A";
     LDX #4          ;LOGICAL FILE #4
     JSR CHKOUT      ;OPEN CHANNEL OUT
     LDA #'A
     JSR CHROUT      ;SEND CHARACTER
Send a byte to output channel

Called by: JSR at E10C/E109 in BASIC's Output a Character, JSR at F135/F1EC in Display Kernal Message, JSR at F5C9/F661 in Display Filename, JSR at F726/F7A9 in Error Message Handler, JSR at F759/F7DC in Find Next Tape Header.

Setup routines: OPEN, CHKOUT (not required if output device is the screen).

Entry requirements: Accumulator should contain the character to be output, in CBM ASCII. JMP (0326) with a default of F1CA/F27A.

If 9A, the current output device, is the screen (3), the ASCII code is displayed on the screen unless the ASCII code is a screen control function (cursor key, DELete, INSerT, and so on). If the character is a control code, the routine performs the action. If the ASCII code is a valid screen display code, the code is displayed on the screen at the current cursor position and then the cursor is advanced to the next position on the screen.

If the current output device, 9A, is a serial device, (> 3), then JMP EDDD/EEE4 to send the character to all open serial devices. When sending a character to a serial device, a onebyte buffer, 95, is maintained. If this buffer is empty, the character to be output is simply stored in the buffer. If the buffer already contains a character, the routine sends the character from the buffer onto the serial bus and stores the character to be output in the buffer. When the serial file is closed or the serial device is commanded to unlisten, the final byte in the buffer is sent.

If the current output device, 9A, is RS-232 (2), the character to be output is stored in the RS-232 transmit buffer, and transmission is started if this is the first byte to be sent.

If the current output device, 9A, is tape (1), store the character in the currently available position in the tape buffer and increment the index to the available position in the tape buffer. Once the index is set to 192, write the tape buffer to tape. Then set the first byte of the tape buffer to 2 (identification for a data buffer) and reset the index to point to the second byte of the tape buffer.

Although the character to be output is in ASCII code for output to the screen, this is not the case for RS-232, serial, or tape. For example, if you are storing bytes to tape containing a code other than ASCII, CHROUT will send them to the tape buffer. For the screen, though, the 64/VIC screen editor is set up to convert ASCII codes to screen codes or screen functions, and would not function well if you did not use ASCII.

CHROUT

This routine (some Commodore references call it BSOUT) sends a byte to the logical file currently specified for output. Except to send output to the screen when the system is set for default I/O, you must open a logical file to the desired device and specify the file as the output target before calling this routine. (See the OPEN and CHKOUT routines.)

For output to tape (device 1), the character is stored at the next available position in the cassette buffer. When the buffer is full, the data block is written to tape.

For output to RS-232 (device 2), the character is stored in the next available position in the RS-232 output buffer, if the buffer is full, the routine waits until a character is sent.

For output to the screen (device 3), the character is printed at the current cursor position. For serial devices (device numbers 4 and higher), the CIOUT routine is called.

Regardless of the output device, the contents of the accumulator, .X, and .Y are preserved during this routine. The status-register carry bit will always be clear upon return, unless output to tape is aborted by pressing the RUN/STOP key. (In that case, the accumulator will also be set to 0, setting the status-register Z bit as well.) For tape, serial, or RS-232 output, the success of the operation will be indicated by the value in the status flag. (See READST for details.)

The JMP to the CHROUT execution routine is by way of the ICHROUT indirect vector at $0326-$0327. You can modify the actions of the routine by changing the vector to point to a routine of your own.

Output a Byte

The routine jumps through a RAM vector at 806 ($326). It is probably one of the best known and most used Kernal routines, because it sends the character in the Accumulator to the current output device. Unless a device has been OPENed and designated as the current output channel using the CHKOUT routine, the character is printed to the screen, which is the default output device. If the cassette is the current device, outputting a byte will only add it to the buffer. No actual transmission of data will occur until the 192-byte buffer is full.

Ein Zeichen auf Ausgabekanal ausgeben

Es wird das im übergebene Zeichen auf die eröffnete und mit CKOUT als Ausgabedatei definierte Datei ausgegeben. Ist der Bildschirm Ausgabedatei (Default), so wird das ASCII-Zeichen in den darzustellenden POKE-Code umgerechnet (ein recht aufwendiges Verfahren. Interessierte sollten sich den entsprechenden Teil im Kernal im C-Bereich ansehen).

Eingabeparameter: .A

Beispiel:

        ;Wechseln des 40/80-Zeichen-Modus
        LDA #$1B  ;<ESC>
        JSR BSOUT ;$FFD2, Zeichen ausgeben
        LDA #"X"  ;<ESC>-X zum Uechseln des Bildschirmstatus
        JSR BSOUT ;ausgeben

(Es gibt allerdings eine spezielle Routine, die man anspringen kann)

output character to channel

This routine will output a character to an already opened channel. Use the OPEN routine, $FFC0, and the CHKOUT routine, $FFC9, to set up the output channel before calling this routine. If these calls are omitted, data will be sent to the default output device, device 3, the screen. The data byte to be output is loaded into the accumulator, and this routine is called. The data is then sent to the specified output device. The channel is left open after the call.

NOTE: Care must be taken when using routine to send data to a serial device since data will be sent to all open output channels on the bus. Unless this is desired, all open output channels on the serial bus other than the actually intended destination channel must be closed by a call to the KERNAL close channel routine.

Output character to channel.

CHROUT. Load the accumulator with your number and call. OPEN and CHKOUT will change the output device.

;Duplicate the command of CMD 4:PRINT "A";
     LDX #4
     JSR CHKOUT
     LDA #'A
     JSR CHROUT
     RTS
;The letter A is printed to the screen; call OPEN first for the printer.
Output byte to current channel
 Registers In  : .A = Byte
 Registers Out : .C = 1 if ERROR (examine READST)
 Memory Changed: Dependent upon current device.
Write byte to default output. (If not screen, must call OPEN and CHKOUT beforehands.)

Input: A = Byte to write. Output: – Used registers: – Real address: ($0326), $F1CA.

output character
in: A=character, C=1 and ST=error      A - -  A - -  - - -
BSOUT Ausgabe, gibt Zeichen im Akku aus
$FFD5 LOAD IO 65493
Load RAM from device
  • Communication registers: A, X, Y
  • Preparatory routines: SETLFS, SETNAM
  • Error returns: 0,4,5,8,9, READST
  • Stack requirements: None
  • Registers affected: A, X, Y

Description: This routine LOADs data bytes from any input device directly into the memory of the Commodore 64. It can also be used for a verify operation, comparing data from a device with the data already in memory, while leaving the data stored in RAM unchanged.

The accumulator (.A) must be set to 0 for a LOAD operation, or 1 for a verify, If the input device is OPENed with a secondary address (SA) of 0 the header information from the device is ignored. In this case, the X and Y registers must contain the starting address for the load. If the device is addressed with a secondary address of 1, then the data is loaded into memory starting at the location specified by the header. This routine returns the address of the highest RAM location loaded.

Before this routine can be called, the KERNAL SETLFS, and SETNAM routines must be called.

NOTE: You can NOT LOAD from the keyboard (0), RS-232 (2), or the screen (3).

How to Use:

  1. Call the SETLFS, and SETNAM routines. If a relocated load is de- sired, use the SETLFS routine to send a secondary address of 0.
  2. Set the A register to 0 for load, 1 for verify.
  3. If a relocated load is desired, the X and Y registers must be set to the start address for the load.
  4. Call the routine using the JSR instruction.

EXAMPLE:

;LOAD A FILE FROM TAPE

     LDA #FILENO      ;SET LOGICAL FILE NUMBER
     LDX #DEVICE1     ;SET DEVICE NUMBER
     LDY CMD1         ;SET SECONDARY ADDRESS
     JSR SETLFS
     LDA #NAME1-NAME  ;LOAD A WITH NUMBER OF
                      ;CHARACTERS IN FILE NAME
     LDX #<NAME       ;LOAD X AND Y WITH ADDRESS OF
     LDY #>NAME       ;FILE NAME
     JSR SETNAM
     LDA #0           ;SET FLAG FOR A LOAD
     LDX #$FF         ;ALTERNATE START
     LDY #$FF
     JSR LOAD
     STX VARTAB       ;END OF LOAD
     STY VARTA B+1
     JMP START
NAME .BYT 'FILE NAME'
NAME1                 ;
LOAD/VERIFY to RAM

Called by: JSR at E175/E172 in BASIC's LOAD /VERIFY.

Setup routines: SETLFS, SETNAM

Entry requirements: Accumulator should be set to 0 for LOAD; accumulator set to 1 for VERIFY.

If relocatable load desired: Set X register to the low byte of load starting address, and Y register to the high byte of load starting address.

JMP F49E/F542 to store the X register and Y register in (C3), the starting address of the load, and then JMP(0330) with a default of F4A5/F549.

At F4A5/F549, determine the device. The keyboard, screen, and RS-232 are illegal devices.

For a serial device you must specify a filename. If you don't, the MISSING FILE NAME error message is displayed. With a valid filename, the computer commands the current serial device to listen and sends the secondary address of $60, indicating a load, followed by the filename. Then it tells the device to unlisten. Next, it tells the current serial device to talk, sends the current secondary address of $60, and receives a byte from the serial bus. If the I/O status word indicates the byte was not returned fast enough, a read time-out has occurred and the FILE NOT FOUND error message is displayed. The first two bytes received from the serial device are used as a pointer to the start of the load area (AE). However, if a secondary address of 0 is specified at entry to load, the X and Y registers stored in (C3) at entry are used as the starting address of the load—thus providing for a relocatable load. Then it receives bytes from the serial bus and stores or verifies them until the EOI status is received. Once the EOI status is received, the serial device is commanded to untalk, and the serial device sends the last buffered character. The serial device then is sent a CLOSE and told to untalk.

For tape LOAD/VERIFY, the LOAD routine first checks if the tape buffer is located in memory >= 0200. If so, it loads the tape buffer with a header retrieved from the tape. If a filename has been specified, a specific he,ader with this filename is loaded; if there is no filename, it loads the next header on the tape. Only tape headers with tape identifiers of 1 or 3 are acceptable for LOAD/VERIFY. A tape identifier of 5 indicates an end-of-tape header, and in this case the routine will exit with carry set and accumulator set to 5. Tape identifiers of 2 or 4 are for sequential files.

A tape identifier of 3 causes a nonrelocatable load even if you have specified values in the X and Y registers at entry and a secondary address of 0. That is, you can't override a tape identifier of 3—it forces a nonrelocatable load.

A tape identifier of 1 allows a relocatable load. If the tape identifier is 1 and the secondary address is 0, the X and Y register values at entry are used to determine the starting address for the load.

For a nonrelocatable load, the starting address for the load is taken from the tape header. The ending address for the load (in both relocatable and nonrelocatable loads) is determined by adding the length of the program to the starting address. After determining whether to do a relocatable or nonrelocatable load, it loads RAM from the next two program blocks on tape (two blocks are used for error correcting purposes; they should be identical copies of each other).

LOAD

This routine loads a program file from tape or disk into a specified area of memory, or verifies a program file against the contents of a specified area of memory. A number of preparatory routines must be called before LOAD: SETLFS, SETNAM, and (for the 128 only) SETBNK. See the discussions of those routines for details.

SETLFS establishes the device number and secondary address for the operation. fThe logical file number isn't significant for loading or verifying.) The secondary-address value determines whether the load/verify will be absolute or relocating. If bit 0 of the secondary address is %0 (if the value is 0 or any even number, for example), a relocating load will be performed: The file will be loaded starting at the address specified in .X and .Y. If the bit is %1 (if the value is 1 or any odd number, for example), an absolute load will be performed: The data will be loaded starting at the address specified in the file itself. For tape files, the secondary-address specification can be overridden by the file's internal type specification. Nonrelocatable tape program files always load at their absolute address, regardless of the secondary address.

When calling the LOAD routine, the accumulator should hold the operation type value (0 for a load, or any nonzero value for a verify). If the secondary address specifies a relocating load, the starting address at which data is to be loaded should be stored in .X (low byte) and .Y (high byte). The values of .X and .Y are irrelevant for an absolute load.

The status-register carry bit will be clear upon return if the file was successfully loaded, or set if an error occurred or if the RUN/STOP key was pressed to abort the load. When carry is se t upon return, the accumulator will hold a Kernal error-code value indicating the problem. Possible error codes include 4 (file was not found), 5 (device was not present), 8 (no name was specified for a serial load), 9 (an illegal device number was specified).

On the 128 only, the load will be aborted if it extends beyond address $FEFF. This prevents corruption of the MMU configuration register at $FFQ0. Ln this case, an error code of 16 will be returned. The success of the operation will also be indicated by the value in the tape/serial status flag. (See READST for details.)

Load RAM from a Device

The routine jumps through a RAM vector at 816 ($330). LOAD is used to transfer data from a device directly to RAM. It can also be used to verify RAM, comparing its contents to those of a disk or tape file. To choose between these operations you must set the Accumulator with a 0 for LOAD, or a 1 for VERIFY.

Since the LOAD routine performs an OPEN, it must be preceded by a call to the SETLFS routine to specify the logical file number, device number, and secondary address, and a call to the SETNAM routine to specify the filename (a LOAD from tape can be performed without a filename being specified). Then the .X and .Y registers should be set with the starting address for the load, and the LOAD routine called. If the secondary address specified was a 1, this starting address will be ignored, and the header information will be used to supply the load address. If the secondary address was a 0, the address supplied by the call will be used. In either case, upon return from the subroutine, the .X and .Y registers will contain the address of the highest RAM location that was loaded.

Laden einer Datei in den Speicher

Bevor mit LOADSP eine Datei geladen werden kann, muß das Gerät, die Sekundäradresse, der Filename etc. durch die Routinen SETLFS, SETNAM und SETBNK definiert worden sein. Im X- (Lo) und Y-Register (Hi) wird die Adresse angegeben, ab der die zu ladende Datei abgelegt werden soll.

Eingabeparameter: .X, .Y

Beispiel:

        ;Laden eines Overlay o.ä.
        JSR PREP  ;SETLFS, SETBNK, SETNAM etc.
        LDX #$00  ;Lo-Byte von $1000
        LDY #$10  ;Hi-Byte von $1000 (Ladeadresse)
        JSR $FFD5 ;Lade Datei ab $1000
load RAM from a device

This routine will load data bytes from any input device directly into the memory of the computer. It can also be used for a verify operation comparing data from a device with the data already in memory, leaving the data stored in RAM unchanged.

The accumulator must be set to 0 for a load operation or 1 for a verify. If the input device was OPENed with a secondary address of 0 the header information from device will be ignored. In this case XY must contain the starting address for the load. If the device was addressed with a secondary address of 1 or 2 the data will load into memory starting at the location specified by the header. This routine returns the address of the highest RAM location which was loaded.

Before this routine can be called, the SETLFS, $FFBA, and SETNAM, $FFBD, routines must be called.

Load RAM from a device.

LOAD. The computer will perform either the LOAD or the VERIFY command. If the ac cumulator is a 1, then LOAD; if 0, then verify.

;Load a program into memory.
     LDA #$08
     LDX #$02
     LDY #$00
     JSR SETLFS
     LDA #$04
     LDX #L,NAME
     LDY #H,NAME
     JSR SETNAM
     LDA #$00
     LDY #$20
     JSR LOAD
     RTS
NAME .BY 'FILE'
;Program 'FILE' will be loaded into memory starting at 8192 decimal, X being the low byte and Y being the high byte for the load.
Loads file into memory (setup via SETLFS,SETNAM)..
 Registers In  : .A = 0 - Load, Non-0 = Verify
                 .XY = load address (if secondary address = 0)
 Registers Out : .A = error code .C = 1 if error.
                 .XY = ending address
 Memory Changed: As per registers / data file.
Load or verify file. (Must call SETLFS and SETNAM beforehands.)

Input: A: 0 = Load, 1-255 = Verify; X/Y = Load address (if secondary address = 0). Output: Carry: 0 = No errors, 1 = Error; A = KERNAL error code (if Carry = 1); X/Y = Address of last byte loaded/verified (if Carry = 0). Used registers: A, X, Y. Real address: $F49E.

load after call SETLFS,SETNAM
in: A=0 load, a=1 verify               A X Y  A X Y  A X Y
    Y/X = dest.addr if sec.addr=0
LOAD, lädt Programm in den Speicher
$FFD8 SAVE IO 65496
Save memory to a device
  • Communication registers: A, X, Y
  • Preparatory routines: SETLFS, SETNAM
  • Error returns: 5,8,9, READST
  • Stack requirements: None
  • Registers affected: A, X, Y

Description: This routine saves a section of memory. Memory is saved from an indirect address on page 0 specified by the accumulator to the address stored in the X and Y registers. It is then sent to a logical file on an input/output device. The SETLFS and SETNAM routines must be used before calling this routine. However, a file name is not required to SAVE to device 1 (the Datassette™ recorder). Any attempt to save to other devices without using a file name results in an error.

NOTE: Device 0 (the keyboard), device 2 (RS-232), and device 3 (the screen) cannot be SAVEd to. If the attempt is made, an error occurs, and the SAVE is stopped.

How to Use:

  1. Use the SETLFS routine and the SETNAM routine (unless a SAVE with no file name is desired on "a save to the tape recorder"),
  2. Load two consecutive locations on page 0 with a pointer to the start of your save (in standard 6502 low byte first, high byte next format).
  3. Load the accumulator with the single byte page zero offset to the pointer.
  4. Load the X and Y registers with the low byte and high byte re- spectively of the location of the end of the save.
  5. Call this routine.

EXAMPLE:

     LDA #1              ;DEVICE = 1:CASSETTE
     JSR SETLFS
     LDA #0              ;NO FILE NAME
     JSR SETNAM
     LDA PROG            ;LOAD START ADDRESS OF SAVE
     STA TXTTAB          ;(LOW BYTE)
     LDA PROG+1
     STA TXTTA B+1       ;(HIGH BYTE)
     LDX VARTAB          ;LOAD X WITH LOW BYTE OF END OF SAVE
     LDY VARTAB+1        ;LOAD Y WITH HIGH BYTE
     LDA #<TXTTAB        ;LOAD ACCUMULATOR WITH PAGE 0 OFFSET
     JSR SAVE
Save contents of memory to device

Called by: JSR at E15F/E15C in BASIC's SAVE.

Setup routines: SETLFS, SETNAM (not required for saving to tape)

Entry requirements: The accumulator should contain the offset within zero page to a two-byte pointer to the start of the area to be saved. The X register should hold the low byte of the address of the end of the area to be saved + 1. Y register should hold the high byte of the address of the end of the area to be saved + 1.

JMP F5DD/F675 to save memory to a serial device or to tape. Saves to the screen, keyboard, or RS-232 are not permitted.

If saving to tape from the VIC, only the contents of memory locations 0-7FFF may be saved. This restriction does not apply when saving to tape from the 64.

A filename is required (through SETNAM) when saving to serial devices; a filename is optional when saving to tape.

At F5DD/F675 , the routine loads the pointer to the end of the save area + 1, (AE), from the X and Y registers. (End + 1 denotes the fact that you must load X and Y to point to the location just past the end of the save area, since the save routines consider the save complete when the pointer to the save area equals the value of the pointer (AE).) It also sets (C1), the pointer to the start of the save area, from the zero page pointer indexed by the accumulator, and then performs an indirect JMP through the vector at (0332), which defaults to F5ED/F675.

For a serial save, the routine commands the current serial device to listen with attention, then sends a secondary address of $61 to indicate a SAVE operation. If the device is present, the filename and the starting address are sent to the serial device. Next, the routine sends all the bytes from the save area over the serial bus. When the save is complete, it sends a secondary address of $E1 to indicate the CLOSE command and commands the serial device to unlisten.

For tape save, it is important that you specify the secondary address correctly. For an even secondary address, the header for the saved program will have a identifier byte of 1, indicating a relocatable program. An odd secondary address produces a header identifier byte of 3, indicating a nonrelocatable program. Also, if you have bit 1 on in the secondary address ($02 or $03 would set bit 1), then an end-of-tape header with a identifier byte of 5 is written following the saved program.

The tape save operation first writes a header to tape. This tape header contains the identifier byte, the starting address and ending address + 1 of the save area, and the filename (if a filename is used). Then data from the save area is written to tape. If bit 1 of the secondary address is 1, an end-of-tape header is also written following the data from the save area. Two identical copies of the tape header(s) and the program are written to tape to allow for error checking and correction during tape loading.

SAVE

This routine saves the contents of a block of memory to disk or tape. It could be a BASIC or ML program, but it doesn't have to be. A number of preparatory routines must be called first: SETLFS, SETNAM, and (for the 128 only) SETBNK. See the discussions of those routines for details.

SETLFS establishes the device number and secondary address for the operation. (The logical file number isn't significant for saving.) The secondary address is irrelevant for saves to serial devices, but for tape it specifies the header type. If bit 0 of the secondary address value is %1 (if the value is 1, for example), the data will be stored in a nonrelocatable file—one that will always load to the same memory address from which it was saved. Otherwise, the data will be stored in a file that can be loaded to another location. If bit 1 of the secondary address is %1 (if the value is 2 or 3, for example), the file will be followed by an end-of-tape marker.

Before calling SAVE, you must also set up a two-byte zero-page pointer containing the starting address of the block of memory to be saved and then store the address of the zeropage pointer in the accumulator. The ending address (plus one) for the save should be stored in .X (low byte) and .Y (high byte). To save the entire contents of the desired area, it's important to remember that .X and .Y must hold an address that is one location beyond the desired ending address.

When the save is complete, the carry will be clear if the file was successfully saved, or set if an error occurred (or if the RUN/STOP key was pressed to abort the save). When carry is set upon return, the accumulator will hold the Kernal error code indicating the problem. Possible error-code values include 5 (serial device was not present), 8 (no name was specified for a serial save), and 9 (an illegal device number was specified). The success of the operation will also be indicated by the value in the tape/serial status flag. (See READST for details.)

Save RAM to a Device

The routine jumps through a RAM vector at 818 ($332). SAVE is used to transfer data directly from RAM to an I/O device. Since the SAVE routine performs an OPEN, it must be preceded by a call to the SETLFS routine to specify the logical file number, device number, and secondary address, and a call to the SETNAM routine to specify the filename (although a SAVE to the cassette can be performed without giving a filename). A Page 0 pointer to the starting address of the area to be saved should be set up, with the low byte of the address first. The accumulator should be loaded with the Page 0 offset of that pointer, then the .X and .Y registers should be set with the ending address for the save, and the SAVE routine called.

Abspeichern eines Bereiches auf Datei

Diese Routine speichert einen Speicherbereich auf eine Datei (Diskette, Kassette) ab. Dazu muß man, wie bei der LOADSP-Routine, zunächst Geräteadresse, Sekundäradresse, RAM-Bank, Filename etc. durch die Routinen SETBNK, SETLFS und SETNAM definieren. Im Akku wird die Zeropage-Adresse angegeben, an der die Anfangsadresse des abzuspeichernden Bereiches steht. Im X- (Lo) und Y-Register (Hi) wird entsprechend die Endadresse des abzuspeichernden Bereiches angegeben.

Eingabeparameter: .A, .X, .Y, Zeropage

Beispiel:

        ;Abspeichern des Bereiches $1000 bis $1100
        JSR PREP  ;SETLFS, SETNAM, SETBNK etc. aufrufen
        LDA #$00  ;Lo-Byte von $1000
        STA $FC   ;in Zeropage speichern
        LDA #$10  ;Hi-Byte von $1000
        STA $FD   ;in Zeropage speichern
        LDA #$FC  ;der Pointer befindet sich an $FC
        LDX #$00  ;Lo-Byte der Endadresse $1100
        LDY #$11  ;Hi-Byte der Endadresse $1100
        JSR $FFD8 ;SAVESP - Speichern des Bereiches $1000-$1100
save RAM to a device

This routine saves a section of memory. Memory is saved from an indirect address on page 0 specified by A, to the address stored in XY, to a logical file. The SETLFS, $FFBA, and SETNAM, $FFBD, routines must be used before calling this routine. However, a file name is not required to SAVE to device 1, the cassette. Any attempt to save to other devices without using a file name results in an error.

NOTE: device 0, the keyboard, and device 3, the screen, cannot be SAVEd to. If the attempt is made, an error will occur, and the SAVE stopped.

Save RAM to device.
Save section of memory to a file.
 Registers In  : .A = Z-page ptr to start adress
                 .XY = end address
 Registers Out : .A = error code, .C = 1 if error.
                 .XY = used.
 Memory Changed: None.
Save file. (Must call SETLFS and SETNAM beforehands.)

Input: A = Address of zero page register holding start address of memory area to save; X/Y = End address of memory area plus 1. Output: Carry: 0 = No errors, 1 = Error; A = KERNAL error code (if Carry = 1). Used registers: A, X, Y. Real address: $F5DD.

save after call SETLFS,SETNAM
in: A=zero page pointer to start.addr  A X Y  - - -  A X Y
    Y/X=ending address
SAVE, speichert Programm ab
$FFDB SETTIM TIME 65499
Set the system clock
  • Communication registers: A, X, Y
  • Preparatory routines: None
  • Error returns: None
  • Stack requirements: 2
  • Registers affected: None

Description: A system clock is maintained by an interrupt routine that updates the clock every 1/60th of a second (one "jiffy"). The clock is three bytes long, which gives it the capability to count up to 5,184,000 jiffies (24 hours). At that point the clock resets to zero. Before calling this routine to set the clock, the accumulator must contain the most significant byte, the X index register the next most significant byte, and the Y index register the least significant byte of the initial time setting (in jiffies).

How to Use:

  1. Load the accumulator with the MSB of the 3-byte number to set the clock.
  2. Load the X register with the next byte.
  3. Load the Y register with the LSB.
  4. Call this routine.

EXAMPLE:

;SET THE CLOCK TO 10 MINUTES = 3600 JIFFIES
     LDA #0               ;MOST SIGNIFICANT
     LDX #>3600
     LDY #<3600           ;LEAST SIGNIFICANT
     JSR SETTIM
Set jiffy clock from registers

Called by: JMP at AA1A/CA1A in BASIC's TI$.

Entry requirements: The accumulator should hold the high byte to be stored in the jiffy clock. The X register should hold the middle byte to be stored in the jiffy clock. The Y register should hold the low byte to be stored in the jiffy clock.

JMP F6E4/F767 to set the three-byte jiffy clock at A2-A0 from the values in the accumulator, X register, and Y register.

SETTIM

This routine sets the value in the software jiffy dock. The value in the accumulator is transferred to the low byte (location $A2), the value in .X to the middle byte (location $A1), and the value in .Y to the high byte (location $A0). The specified value should be less than $4F1A01, which corresponds to 24:00:00 hours.

Set the Software Clock from the .A, .X, and .Y Registers

This routine performs the reverse operation from RDTIM, storing the value in the .Y register into location 160 ($A0), the .X register into 161 ($A1), and the Accumulator into 162 ($A2). Interrupts are first disabled, to make sure that the clock will not be updated while being set.

Setzen der Systemuhr TI

Die Routine setzt die Systemuhr TI, die ab Adresse $A0 definiert ist. Diese Uhr wird von der Kernal-IRQ-Routine gesteuert und ist nicht sehr genau. Legen Sie auf eine genauere Uhr Wert, so benutzen Sie die Timer in den beiden CIAs. (Siehe auch entsprechendes Kapitel) Das höchstwertige Byte der 24-Stunden-Uhr wird im Y-Register übergeben.

Eingabeparameter: .A, .X, .Y

Beispiel:

        ;Rücksetzen der Systemuhr
        LDA #$00  ;Rücksetzen bedeutet
        TAY       ;auf 0,0,0 setzen
        TAX       ;Alle drei Register auf null
        JSR $FFDB ;SETTIM
set the real time clock

The system clock is maintained by an interrupt routine that updates the clock every 1/60th of a second. The clock is three bytes long which gives the capability to count from zero up to 5,184,000 jiffies - 24 hours plus one jiffy. At that point the clock resets to zero. Before calling this routine to set the clock the new time, in jiffies, should be in YXA, the accumulator containing the most significant byte.

Set realtime clock.

SETTIM is the opposite of RDTIM: it SETs the system clock instead of ReaDing it.

;Set system clock to 10 minutes =3600 jiffies.
     LDA #0
     LDX #L,3600
     LDY #H,3600
     JSR SETTIM
;This allows very accurate timing for many things.
Set internal clock (TI$).
 Registers In  : .AXY - Clock value in jiffies (1/60 secs).
 Registers Out : None.
 Memory Changed: Relevant system time locations set.
Set Time of Day, at memory address $00A0-$00A2.

Input: A/X/Y = New TOD value. Output: – Used registers: – Real address: $F6E4.

set jiffy clock
in: A=MSB, X=middle, Y=LSB             A X Y  - - -  - - -
setzt die laufende Zeit neu
$FFDE RDTIM TIME 65502
Read system clock
  • Communication registers: A, X, Y
  • Preparatory routines: None
  • Error returns: None
  • Stack requirements: 2
  • Registers affected: A, X, Y

Description: This routine is used to read the system clock. The clock's resolution is a 60th of a second. Three bytes are returned by the routine. The accumulator contains the most significant byte, the X index register contains the next most significant byte, and the Y index register contains the least significant byte.

EXAMPLE:

     JSR RDTIM
     STY TIME
     STX TIME+1
     STA TIME+2
     ...
TIME *=*+3
Read jiffy clock into registers

Called by: JSR at AF84/CF84 in BASIC's TI and TI$.

JMP F6DD/F760.

This routine reads the jiffy clock (A2-A0) into the accumulator, X register, and Y register.

A0 is updated every 1/60 second. When the jiffy clock reaches a value equal to 24 hours, it is reset to 0.

Exit conditions: Accumulator holds high byte of jiffy clock. X register holds middle byte of jiffy clock. Y register holds low byte of jiffy clock.

RDTIM

This routine returns the current value of the jiffy dock. The dock value corresponds to the number of jiffies (1 /60-second intervals) that have elapsed since the system was turned on or reset, or the number of jiffies since midnight if the dock value has been set. The low byte of the clock value (location $A2) is returned in .A, the middle byte (location $A1) in .X, and the high byte loocation $A0) in .Y.

Read the Time From the Software Clock into the .A, .X, and .Y Registers

It reads the software clock (which counts sixtieths of a second) into the internal registers. The .Y register contains the most significant byte (from location 160 ($A0)), the .X register contains the middle byte (from location 161 ($A1)), and the Accumulator contains the least significant byte (from location 162 ($A2)).

Auslesen der Systemuhr

Diese Routine liest die 24-Stunden-Uhr aus und übergibt die drei Bytes den Registern Y (höchstwertig), X und (niederwertig).

Ausgabeparameter: .A, .X, .Y

Beispiel:

        ;Auslesen der 24-Stunden-Uhr
        JSR $FFDE ;RDTIM aufrufen
        STY $FC   ;MSB merken
        STX $FD   ;mittleres Byte merken
        STA $FE   ;LSB merken
read the real time clock

This routine returns the time, in jiffies, in AXY. The accumulator contains the most significant byte.

Read realtime clock.

RDTIM. Locations 160-162 are transferred, in order, to the Y and X registers and the accumulator.

;Store system clock to screen.
     JSR RDTIM
     STA 1026
     STX 1025
     STY 1024
;The system clock can be translated as hours/minutes/ seconds.
Reads internal clock (TI$)
 Registers In  : None.
 Registers Out : .AXY - Clock value in jiffies (1/60 secs).
 Memory Changed: None.
read Time of Day, at memory address $00A0-$00A2.

Input: – Output: A/X/Y = Current TOD value. Used registers: A, X, Y. Real address: $F6DD.

read jiffy clock
out:A=MSB, X=middle, Y=LSB             - - -  A X Y  A X Y
holt die laufende Zeit
$FFE1 STOP KBD 65505
Check if key is pressed
  • Communication registers: A
  • Preparatory routines: None
  • Error returns: None
  • Stack requirements: None
  • Registers affected: A, X

Description: If the key on the keyboard was pressed during a UDTIM call, this call returns the Z flag set. In addition, the channels will be reset to default values. All other flags remain unchanged. If the key is not pressed then the accumulator will contain a byte representing the lost row of the keyboard scan. The user can also check for certain other keys this way.

How to Use:

  1. UDTIM should be called before this routine.
  2. Call this routine.
  3. Test for the zero flag.

EXAMPLE:

     JSR UDTIM   ;SCAN FOR STOP
     JSR STOP
     BNE *+5     ;KEY NOT DOWN
     JMP READY   ;=... STOP
Test for STOP key

Called by: JSR at A82C/C82C in BASIC's Test for STOP Key, JSR at F4F9/F590 in Load/Verify from Serial Device, JSR at F62E/F6C6 in Save to Serial Device; JSR at F8D0/F94B Test for STOP Key During Tape I/O; JSR at FE61/FECD in NMI Interrupt Handler (to find STOP and RESTORE).

JMP (0328) with a default of F6ED/F770. At F6ED/F770, test 91 for the value $7F/$FE. Location 91 contains the key switch value of the STOP key column (column seven/three) of the keyboard scan. If $7E/$FE is found, set the Z flag of the status register to 1, call FFCC to reset I/O channels, and set C6, the number of characters in the keyboard buffer, to 0.

If $7E/$FE is not found, the Z flag will be 0 on exit (BNE condition). In this case, the accumulator can still be tested for the keys shown below using the value shown following it.

STOP Routine Return Values

Commodore 64 Key Accumulator VIC-20 Key Accumulator
1 $FE Cursor down $7F
Left arrow $FD / $BF
CTRL $FB , $DF
2 $F7 N $EF
Space $EF V $F7
Commodore $DF X $FB
Q $BF Left SHIFT $FD

If no key is down in the STOP column, the routine returns $FF in the accumulator (64 and VIC).

STOP

This routine checks whether the RUN/STOP key is currently pressed. It returns with the status-register Z bit clear if the key is not pressed, or with the bit set if it is pressed. Additionally, if RUN/STOP is pressed the CLRCH routine is called to restore default I/O channels, and the count of keys in the keyboard buffer is reset to zero. The JMP to the STOP execution routine is by way of the ISTOP indirect vector at $0328-$0329. You can modify the actions of the routine by changing the vector to point to a routine of your own.

Test STOP Key

This routine is vectored through RAM at 808 ($328). The routine checks to see if the STOP key was pressed during the last UDTIM call. If it was, the Zero flag is set to 1, the CLRCHN routine is called to set the input and output devices back to the keyboard and screen, and the keyboard queue is emptied.

Abfrage der Stop-Taste

Wenn bis zum letzten IRQ-Aufruf die Stop-Taste betätigt worden ist, so wird das ZERO-Flag gesetzt und es wird ein CLRCH ausgeführt. Wurde die Stop-Taste nicht betätigt, so wird das ZERO-Flag gelöscht.

Ausgabeparameter: ZERO-Flag

Beispiel:

        ;Auf STOP prüfen
        JSR $FFE1  ;STOP-Taste gedrückt?
        BEQ Jawoll ;Ist gedrückt
scan the stop key

If the STOP key on the keyboard is pressed when this routine is called the Z flag will be set. All other flags remain unchanged. If the STOP key is not pressed then the accumulator will contain a byte representing the last row of the keyboard scan.

The user can also check for certain other keys this way.

Check for STOP key.

STOP will set the Z flag of the accumulator if the STOP key was pressed.

;Check for STOP key being pressed.
WAIT JSR STOP
     BNE WAIT
     RTS
;STOP must be called if the STOP key is to remain functional.
Scans STOP key.
 Registers In  : None.
 Registers Out : .A = last keyboard row, .X = destroyed (if stop key)
 Memory Changed: None.
 Note          : The last keyboard row is as follows:
                 .A -> | 7   | 6   | 5   | 4   | 3   | 2   | 1  | 0
                  KEY: |STOP |Q    |C=   |SPACE|2    |CTRL |<-  |1
Query Stop key indicator, at memory address $0091; if pressed, call CLRCHN and clear keyboard buffer.

Input: – Output: Zero: 0 = Not pressed, 1 = Pressed; Carry: 1 = Pressed. Used registers: A, X. Real address: ($0328), $F6ED.

check stop key
out:Z=0 if STOP not used; X unchanged  - - -  A - -  A - -        Z=1 if STOP used; X changed        - - -  A - -  A X -        A=last line of keyboard matrix
fragt die STOP-Taste ab
$FFE4 GETIN KBD 65508
Get a character
  • Communication registers: A
  • Preparatory routines: CHKIN, OPEN
  • Error returns: See READST
  • Stack requirements: 7+
  • Registers affected: A (X, Y)

Description: If the channel is the keyboard, this subroutine removes one character from the keyboard queue and returns it as an ASCII value in the accumulator. If the queue is empty, the value returned in the accumulator will be zero. Characters are put into the queue automatically by an interrupt driven keyboard scan routine which calls the SCNKEY routine. The keyboard buffer can hold up to ten characters. After the buffer is filled, additional characters are ignored until at least one character has been removed from the queue. If the channel is RS-232, then only the A register is used and a single character is returned. See READST to check validity. If the channel is serial, cassette, or screen, call BASIN routine.

How to Use:

  1. Call this routine using a JSR instruction.
  2. Check for a zero in the accumulator (empty buffer).
  3. Process the data.

EXAMPLE:

     ;WAIT FOR A CHARACTER
WAIT JSR GETIN
     CMP #0
     BEQ WAIT
Retrieve character from channel

Called by: JSR at E121 in BASIC's Get a Character.

Setup routines: OPEN, CHKIN

JMP(032A) with a default of F13E/F1F5.

When retrieving characters from the keyboard, if any characters are in the keyboard buffer, the first character (an ASCII value) in the buffer is returned in the accumulator, and the rest of the characters are moved up one position in the buffer. If no characters are in the keyboard buffer, return with accumulator cleared to 0.

You would use GETIN to retrieve the first character in the keyboard buffer. Contrast this to CHRIN, which does not retrieve anything until RETURN is entered, then returns a character from the logical screen line.

If retrieving from device 2, RS-232, see if the RS-232 receive buffer contains any characters. If it is empty, return with accumulator set to 0. If it contains characters, return with accumulator containing next character in the receive buffer and increment the pointer into the receive buffer.

If retrieving from channel 3 (the screen), channels >= 4 (serial devices), or channel 1 (tape), do the same routines for GETIN that CHRIN does for these devices.

For screen GETIN, return the ASCII code for the screen character in the current logical line pointed to by D3, the column the cursor is on. D3 is then incremented to point to the next character in the line. If D3 is on the end of the line, return the ASCII code $0D for return.

For serial GETIN, the accumulator returns the byte received over the serial bus. However, if any I/O status errors occur, return with accumulator containing $0D.

For tape GETIN, return the next byte from the tape buffer. Also, read one byte ahead to see if the next byte is zero, indicating end of file, and if true, set end-of-file status in 90.

GETIN

This routine retrieves a single character from the current input device. The routine first checks to see whether the input device number is 0 (keyboard) or 2 (RS-232). If it's not either of these, the Kernal CHRIN routine is called instead. For keyboard or RS-232, the retrieved character will be in the accumulator upon return, and the status-register carry bit wall be clear. If no character is available, the accumulator will contain 0. (CHREM, by contrast, will wait for a character.) The contents of .Y are unaffected, but .X will be changed. For RS-232, bit 3 of the status flag will also be set if no characters are available. (See READST for details.)

The JMP to the GETIN execution routine is by way of the IGETIN indirect vector at $032A-$032B. You can modify the actions of the routine by changing the vector to point to a routine of your own.

Get One Byte from the Input Device

The routine jumps through a RAM vector at 810 ($32A). Its function is to get a character from the current input device (whose device number is stored at 153 ($99)). In practive, it operates identically to the CHRIN routine below for all devices except for the keyboard. If the keyboard is the current input device, this routine gets one character from the keyboard buffer at 631 ($277). It depends on the IRQ interrupt routine to rad the keyboard and put characters into the buffer.

Holt ein Zeichen aus Tastaturbuffer oder RS232

Holt von der definierten Eingabedatei ein Zeichen. Ist kein Zeichen bereit gestellt, so wird der mit null übergeben.

Ausgabeparameter: .A

get character from input device

In practice this routine operates identically to the CHRIN routine, $FFCF, for all devices except for the keyboard. If the keyboard is the current input device this routine will get one character from the keyboard buffer. It depends on the IRQ routine to read the keyboard and put characters into the buffer.

If the keyboard buffer is empty the value returned in the accumulator will be zero.

Get character from keyboard buffer.

GETIN will get one piece of data from the input device. OPEN and CHKIN can be used to change the input device.

;Wait for a key to be pressed.
WAIT JSR GETIN
     CMP #0
     BEQ WAIT
;If the serial bus is used, then all registers are altered.
Read buffered data from file.
                 Keyboard - Read from keyboard buffer, else return null ($00).
                 Rs-232   - Read from Rs-232 buffer, else null is returned.
                 Serial   - See BASIN
                 Cassette - See BASIN
                 Screen   - See BASIN
 Registers In  : None.
 Registers Out : .A = character, .C = 1 if error.
                 .XY = used.
 Memory Changed: None.
Read byte from default input. (If not keyboard, must call OPEN and CHKIN beforehands.)

Input: – Output: A = Byte read. Used registers: A, X, Y. Real address: ($032A), $F13E.

get a byte from channel
out:keyboard:A=0 if puffer empty       - - -  A - -  A X Y
    RS232:status byte                  - - -  A - -  A - -        serial:status byte                 - - -  A - -  A - -        tape:status byte                   - - -  A - -  A - Y
GET, holt ein Zeichen in den Akku
$FFE7 CLALL IO 65511
Close all files
  • Communication registers: None
  • Preparatory routines: None
  • Error returns: None
  • Stack requirements: 11
  • Registers affected: A, X

Description: This routine closes all open files. When this routine is called, the pointers into the open file table are reset, closing all files. Also, the CLRCHN routine is automatically called to reset the I/O channels.

How to Use:

  1. Call this routine.

EXAMPLE:

     JSR CLALL   ;CLOSE ALL FILES AND SELECT DEFAULT I/O CHANNELS
     JMP RUN     ;BEGIN EXECUTION
Close all channels and files

Called by: JSR at A660/C660 in BASIC's CLR.

JMP (0322) with a default of F32F/F3EF.

Set 98, the number of currently open files, to 0.

If the current output device is a serial device, send an UNLISTEN command on the serial bus.

If the current input device is a serial device, send an UNTALK command on the serial bus.

Set 99, the current input device, to be the keyboard.

Set 9A, the current output device, to be the screen.

CLALL

This routine resets the number of open files (location $98) to zero, then falls through into the CLRCH routine to reset default t/O. The contents of .A and .X are changed, but .Y is unaffected.

Despite its name, the routine doesn't actually close any files that may be open to tape, disk, or RS-232 devices. Unclosed files may cause problems, particularly on disks, so this routine is of limited usefulness. The 128 Kernal provides an alternate routine that does properly close all files open to a serial device. (See CLOSE_ALL.)

The JMP to the CLALL execution routine is by way of the JCLALL indirect vector at $032C-$032D. You can modify the actions of the routine by changing the vector to point to a routine of your own.

Close All Logical I/O Files

The routine jumps through a RAM vector at 812 ($32C). It closes all open files, by resetting the index into open files at 152 ($98) to zero. It then falls through to the next routine, which restores the default I/O devices.

Alle offenen Dateien schließen

Alle mittels OPEN eröffneten Dateien werden geschlossen oder besser gelöscht - es wird nämlich kein CLOSE ausgeführt. Beispielsweise bei offenen Floppy-Dateien kann dies sehr ärgerlich sein (WRITE FILE OPEN ERROR ist eine Konsequenz). Ferner wird nach dem Löschen der logischen Dateien ein CLRCH (s.o.) ausgeführt. CLALL ist also mit Vorsicht anzuwenden.

close all channels and files

This routine closes all open files. When this routine is called, the pointers into the open file table are reset, closing all files. Also the routine automatically resets the I/O channels.

Close all channels and files.

CLALL really does what its name implies-it closes all files and resets all channels.

;Close all files.
     JSR CLALL
     RTS
;The CLRCHN routine is called automatically.
Close all open files and channels.
 Registers In  : None.
 Registers Out : .AX used.
 Memory Changed: None.
 Note          : This routine does not _actually_ close the files, rather it
                 removes their prescense from the file tables held in memory.
                 It's recommended to use close to close files instead of using
                 this routine.
Clear file table; call CLRCHN.

Input: – Output: – Used registers: A, X. Real address: ($032C), $F32F.

close or abort all files
                                       - - -  - - -  A X -
CLALL, setzt alle Ein-/Ausgabekanäle

zurück, die Dateien werden jedoch nicht geschlossen

$FFEA UDTIM TIME2) 65514
Update the system clock
  • Communication registers: None
  • Preparatory routines: None
  • Error returns: None
  • Stack requirements: 2
  • Registers affected: A, X

Description: This routine updates the system clock. Normally this routine is called by the normal KERNAL interrupt routine every 1/60th of a second. If the user program processes its own interrupts this routine must be called to update the time. In addition, the <STOP> key routine must be called, if the <STOP> key is to remain functional.

How to Use:

  1. Call this routine.

EXAMPLE:

Increment jiffy clock

Called by: JSR at EA31/EABF in IRQ Interrupt Handler.

JMP F69B/F734 to update the jiffy clock at A2-A0 and store a value from the keyboard row for column number seven/three (which contains the STOP key) in 91 if a key in that row is detected.

Normally, this routine is called by the IRQ interrupt handler (64 and VIC) or by the NMI interrupt handler (VIC only). However, if you run a program with IRQ interrupts disabled, you should call this routine if you want the jiffy clock incremented and the STOP key column value saved in 91.

UDTIM

This routine increments the software jiffy dock and scans the keyboard column containing the RUN/STOP key. (The 128 version of the routine also decrements a countdown timer.) This routine is normally called every 1 /60 second as part of the standard lRQ service routine.

Update the Software Clock and Check for the STOP Key

This routine is normally called by the IRQ interrupt handler once every sixtieth of a second. It adds one to the value in the three-byte software jiffy clock at 160-162 ($A0-$A2), and sets the clock back to zero when it reaches the 24 hour point. In addition, it scans the keyboard row in which the STOP key is located, and stores the current value of that key in location 145 ($91). This variable is used by the STOP routine which checks for the STOP key.

Systemuhr anpassen (updaten)

Diese Routine wird vornehmlich von der IRQ-Routine aufgerufen. Es wird die Drei-Byte-24-Stunden-Uhr um eine Einheit hochgezählt.

increment real time clock

This routine updates the system clock. Normally this routine is called by the normal KERNAL interrupt routine every 1/60th of a second. If the user program processes its own interrupts this routine must be called to update the time. Also, the STOP key routine must be called if the stop key is to remain functional.

Increment realtime clock.

UDTIM. If you are using your own interrupt system, you can update the system clock by calling UDTIM.

;Update the system clock.
     JSR UDTIM
     RTS
;It is useful to call UDTIM before calling STOP.
Update internal (TI$) clock by 1 jiffie (1/60 sec).
 Registers In  : None.
 Registers Out : .A,.X destroyed.
 Memory Changed: Relevant system time locations changed.
Update Time of Day, at memory address $00A0-$00A2, and Stop key indicator, at memory address $0091.

Input: – Output: – Used registers: A, X. Real address: $F69B.

update jiffy clock
                                       - - -  - - -  A X -
erhöht die laufende Zeit um eine

sechzigstel Sekunde

$FFED SCREEN EDITOR 65517
Return screen format
  • Communication registers: X, Y
  • Preparatory routines: None
  • Stack requirements: 2
  • Registers affected: X, Y

Description: This routine returns the format of the screen, e.g., 40 columns in X and 25 lines in Y. The routine can be used to determine what machine a program is running on. This function has been implemented on the Commodore 64 to help upward compatibility of your programs.

How to Use:

  1. Call this routine.

EXAMPLE:

     JSR SCREEN
     STX MAXCOL
     STY MAXROW
Return number of columns and rows

Called by: None.

JMP E505 to return the number of columns on the standard display screen in the X register and the number of rows in the Y register. On the 64, the routine returns 40 in X and 25 in Y. The VIC routine returns 22 in X and 23 in Y.

A definitive way to let a program know whether it's running on the VIC or the 64 is to JSR to SCREEN and test the values returned.

SCREEN

This routine (Commodore 128 literature calls it SCRORG) returns information on the size of the screen display. For the 64, the routine always returns the same values—the screen width in columns (40) in .X and the screen height in rows (25) in .Y. The accumulator is unaffected. For the 128, the values returned reflect the size of the current output window. The X register will contain in the current window the number of columns minus one, and .Y will contain the number of rows minus one. The accumulator will hold the maximum column number for the display currently active (39 for the 40-column screen or 79 for the 80-column screen).

Store Number of Screen Rows and Columns in .Y and .X

When called, this subroutine returns the number of screen columns in the .X register, and the number of screen rows in .Y. Thus, a program can detect the screen format of the machine on which it is running, and make sure that text output is formatted accordingly.

The present version of this routine loads the .X register with 40 ($28) and the .Y register with 25 ($19).

Größe des aktuellen Fensters holen

Die Routine SCRORG holt die aktuellen Fensterwerte in die Register. Der enthält nach dem Aufruf die maximale Spaltenzahl, im Y-Register befindet sich die Anzahl der Zeilen im Fenster und im X-Register die Anzahl der Spalten des Fensters.

Ausgabeparameter: .A, .X, .Y

return X,Y organization of screen

This routine returns the x,y organisation of the screen in X,Y

Return X,Y organization of screen.

SCREEN returns the number of columns and rows the screen has in the X and Y registers.

;Determine the screen size.
     JSR SCREEN
     STX MAXCOL
     STY MAXROW
     RTS
;SCREEN allows further compatibility between the 64, the VIC-20, and future versions of the 64.
Returns current window/screen size
 Registers In  : None.
 Registers Out : .X - Window Row Max
                 .Y - Window Col Max
                 .A - Screen Col Max (128 only, 64 unchanged)
 Memory Changed: None
Fetch number of screen rows and columns.

Input: – Output: X = Number of columns (40); Y = Number of rows (25). Used registers: X, Y. Real address: $E505.

return screen size
out:X=columns, Y=rows                  - - -  - X Y  - X Y
SCREEN holt die Anzahl der Zeilen und

Spalten des Bildschirms

$FFF0 PLOT EDITOR 65520
Set cursor location
  • Communication registers: A, X, Y
  • Preparatory routines: None
  • Error returns: None
  • Stack requirements: 2
  • Registers affected: A, X, Y

Description: A call to this routine with the accumulator carry flag set loads the current position of the cursor on the screen (in X,Y coordinates) into the Y and X registers. Y is the column number of the cursor location (6-39), and X is the row number of the location of the cursor (0-24). A call with the carry bit clear moves the cursor to X,Y as determined by the Y and X registers.

How to Use:

READING CURSOR LOCATION

  1. Set the carry flag.
  2. Call this routine.
  3. Get the X and Y position from the Y and X registers, respectively.

SETTING CURSOR LOCATION

  1. Clear carry flag.
  2. Set the Y and X registers to the desired cursor location.
  3. Call this routine.

EXAMPLE:

;MOVE THE CURSOR TO ROW 10, COLUMN 5 (5,10)
     LDX #10
     LDY #5
     CLC
     JSR PLOT
Read or set cursor location

Called by: JSR at AAE9/CAE9 in BASIC's Tab to Column for PRINT, JSR at AAFA/CAFA in BASIC'S TAB and SPC, JSR at B39F/D39F in BASIC'S POS.

Entry requirements: Carry bit should be set or clear, depending on function desired: Set carry to read cursor location (X register = row, and Y register = column).

Clear carry to set cursor location (X register = row, and Y register = column).

JMP E50A (see screen routines in chapter 7).

If the carry bit is clear at entry, move the cursor to the specified location. The contents of the the X register determine the new cursor row andthe contents of the Y register determine the new cursor column.

If the carry bit is set at entry, read the cursor location and place the row value for the current cursor location into the X register and column value for the current cursor location into the Y register.

The row number indicates the physical line, while the column number indicates the column within a logical line. Valid physical line numbers in decimal are 0-24 (64) and 0-22 (VIC). Valid logical column numbers in decimal are 0-79 (64) and 0-87 (VIC).

PLOT

This routine reads or sets the cursor position on the active display, if it is called with the status-register carry bit clear, the value in .X specifies the new cursor row (vertical position), and the value in .Y specifies the column (horizontal position). The carry bit will be set upon return if the specified column or row values are beyond the right or bottom margins of the current output window, or it will be clear if the cursor was successfully positioned.

If the routine is called with the carry bit set, the row number for the current cursor position is returned in .X and the current column number is returned in .Y. For the Commodore 128, the cursor position will be relative to the home position of the current output window rather than to the upper left corner of the screen. Of course, in the case of a full-screen output window—the default condition—the upper left comer of the screen is the home position of the window,

Read/Set Location of the Cursor

The routine allows the user to read or set the position of the cursor. If the carry flag is set with the SEC instruction before calling this subroutine, cursor column (X position) will be returned in the .X register, and the cursor row (Y position) will be returned in the .Y register. If the carry flag is cleared with a CLC instruction before entering this routine, and the .Y and .X registers are loaded with the desired row and column positions respectively, this routine will set the cursor position accordingly.

The current read routine loads .X and .Y from locations 214 ($D6) and 211 ($D3) respectively. The cursor set routine stores .X and .Y in these locations, and calls the routine that sets the screen pointers at 58732 ($E56C).

The user can access this routine from BASIC by loading the .X, .Y, and .P register values desired to the save area starting at 780 ($30C).

Cursor-Position holen/setzen

Je nach Zustand des CARRY-Flags wird entweder die Cursorposition geholt oder gesetzt. X- und Y-Register sind auf jeden Fall die Kommunikationsregister. Das Y-Register definiert die Zeile (Erste Zeile im Fenster ist null) und das X-Register die Spalte des Cursors. Ist das CARRY-Flag gesetzt, so wird die aktuelle Cursorpostion im Fenster in X- und Y-Register zurückgegeben.

Eingabeparameter: .X, .Y, CARRY

Beispiel:

        ;Einen Stern (*) in die Fenstermitte setzen
        JSR $FFED ;SCRORG aufrufen
        TXA       ;Spaltenzahl nach <Akku>
        LSR A     ;Divisiondurch zwei (Mitte)
        TAX       ;und als Spalte wieder nach X
        TYA       ;Zeilenzahl nach <Akku>
        LSR A     ;Divisiondurch zwei (Mitte)
        TAY       ;und wieder als Zeile nach Y
        CLC       ;Gelöschtes Carry=Setzen Cursorposition
        JSR $FFF0 ;Setze Cursorposition
        LDA #"*"  ;<Akku> mit Stern laden
        JSR $FFD2 ;und ausgeben.
read/set X,Y cursor position

This routine, when called with the carry flag set, loads the current position of the cursor on the screen into the X and Y registers. X is the column number of the cursor location and Y is the row number of the cursor. A call with the carry bit clear moves the cursor to the position determined by the X and Y registers.

Read/set X,Y cursor position.

PLOT. If the carry bit of the accumulator is set, then the cursor X,Y is returned in the Y and X registers. If the carry bit is clear, then the cursor is moved to X,Y as determined by the Y and X registers.

;Move cursor to row 12, column 20 (12,20).
     LDX #12
     LDY #20
     CLC
     JSR PLOT
;The cursor is now in the middle of the screen.
Read or set cursor position.
 Registers In  : .C = 1 (Read)        |      .C = 0 (Set)
                   None.              |        .X = Col
                                      |        .Y = Row
 Registers Out : .C = 1 (Read)        |      .C = 0 (Set)
                   .X = Current Col   |         None.
                   .Y = Current Row   |
 Memory Changed:  None                |      Screen Editor Locations.
Save or restore cursor position.

Input: Carry: 0 = Restore from input, 1 = Save to output; X = Cursor column (if Carry = 0); Y = Cursor row (if Carry = 0). Output: X = Cursor column (if Carry = 1); Y = Cursor row (if Carry = 1). Used registers: X, Y. Real address: $E50A.

read/set cursor position
in: C=0, X=row, Y=column               - X Y  - X Y  - - -    out:C=1, X=row, Y=column               - - -  - X Y  - X Y
bei gelöschtem Carry-Flag wird der Cursor

auf die Position X/Y gesetzt, bei gesetztem Carry-Flag wird die Cursorposition nach X/Y geholt (X-Reg = Zeile, Y-Reg = Spalte)

$FFF3 IOBASE MEM 65523
Define I/O memory page
  • Communication registers: X, Y
  • Preparatory routines: None
  • Error returns:
  • Stack requirements: 2
  • Registers affected: X, Y

Description: This routine sets the X and Y registers to the address of the memory section where the memory mapped 110 devices are located. This address can then be used with an offset to access the memory mapped I/O devices in the Commodore 64. The offset is the number of locations from the beginning of the page on which the I/O register you want is located. The X register contains the low order address byte, while the Y register contains the high order address byte.

This routine exists to provide compatibility between the Commodore 64, VIC-20, and future models of the Commodore 64. If the I/O locations for a machine language program are set by a call to this routine, they should still remain compatible with future versions of the Commodore 64, the KERNAL and BASIC.

How to Use:

  1. Call this routine by using the JSR instruction.
  2. Store the X and the Y registers in consecutive locations.
  3. Load the Y register with the offset.
  4. Access that I/O location.

EXAMPLE:

;SET THE DATA DIRECTION REGISTER OF THE USER PORT TO 0 (INPUT)
     JSR IOBASE
     STX POINT       ;SET BASE REGISTERS
     STY POINT+1
     LDY #2
     LDA #0          ;OFFSET FOR DDR OF THE USER PORT
     STA (POINT),Y   ;SET DDR TO 0
Return base address of I/O registers

Called by: JSR at E09E/E09B BASIC's in RND

JMP E500.

This routine returns (to the X and Y registers) the address of the start of the I/O registers that control the 6526 CIA/6522 VIA chips. You can write programs that refer to the I/O registers without knowing the exact address of the I/O register. To write a program in this manner, you would call IOBASE to get the starting address of the I/O registers and add an index to the particular I/O register to which you are referring.

IOBASE for the VIC returns with X register set to $10 and Y register set to $91 (the address of the first register of VIA #1 is 9110). IOBASE for the 64 returns with X register set to $00 and Y register set to $DC (the address of the first register of CIA #1 is DC00). By calling IOBASE, you can determine both the starting address of the I/O registers and which computer the program is running on. Thus, your program could test which computer it is running on and read or write to the appropriate I/O register for this computer, giving you the ability to write one program that works on both the 64 and the VIC. You still will have to know what the CIA/VIA registers do and how to modify them, since what works for a VIA register does not necessarily work the same way on the corresponding CIA register.

BASIC's RND uses this routine to access the CIA/VIA timer registers in generating a random number.

IOBASE

This routine returns a constant 1/0 chip base-address value in .X (low byte) and .Y (high byte). The accumulator is unaffected. For the 64, the value returned is $DC00—the address of CLA #1. For the 128, the value is $D000—the address of the VIC chip.

Store Base Address of Memory-Mapped I/O Devices in .X and .Y Registers

When called, this routine sets the .X register to the low byte of the base address of the memory-mapped I/O devices, and puts the high byte in the .Y register. This allows a user to set up a zero-page pointer to the device, and to load and store indirectly through that pointer. A program which uses this method, rather than directly accessing such devices could be made to function without change on future Commodore models, even though the I/O chips may be addressed at different locations. This of course assumes that the CIA or a similar chip will be used. This routine is of limited value for creating software that is compatible with both the VIC-20 and the 64 because of the differences in the VIA I/O chip that the VIC uses.

The current version of this routine loads the .X register with a 0, and the .Y register with 220 ($DC), thus pointing to CIA #1, which is at 56320 ($DC00).

Holt die Basisadresse des I/O-Bereiches

Es wird die Adresse des Ein- und Ausgabebereiches in X- (Lo) und Y-Register (Hi) übergeben. Diese Adresse ist beim C128 natürlich immer $D000. Für spätere Erweiterungen bzw. Verschiebungen ist es aus Kompatibilitätsgründen ratsam, diese Routine in die Software mit zu integrieren und sich darauf zu beziehen.

Ausgabeparameter: .X, .Y

Beispiel:

        ;Anfang des Programmes:
        JSR $FFF3 ;IOBASE
        STX $FD   ;Lo-Byte merken
        STY $FE   ;Hi-Byte merken

Im Programm bezieht man diese Adresse dann wie folgt ein:

        STA ($FD),Y ;In I/O-Bereich
return the base address of the I/O devices

This routine will set XY to the address of the memory section where the memory mapped I/O devices are located. This address can then be used with an offset to access the memory mapped I/O devices in the computer.

Return base address of I/O devices.

IOBASE returns the low and high bytes of the starting address of the I/O devices in the X and Y registers.

;Set the Data Direction Register of the user port to 0 (input).
     JSR IOBASE
     STX POINT
     STY POINT+1
     LDY #2
     LDA #0
     STA (POINT),Y
;POINT is a zero-page address used to access the DDR indirectly.
Returns base of I/O Block
 Registers In  : None.
 Registers Out : .XY = address of I/O block ($D000)
 Memory Changed: Screen Editor Locations.
Fetch CIA #1 base address.

Input: – Output: X/Y = CIA #1 base address ($DC00). Used registers: X, Y. Real address: $E500.

returns the addr of I/O devices
out:Y/X=addr($DC00)                    - - -  - X Y  - X Y
holt die Startadresse des I/O-Bausteins

1) intended to be called from a cartridge ROM
2) intended to be called from a replacement IRQ handler