Thornton 2 dot Com
1K61U

GEOS Memory Map

Ariel's GEOS Programmer's Reference Guide
Back: File Header Format (TODO) Up: Contents Next: GEOS Errors

Variables are listed here more or less in the order they appear in memory, from lowest address to highest. Some exceptions are made for plainly related variables at out-of-sequence addresses, such as the application pseudo-registers. Variable names are names, equates, and symbols found in geoProgrammer, the Official GEOS Programmer's Reference Guide, the Hitchhiker's Guide to GEOS, and other sources.

For variables defined as different addresses in different GEOS ports, they are listed at addresses in the following order of preference:

  1. Its address in Commodore 64 GEOS,
  2. Its address in GEOS 128 if it doesn't exist in 64 GEOS, or
  3. Its address in Apple II GEOS if it doesn't exist in either Commodore GEOS port.

You can use this alphabetically sorted list of memory map symbols to jump straight to a variable's addresses, description, and usage.

Table of Contents

Overall Commodore 64 GEOS Memory Map

Equate is the geoProgrammer symbol name in geosSym. Start and End are the hexadecimal addresses of the range, inclusive. Size is the range size in bytes, expressed in decimal. Spaces explicitly reserved for your applications are highlighted in bold text.

Equate Start End Size Description
zpage $0000 $0001 2 6510 data direction and I/O registers
$0002 $006f 110 GEOS and application zpage space
$0070 $007f 16 Application-only zpage space (a2 through a9)
$0080 $00fa 123 Kernal ROM and Basic ROM zpage space
$00fb $00fe 4 Application-only zpage space (a0 and a1)
$00ff $00ff 1 Kernal ROM and Basic ROM zpage space
$0100 $01ff 256 6510 stack page
$0200 $03ff 512 RAM used by Kernal ROM routines
APP_RAM $0400 $5fff 23,552 Application program and data space
BACK_SCR_BASE $6000 $78ff 6,400 Background screen (screen 2) card rows 1-20
PRINTBASE $7900 $7f3f 1,600 Background screen (screen 2) card rows 21-25 or printer driver
APP_VAR $7f40 $7fff 192 Application RAM
OS_VARS $8000 $89ff 2,560 GEOS variables and disk buffers
SPRITE_PICS $8a00 $8bff 512 Sprite image data
COLOR_MATRIX $8c00 $8fd7 1,000 Video color matrix
$8fd8 $8ff7 16 GEOS space
$8ff8 $8fff 8 Sprite pointers
DISK_BASE $9000 $9fff 4,096 GEOS code and disk driver
SCREEN_BASE $a000 $bf3f 8,000 Foreground screen (screen 1) or Basic ROM
$bf40 $bfff 192 GEOS tables or Basic ROM
OS_ROM $c000 $cfff 4,096 GEOS Kernal, always resident
vicbase $d000 $d3ff 1,024 GEOS Kernal or VIC I/O
sidbase $d400 $d7ff 1,024 GEOS Kernal or SID I/O
ctab $d800 $dbff 1,024 GEOS Kernal or color table I/O
cia1base $dc00 $dcff 256 GEOS Kernal or CIA #1 I/O
cia2base $dd00 $ddff 256 GEOS Kernal or CIA #2 I/O
$de00 $deff 256 GEOS Kernal or I/O #1
EXP_BASE $df00 $dfff 256 GEOS Kernal or I/O #2 or REU access
$e000 $fe7f 7,808 GEOS Kernal or Kernal ROM
MOUSE_BASE $fe80 $fff9 378 Input driver or Kernal ROM
END_MOUSE $fffa $ffff 6 6510 NMI, IRQ, and reset vectors

The overall memory map in GEOS 128 is similar, but a major difference is that the input driver is in the 384-byte range $fd00-$fe7f instead, ending just before the byte where the 64 input driver would start.

Go to Table of Contents.

6510 CPU Registers

Name Address Size
64 128 Apple
zpage $0000 $0000 page
CPU_DDR $00 $00 byte
CPU_DATA $01 $01 byte

zpage is the base of page $00.

CPU_DDR is the MOS 6510 data direction register, a bitmask that determines whether the corresponding bit in CPU_DATA is read-write (set) or read-only (clear). The default value in GEOS is $2f. This is label D6510 in the Commodore 64 Programmer's Reference Guide and Commodore 128 Programmer's Reference Guide.

CPU_DATA is the MOS 6510 data register, controlling the Commodore 64 hardware and memory map. The following constants are used:

Constant Value Mapping
RAM_64K $30 64K RAM
IO_IN $35 60K RAM, 4K I/O
KRNL_IO_IN $36 52K RAM, 4K I/O, 8K Kernal ROM
KRNL_BAS_IO_IN $37 44K RAM, 8K Basic ROM, 4K I/O, 8K Kernal ROM

All four constants set the datasette output signal level to 0, datasette button status to none pressed, and datasette motor control to off. The default value when the GEOS Main Loop calls any of your routines is $30 (RAM_64K), and the default value when the GEOS Interrupt Level calls any of your routines is $35 (IO_IN).

On the Commodore 128: These variables are present but unused, ensuring their use by 64-specific code is harmless. The I/O space is always mapped in.

When you need to map the I/O space in, use InitForIO and DoneWithIO instead of manipulating these variables directly.

This is label R6510 in the Commodore 64 Programmer's Reference Guide and Commodore 128 Programmer's Reference Guide.

Go to Table of Contents.

GEOS Zero Page Variables

Pseudoregisters

Name Address Size
64 128 Apple
r0 $02 $02 $00 word
r1 $04 $04 $02 word
r2 $06 $06 $04 word
r3 $08 $08 $06 word
r4 $0a $0a $08 word
r5 $0c $0c $0a word
r6 $0e $0e $0c word
r7 $10 $10 $0e word
r8 $12 $12 $10 word
r9 $14 $14 $12 word
r10 $16 $16 $14 word
r11 $18 $18 $16 word
r12 $1a $1a $18 word
r13 $1c $1c $1a word
r14 $1e $1e $1c word
r15 $20 $20 $1e word

r0L $02 $02 $00 byte
r1L $04 $04 $02 byte
r2L $06 $06 $04 byte
r3L $08 $08 $06 byte
r4L $0a $0a $08 byte
r5L $0c $0c $0a byte
r6L $0e $0e $0c byte
r7L $10 $10 $0e byte
r8L $12 $12 $10 byte
r9L $14 $14 $12 byte
r10L $16 $16 $14 byte
r11L $18 $18 $16 byte
r12L $1a $1a $18 byte
r13L $1c $1c $1a byte
r14L $1e $1e $1c byte
r15L $20 $20 $1e byte

r0H $03 $03 $01 byte
r1H $05 $05 $03 byte
r2H $07 $07 $05 byte
r3H $09 $09 $07 byte
r4H $0b $0b $09 byte
r5H $0d $0d $0b byte
r6H $0f $0f $0d byte
r7H $11 $11 $0f byte
r8H $13 $13 $11 byte
r9H $15 $15 $13 byte
r10H $17 $17 $15 byte
r11H $19 $19 $17 byte
r12H $1b $1b $19 byte
r13H $1d $1d $1b byte
r14H $1f $1f $1d byte
r15H $21 $20 $1f byte

Word-size pseudoregisters for interfacing with GEOS Kernal routines. Each of the 16 pseudoregisters has seprately addressable low bytes and high bytes.

Even if a routine doesn't use a specific pseudoregister for input or output, it could still be altered by other parts of the GEOS Kernal during a routine call.

Go to Table of Contents.

Pseudoaccumulators or Application Pseudoregisters

Name Address Size
64 128 Apple
a0 $fb $fb word
a1 $fd $fd word
a2 $70 $70 word
a3 $72 $72 word
a4 $74 $74 word
a5 $76 $76 word
a6 $78 $78 word
a7 $7a $7a word
a8 $7c $7c word
a9 $7e $7e word

a0L $fb $fb byte
a1L $fd $fd byte
a2L $70 $70 byte
a3L $72 $72 byte
a4L $74 $74 byte
a5L $76 $76 byte
a6L $78 $78 byte
a7L $7a $7a byte
a8L $7c $7c byte
a9L $7e $7e byte

a0H $fc $fc byte
a1H $fe $fe byte
a2H $71 $71 byte
a3H $73 $73 byte
a4H $75 $75 byte
a5H $77 $77 byte
a6H $79 $79 byte
a7H $7b $7b byte
a8H $7d $7d byte
a9H $7f $7f byte

Word-size pseudoaccumulators, or pseudoregisters reserved for application use. Each of the 10 pseudoregisters has separately addressable low bytes and high bytes.

Note: These variables do not all occupy consecutive addresses.

These variables are reserved exclusively for GEOS application use. The GEOS Kernal does not touch them, and GEOS desk accessories are expected to leave them untouched.

Go to Table of Contents.

Saved GEOS Zero Page Variables

The GEOS Kernal saves variables from $22 through $38 whenever desk accessories and dialog boxes are called up, and it restores them when they exit.


Name Address Size
64 128 Apple
curPattern $22 $22 $022c word

Pointer to the first byte of the current fill pattern. Each 8x8 pattern is 1 byte wide and 8 bytes high.

In Apple GEOS, the patterns are in auxiliary high RAM, and they should be accessed with SetPattern, GetPattern, and SetUserPattern, not directly.

See Fill Patterns in the Appendix for the patterns available.

The previous name for curPattern was "currentPattern".


Name Address Size
64 128 Apple
string $24 $24 $53 word

Used by GetString as a pointer to an input string buffer. Note: This buffer is not kept null-terminated in GEOS or GEOS 128 while text is being input. It's kept null-terminated during input only in Apple GEOS.


Name Address Size
64 128 Apple
fontData $26 $26 $0218 8 bytes (CBM), 5 bytes (Apple)

A label grouping the font-related variables baselineOffset, curSetWidth, curHeight, curIndexTable, cardDataPntr, and currentMode together. (Not in geosSym.)


Name Address Size
64 128 Apple
baselineOffset $26 $26 $0218 byte
curSetWidth $27 $27 $0219 word
curHeight $29 $29 $021b byte

baselineOffset is the current font's pixel offset from the top to the baseline. In the default system font, BSW 9, the value is $06.

curSetWidth is the current font's card width in pixels. In the default system font, BSW 9, the value is $3c.

curHeight is the current font's card height in pixels. In the default system font, BSW 9, the value is $09.

The previous names for curSetWidth and curHeight were "currentSetWidth" and "currentHeight".


Name Address Size
64 128 Apple
curIndexTable $2a $2a $5e word
cardDataPntr $2c $2c $60 word

Pointers to the table of card sizes (curIndexTable) and the card graphics data (cardDataPntr) for the current font.

Apple note: curIndexTable is in auxiliary RAM. Applications must switch zero pages before accessing it directly.

In the default system font, BSW 9, the default values are:

Variable CBM value Apple value
curIndexTable $d218 $0c08
cardDataPntr $d2dc $0150

The previous names for curIndexTable and cardDataPntr were "currentIndexTable" and "cardDataPointer".


Name Address Size
64 128 Apple
currentMode $2e $2e $021c byte

Current text drawing mode.

Each bit is a style flag: When set, the style is active, and when clear, the style is off. When all bits are clear, the text mode is plain. (Plain is the default mode.)

The style bits and the constants for setting/clearing them are:

Bit Bit constant Set constant Set value
7 UNDERLINE_BIT SET_UNDERLINE %10000000
6 BOLD_BIT SET_BOLD %01000000
5 REVERSE_BIT SET_REVERSE %00100000
4 ITALIC_BIT SET_ITALIC %00010000
3 OUTLINE_BIT SET_OUTLINE %00001000
2 SUPERSCRIPT_BIT SET_SUPERSCRIPT %00000100
1 SUBSCRIPT_BIT SET_SUBSCRIPT %00000010
0

The constant SET_PLAINTEXT (0) is used for clearing all styles in this variable.

Bits 2 and 1 (SUPERSCRIPT_BIT and SUBSCRIPT_BIT) aren't supported by GEOS Kernal routines. They're used by geoWrite in ruler escape strings and by some printer drivers in Apple GEOS.


Name Address Size
64 128 Apple
dispBufferOn $2f $2f $021d byte

Current screen being drawn on. Two bits are used as on-off flags for the foreground and background screens. When both are on, both screens are drawn on simultaneously. Bits and constants:

Bit Constant Value Meaning
7 ST_WR_FORE $80 Write to foreground (screen 1)
6 ST_WR_BACK $40 Write to background (screen 2)
5 ST_WRGS_FORE $20 Write graphics strings (and text strings?) only to foreground
4-0 Reserved for future use, should always be %00000.

The default value seems to be $c0 (ST_WR_FORE | ST_WR_BACK), but your program should set it explicitly during its initialization routine. The default when a dialog box is displayed is $a0 (ST_WR_FORE | ST_WRGS_FORE).

Boyce and Zimmerman say that if bit 5 is set, then only screen 1 is used for text. The geosConstants file from geoProgrammer says of ST_WRGS_FORE, "graphics strings only write to foreground."

Clearing bits 7 and 6 both is undefined behavior. The Hitchhiker's Guide to GEOS warns doing this "will not produce useful results." It goes on:

In most cases, the internal address calculations will force your graphics objects to appear in the center of the drawing area where they can do little harm. If the center line on the screen becomes garbled, dispBufferOn probably contains a bad value.

The previous name was "displayBufferOn".


Name Address Size
64 128 Apple
mouseOn $30 $30 $5d byte

Flags indicating whether mouse, menu, and icons are on. When a bit is set, the mode is on, and when clear, the mode is off. The mode bits and the constants which set them are:

Bit Bit constant Set constant Set value
7 MOUSEON_BIT SET_MSE_ON %10000000
6 MENUON_BIT SET_MENUON %01000000
5 ICONSON_BIT SET_ICONSON %00100000
4-0

Note: The Official GEOS Programmer's Reference Guide and the Hitchhiker's Guide to GEOS say that the #7 set constant is SET_MOUSEON, but geoProgrammer's geosSym and geosConstants files define SET_MSE_ON instead.

The Hitchhiker's Guide to GEOS says the default value is $e0 (all three modes on), but the actual value depends on whether your application has menu and icon tables or not.

BSW docs say only indirectly what each mode means. Boyce and Zimmerman say that these bits are for making the mouse pointer visible, checking the mouse against current menu limits, and checking the mouse against the current icons table, respectively.

The Official GEOS Programmer's Reference Guide says that the joystick driver looks at bit 7 and doesn't check the device unless it's set. This is supported by disassemblies of the other input device drivers included with GEOS and GEOS 128. The OGPRG implies that bit 7 should be changed by calls to MouseOff and MouseUp, not directly.

Important: If your program installs a menu table, then bit 5 will be set as well as bit 6, causing GEOS to check an icon table that may not exist. BSW docs say that if you need menus but not icons, you should install a dummy icon table as a workaround.


Name Address Size
64 128 Apple
msePicPtr $31 $31 word

Pointer to mouse pointer graphics data. Default value: mousePicData.

The previous name was "mousePicture".


Name Address Size
64 128 Apple
windowTop $33 $33 $021e byte
windowBottom $34 $34 byte
leftMargin $35 $35 $0220 word
rightMargin $37 $37 $0222 word

These four variables define the bounding box for text drawing routines.

Characters overlapping above windowTop or below windowBottom will be clipped. Displaying a CR character (ASCII code 13) will cause the next character to be displayed at leftMargin on the next row of text.

Attempting to display a character whose right edge crosses rightMargin or a character starting left of leftMargin will cause GEOS to vector through StringFaultVec to a routine that handles the condition instead.

The default values are the extreme edges of the current display mode's screen dimensions:

Variable 64/128 40-column 128 80-column Apple
windowTop 0 0 0
windowBottom 199 199 not defined
leftMargin 0 0 0
rightMargin 319 639 559

Note: Apple GEOS does not have a windowBottom variable defined.

Go to Table of Contents.

Other GEOS Zero Page Variables

Unlike the variables above, these variables are not saved or restored when a dialog box is shown or a desk accessory is run.


Name Address Size
64 128 Apple
pressFlag $39 $39 $08fe byte

Flags indicating a new keypress or input device data. When a bit is set, the corresponding data is new.

Bit New data Bit constant Set constant Set value
7 Keypress KEYPRESS_BIT SET_KEYPRESS %10000000
GEOS also sets keyData with the key pressed, or it buffers the keypress for retrieval by GetNextChar if the waiting keypress hasn't been serviced first yet. See also keyVector.
6 Input & direction INPUT_BIT SET_INPUTCHG %01000000
The input driver also sets inputData with the new pointer direction, speed, and possibly other data. See also inputVector.
5 Mouse button MOUSE_BIT SET_MOUSE %00100000
The input driver also sets mouseData with the new mouse button state. See also mouseVector and (more usefully) otherPressVec.
4-0

Note: Both the Official GEOS Programmer's Reference Guide and the Hitchhiker's Guide to GEOS are wrong about bit 6 in their variable definitions. Boyce, Zimmerman, and OGPRG (in its constants definitions) are right.

Note: Both OGPRG and HHGG also say that the #6 set constant is SET_INPUTCHANGE, but geoProgrammer's geosSym and geosConstants files define SET_INPUTCHG instead.


Name Address Size
64 128 Apple
mouseXPos $3a $3a $0241 word
mouseYPos $3c $3c $0243 byte

The current (X,Y) coordinates of the mouse pointer.

Note: Because these variables are updated by GEOS Interrupt Level routines, the value of mouseXPos may change between reads of its low and high bytes. To prevent this from being a problem, save the status register, disable IRQ, shadow mouseXPos in a temporary variable, restore the status register, and act on the shadowing variable instead. The Hitchhiker's Guide to GEOS gives this example using r0 as the shadow:

;Check if mouse is within the left and right text margin
IsMseInMargins:
       php                    ;disable interrupts around mouseXPos
       sei                    ; access and copy current pos to a
       MoveW  mouseXPos,r0    ; working location
       plp                    ;restore interrupts

       CmpW   r0,leftMargin   ;check left margin
       bge    10$             ;branch if inside left
       lda    #FALSE          ;else, flag fault
       beq    99$             ;branch always to exit
10$:
       CmpW   r0,rightMargin  ;check right margin
       ble    20$             ;branch if inside right
       lda    #FALSE          ;else, flag fault
       beq    99$             ;branch always to exit
20$:
       lda    #TRUE           ;no fault (inside text margins)
99$:
       rts                    ;exit

The reason this example doesn't run CmpW between sei and plp is because plp would undo CmpW's changes to the N, Z, and C flags as a side effect of restoring the I flag to its previous value. The reason this example doesn't use cli is because it's possible IRQ may have been previously disabled and would need to stay disabled, so it's quicker and shorter to just push and pop the status register than check any of its flags.

The previous names for mouseXPos and mouseYPos were "mouseXPosition" and "mouseYPosition".


Name Address Size
64 128 Apple
returnAddress $3d $3d $64 word

GEOS uses the address here for returning from an inline call. This isn't the actual return address; GEOS uses and updates this while computing offsets from inline data.


Name Address Size
64 128 Apple
graphMode $3f byte

Flag indicating or setting the video mode of the Commodore 128.

The actual mode change is made by setting this variable to the new mode, then calling SetNewMode.


Variables discussed in Boyce's and Zimmerman's guides between $3f and $6f inclusive are either not official, not correct, or not valid for any versions of GEOS after 1.3.

Go to Table of Contents.

Kernal ROM Zero Page Variables

These variables aren't managed directly by GEOS but are still used by GEOS. Detailed information about these variables can be found in reference guides such as the Commodore 64 Programmer's Reference Guide (C64PRG), the Commodore 128 Programmer's Reference Guide (C128PRG), the Apple IIe Technical Reference Manual, and the Apple IIc Technical Reference Manual.


Name Address Size
64 128 Apple
STATUS $90 byte

Status of serial bus and datasette I/O.

Bit Serial bus Datasette
7 Set: Device not present
6 Set: End of file reached Set: EOF reached (only during reading data files)
5 Set: Checksum error occurred
4 Set: VERIFY error (only during VERIFY), the file read from the device did not match that in memory Set: Not all bytes read during pass 1 could be corrected in pass 2, or VERIFY error
3 Set: Block too long (over 192 bytes)
2 Set: Block too short (under 192 bytes)
1 Set: Timeout occurred
0 Transfer direction during which timeuot occurred (clear = input, set = output)

Name Address Size
64 128 Apple
curDevice $ba $ba byte

Current serial device number, label FA in C64PRG and C128PRG. See also curDrive.

Go to Table of Contents.

Apple GEOS Low Variables

Name Address Size
64 128 Apple
mouseXOffset $0229 word
mouseYOffset $022b byte

Signed integer offsets from mouseXPos and mouseYPos to draw the mouse pointer soft-sprite.


Name Address Size
64 128 Apple
noEraseSprites $0240 byte

Flag to stop TempHideMouse from erasing soft-sprites 2-7.


Name Address Size
64 128 Apple
offFlag $027c byte

Flag telling whether the mouse pointer needs to be redrawn:

Value Mouse pointer state
$00 Normal: Displayed, must be erased before drawn at a new position.
$40 Erased: Okay to redraw at next Interrupt Level.
$80 Erased: Do not redraw at next Interrupt Level.
$ff TempHideMouse was called.

Name Address Size
64 128 Apple
machineType $02c4 byte

Apple II-series type:


Name Address Size
64 128 Apple
intSource $02c6 byte

Source of Interrupt Level trigger in Apple GEOS:

Value Interrupt Source
$80 Mouse card
$40 Interrupt management card
$00 Software interrupt

The previous name was "interruptSource".



Name Address Size
64 128 Apple
reqXpos0 $0800 word
reqXpos1 $0802 word
reqXpos2 $0804 word
reqXpos3 $0806 word
reqXpos4 $0808 word
reqXpos5 $080a word
reqXpos6 $080c word
reqXpos7 $080e word

The X coordinate of each soft-sprite 0-7.

Aside from being word-length values, these are used much like mob0xpos through mob7xpos on the Commodore 64/128.

Go to Table of Contents.

Kernal ROM Variables

These variables bear relevance in GEOS even though it's the ROMs that use them.


Name Address Size
64 128 Apple
irqvec $0314 $0314 word

Commodore hardware IRQ interrupt vector in RAM. Label CINV in the Commodore 64 Programmer's Reference Guide, label IIRQ in the Commodore 128 Programmer's Reference Guide.

Every 1/60th or 1/50th of a second (NTSC or PAL), during the video hardware vertical blank cycle, the 6510 or 8502 CPU vectors through $fffe to an IRQ and brk handler. When the Kernal ROM is banked in, the ROM handler vectors through here on IRQ.

GEOS programs will typically use intTopVector or intBotVector when needing to add IRQ code.

Warning: Never change this vector while IRQ is enabled. If an IRQ is generated while it's being changed, the CPU could vector to a wrong adddress and crash the system. Push the status register and disable IRQ first, then change the vector, and pull the status register back. See intTopVector for an example of installing and removing an IRQ-sensitive vector safely.


Name Address Size
64 128 Apple
bkvec $0316 $0316 word

Commodore hardware brk vector in RAM. Label CBINV in the Commodore 64 Programmer's Reference Guide, label IBRK in the Commodore 128 Programmer's Reference Guide.

Whenever the 6510 or 8502 CPU encounters a brk instruction, it vectors through $fffe to an IRQ and brk handler. When the Kernal ROM is banked in, the ROM handler vectors through here on brk.

The default vector is the Kernal's default routine.


Name Address Size
64 128 Apple
nmivec $0318 $0318 word

Commodore hardware NMI interrupt vector in RAM. Label NMINV in the Commodore 64 Programmer's Reference Guide, label INMI in the Commodore 128 Programmer's Reference Guide.

When anything triggers an NMI (such as the user pressing the Restore key), the CPU vectors through $fffa to an NMI handler. When the Kernal ROM is banked in, the ROM handler vectors through here on NMI.


Name Address Size
64 128 Apple
kernalVectors $031a $031a 26 bytes (13 words)

Vectors to routines in Kernal ROM, copied from kernalList by Kernal ROM during startup:

Offset Address Label Vector Description
0 $031a IOPEN Kernal OPEN Routine
2 $031c ICLOSE Kernal CLOSE Routine
4 $031e ICHKIN Kernal CHKIN Routine
6 $0320 ICKOUT Kernal CHKOUT Routine
8 $0322 ICLRCH Kernal CLRCHN Routine
10 $0324 IBASIN Kernal CHRIN Routine
12 $0326 IBSOUT Kernal CHROUT Routine
14 $0328 ISTOP Kernal STOP Routine
16 $032a IGETIN Kernal GETIN Routine
18 $032c ICLALL Kernal CLALL Routine
20 $032e USRCMD (64) User-Defined Vector (64)
EXMON (128) Monitor Command Vector (128)
22 $0330 ILOAD Kernal LOAD Routine
24 $0332 ISAVE Kernal SAVE Routine

See Chapter 5 of the Commodore 64 Programmer's Reference Guide and Chapter 12 of the Commodore 128 Programmer's Reference Guide for details.

Go to Table of Contents.

Application RAM

Although not technically variables, symbols in some compilers (such as cc65) are defined for labeling the two main areas reserved for your application programs. The end of all application areas is indicated by the symbol OS_VARS (the start of GEOS Variables).


Name Address Size
64 128 Apple
APP_RAM $0400 $0400 23,552 bytes

The base address for your applications. The Official GEOS Programmer's Reference Guide labels this "APPLICATION_RAM".


Name Address Size
64 128 Apple
BACK_SCR_BASE $6000 $6000 8,000 bytes

Background screen (screen 2) area. In GEOS 128 80-column mode, this is the lower 100 lines of the background screen area, the upper 100 lines being at SCREEN_BASE. Part of this range is overlapped by the printer driver when it is loaded. The Official GEOS Programmer's Reference Guide labels this "BACK_SCREEN_BASE".


Name Address Size
64 128 Apple
PRINTBASE $7900 $7900 1,600 bytes

Printer driver area. This area overlaps the end of the background screen (screen 2) area. Calling printer driver routines will have unpredictable results if the printer driver is not loaded or if the background screen is drawn on or erased while the printer driver is loaded.


Name Address Size
64 128 Apple
APP_VAR $7f40 $7f40 192 bytes

Space for your application's variables, although you can use it for anything you want if kept below the limit. The Official GEOS Programmer's Reference Guide labels this "APPLICATION_VAR".

Go to Table of Contents.

GEOS Back-RAM/Auxiliary RAM Variables

These variables reside in back-RAM on the Commodore 128 and in auxiliary RAM on the Apple II. They do not exist on the Commodore 64.


Name Address Size
64 128 Apple
curEnable $1300 $d951 byte

Soft-sprite enable bit flags, mirroring mobenble. Not in main RAM.

Each bit corresponds to a soft-sprite: bit 0 to sprite 0, bit 1 to sprite 1, etc. When a bit is set, the corresponding soft-sprite is enabled and potentially drawn on the screen. When a bit is clear, the corresponding soft-sprite is not drawn.


Name Address Size
64 128 Apple
curmoby2 $1301 $d952 byte

Soft-sprite double-height flags, mirroring moby2. Not in main RAM.

Each bit corresponds to a soft-sprite. When a bit is set, the soft-sprite is stretched to double on the Y axis.


Name Address Size
64 128 Apple
curmobx2 $1302 $d953 byte

Soft-sprite double-width flags, mirroring mobx2. Not in main RAM.

Each bit corresponds to a soft-sprite. When a bit is set, the soft-sprite is stretched to double on the X axis.


Name Address Size
64 128 Apple
curXpos0 $1303 $d954 16 bytes (8 words)
curYpos0 $1313 $d964 8 bytes

Soft-sprite (X,Y) coordinates. Not in main RAM.

Each word of curXpos0 and each byte of curYpos0 are used for each of the soft-sprites 0-7. Note that these are grouped as first all 8 X coordinates, then all 8 Y coordinates.


Name Address Size
64 128 Apple
backBufPtr $131b $9d7c 16 bytes (8 words)

Eight word-size pointers to background buffers for soft-sprites 0-7. Not in main RAM.

The Apple address was taken from the Hitchhiker's Guide to GEOS. Based on related variable addresses and sizes, it's possible that "9d7c" was a typo and that the actual address would be $d97c.


Name Address Size
64 128 Apple
backXBufNum $132b $d98c 8 bytes
backYBufNum $1333 $d994 8 bytes

Each byte of backXBufNum and backYBufNum lists the width in bytes and the height in scanlines respectively of each soft-sprite 0-7. Not in main RAM.


Name Address Size
64 128 Apple
sspr1back $133b $56d0 294 bytes (128), 336 bytes (Apple)
sspr2back $1461 $5820 294 bytes (128), 336 bytes (Apple)
sspr3back $1587 $5970 294 bytes (128), 336 bytes (Apple)
sspr4back $16ad $5ac0 294 bytes (128), 336 bytes (Apple)
sspr5back $17d3 $5c10 294 bytes (128), 336 bytes (Apple)
sspr6back $18f9 $5d60 294 bytes (128), 336 bytes (Apple)
sspr7back $1a1f $5eb0 294 bytes (128), 336 bytes (Apple)

Background buffers for each of the soft-sprites 1-7. (Soft-sprite 0 is treated separately.) Not in main RAM.

In GEOS 128, each buffer is 7 bytes wide and 42 scanlines high (for 292 bytes).

In Apple GEOS, each buffer is 8 bytes wide and 42 scanlines high. The extra byte of width is needed because the Apple II stores only 7 pixels per byte.

These buffers are large enough to hold the largest possible soft-sprite size (doubled in both X and Y directions) and include an extra byte in width to save backgrounds on byte boundaries.


Name Address Size
64 128 Apple
shiftBuf $1b45 $0070 7 bytes

Buffer for shifting or doubling soft-sprites. Not in main RAM.


Name Address Size
64 128 Apple
shiftOutBuf $1b4c $0078 7 bytes

Buffer for shifting, doubling, or bitwise-or'ing soft-sprites. Not in main RAM.


Name Address Size
64 128 Apple
sizeFlags $1b53 $db1c byte

Soft-sprite height and 9-pixel flag:

Bit Meaning
7 Set = Soft-sprite is only 9 pixels wide.
6-0 Soft-sprite height in scanlines.

This value is taken from the 64th byte of a soft-sprite's definition. Not in main RAM.


Name Address Size
64 128 Apple
doResetFlag $1b54 $db1d byte

Set to TRUE if any soft-sprites need to be redrawn, which means all higher priority soft-sprites need to be redrawn as well, or to FALSE otherwise. Not in main RAM.


Name Address Size
64 128 Apple
mouseSave $1b55 $ee53 24 bytes

Screen data for what is underneath the mouse pointer soft-sprite. Not in main RAM.


Name Address Size
64 128 Apple
softZeros $1b6d $d0e0 192 bytes
softOnes $1c2d $d000 192 bytes

Buffers used for drawing soft-sprite bitmaps on the screen without disturbing the background. Not in main RAM.


Name Address Size
64 128 Apple
invertBuffer $1ced 80 bytes

Buffer area used by GEOS 128 in 80-column mode to speed up the InvertLine routine. Not in main RAM.

Go to Table of Contents.

GEOS Variables

Most of the programmer-accessible GEOS variables reside at OS_VARS ($8000) on the Commodore 64 and 128.

Disk Buffers

Name Address Size
64 128 Apple
diskBlkBuf $8000 $8000 $f659 256 bytes (CBM), 512 bytes (Apple)

General disk block buffer.


Name Address Size
64 128 Apple
fileHeader $8100 $8100 $f859 256 bytes (CBM), 512 bytes (Apple)

Buffer for the header block of a GEOS file. The GEOS Kernal VLIR file routines use this buffer for the VLIR index table instead.


Name Address Size
64 128 Apple
curDirHead $8200 $8200 $fa80 256 bytes (CBM), 39 bytes (Apple)

In GEOS and GEOS 128: Buffer with header information for the disk in the current drive. The GEOS disk drivers for the Commodore 1571 and 1581 also use the variables dir2Head and dir3Head to extend the buffer.

In Apple GEOS: Buffer with the header of the current directory.


Name Address Size
64 128 Apple
fileTrScTab $8300 $8300 256 bytes

Buffer for a file's track and sector chain. The size of this buffer limits the size of a VLIR file to 32,258 bytes per record and any other type of GEOS file to 32,258 bytes total.

Note: The Official GEOS Programmer's Reference Guide is wrong about the address of this variable.


Name Address Size
64 128 Apple
dirEntryBuf $8400 $8400 $fa59 30 bytes (CBM), 39 bytes (Apple)

Buffer for building a file's directory entry.

Note: The Official GEOS Programmer's Reference Guide is wrong about the address of this variable, and the Hitchhiker's Guide to GEOS is wrong about its size.

Go to Table of Contents.

Disk Variables

Name Address Size
64 128 Apple
DrACurDkNm $841e $841e $faa7 18 bytes (CBM), 16 bytes (Apple)
DrBCurDkNm $8430 $8430 $fab7 18 bytes (CBM), 16 bytes (Apple)

Drive A Current Disk Name and Drive B Current Disk Name respectively.

On Commodore disks, the 16-byte name is padded with $a0, and bytes 17-18 are the disk ID. On Apple disks, the name is padded and terminated with $00.

Related variables: DrCCurDkNm and DrDCurDkNm.


Name Address Size
64 128 Apple
dataFileName $8442 $8442 $02a4 17 bytes (CBM), 16 bytes (Apple)
dataDiskName $8453 $8453 $02b4 18 bytes (CBM), 16 bytes (Apple)

If the program starting your program passes a data file to yours, then GEOS saves the file name in dataFileName and the name of the disk it's on in dataDiskName. Both of these names are null-terminated, except dataDiskName on Commodores (which is padded with $a0 and terminated with the disk ID instead). See LdApplic and StartAppl for passing data file and disk names to another program.

Boyce says $8442 was DrCCurDkNm and $8454 was DrDCurDkNm (which he named DNAME2 and DNAME3), but Zimmerman corrects these errors.


Name Address Size
64 128 Apple
PrntFilename $8465 $8465 $08ac 17 bytes (CBM)
PrntDiskName $8476 $8476 19 bytes

Null-terminated name of the current printer driver and the null-terminated name/disk ID of the disk the current printer driver is on.

BSW docs don't say what the size of PrntFilename is in Apple GEOS, but the next defined symbol after it is inputDevName, 32 bytes after.

The Hitchhiker's Guide to GEOS says PrntDiskName is 18 bytes. While that's effectively true, the Official GEOS Programmer's Reference Guide and the geosMemoryMap file from geoProgrammer explicitly state that the 19th byte is a terminator.


Name Address Size
64 128 Apple
curDrive $8489 $8489 $f60d byte

Currently active disk drive's device number. In GEOS and GEOS 128, the allowed values are 8-11; in Apple GEOS, the allowed values are 0-3.


Name Address Size
64 128 Apple
diskOpenFlg $848a $848a $f617 byte

Flag byte indicating if the current disk is open: TRUE ($ff) if yes, FALSE ($00) if no.

The GEOS Kernal sets this to FALSE on startup, then it never accesses this variable again. It is used and maintained by the deskTop program while it is running. It is available for use by your application for any purpose, but your application will have to maintain it just like an application-specific variable.


Name Address Size
64 128 Apple
isGEOS $848b $848b byte

Flag indicating whether the current disk is a GEOS disk or a non-GEOS CBM disk. Boyce and Zimmerman say the value is $00 for a GEOS disk or $ff for a non-GEOS disk, and disassembled disk drivers bear this out. Apple ProDOS disks are always Apple GEOS disks.


Name Address Size
64 128 Apple
interleave $848c $848c byte

Ideal sector interleave between successive file blocks on a track. This variable is usually managed by GEOS internally and used by BlkAlloc and SetNextFree.

Apple GEOS doesn't have this variable because ProDOS devices handle physical interleaving when mapping block numbers to physical sectors.


Name Address Size
64 128 Apple
numDrives $848d $848d $f60e byte

Number of disk drives attached to the system.


Name Address Size
64 128 Apple
driveType $848e $848e $faf3 4 bytes

Each byte identifies the type of a single drive. In GEOS and GEOS 128, the bytes identify devices 8, 9, 10, and 11 respectively, and in Apple GEOS, the bytes identify drives 0, 1, 2, and 3 respectively.

Structure:


Name Address Size
64 128 Apple
turboFlags $8492 $8492 4 bytes

Byte flags indicading the state of diskTurbo in devices 8, 9, 10, and 11 respectively. Bit 7 is set if diskTurbo is loaded in the disk drive, and bit 6 is set if diskTurbo is active in the disk drive. The normal values are $00 (absent), $80 (present), and $c0 (active).

By coincidence, diskOpenFlg can be used as a base address and curDrive can be used as an index to read the turboFlags state of the current drive:

ldy curDrive
lda diskOpenFlg,y
Go to Table of Contents.

VLIR File Variables

Name Address Size
64 128 Apple
curRecord $8496 $8496 $f618 byte

Signed integer. When a VLIR file is open, this is the current record number (1-127) or -1 ($ff) if the file has no records. OpenRecordFile sets this to 0 or -1, depending on if it has any records or not.


Name Address Size
64 128 Apple
usedRecords $8497 $8497 $f619 byte

Total number of records used in the open VLIR file. The value for a newly created or still-empty VLIR file is 0.


Name Address Size
64 128 Apple
fileWritten $8498 $8498 $f61a byte

Flag indicating if the open VLIR file has been written to since the last update of the index table and BAM: TRUE ($ff) if so, FALSE ($00) if not.


Name Address Size
64 128 Apple
fileSize $8499 $8499 $f61b word

Size in blocks of a file. This is pulled in from and written out to the file's directory entry.

Go to Table of Contents.

GEOS Vectors

Vectors are variables that allow for indirect jmp instructions to alternative routines. GEOS uses these at various points in its Main Loop, Interrupt Level, and Process Management phases so that you can extend them with whatever features your programs need.

Some of these vectors have a default value of $0000, signaling that neither GEOS nor your routine hooking into the vector should actually jump there. GEOS provides the CallRoutine kernal routine to shift the burden of checking the vector address from your program to the GEOS kernal.

GEOS saves all of these vectors when preparing to show a dialog box or to run a desk accessory, and GEOS restores them when they finish.


Name Address Size
64 128 Apple
appMain $849b $849b $0200 word

Vector allowing your program to add your own Main Loop routine. If the value is not $0000, GEOS vectors through here at the end of every Main Loop cycle. Set this vector to your Main Loop routine's entry point. Your routine should end with an rts instruction to return control to GEOS.

The default value is $0000.

The previous name for appMain was "applicationMain".


Name Address Size
64 128 Apple
intTopVector $849d $849d $0202 word
intBotVector $849f $849f $0204 word

Vectors allowing your program to add your own Interrupt Level routines.

If the respective value is not $0000, GEOS vectors through intTopVector and intBotVector at the beginning and end (top and bottom) of every Interrupt Level cycle. Set the right vector to your Interrupt Level routine's entry point.

Your intTopVector routine should end with a jump through the original vector, and your intBotVector routine should end with an rts instruction, not with an rti typical of interrupt code.

Note: On Commodores, intTopVector usually points to InterruptMain, but on Apples, this vector is not normally used. If the address your program finds here isn't $0000, then your routine should end with a jump to that address. Use CallRoutine to let GEOS decide and jump through the vector for you.

Warning: Never change these vectors while IRQ is enabled. If an interrupt triggers a GEOS Interrupt Level while one of these vectors is being changed, the CPU will vector to a wrong address and crash the system. Push the status register and disable IRQ first, then change the vector, and pull the status register back. Example:

;Install our hook into intTopVector
InstallITV:
        php                             ;Save current interrupt state
        sei                             ;Disable interrupts
        MoveW  intTopVector,oldITV      ;Save original vector
        LoadW  intTopVector,#MyITVRout  ;Install our vector
        plp                             ;Restore previous interrupt state
        rts

;Remove our hook into intTopVector
RemoveITV:
        php                             ;Save current interrupt state
        sei                             ;Disable interrupts
        MoveW  oldITV,intTopVector      ;Restore original vector
        plp                             ;Restore previous interrupt state
        rts

;Example intTopVector hook routine
MyITVRout:
        nop                             ;Insert code here.
        lda    oldITV                   ;Load original vector, use GEOS
        ldx    oldITV+1                 ; to jump there, and let its rts
        jmp    CallRoutine              ; go back to Interrupt Level.

The reason this example doesn't use cli is because it's possible IRQ may have been previously disabled and would need to stay disabled, so it's quicker and shorter to just push and pop the status register than check any of its flags.

The previous names for intTopVector and intBotVector were "interruptTopVector" and "interruptBottomVector".


Name Address Size
64 128 Apple
mouseVector $84a1 $84a1 $0206 word

Vector to routine that handles all mouse clicks. GEOS vectors through here on every Main Loop cycle in which pressFlag shows a new button state and mouseData shows a click. In most situations, otherPressVec is the vector you want to use, not this one.

The default value is the GEOS Kernal mouse click dispatcher. The dispatcher handles clicks on menus and icons internally, and passes all clicks on anything else through otherPressVec if set.

If you override this vector with your own routine, then GEOS will no longer be able to handle clicks on menus and icons.

Your routine should end with an rts instruction if the override is okay or a jump to the original vector address if you still want GEOS to process icons and menus after you're done.


Name Address Size
64 128 Apple
keyVector $84a3 $84a3 $0208 word

Vector allowing your program to handle keyboard key presses. If the value is not $0000, GEOS vectors through here during every Main Loop cycle in which pressFlag shows a new key pressed. See also keyData.

The default when your program starts is $0000.

Your routine should end with an rts instruction.


Name Address Size
64 128 Apple
inputVector $84a5 $84a5 $020a word

Vector allowing your program to handle changes in the mouse direction and state. If the value is not $0000, GEOS vectors through here on every Main Loop cycle in which pressFlag shows a mouse state change.

Berkeley Softworks's intention for this vector was to allow applications to access nonstandard data that any then-hypothetical input device driver would expose in a specialized hardware device.

Your routine should end with an rts instruction.


Name Address Size
64 128 Apple
mouseFaultVec $84a7 $84a7 $020c word

Vector allowing your program to handle attempts to move the mouse pointer outside its bounding rectangle or off a menu. If the value is not $0000, GEOS vectors through here on any Main Loop cycle where it detects the following conditions:

See faultData for which condition caused the mouse fault event. If the pointer position is outside its bounding rectangle, GEOS will also reset it to the nearest point on the edge before vectoring through here.

Your routine should end with an rts instruction.

The previous name for mouseFaultVec was "mouseFaultVector".


Name Address Size
64 128 Apple
otherPressVec $84a9 $84a9 $020e word

Vector allowing your program to handle mouse clicks without preventing GEOS from handling clicks on menus and icons. If the value is not $0000, GEOS vectors through here on any Main Loop cycle in which pressFlag shows the mouse button was just clicked or just released, and in which the click was not on any menu or any icon.

The GEOS Kernal mouse click dispatcher handles only clicks on menus and icons. It does not handle releases, even on menus or icons. This means that GEOS won't vector through here on every click, but it will vector through here on every release. Check mouseData to tell the difference.

Your routine should end with an rts instruction.

The previous name for otherPressVec was "otherPressVector".


Name Address Size
64 128 Apple
StringFaultVec $84ab $84ab $0210 word

Vector allowing your program to handle attempts to display characters outside the left and right margins. If the value is not $0000, then the PutChar routine vectors through here whenever any part of a character would be left of leftMargin or any part of a character would be right of rightMargin.

Whether the value is $0000 or not, PutChar will not display the character causing the string fault. Note: SmallPutChar does not vector through here; it clips the character instead.

When the value is $0000 and a string fault occurs, PutChar won't display the character. However, if PutChar is called by PutString, then PutString won't know a string fault occurred, and it will keep going with the next characters in the string. This can lead to a situation where, because no hook routine is installed in this vector, characters skinny enough to fit in the remaining margin space will be displayed out of order, skipping over characters undisplayed because they're too wide.

When this vector is used, r11 will hold an X coordinate, and r1H will hold the Y coordinate of the character's baseline. The X coordinate will be the left edge of the character if rightMargin was exceeded (the usual case), or the left edge of the next character if leftMargin was exceeded.

The character causing the fault is not guaranteed to be in A when this vector is used. If you call PutChar, you should store the character in a byte variable just before the call, and read it in your hook routine. If you call PutString and it causes a fault, then r0 points to the character causing the fault. You will have to find a way to have your hook routine determine whether the fault was caused by PutChar called by PutString or by PutChar called directly by your program.

GEOS expects your hook routine to make whatever changes are necessary, including making its own call to PutChar or SmallPutChar for the character if your routine decides it needs to display it, then ending with an rts instruction. This will return transparently and ultimately to the text or string display routine that was interrupted by this string fault; the GEOS Kernal will not let the rest of your program know that a string fault event occurred.

In Apple GEOS, the values in var(r11) and var(r1H) are stored in auxiliary RAM.

The previous names for StringFaultVec were "StringFaultVector" and "stringFaultVec".


Name Address Size
64 128 Apple
alarmTmtVector $84ad $84ad $0212 word

Vector allowing your program to handle an alarm clock timeout. If the value is $0000, then GEOS does nothing when the alarm time is reached. See also alarmSetFlag. Your routine should end with an rts instruction.

According to reverse-engineered source code, if the value here is $0000, then GEOS will give a short beep through SID voice 1 instead of doing nothing.


Name Address Size
64 128 Apple
BRKVector $84af $84af $0214 word

Vector for intercepting the brk instruction. When a 6502-series CPU encounters a brk instruction, it vectors through $fffe (the 6502 IRQ vector) with the Break flag set. The GEOS Kernal's IRQ handler detects this and vectors through here instead.

The default vector is $cf85 on Commodores and $fef3 on Apples, an internal routine that calls the Kernal Panic routine: When GEOS executes a brk instruction, it shows a dialog box with its address and effectively halts the system.

If it's appropriate for your routine to return control to GEOS (for example, if you're using brk as debugging breakpoints), it should end with an rts instruction, not with an rti typical of interrupt code.


Name Address Size
64 128 Apple
RecoverVector $84b1 $84b1 $0216 word

Vector allowing your program to override how menus, dialog boxes, and desk accessories are erased. Usually, this is a vector to RecoverRectangle. Your routine should end with an rts instruction.

If you point this vector to a custom routine, your routine will have to reimplement RecoverRectangle with the same input and output. Your routine can also disregard the input rectangle and redraw the entire foreground screen instead if you want. See the RecoverRectangle routine for details.

Keep in mind that GEOS will vector through here twice when recovering from dialog boxes with a drop-shadow region defined: once to recover the box's drop-shadow region, and again to recover the box proper. There's an Apple-specific flag variable called recoverOnce to prevent the call that recovers the drop-shadow, but its address and values are undocumented.

Go to Table of Contents.

Saved Global Variables

GEOS saves these variables when preparing to show a dialog box or run a desk accessory, and GEOS restores them when they finish.


Name Address Size
64 128 Apple
selectionFlash $84b3 $84b3 $0224 byte

Speed at which menu items and icons are flashed when clicked. Default value: SELECTION_DELAY (10). ("SELECTION_DELAY" is not in geosSym.)


Name Address Size
64 128 Apple
alphaFlag $84b4 $84b4 $0225 byte

Flag for alphanumeric input. Has the following bit values when getting text input or $00 when not:

Bit Type Description
7 Flag Alphanumeric input on when set
6 Flag Prompt is visible when set
5-0 Counter Timer before prompt flashes

Name Address Size
64 128 Apple
iconSelFlag $84b5 $84b5 $0226 byte

Flags indicating how an icon should flash when clicked.

Bit Meaning when set Constant Value
7 Flash icon, ignore bit 6 ST_FLASH $80
6 Invert icon, leave inverted ST_INVERT $40
5-0

The icon's service routine is not called until the icon finishes flashing or inverting. With both bits off, an icon's service routine is simply called with no user feedback first.


Name Address Size
64 128 Apple
faultData $84b6 $84b6 $0227 byte

Mouse fault event flags. When a mouse fault occurs and GEOS tries to vector through mouseFaultVec, this byte tells which condition caused the fault.

Bit Fault condition Bit constant
7 mouseYPos above mouseTop OFFTOP_BIT
6 mouseYPos below mouseBottom OFFBOTTOM_BIT
5 mouseXPos left of mouseLeft OFFLEFT_BIT
4 mouseXPos right of mouseRight OFFRIGHT_BIT
3 Pointer left menu area OFFMENU_BIT
2-0

The other constants available in geosSym are:

Set constant Set value
SET_OFFTOP %10000000
SET_OFFBOTTOM %01000000
SET_OFFLEFT %00100000
SET_OFFRIGHT %00010000
SET_OFFMENU %00001000
ANY_FAULT %11111000

Name Address Size
64 128 Apple
menuNumber $84b7 $84b7 $0228 byte

Number of the currently working menu. If no menus are open, the value is 0.


Name Address Size
64 128 Apple
mouseTop $84b8 $84b8 $57 byte
mouseBottom $84b9 $84b9 $58 byte
mouseLeft $84ba $84ba $59 word
mouseRight $84bc $84bc $5b word

The four edges of the bounding box for the mouse pointer.

If the pointer goes past one of these edges, GEOS resets mouseXPos and/or mouseYPos to the nearest edge point, sets faultData with the edge exceeded, then tries to vector through mouseFaultVec.

The default values are the extreme edges of the current screen dimensions:

Variable 64/128 40-column 128 80-column Apple
mouseTop 0 0 0
mouseBottom 199 199 191
mouseLeft 0 0 0
mouseRight 319 639 559

Name Address Size
64 128 Apple
stringX $84be $84be $022e word
stringY $84c0 $84c0 $0230 byte

The (X,Y) coordinates of the text prompt. This coordinate is the upper-left corner, not the baseline-left corner, of the next character that's usually shown as echoed text input. If you want to use PutChar to display a character here, add baselineOffset to stringY and save that in r1H.

Go to Table of Contents.

Other Global Variables

Name Address Size
64 128 Apple
mousePicData $84c1 $84c1 64 bytes

Mouse pointer sprite data. This location is pointed to by msePicPtr.


Name Address Size
64 128 Apple
maxMouseSpeed $8501 $8501 $027d byte
minMouseSpeed $8502 $8502 $027e byte
mouseAccel $8503 $8503 $027f byte

Maximum speed, minimum speed, and acceleration rate of the mouse pointer in either axis, respectively.

The previous names for maxMouseSpeed, minMouseSpeed, and mouseAccel were "maximumMouseSpeed", "minimumMouseSpeed", and "mouseAccelecation".


Name Address Size
64 128 Apple
keyData $8504 $8504 $0245 byte

ASCII code of the current last key pressed, managed by keyboard service routines.


Name Address Size
64 128 Apple
mouseData $8505 $8505 byte

Input device dependent. The input driver updates bit 7 with the button status: clear = pressed, set = released.


Name Address Size
64 128 Apple
inputData $8506 $8506 $0247 4 bytes

Input device dependent. The input driver updates these bytes with additional data:

inputData+0
8-point compass direction of the pointer's movement. The joystick driver converts stick presses as follows:
Value Movement direction
-1 Not moving
0 Right
1 Up and right
2 Up
3 Up and left
4 Left
5 Down and left
6 Down
7 Down and right
The mouse driver converts mouse movement into an approximate 8-point direction.
inputData+1
Current pointer speed. This is maintained by the joystick driver but not by the mouse driver.
inputData+2
Device dependent.
inputData+3
Device dependent.

Name Address Size
64 128 Apple
mouseSpeed $8507 $8507 $0248 byte

An alternate label name for inputData+1, maintained by the joystick driver but not by the mouse driver. (Not in geosSym.)


Name Address Size
64 128 Apple
random $850a $850a $024c word

Variable incremented each interrupt to give a random number. Note: Stock 8-bit computers like Apples and Commodores are incapable of generating cryptographically secure randomness.

On each Interrupt Level, the value is recomputed to be: ( 2 * (random + 1) modulo $fff1 (65521).

This is not a very effective pseudorandom generator, as it can lead to obviously guessed patterns instead of effective randomness. If you need better randomness on a stock Commodore, consider using the noise generator in SID voice 3 instead.


Name Address Size
64 128 Apple
saveFontTab $850c $850c $024e 9 bytes (CBM), 10 bytes (Apple)

When a menu is selected, GEOS saves the user active font table here. The Hitchhiker's Guide to GEOS calls this variable "fontData" as well as "saveFontTab".


Name Address Size
64 128 Apple
dblClickCount $8515 $8515 $0258 byte

Counter used to determine whether or not a second click is a double-click.

When the user clicks on an icon, GEOS loads this variable with a value (CLICK_COUNT, 30, according to the Hitchhiker's Guide to GEOS). On every Interrupt Level following, GEOS decrements this counter until it reaches 0 or the user clicks again.

If this counter is 0 when the user clicks on an icon, then GEOS loads FALSE into r0H (double-click flag) and calls the icon's service routine. If the user clicks on the icon again before this counter reaches 0, then GEOS loads TRUE into r0H and calls the icon's service routine.

(CLICK_COUNT is not in geosSym.)


Name Address Size
64 128 Apple
year $8516 $8516 $f200 byte
month $8517 $8517 $f201 byte
day $8518 $8518 $f202 byte

The calendar year (0-99), month, and date components of the time of day clock. GEOS does not track the century, and most 1980s applications making any assumptions now incorrectly assume "19" for the century. BSW docs say that year is an offset from 1900, but reverse-engineered GEOS Kernal sources don't treat it that way, instead resetting it to 0 every time it reaches 100.


Name Address Size
64 128 Apple
hour $8519 $8519 $f203 byte
minutes $851a $851a $f204 byte
seconds $851b $851b $f205 byte

The clock hour, minute, and second components of the time of day clock. The hour is in 24-hour format.

On Commodores, GEOS uses the time of day clock built into the CIA #1 chip to keep the time current. The values stored here are regular binary numbers, not BCD or any other encoding.


Name Address Size
64 128 Apple
alarmSetFlag $851c $851c byte

TRUE if the alarm is set for GEOS to monitor, FALSE otherwise.

On Commodores, GEOS uses the alarm clock built into the CIA #1 chip. However, instead of setting it to trigger an IRQ, GEOS polls cia1icr bit 2 during the Main Loop cycle. Also, when the alarm time is reached while bit 7 is set, GEOS changes the value to $4a just before trying to vector through alarmTmtVector.

The default value is FALSE.


Name Address Size
64 128 Apple
sysDBData $851d $851d $0259 byte

Used internally by GEOS to indicate which dialog box icon causes a return to the application. The actual value is returned in r0L.

If you use a service routine within a dialog box, you can store a code here, and GEOS will return it to the routine that called the dialog box.


Name Address Size
64 128 Apple
screencolors $851e $851e byte

The foreground and background colors. The high nybble is the foreground color, and the low nybble is the background color. The default value if the user hasn't changed it in the Preferences DA is $bf: dark grey (11) foreground, light grey (15) background.

This variable is not present in GEOS 1.0, but it is in GEOS 1.2 and later.

Most programming references say that your program should grab and save the byte at COLOR_MATRIX on start-up instead regardless of GEOS version. In the overwhelming majority of cases, this will achieve the same effect, but it can't be relied on if the user runs your program after running a program that alters and doesn't properly restore the color matrix. geoAssembler and geoLinker from the geoProgrammer package are two such programs known to exist.

GEOS uses this variable to repair the screen color matrix when a desk accessory quits.


Name Address Size
64 128 Apple
dlgBoxRamBuf $851f $851f $f381 417 bytes (CBM), 649 bytes (Apple)

Buffer for saved GEOS variables, menu information, process information, and sprite information. GEOS uses this buffer when running desk accessories or showing dialog boxes.


Undocumented Memory Range

There's an undocumented 507-byte gap on Commodores here: $86c0 to $88ba.


Name Address Size
64 128 Apple
savedmoby2 $88bb $88bb byte

Saved value of moby2 while a dialog box is shown or a desk accessory is running.

The original GEOS context save code did not save the state of moby2, so the fixed code saves it here to remain compatible with desk accessories and other programs that use the size of TOT_SRAM_SAVED for determining what was saved.


Name Address Size
64 128 Apple
scr80polar $88bc byte

Block copy, reverse-screen, character blink rate, and vertical smooth scroll. This is a copy of VDC register 24.


Name Address Size
64 128 Apple
scr80colors $88bd byte

Screen colors for 80-column mode in GEOS 128. The high nybble is the foreground color, and the low nybble is the background color. This is a copy of VDC register 26.


Name Address Size
64 128 Apple
vdcClrMode $88be byte

Current color mode for Commodore 128 color routines.


Name Address Size
64 128 Apple
driveData $88bf $88bf 4 bytes

One byte is reserved for each disk drive device (8-11) and is used by the disk driver.


Name Address Size
64 128 Apple
ramExpSize $88c3 $88c3 byte

Number of 64 KB RAM banks present in the REU if one is installed.


Name Address Size
64 128 Apple
sysRAMFlg $88c4 $88c4 byte

If a REU is installed, GEOS reserves RAM bank 0 for its own use. This byte has bit flags indicating how bank 0 is used:

Bit Meaning when set
7 MoveData uses $0000-$78ff.
6 The disk drivers for Drives A, B, and C are stored in $8300-$b8ff.
5 Bank RAM area $7900-$7dff is loaded with GEOS main RAM area $8400-$88ff by ToBasic when going into BASIC.
4 $7e00-$82ff is loaded with reboot code by a setup autoexec file, which is loaded by the GEOS restart code at main RAM $c000 if this flag is set, at $6000, instead of loading "GEOS BOOT".
• Also, the area $b900-$fc3f saved with the Kernal for fast reboot without the system disk (depending on the setup file). This area should be updated when input devices are changed (implemented in deskTop V1.3).
3-0

Name Address Size
64 128 Apple
firstBoot $88c5 $88c5 $0281 byte

While GEOS is starting up, the value is $00. GEOS finishes starting up by loading deskTop, which changes this value to $ff. Autoexecs can use this flag to tell whether GEOS ran it because it's starting up or because the user double-clicked on its icon.


Name Address Size
64 128 Apple
curType $88c6 $88c6 byte

Current drive type. GEOS and GEOS 128 copy the byte from driveType corresponding to the current drive number here.


Name Address Size
64 128 Apple
ramBase $88c7 $88c7 4 bytes

Each byte identifies the REU RAM bank used by devices 8, 9, 10, and 11 respectively, if the drive type is either a RAM disk or a shadowed disk drive.


Name Address Size
64 128 Apple
inputDevName $88cb $88cb $08cc 17 bytes (CBM), 16 bytes (Apple)

Null-terminated string holding the current input device (mouse) driver filename.

Name Address Size
64 128 Apple
DrCCurDkNm $88dc $88dc $fac7 18 bytes (CBM), 16 bytes (Apple)
DrDCurDkNm $88ee $88ee $fad7 18 bytes (CBM), 16 bytes (Apple)

Drive C Current Disk Name and Drive D Current Disk Name, respectively.

On Commodore disks, the 16-byte name is padded with $a0, and bytes 17-18 are the disk ID. On Apple disks, the name is padded and terminated with $00.

Related variables: DrACurDkNm and DrBCurDkNm.


Name Address Size
64 128 Apple
dir2Head $8900 $8900 256 bytes

First extended buffer with header information for the disk in the current drive. This buffer extends curDirHead and is used by the Commodore 1571 and 1581 GEOS disk drivers. The 1581 driver also uses dir3Head to extend the buffer.


Commodore 1581 Disk Driver Variable

Name Address Size
64 128 Apple
dir3Head $9c80 $9c80 256 bytes

Second extended buffer with header information for the disk in the current drive. This buffer extends curDirHead and dir2Head, and is used by the Commodore 1581 GEOS disk driver. (Not in geosSym.)

Warning: This buffer is actually located inside the 1581 driver code. Do not use or access this space while any other disk drivers are loaded, unless the disk driver is explicitly 1581-compatible. The Commodore 1541 and 1571 disk drivers are not.

Go to Table of Contents.

Hardware Sprite Picture Data

GEOS uses the hardware sprites of the Commodore 64 and of the Commodore 128 in 40-column mode. GEOS manages software sprites on the Commodore 128 in 80-column mode and the Apple II instead.


Name Address Size
64 128 Apple
SPRITE_PICS $8a00 $8a00 512 bytes
spr0pic $8a00 $8a00 64 bytes
GEOS uses this sprite for the mouse pointer.
spr1pic $8a40 $8a40 64 bytes
GEOS uses this sprite for the text input cursor. InitTextPrompt sets this sprite's image.
spr2pic $8a80 $8a80 64 bytes
spr3pic $8ac0 $8ac0 64 bytes
spr4pic $8b00 $8b00 64 bytes
spr5pic $8b40 $8b40 64 bytes
spr6pic $8b80 $8b80 64 bytes
spr7pic $8bc0 $8bc0 64 bytes

These are the picture data buffers for the hardware sprites.

Each sprite is 3 bytes wide and 21 scanlines high. The 3 bytes work out to 24 pixels in bitmap mode and 12 pixels in multi-color mode. The default in GEOS is bitmap mode for every sprite, for a resolution of 24x21 each.

GEOS uses VIC bank 2 ($8000-$bfff) for graphics data. (The VIC bank is selected by cia2pra.)

See Chapter 6 of the Commodore 64 User's Guide, Section II Chapter 6 of the Commodore 128 System Manual, Chapter 3 of the Commodore 64 Programmer's Reference Guide, and Chapter 9 of the Commodore 128 Programmer's Reference Guide for details on how to program sprites.


Name Address Size
64 128 Apple
COLOR_MATRIX $8c00 $8c00 1,000 bytes

The GEOS color matrix sits in between these two sets of sprite data. Each byte corresponds to a screen card. The high nybble determines the card's foreground color, and the low nybble determines the card's background color.


Name Address Size
64 128 Apple
obj0Pointer $8ff8 $8ff8 byte
obj1Pointer $8ff9 $8ff9 byte
obj2Pointer $8ffa $8ffa byte
obj3Pointer $8ffb $8ffb byte
obj4Pointer $8ffc $8ffc byte
obj5Pointer $8ffd $8ffd byte
obj6Pointer $8ffe $8ffe byte
obj7Pointer $8fff $8fff byte

These are the VIC-II pointers to the hardware sprite picture data buffers. They start at offset $3f8 from the color matrix base address.

Each byte is bits 7-13 of a 64-byte sprite image base address relative to the VIC bank. Bits 0-6 of each 13-bit base address are always 0s.

In GEOS, they point to spr0pic through spr7pic via their actual values of $28 through $2f by default.

See cia2pra for VIC bank selection.

Go to Table of Contents.

High Base Addresses

Name Address Size
64 128 Apple
DISK_BASE $9000 $9000 4,096 bytes
Disk drive device driver.
SCREEN_BASE $a000 $a000 $2000 8,000 bytes (64/128), 8,192 bytes (Apple)
Foreground screen (screen 1) area used by the VIC-II. In GEOS 128 80-column mode, upper 100 lines of the background screen area (lower 100 lines at BACK_SCR_BASE). In Apple GEOS, present in both RAM banks at these 8,192 addresses (for 16,384 bytes total); see GetScreenLine.
OS_ROM $c000 $c000 256 bytes
OS_JUMPTAB $c100 $c100 501 bytes?
GEOS Kernal routines jump table. See GEOS Kernal Routines by Call Address: Commodore for details.
RAMC_BASE $de00 $de00 256 bytes?
RAMC_WINDOW $df00 $df00 256 bytes?
EXP_BASE $df00 $df00 256 bytes?
REU access?
MOUSE_BASE_128 $fd00 $fd00 384 bytes
MOUSE_JMP_128 $fd00 $fd00 <384 bytes
END_MOUSE_128 $fe80 $fe80 0 bytes
GEOS 128 input driver code and jump table.
MOUSE_BASE $fe80 $fe80 378 bytes
MOUSE_JMP $fe80 $fe80 <378 bytes
config $ff00 1
Commodore 128 MMU configuration register. Default: CIO_IN ($7e).
END_MOUSE $fffa $fffa 0 bytes
GEOS input driver code and jump table.
NMI_VECTOR $fffa $fffa word
RESET_VECTOR $fffc $fffc word
IRQ_VECTOR $fffe $fffe word

Note: The following variables are not in geosSym: RAMC_BASE, RAMC_WINDOW, MOUSE_BASE_128, MOUSE_JMP_128, END_MOUSE_128, config.

Go to Table of Contents.

Page $C0 GEOS Equates

Name Address Size
64 128 Apple
bootName $c006 $c006 $e003 9 bytes

The string "GEOS BOOT" in ASCII and PETSCII Set 1.

This is also true in the third-party upgrade Wheels, but the string is "GATEWAY " (followed by 5 bytes of padding) in the third-party upgrade gateWay.


Name Address Size
64 128 Apple
version $c00f $c00f $e00c byte

The GEOS version number. The high nybble encodes the major version, and the low nybble encodes the minor version. For example, this address holds $12 in GEOS v1.2, $13 in v1.3, and $20 in v2.0.

In the third-party upgrade gateWay, this byte holds $20, the version of GEOS it upgrades. Your program can use the byte at $c007 (the second byte of bootName) to tell whether it's running in stock GEOS or gateWay: It will hold $45 ("E") in stock GEOS and $41 ("A") in gateWay.

This address holds $41 in the third-party upgrade Wheels.


Name Address Size
64 128 Apple
nationality $c010 $c010 $e00d byte

GEOS Kernal nationality:

ValueMeaning
$00 0 American
$01 1 German
$02 2 French (France & Belgium)
$03 3 Dutch
$04 4 Italian
$05 5 Swiss (Switzerland)
$06 6 Spanish
$07 7 Portuguese
$08 8 Finnish (Finland)
$09 9 UK
$0a 10 Norwegian (Norway)
$0b 11 Danish (Denmark)
$0c 12 Swedish

The nationality of the cbmfiles distributions of GEOS is 0. The nationality of the third-party upgrade Wheels, as compiled by the mist64 source code, is 1.


Name Address Size
64 128 Apple
sysFlgCopy $c012 $c012 byte

A copy of sysRAMFlg, saved here when going from GEOS into BASIC.


Name Address Size
64 128 Apple
c128Flag $c013 $c013 byte

In GEOS v1.3 and later, a signed byte flag indicating whether the current OS is GEOS or GEOS 128. Bit 7 is clear in GEOS and set in GEOS 128.

Potentially garbage data in GEOS v1.2 and earlier: Check that version is $13 or greater before accessing this variable.


Name Address Size
64 128 Apple
dateCopy $c018 $c018 3 bytes

A copy of the variables year, month, and day, in that order.

Go to Table of Contents.

Other Commodore 64 Variables

See the Commodore 64 Programmer's Reference Guide for more details about the addresses corresponding to these variables.


Name Address Size
64 128 Apple
vicbase $d000 $d000 1 KB

When I/O is banked in, this is the base of VIC chip memory locations. Parts of the GEOS Kernal lie in the RAM underneath.


Name Address Size
64 128 Apple
sidbase $d400 $d400 1 KB

When I/O is banked in, this is the base of SID chip memory locations. Parts of the GEOS Kernal lie in the RAM underneath.


Name Address Size
64 128 Apple
mmu $d500 1 KB

Commodore 128 memory management unit. Parts of the GEOS Kernal lie in the RAM underneath. (Not in geosSym.)


Name Address Size
64 128 Apple
VDC $d600 1 KB

Commodore 128 video display controller. This handles all aspects of video in 80-column mode. (Not in geosSym.)

Name Address Size
64 128 Apple
vdcreg $d600 byte
vdcdata $d601 byte

Commodore 128 VDC register selection and data windows. See the Commodore 128 Programmer's Reference Guide for details. (Not in geosSym.)


Name Address Size
64 128 Apple
ctab $d800 $d800 1 KB

When I/O is banked in, this is the base of color memory in Standard Character Mode, Multi-Color Character Mode, Extended Background Color Mode, and Multi-Color Bit Map Mode. It is not used in Standard Bit Map mode, which is the display mode GEOS uses. Only the low nybble of each byte is used. Parts of the GEOS Kernal lie in the RAM underneath.


Name Address Size
64 128 Apple
cia1base $dc00 $dc00 256 bytes
cia2base $dd00 $dd00 256 bytes

When I/O is banked in, these are the base of CIA1 and CIA2 chip memory locations. CIA1 interfaces with the keyboard and controller ports, and CIA2 interfaces with the Serial Bus and the User Port. Parts of the GEOS Kernal lie in the RAM underneath.


Name Address Size
64 128 Apple
kernalList $fd36 $fd36 26 bytes (13 words)

The Official GEOS Programmer's Reference Guide lists this variable but does not describe its purpose. Other GEOS references, including geoProgrammer, don't list this variable at all.

The range $fd30-$fd4f is a table of default vectors in the Kernal ROM that are copied into the RAM vectors at $0314-$0333. The vector at each offset from this address is copied to the corresponding offset from kernalVectors.

Parts of the GEOS Kernal lie in the RAM underneath.


Remember that when the CPU writes to the address of an I/O register, it also writes to the same address of RAM regardless of the current memory map configuration. Sources show the GEOS Kernal writing to officially documented register addresses without regard for the RAM underneath; it should be assumed probably safe to write to documented register addresses in documented ways and unsafe to write to any undocumented location in any I/O device's range.

Go to Table of Contents.

Commodore VIC-II Registers

These are accessible and used by GEOS and GEOS 128 while I/O space is mapped in. Parts of the GEOS Kernal lie in the RAM underneath this range of memory; when the CPU writes to the address of an I/O register, it also writes to the same address of RAM regarless of the current memory map. The variable names and addresses given here are listed in official GEOS documentation.

The Commodore 128 uses these variables only while in 40-column mode. All aspects of display are handled by the VDC instead while in 80-column mode. See the Commodore 128 Programmer's Reference Guide for details on programming the VDC directly.

See the Commodore 64 Programmer's Reference Guide for details on programming these registers directly.


Name Address Size
64 128 Apple
mob0xpos $d000 $d000 byte
mob0ypos $d001 $d001 byte
GEOS reserves sprite 0 for the mouse pointer.
mob1xpos $d002 $d002 byte
mob1ypos $d003 $d003 byte
GEOS reserves sprite 1 for the text cursor.
mob2xpos $d004 $d004 byte
mob2ypos $d005 $d005 byte
mob3xpos $d006 $d006 byte
mob3ypos $d007 $d007 byte
mob4xpos $d008 $d008 byte
mob4ypos $d009 $d009 byte
mob5xpos $d00a $d00a byte
mob5ypos $d00b $d00b byte
mob6xpos $d00c $d00c byte
mob6ypos $d00d $d00d byte
mob7xpos $d00e $d00e byte
mob7ypos $d00f $d00f byte

The (X,Y) coordinates of the 8 hardware sprites. The X coordinate is 9 bits (0-511), but the ninth bit is stored in a bit position of msbxpos.

The hardware sprite coordinates are offset from the GEOS screen coordinates: (24,50) in these registers is (0,0) on the GEOS screen. The geosSym constants VIC_XPOS_OFF and VIC_YPOS_OFF can be used for translating offsets.

Apple GEOS uses reqXpos0 through reqXpos7 for soft-sprites. The Hitchhikers Guide to GEOS says that Apple GEOS defines these variables as well (presumably for soft-sprites), but the addresses are not documented.


Name Address Size
64 128 Apple
msbxpos $d010 $d010 byte

Each bit holds the most significant bit of the corresponding sprite's X coordinate: bit 0 for sprite 0, bit 1 for sprite 1, etc. The remaining 8 least significant bits of each sprite X coordinate are in mob0xpos through mob7xpos.


Name Address Size
64 128 Apple
grcntrl1 $d011 $d011 byte

Graphics Control Register 1.

Bit Meaning
7 Raster compare bit 8 (see rasreg)
6 Extended Color Text Mode (set = enabled)
5 Bitmap Mode (set = enabled)
4 Blank screen to border color (set = enabled)
3 24/25 text rows (set=25, clear=24)
2-0 Smooth-scroll Y offset (0-7 pixels)

The Hitchhiker's Guide to GEOS and the Official GEOS Programmer's Reference Guide mention constants st_ecm ($40) for bit 6, st_bmm ($20) for bit 5, st_den ($10) for bit 4, and st_25row ($08) for bit 3. They are not in geosSym.


Name Address Size
64 128 Apple
rasreg $d012 $d012 byte

Raster register.

Bit 8 of this register is accessed by bit 7 of grcntrl1. Reading and writing that bit has the same meaning as reading and writing the bits of this register.


Name Address Size
64 128 Apple
lpxpos $d013 byte
lpypos $d014 byte

The (X,Y) coordinates of the light pen. The coordinate plane is the same as for sprites. Translation is required for GEOS screen coordinates; see mob7ypos.

The register lpxpos is the X coordinate divided by 2. This means that the resolution of a light pen coordinate is two pixels by one scanline.

The value of the light pen's button is read from cia1prb with the help of cia1ddrb.

Light pens are rarely used because of a variety of design limitations making them impractical for precision use on CRT displays and impossible to use on LCD displays.


Name Address Size
64 128 Apple
mobenble $d015 $d015 $0818 byte

Sprite enable bit flags. Each bit corresponds to a sprite: bit 0 to sprite 0, bit 1 to sprite 1, etc. When a bit is set, the corresponding sprite is enabled and potentially visible on the screen. When a bit is clear, the corresponding sprite is disabled.

In all Commodore 64 and GEOS references, including the geosSym file of geoProgrammer, the name of this variable is spelled without an A.

See curEnable for soft-sprites used by GEOS 128 in 80-column mode and Apple GEOS.


Name Address Size
64 128 Apple
grcntrl2 $d016 $d016 byte

Graphics Control Register 2.

Bit Meaning
7-6
5 Must always be clear (0)!
4 Text or Bitmap Multicolor Mode (set = enabled)
3 38/40 text columns (set=40, clear=38)
2-0 Smooth-scroll X offset (0-7 pixels)

The Hitchhiker's Guide to GEOS and the Official GEOS Programmer's Reference Guide mention constants st_mcm ($10) for bit 4 and st_40col ($08) for bit 3. They are not in geosSym.


Name Address Size
64 128 Apple
moby2 $d017 $d017 $081a byte

Sprite double-height bit flags. Each bit corresponds to a sprite: bit 0 to sprite 0, bit 1 to sprite 1, etc. When a bit is set, the corresponding sprite image is stretched to double on the Y axis. When a bit is clear, the corresponding sprite is displayed at native resolution on the Y axis.

When matching bits of this register and mobx2 are set, the corresponding sprite image is magnified 4x without distortion.


Name Address Size
64 128 Apple
grmemptr $d018 $d018 byte

Graphics memory pointer.

Bits 7-4 are bits 13-10 of the 1K screen memory base address relative to the VIC bank.

In text mode, bits 3-1 are bits 13-11 of the 2K character memory base address relative to the VIC bank. In VIC banks 0 and 2, values %010 and %011 for these bits select the character ROM instead.

In bitmap mode, bit 3 is bit 13 of the 8K bitmap memory base address relative to the VIC bank.

The low bits of each 13-bit base address are always 0s.

The default value in GEOS is $38, putting the 1K screen memory base address at COLORMATRIX ($8c00) and the bitmap memory base address at SCREENBASE ($a000).

See cia2pra for VIC bank selection.


Name Address Size
64 128 Apple
grirq $d019 $d019 byte

VIC interrupt flag register. See grirqen for enabling or disabling the interrupts flagged here.

Bit IRQ Condition
7 Any enabled and unacknowledged VIC IRQ condition
6-4
3 Light pen signal arrived
2 Sprite to sprite collision occurred
1 Sprite to background collision occurred
0 Raster interrupt line is current raster line

On reading, when a bit is set, the corresponding IRQ occurred. On writing, setting a bit (0-3) acknowledges the corresponding interrupt.


Name Address Size
64 128 Apple
grirqen $d01a $d01a byte

VIC interrupt enable mask register.

Bit IRQ Condition Enabled
7-4
3 Light pen
2 Sprite to sprite collision
1 Sprite to background collision
0 Raster line interrupt (see rasreg)

When a bit is set, the corresponding IRQ event is enabled. When an enabled event occurs, the VIC sets bits in grirq and signals an IRQ.

The Hitchhiker's Guide to GEOS and the Official GEOS Programmer's Reference Guide mention a constant, st_rasen ($01), for bit 0. This constant is not in geosSym.


Name Address Size
64 128 Apple
mobprior $d01b $d01b byte

Sprite to background priority bit flags. Each bit corresponds to a sprite: bit 0 to sprite 0, bit 1 to sprite 1, etc. When a bit is set, the corresponding sprite is shown in front of the background. When a bit is clear, the corresponding sprite is shown behind any pixels in the background not set to the background color.


Name Address Size
64 128 Apple
mobmcm $d01c $d01c byte

Sprite Multi-Color Mode bit flags. Each bit corresponds to a sprite: bit 0 to sprite 0, bit 1 to sprite 1, etc. When a bit is set, the corresponding sprite is shown in Multi-Color Mode. When a bit is clear, the corresponding sprite is shown in standard Bitmap Mode.


Name Address Size
64 128 Apple
mobx2 $d01d $d01d $0819 byte

Sprite double-width bit flags. Each bit corresponds to a sprite: bit 0 to sprite 0, bit 1 to sprite 1, etc. When a bit is set, the corresponding sprite image is stretched to double on the X axis. When a bit is clear, the corresponding sprite is displayed at native resolution on the X axis.

When matching bits of this register and moby2 are set, the corresponding sprite image is magnified 4x without distortion.


Name Address Size
64 128 Apple
mobmobcol $d01e $d01e byte

Sprite to sprite collision bit flags. Each bit corresponds to a sprite: bit 0 to sprite 0, bit 1 to sprite 1, etc.

When a bit is set, the corresponding sprite is colliding with another sprite. That is, at least one non-background pixel of the sprite is overlapping a non-background pixel of another sprite.

Writing a bitmask enables further detection of sprite to sprite collisions for the sprites corresponding to set bits.


Name Address Size
64 128 Apple
mobbakcol $d01f $d01f byte

Sprite to background collision bit flags. Each bit corresponds to a sprite: bit 0 to sprite 0, bit 1 to sprite 1, etc.

When a bit is set, the corresponding sprite is colliding with the background image. That is, at least one non-background pixel of the sprite is overlapping a non-background pixel of the background image.

Writing a bitmask enables further detection of sprite to background collisions for the sprites corresponding to set bits.


Name Address Size
64 128 Apple
extclr $d020 $d020 byte
Border color.
bakclr0 $d021 $d021 byte
bakclr1 $d022 $d022 byte
bakclr2 $d023 $d023 byte
bakclr3 $d024 $d024 byte
Background colors. Register bakclr0 is the main background color.
mcmclr0 $d025 $d025 byte
mcmclr1 $d026 $d026 byte
Sprite Multi-Color Mode colors.
mob0clr $d027 $d027 byte
mob1clr $d028 $d028 byte
mob2clr $d029 $d029 byte
mob3clr $d02a $d02a byte
mob4clr $d02b $d02b byte
mob5clr $d02c $d02c byte
mob6clr $d02d $d02d byte
mob7clr $d02e $d02e byte
Sprite foreground colors, one byte per sprite.

Each color register uses only the low nybble. Valid colors:

Value Constant Name RGB code Color
0 BLACK Black #000000 ___
1 WHITE White #ffffff ___
2 RED Red #880000 ___
3 CYAN Cyan #aaffee ___
4 PURPLE Purple #cc44cc ___
5 GREEN Green #00cc55 ___
6 BLUE Blue #0000aa ___
7 YELLOW Yellow #eeee77 ___
8 ORANGE Orange #dd8855 ___
9 BROWN Brown #664400 ___
10 LTRED Light red #ff7777 ___
11 DKGREY Dark grey #333333 ___
12 GREY Medium grey #777777 ___
MEDGREY
13 LTGREEN Light green #aaff66 ___
14 LTBLUE Light blue #0088ff ___
15 LTGREY Light grey #bbbbbb ___

The RGB color codes given here are approximate. The actual colors displayed depend heavily on the tuning of the monitor used with real Commodores and the configuration settings of emulated Commodores.


Name Address Size
64 128 Apple
keyreg $d02f byte

The Commodore 128 keyboard has 24 additional keys for keyboard polling, and bits 2-0 of this register access them. See cia1pra and cia1prb for polling the keys common to both 64 and 128 mode.

When a new 128 key (on the top row or the ten-key pad) is pressed, cia1pra is $ff, and keyreg has the value at the top of the matching column selected, then the value read from cia1prb will be the value on the left of the matching row:

$fb $fd $fe
$7f Alt Esc Help
$bf 0 + 8
$df . - 5
$ef Line Feed Tab
$f7 Enter 2
$fb 6 4
$fd 9 7
$fe No Scrl 3 1

Bits 7-3 are unused and always set when read.

This variable is not in geosSym.


Name Address Size
64 128 Apple
clkreg $d030 byte

Clock speed bits:

Bit Meaning
7-2
1 This bit must be clear for normal operation.
0 When clear: CPU runs at 1 MHz, VIC video is normal.
When set: CPU runs at 2 MHz, VIC video is disabled.

The 2 MHz clock speed of the 8502 CPU is available in 64-mode (thus C64 GEOS when running on the Commodore 128), but the CPU will stay at 1 MHz unless the screen is blanked. So:

  1. Set grcntrl1 bit 4 to blank the screen, then set clkreg bit 0 to start 2 MHz mode, and
  2. Clear clkreg bit 0 to stop 2 MHz mode, then clear grcntrl1 bit 4 to unblank the screen again.

This variable is not in geosSym.


Remember that when the CPU writes to the address of an I/O register, it also writes to the same address of RAM regardless of the current memory map configuration. Sources show the GEOS Kernal writing to officially documented register addresses without regard for the RAM underneath; it should be assumed probably safe to write to documented register addresses in documented ways and unsafe to write to any undocumented location in any I/O device's range.

Go to Table of Contents.

Commodore SID Registers

These are accessible by GEOS and GEOS 128 while I/O space is mapped in. Parts of the GEOS Kernal lie in the RAM underneath this range of memory; when the CPU writes to the address of an I/O register, it also writes to the same address of RAM regardless of the current memory map.

The variable names and addresses given here are listed in official GEOS documentation, but they are not in geoProgrammer.

See the Commodore 64 Programmer's Reference Guide and the Commodore 128 Programmer's Reference Guide for details on programming these registers.

Write-Only Registers

Name Address Size
64 128 Apple
v1freqlo $d400 $d400 byte
v1freqhi $d401 $d401 byte

Voice 1 frequency control, low and high bytes.


Name Address Size
64 128 Apple
v1pwlo $d402 $d402 byte
v1pwhi $d403 $d403 byte

Voice 1 pulse waveform width, low byte and high nybble. This pair of bytes forms a 12-bit value. Bits 7-4 of v1pwhi are unused.


Name Address Size
64 128 Apple
v1cntrl $d404 $d404 byte

Voice 1 control register:

Bit Meaning
7 Select random noise waveform (set = on)
6 Select pulse waveform (set = on)
5 Select sawtooth waveform (set = on)
4 Select triangle waveform (set = on)
3 Test bit (set = disable oscillator 1)
2 Ring modulate oscillator 1 with oscillator 3 output (set = on)
1 Synchronize oscillator 1 with oscillator 3 frequency (set = on)
0 Gate bit (set = start ADS, clear = start R)

Name Address Size
64 128 Apple
v1attdec $d405 $d405 byte
v1susrel $d406 $d406 byte

ADSR envelope generator 1. v1attdec controls the attack and decay cycles, and v1susrel controls the sustain and release cycles.


Name Address Size
64 128 Apple
v2freqlo $d407 $d407 byte
v2freqhi $d408 $d408 byte
v2pwlo $d409 $d409 byte
v2pwhi $d40a $d40a byte
v2cntrl $d40b $d40b byte
v2attdec $d40c $d40c byte
v2susrel $d40d $d40d byte

Same as v1freqlo, v1freqhi, v1pwlo, v1pwhi, v1cntrl, v1attdec, and v1susrel, but for voice 2.

Bits 2 and 1 of v2cntrl ring-modulate and synchronize oscillator 2 with oscillator 1, instead of 1 with 3.


Name Address Size
64 128 Apple
v3freqlo $d40e $d40e byte
v3freqhi $d40f $d40f byte
v3pwlo $d410 $d410 byte
v3pwhi $d411 $d411 byte
v3cntrl $d412 $d412 byte
v3attdec $d413 $d413 byte
v3susrel $d414 $d414 byte

Same as v1freqlo, v1freqhi, v1pwlo, v1pwhi, v1cntrl, v1attdec, and v1susrel, but for voice 3.

Bits 2 and 1 of v3cntrl ring-modulate and synchronize oscillator 3 with oscillator 2, instead of 1 with 3.


Name Address Size
64 128 Apple
fclo $d415 $d415 byte
fchi $d416 $d416 byte

Filter cutoff frequency, low nybble and high byte. This pair of bytes forms an 11-bit value. Bits 7-3 of fclo are unused.


Name Address Size
64 128 Apple
resfilt $d417 $d417 byte

Filter resonance and voice input control register:

Bit Meaning
7-4 Select filter resonance (0-15)
3 Filter external input (set = yes)
2 Filter voice 3 output (set = yes)
1 Filter voice 2 output (set = yes)
0 Filter voice 1 output (set = yes)

Name Address Size
64 128 Apple
modevol $d418 $d418 byte

Filter mode and volume register:

Bit Meaning
7 Cut-off voice 3 output (set = off, clear = on)
6 Select filter high-pass mode (set = on)
5 Select filter band-pass mode (set = on)
4 Select filter low-pass mode (set = on)
3-0 Select output volume (0-15)

Read-Only Registers

Name Address Size
64 128 Apple
potx $d419 $d419 byte

Game paddle X potentiometer value, or proportional mouse or graphics tablet up-down value (0-255).

A paddle knob turned fully clockwise is 0, and a paddle knob turned fully counter-clockwise is 255.

The SID measures the analog input once every 512 machine cycles.

When used to read a Commodore 1351 mouse in default proportional mode, the bits have the following meanings:

Bit Meaning
7 Undefined
6-1 X position modulo 64
0 Noise bit

Use bit 0 to determine whether the mouse has moved or not.

A normal keyscan affects this register. For the reading here to be valid, the mouse must be reconnected for at least 1.6 ms. The best way is wedging a mouse driver into the IRQ handler before the keyboard polling. GEOS provides intTopVector for this purpose.

Using a Commodore 1350 mouse (or a 1351 mouse in joystick mode) does not involve this register except for the right button: Bit 7 is clear when the button is pressed (clicked) and set when the button isn't.

See cia1pra and cia1ddra for selecting which pair of paddles (or other controller) is read.


Name Address Size
64 128 Apple
poty $d41a $d41a byte

Game paddle Y potentiometer value, or proportional mouse or graphics tablet left-right value (0-255).

A paddle knob turned fully clockwise is 0, and a paddle knob turned fully counter-clockwise is 255.

The SID measures the analog input once every 512 machine cycles.

When used to read a Commodore 1351 mouse in default proportional mode, the bits have the following meanings:

Bit Meaning
7 Undefined
6-1 Y position modulo 64
0 Noise bit

Use bit 0 to determine whether the mouse has moved or not.

A normal keyscan affects this register. For the reading here to be valid, the mouse must be reconnected for at least 1.6 ms. The best way is wedging a mouse driver into the IRQ handler before the keyboard polling. GEOS provides intTopVector for this purpose.

Neither the Commodore 1350 mouse nor the 1351 mouse in joystick mode use this port. See potx for reading the right button state.

See cia1pra and cia1ddra for selecting which pair of paddles is read.


Name Address Size
64 128 Apple
osc3rand $d41b $d41b byte

Oscillator 3 random number generator.


Name Address Size
64 128 Apple
env3 $d41c $d41c byte

Envelope generator 3 output.


Remember that when the CPU writes to the address of an I/O register, it also writes to the same address of RAM regardless of the current memory map configuration. Sources show the GEOS Kernal writing to officially documented register addresses without regard for the RAM underneath; it should be assumed probably safe to write to documented register addresses in documented ways and unsafe to write to any undocumented location in any I/O device's range.

Go to Table of Contents.

Commodore 64 CIA Registers

These are accessible and used by GEOS while I/O space is mapped in. Parts of the GEOS Kernal lie in the RAM underneath this range of memory; when the CPU writes to the address of an I/O register, it also writes to the same address of RAM regardless of the current memory map.

The variable names and addresses given here are listed in official GEOS documentation, but they are not in geoProgrammer.

See the Commodore 64 Programmer's Reference Guide for details on how to program these registers.

Complex Interface Adapter #1

The interrupts generated by CIA#1 are IRQ interrupts. Use CIA#2 if you need to generate NMI interrupts.

Name Address Size
64 128 Apple
cia1pra $dc00 byte

Data port A (keyboard, controllers in port 2). cia1ddra determines which bits of this port can be written to.

For keyboard use: Each bit corresponds to a column of the keyboard matrix. When a bit here is selected clear and any of the eight keys in the column are pressed, the corresponding bit(s) of cia1prb will be read as clear.

Like the Kernal ROM, GEOS modifies this value during Interrupt Level (IRQ) to scan the keyboard.

If you're looking for a simple keyboard interface, use keyVector or another of the GEOS Vectors instead.

For joystick use: When read, each bit corresponds to a button on controller 2:

Bit Meaning When Clear
7-5
4 Fire button pressed
3 Joystick pushed right
2 Joystick pushed left
1 Joystick pushed down (towards player)
0 Joystick pushed up (away from player)

The joystick can be pushed in the in-between directions as well, causing two direction bits to be clear.

For Commodore 1350 mouse use: The 1350 is essentially a "rolling joystick." When moved, it generates joystick signals in the direction of movement for 20 ms. The left button is mapped to the joystick fire button (bit 4), and the right button is mapped to potx.

For Commodore 1351 mouse use: In joystick mode, it functions like a Commodore 1350 mouse. In proportional mode, movement is read almost like paddles from potx and poty, left button presses are read like the joystick fire button (bit 4), and right button presses are read like the joystick pushed up (bit 0).

For CMD Smart Mouse use: Identical in operation to a Commodore 1351 (including joystick mode). In proportional mode, center button presses are read like the joystick pushed down (bit 1).

For paddle use: The values of the paddles' control knobs are read from the SID at potx and poty, but only one control port's paddles can be read at a time. Writing %01 to bits 7-6 selects the paddles in control port 1, and writing %10 to bits 7-6 selects the paddles in control port 2.

When read, bits 3-2 are the fire button states of the paddles in control port 2. Bit 3 is clear when the Y paddle's fire button is pressed, and bit 2 is clear when the X paddle's fire button is pressed.

For graphics tablet use: Graphics tablets are generally used like a pair of paddles, except that the values of potx and poty can change very drastically between readings.

The KoalaPad specifically maps the left button to paddle X's fire button and the right button to paddle Y's fire button.

For light pen use: Light pens can only be used in control port 1. See cia1prb for light pen programming.


Name Address Size
64 128 Apple
cia1prb $dc01 byte

Data port B (keyboard, controllers in port 1, light pen). cia1ddrb determines which bits of this port can be written to.

For keyboard use: Each bit corresponds to a row of the keyboard matrix. When a bit in cia1pra is selected clear and any of the eight keys in the column are pressed, the corresponding bit(s) here will be read as clear.

Like the Kernal ROM, GEOS uses this value during Interrupt Level (IRQ) to scan the keyboard.

If you're looking for a simple keyboard interface, use keyVector or another of the GEOS Vectors instead.

When a single key is pressed and cia1pra has the value at the top of the matching column selected, the value read from here will be the value on the left of the matching row:

$7f $bf $df $ef $f7 $fb $fd $fe
$7f Stop / , n v x Lshft
$bf q @ o u t e f5
$df C= = : k h f s f3
$ef Spc Rshft . m b c z f1
$f7 2 Clr - 0 8 6 4 f7
$fb Ctrl ; l j g
a
$fd * p i y r w Ret
$fe 1 £ + 9 7 5 3 Del

If the matching column is not selected, then the value read here will be $ff. If no key is pressed, then the value will be $ff regardless of the column selected. No more than 2 keys pressed at the same time can be correctly detected reliably.

This port is also used for reading keys on the Commodore 128's keyboard in GEOS 128. See keyreg for reading the new keys.

For joystick use: When read, each bit corresponds to a button on controller 1:

Bit Meaning When Clear
7-5
4 Fire button pressed
3 Joystick pushed right
2 Joystick pushed left
1 Joystick pushed down (towards player)
0 Joystick pushed up (away from player)

The joystick can be pushed in the in-between directions as well, causing two direction bits to be clear.

If the keyboard is used at the same time, then spurious keypresses can be unintentionally generated by the port 1 joystick.

For Commodore 1350 mouse use: The 1350 is essentially a "rolling joystick." When moved, it generates joystick signals in the direction of movement for 20 ms. The left button is mapped to the joystick fire button (bit 4), and the right button is mapped to potx.

For Commodore 1351 mouse use: In joystick mode, it functions like a Commodore 1350 mouse. In proportional mode, movement is read almost like paddles from potx and poty, left button presses are read like the joystick fire button (bit 4), and right button presses are read like the joystick pushed up (bit 0).

For CMD Smart Mouse use: Identical in operation to a Commodore 1351 (including joystick mode). In proportional mode, center button presses are read like the joystick pushed down (bit 1).

For paddle use: The values of the paddles' control knobs are read from the SID at potx and poty, but only one control port's paddles can be read at a time. Use cia1pra to select which port's paddle knobs are read.

When read, bits 3-2 are the fire button states of the paddles in control port 1. Bit 3 is clear when the Y paddle's fire button is pressed, and bit 2 is clear when the X paddle's fire button is pressed.

For graphics tablet use: Graphics tablets are generally used like a pair of paddles, except that the values of potx and poty can change very drastically between readings.

The KoalaPad specifically maps the left button to paddle X's fire button and the right button to paddle Y's fire button.

For light pen use: The light pen coordinates are read from lpxpos and lpypos. The light pen's button state is read from bit 4, just like a joystick's fire button.

For CIA#1 timer use: Timer A toggles or pulses bit 6, depending on cia1ddrb bit 6 and cia1cra bits 2 and 1. Timer B toggles or pulses bit 7, depending on cia1ddrb bit 7 and cia1crb bits 2 and 1.


Name Address Size
64 128 Apple
cia1ddra $dc02 byte

Data direction register for cia1pra. When a bit is clear, the matching bit in cia1pra is read-only; when set, the matching bit is read-write.

For keyboard use: The value should be $ff for selecting each column in turn.

For joystick use: The value should be $00 for reading control port 2.

For paddle use: The value should be $c0 when selecting which control port's paddle knobs are read or $00 for reading just the fire buttons' states.


Name Address Size
64 128 Apple
cia1ddrb $dc03 byte

Data direction register for cia1prb. When a bit is clear, the matching bit in cia1prb is read-only; when set, the matching bit is read-write.

For keyboard use: The value should be $00 for reading each key on the row.

For joystick use: The value should be $00 for reading control port 1.

For paddle use: The value should be $00 for reading control port 1.


Name Address Size
64 128 Apple
cia1talo $dc04 byte
cia1tahi $dc05 byte

Timer A low and high bytes. When running, it counts down one value per CPU clock cycle (1,022,730 cycles per second on NTSC, or 985,250 cycles per second on PAL) or one value per pulse on User Port CNT line (see cia1cra). When the timer reaches 0, bit 0 of cia1icr will be set.

When read: Current timer value.

When written: Place the start value in the timer latch. Use the Force Load bit of cia1cra to actually load the timer from the latch.

See programming references such as Compute's Mapping the Commodore 64 and 64C (pp. 172-186) for more details.


Name Address Size
64 128 Apple
cia1tblo $dc06 byte
cia1tbhi $dc07 byte

Timer B low and high bytes. When running, it counts down one value per CPU clock cycle (1,022,730 cycles per second on NTSC, or 985,250 cycles per second on PAL), or one value per pulse on User Port CNT line, or one value per time the 16-bit timer cia1tahi/cia1talo passes 0 (see cia1crb). When the timer reaches 0, bit 1 of cia1icr will be set.

When read: Current timer value.

When written: Place the start value in the timer latch. Use the Force Load bit of cia1crb to actually load the timer from the latch.

See programming references such as Compute's Mapping the Commodore 64 and 64C (pp. 172-186) for more details.


Name Address Size
64 128 Apple
cia1tod10ths $dc08 byte

Time of day clock, current tenths of the second, encoded in BCD.

The high nybble is unused. The low nybble is the current decimal tenth of a second.

When read: Current clock time. When written: Set current clock time or alarm clock time depending on cia1crb.

Important: When the cia1todhr register is read, the chip will freeze the output of the cia1todmin, cia1todsec, and cia1tod10ths registers as well, so that they can be read without a potential rollover causing incorrect readings. The TOD clock runs normally; only the output is frozen. Reading the cia1tod10ths register unfreezes these registers.

Likewise, when setting the time of day, the clock will halt when cia1todhr is written, and the clock will not start again until cia1tod10ths is written.


Name Address Size
64 128 Apple
cia1todsec $dc09 byte

Time of day clock, current second of the minute, encoded in BCD.

The high nybble except bit 7 is the tens digit of the current second. The low nybble is the unit digit of the current second.

When read: Current clock time. When written: Set current clock time or alarm clock time depending on cia1crb.

Important: When setting the alarm clock time, if both cia1todsec and cia1tod10ths are set to $00 (precisely the top of any minute), then the chip may not generate an alarm IRQ. Set cia1tod10ths to $01 (1/10 of a second later) to work around this flaw.


Name Address Size
64 128 Apple
cia1todmin $dc0a byte

Time of day clock, current minute of the hour, encoded in BCD.

The high nybble except bit 7 is the tens digit of the current minute. The low nybble is the unit digit of the current minute.

When read: Current clock time. When written: Set current clock time or alarm clock time depending on cia1crb.


Name Address Size
64 128 Apple
cia1todhr $dc0b byte

Time of day clock, current hour of the day in 12-hour format, encoded in BCD.

Bit 7 is the AM/PM flag: clear = AM, set = PM. Bit 4 is the tens digit of the current hour. The low nybble is the unit digit of the current hour.

When read: Current clock time. When written: Set current clock time or alarm clock time depending on cia1crb.

Important: When the cia1todhr register is read, the chip will freeze the output of the cia1todmin, cia1todsec, and cia1tod10ths registers as well, so that they can be read without a potential rollover causing incorrect readings. The TOD clock runs normally; only the output is frozen. Reading the cia1tod10ths register unfreezes these registers.

Likewise, when setting the time of day, the clock will halt when cia1todhr is written, and the clock will not start again until cia1tod10ths is written.


Name Address Size
64 128 Apple
cia1sdr $dc0c byte

Serial data register for the User Port. Input or output depending on cia1cra. Gated in or out MSB first through the User Port SP line and CNT line at a baud rate determined by cia1tahi/cia1talo.


Name Address Size
64 128 Apple
cia1icr $dc0d byte

Interrupt control and status register.

When read:

Bit Meaning
7 Set = An IRQ has been generated
6-5
4 Signal level on FLAG pin of datasette input or serial bus SRQ IN
3 Set = A complete byte has been received into or sent from cia1sdr
2 Set = Current time of day is the alarm time
1 Set = Timer B (cia1tblo) underflowed
0 Set = Timer A (cia1talo) underflowed

When written:

Bit Meaning
7 Fill bit. Bits below that are set, are actually set or cleared to this bit's value. Bits below that are clear, are actually left unchanged.
6-5
4 Set: #7 set/clear = Enable/disable IRQs generated by FLAG pin positive edge
3 Set: #7 set/clear = Enable/disable IRQs generated by sending or receiving a byte through cia1sdr
2 Set: #7 set/clear = Enable/disable time of day alarm clock IRQ
1 Set: #7 set/clear = Enable/disable IRQs generated by Timer B underflow
0 Set: #7 set/clear = Enable/disable IRQs generated by Timer A underflow

Despite no CIA registers being listed in geosSym, the constant ALARMMASK (%00000100) is defined for masking the alarm bit. This register is the one GEOS polls during Main Loop cycles to see if the alarm clock time has arrived. See alarmSetFlag and alarmTmtVector.


Name Address Size
64 128 Apple
cia1cra $dc0e byte

Control register for Timer A (cia1tahi/cia1talo):

Bit Clear Set
7 60 Hz TOD clock 50 Hz TOD clock
6 cia1sdr is input cia1sdr is output
5 Timer counts CPU cycles Timer counts CNT line positive edges
4 Load Timer start value
3 Timer restarts on underflow Stops on underflow
2 Toggle cia1prb bit 6 on underflow Pulse cia1prb bit 6 for 1 CPU cycle on underflow
1 Don't... Indicate underflow on cia1prb bit 6
0 Stop timer Start timer

In order to indicate a Timer A underflow on cia1prb bit 6, cia1ddrb bit 6 must be set.

GEOS sets the time of day clock frequency (bit 7) during startup based on the system's PAL/NTSC flag: $02a6 on the Commodore 64 or $0a03 on the Commodore 128. (0 = NTSC, 1 = PAL.)

Important: The accuracy of the CIA chip's time of day clock depends on the main power supply's AC frequency, not the video standard's frequency. Set or clear bit 7 based on that. An exception to this rule is the Commodore SX-64, both NTSC and PAL versions, which feeds the CIAs from a 60 Hz crystal. See other resources such as this Codebase 64 wiki article for how to detect the right frequency with some reliability.


Name Address Size
64 128 Apple
cia1crb $dc0f byte

Control register for Timer B (cia1tbhi/cia1tblo):

Bit Clear Set
7 Set current TOD clock time Set alarm clock time
6-5 %00 = Timer B counts CPU cycles
%01 = Timer B counts CNT line positive edges
%10 = Timer B counts Timer A underflows
%11 = Timer B counts Timer A underflows along with CNT line positive edges
4 Load Timer start value
3 Timer restarts on underflow Stops on underflow
2 Toggle cia1prb bit 7 on underflow Pulse cia1prb bit 7 for 1 CPU cycle on underflow
1 Don't... Indicate underflow on cia1prb bit 7
0 Stop timer Start timer

In order to indicate a Timer B underflow on cia1prb bit 7, cia1ddrb bit 7 must be set.


Complex Interface Adapter #2

The interrupts generated by CIA#2 are NMI interrupts. Use CIA#1 if you need to generate IRQ interrupts.


Name Address Size
64 128 Apple
cia2pra $dd00 byte

Data port A (serial bus, RS-232, VIC memory control). cia2ddra determines which bits of this port can be written to.

Bit Meaning
7 Serial bus DATA IN: %0 = low, %1 = high
6 Serial bus CLOCK IN: %0 = low, %1 = high
5 Serial bus DATA OUT: %0 = high, %1 = low
4 Serial bus CLOCK OUT: %0 = high, %1 = low
3 Serial bus ATN OUT: %0 = high, %1 = low
2 RS-232 TXD line, output bit
1-0 %00 = VIC bank 3: $c000-$ffff
%01 = VIC bank 2: $8000-$bfff
%10 = VIC bank 1: $4000-$7fff
%11 = VIC bank 0: $0000-$3fff

Despite no CIA registers being listed in geosSym, the following constants are defined for bank selection:

Constant Value Meaning
GRBANK0 %11 VIC bank 0
GRBANK1 %10 VIC bank 1
GRBANK2 %01 VIC bank 2
GRBANK3 %00 VIC bank 3

GEOS uses VIC bank 2.


Name Address Size
64 128 Apple
cia2prb $dd01 byte

Data port B (user port, RS-232). cia2ddrb determines which bits of this port can be written to.

When read:

Bit Meaning
7 RS-232 DSR line: set = Receiver ready to receive
6 RS-232 CTS line: set = Sender ready to send
5 User port H pin
4 RS-232 DCD line
3 RS-232 RI line
2-1
0 RS-232 RXD line, input bit

When written:

Bit Meaning
7-6
5 User port H pin
4 RS-232 DCD line
3 RS-232 RI line
2 RS-232 DTR line: set = Receiver ready to receive
1 RS-232 RTS line: set = Sender ready to send
0

The CIA#2 timers also make use of this port. Timer A toggles or pulses bit 6, depending on cia2ddrb bit 6 and cia2cra bits 2 and 1. Timer B toggles or pulses bit 7, depending on cia2ddrb bit 7 and cia2crb bits 2 and 1.


Name Address Size
64 128 Apple
cia2ddra $dd02 byte
cia2ddrb $dd03 byte

Data direction registers for cia2pra and cia2prb respectively. When a bit is clear, the matching bit in the corresponding port register is read-only; when set, the matching bit is read-write.


Name Address Size
64 128 Apple
cia2talo $dd04 byte
cia2tahi $dd05 byte

Timer A low and high bytes. When running, it counts down one value per CPU clock cycle (1,022,730 cycles per second on NTSC, or 985,250 cycles per second on PAL) or one value per pulse on User Port CNT line (see cia2cra). When the timer reaches 0, bit 0 of cia2icr will be set.

When read: Current timer value.

When written: Place the start value in the timer latch. Use the Force Load bit of cia2cra to actually load the timer from the latch.

See programming references such as Compute's Mapping the Commodore 64 and 64C (pp. 172-186) for more details.


Name Address Size
64 128 Apple
cia2tblo $dd06 byte
cia2tbhi $dd07 byte

Timer B low and high bytes. When running, it counts down one value per CPU clock cycle (1,022,730 cycles per second on NTSC, or 985,250 cycles per second on PAL), or one value per pulse on User Port CNT line, or one value per time the 16-bit timer cia2tahi/cia2talo passes 0 (see cia2crb). When the timer reaches 0, bit 1 of cia2icr will be set.

When read: Current timer value.

When written: Place the start value in the timer latch. Use the Force Load bit of cia2crb to actually load the timer from the latch.

See programming references such as Compute's Mapping the Commodore 64 and 64C (pp. 172-186) for more details.


Name Address Size
64 128 Apple
cia2tod10ths $dd08 byte

Time of day clock, current tenths of the second, encoded in BCD.

The high nybble is unused. The low nybble is the current decimal tenth of a second.

When read: Current clock time. When written: Set current clock time or alarm clock time depending on cia2crb.

Important: When the cia2todhr register is read, the chip will freeze the output of the cia2todmin, cia2todsec, and cia2tod10ths registers as well, so that they can be read without a potential rollover causing incorrect readings. The TOD clock runs normally; only the output is frozen. Reading the cia2tod10ths register unfreezes these registers.

Likewise, when setting the time of day, the clock will halt when cia2todhr is written, and the clock will not start again until cia2tod10ths is written.


Name Address Size
64 128 Apple
cia2todsec $dd09 byte

Time of day clock, current second of the minute, encoded in BCD.

The high nybble except bit 7 is the tens digit of the current second. The low nybble is the unit digit of the current second.

When read: Current clock time. When written: Set current clock time or alarm clock time depending on cia2crb.

Important: When setting the alarm clock time, if both cia2todsec and cia2tod10ths are set to $00 (precisely the top of any minute), then the chip may not generate an alarm NMI. Set cia2tod10ths to $01 (1/10 of a second later) to work around this flaw.


Name Address Size
64 128 Apple
cia2todmin $dd0a byte

Time of day clock, current minute of the hour, encoded in BCD.

The high nybble except bit 7 is the tens digit of the current minute. The low nybble is the unit digit of the current minute.

When read: Current clock time. When written: Set current clock time or alarm clock time depending on cia2crb.


Name Address Size
64 128 Apple
cia2todhr $dd0b byte

Time of day clock, current hour of the day in 12-hour format, encoded in BCD.

Bit 7 is the AM/PM flag: clear = AM, set = PM. Bit 4 is the tens digit of the current hour. The low nybble is the unit digit of the current hour.

When read: Current clock time. When written: Set current clock time or alarm clock time depending on cia2crb.

Important: When the cia2todhr register is read, the chip will freeze the output of the cia2todmin, cia2todsec, and cia2tod10ths registers as well, so that they can be read without a potential rollover causing incorrect readings. The TOD clock runs normally; only the output is frozen. Reading the cia2tod10ths register unfreezes these registers.

Likewise, when setting the time of day, the clock will halt when cia2todhr is written, and the clock will not start again until cia2tod10ths is written.


Name Address Size
64 128 Apple
cia2sdr $dd0c byte

Serial data register for the User Port. Input or output depending on cia2cra. Gated in or out MSB first through the User Port SP line and CNT line at a baud rate determined by cia2tahi/cia2talo.


Name Address Size
64 128 Apple
cia2icr $dd0d byte

Interrupt control and status register.

When read:

Bit Meaning
7 Set = An NMI has been generated
6-5
4 Signal level on FLAG pin (RS-232 data received)
3 Set = A complete byte has been received into or sent from cia2sdr
2 Set = Current time of day is the alarm time
1 Set = Timer B (cia2tblo) underflowed
0 Set = Timer A (cia2talo) underflowed

When written:

Bit Meaning
7 Fill bit. Bits below that are set, are actually set or cleared to this bit's value. Bits below that are clear, are actually left unchanged.
6-5
4 Set: #7 set/clear = Enable/disable NMIs generated by FLAG pin positive edge
3 Set: #7 set/clear = Enable/disable NMIs generated by sending or receiving a byte through cia2sdr
2 Set: #7 set/clear = Enable/disable time of day alarm clock NMI
1 Set: #7 set/clear = Enable/disable NMIs generated by Timer B underflow
0 Set: #7 set/clear = Enable/disable NMIs generated by Timer A underflow

Despite no CIA registers being listed in geosSym, the constant ALARMMASK (%00000100) is defined for masking the alarm bit. (GEOS polls cia1icr for the alarm clock.)


Name Address Size
64 128 Apple
cia2cra $dd0e byte

Control register for Timer A (cia2tahi/cia2talo):

Bit Clear Set
7 60 Hz TOD clock 50 Hz TOD clock
6 cia2sdr is input cia2sdr is output
5 Timer counts CPU cycles Timer counts CNT line positive edges
4 Load Timer start value
3 Timer restarts on underflow Stops on underflow
2 Toggle cia2prb bit 6 on underflow Pulse cia2prb bit 6 for 1 CPU cycle on underflow
1 Don't... Indicate underflow on cia2prb bit 6
0 Stop timer Start timer

In order to indicate a Timer A underflow on cia2prb bit 6, cia2ddrb bit 6 must be set.

GEOS sets the time of day clock frequency (bit 7) during startup based on the system's PAL/NTSC flag: $02a6 on the Commodore 64 or $0a03 on the Commodore 128. (0 = NTSC, 1 = PAL.)

Important: The accuracy of the CIA chip's time of day clock depends on the main power supply's AC frequency, not the video standard's frequency. Set or clear bit 7 based on that. An exception to this rule is the Commodore SX-64, both NTSC and PAL versions, which feeds the CIAs from a 60 Hz crystal. See other resources such as this Codebase 64 wiki article for how to detect the right frequency with some reliability.


Name Address Size
64 128 Apple
cia2crb $dd0f byte

Control register for Timer B (cia2tbhi/cia2tblo):

Bit Clear Set
7 Set current TOD clock time Set alarm clock time
6-5 %00 = Timer B counts CPU cycles
%01 = Timer B counts CNT line positive edges
%10 = Timer B counts Timer A underflows
%11 = Timer B counts Timer A underflows along with CNT line positive edges
4 Load Timer start value
3 Timer restarts on underflow Stops on underflow
2 Toggle cia1prb bit 7 on underflow Pulse cia2prb bit 7 for 1 CPU cycle on underflow
1 Don't... Indicate underflow on cia2prb bit 7
0 Stop timer Start timer

In order to indicate a Timer B underflow on cia2prb bit 7, cia2ddrb bit 7 must be set.


Remember that when the CPU writes to the address of an I/O register, it also writes to the same address of RAM regardless of the current memory map configuration. Sources show the GEOS Kernal writing to officially documented register addresses without regard for the RAM underneath; it should be assumed probably safe to write to documented register addresses in documented ways and unsafe to write to any undocumented location in any I/O device's range.

Go to Table of Contents.

Apple GEOS High Variables

Name Address Size
64 128 Apple
totNumBlks $f60b word
Total number of blocks in the current volume.
dirBlkno $f620 word
Block number of the key block of the directory containing this file's entry.
dirPtr $f622 word
Pointer into diskBlkBuf for this file's entry.
indexBlkno $f624 word
Block number of VLIR index table (ProDOS master index block).
Name Address Size
64 128 Apple
devTabHi $fae7 4 bytes
Each byte is the high byte of the 4 possible device drivers. The low bytes are in devTabLo.
devTabLo $faeb 4 bytes
Each byte is the low byte of the 4 possible device drivers. The high bytes are in devTabHi.
devUnitTab $faef 4 bytes
ProDOS unit numbers of the 4 possible devices. Used for communicating with device drivers.
drSizeLo $faf7 4 bytes
Each byte is the low byte of the size of the 4 possible devices. The high bytes are in drSizeHi.
• In early versions, this variable was named "driveSizeLo".
drSizeHi $fafb 4 bytes
Each byte is the high byte of the size of the 4 possible devices. The low bytes are in drSizeLo.
• In early versions, this variable was named "driveSizeHi".
Go to Table of Contents.

Commodore Kernal ROM Routines

The Kernal ROM routines of the Commodore 64 and 128 are accessible directly from within GEOS, but only while the ROM and other expected memory structures are banked in. They are listed as variables in the Official GEOS Programmer's Reference Guide (OGPRG).

See the Commodore 64 Programmer's Reference Guide, Chapter 5, section "The KERNAL," and the Commodore 128 Programmer's Reference Guide, Chapter 13, for details on how to use them.

This list is not complete or intended to be complete.

OGPRG Name Address C64/128 Label C64 PRG C128 PRG
Cint $ff81 CINT page 280 page 414
Initialize the screen editor and parts of the VIC and SID chips. Usage is different between the 64 and 128.
Ioinit $ff84 IOINIT page 285 page 415
Initialize all I/O devices.
Restor $ff8a RESTOR page 293 page 416
Restore default system and interrupt vectors. Usage is different between the 64 and 128. OGPRG has this name commented out.
Setmsg $ff90 SETMSG page 298 page 418
Control system message output.
Second $ff93 SECOND / SECND page 296 page 418
Send secondary address for Listen.
Tksa $ff96 TKSA page 302 page 419
Send secondary address for Talk.
Memtop $ff99 MEMTOP page 288 page 419
Set or read the top of memory.
Membot $ff9c MEMBOT page 287 page 420
Set or read the bottom of memory.
Scnkey $ff9f SCNKEY / KEY page 295 page 421
Scan the keyboard.
Acptr $ffa5 ACPTR page 274 page 422
Accept a character from the serial bus.
Ciout $ffa8 CIOUT page 279 page 423
Send a byte over the serial bus.
Untlk $ffab UNTLK page 304 page 424
Command all serial bus devices to stop talking.
Unlsn $ffae UNLSN page 303 page 424
Command all serial bus devices to stop listening for data.
Listen $ffb1 LISTEN / LISTN page 285 page 425
Command a serial bus device to receive data.
Setlfs $ffba SETLFS page 297 page 426
Set up a logical file.
Setnam $ffbd SETNAM page 298 page 427
Set up a filename.
Open $ffc0 OPEN page 289 page 427
Open a logical file. OGPRG warns, "DON'T EVER USE THIS INCREDIBLY STUPID ROUTINE!," because it writes to $fd30 and $0314 (irqvec).
Close $ffc3 CLOSE page 281 page 428
Close a logical file.
Chkin $ffc6 CHKIN page 275 page 429
Open a logical file channel for input.
Chkout $ffc9 CHKOUT / CKOUT page 276 page 430
Open a logical file channel for output.
Clrchn $ffcc CLRCHN / CLRCH page 282 page 431
Clear all I/O channels, restore default channels.
Chrin $ffcf CHRIN / BASIN page 277 page 432
Read input channel data.
Chrout $ffd2 CHROUT / BSOUT page 278 page 433
Write output channel data.
Load $ffd5 LOAD page 286 page 434
Load data from an input device (a file) into RAM.
Save $ffd8 SAVE page 293 page 435
Save memory to a device.
Getin $ffe4 GETIN page 283 page 438
Read buffered data, such as from the keyboard queue. OGPRG says this isn't used.
Clall $ffe7 CLALL page 281 page 439
Close all open files and channels.
Iobase $fff3 IOBASE page 284 page 442
Return base address of I/O space in memory. OGPRG says this isn't used. The C128PRG says this isn't used but is included for compatibility.
Go to Table of Contents.