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:
- Its address in Commodore 64 GEOS,
- Its address in GEOS 128 if it doesn't exist in 64 GEOS, or
- 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
- 6510 CPU Registers
- GEOS Zero Page Variables
- Kernal ROM Zero Page Variables
- Apple GEOS Low Variables
- Kernal ROM Variables
- Application RAM
- GEOS Back-RAM/Auxiliary RAM Variables
- GEOS Variables
- Hardware Sprite Picture Data
- High Base Addresses
- Page $C0 GEOS Equates
- Other Commodore 64 Variables
- Commodore VIC-II Registers
- Commodore SID Registers
- Commodore 64 CIA Registers
- Apple GEOS High Variables
- Commodore Kernal ROM Routines
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.
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.
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.
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.
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.
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.
- When the value is GR_40 ($00), the mode is or will be 40-column.
- When the value is GR_80 ($80), the mode is or will be 80-column.
- (Neither graphMode nor GR_40 nor GR_80 are defined in geoProgrammer.)
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.
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.
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.
- $00 (or bit 7 clear): Okay to erase sprites.
- $80 (or bit 7 set): Do not erase sprites.
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:
- $00: Apple IIe.
- $80: Apple IIc or another 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.
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.
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".
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.
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.
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:
- On Commodores:
- If bit 7 is set, then the drive is a RAM disk, not a real drive.
- If bit 6 is set, then the drive is shadowed in the REU. Both bits 7 and 6 can't be set at the same time.
- Bits 5-0 determine the drive type:
Value Drive Type Contsant 0 No disk drive at this address DRV_NULL 1 Commodore 1541 DRV_1541 2 Commodore 1571 DRV_1571 3 Commodore 1581 DRV_1581 15 GEOS geoNet virtual drive DRV_NETWORK - Boyce and Zimmerman say that the boot disk drive is indicated by the value $01, but this is a coincidence. A genuine copy-protected GEOS boot disk presents itself as a 1541 disk, used in a real and typically non-shadowed 1541 drive. The boot disk drive can't be reliably detected this way if GEOS is booted from a shadowed 1541 or from any other media, such as a 1581 disk made with geoMakeBoot.
- On Apples:
- The only difference between drive types visible to GEOS is whether
their media is removable (floppy drives) or fixed (hard drives). The
bits of each byte have the following meanings:
Bit Meaning when set Meaning when clear 7 Removable disk Fixed disk 6 Device is interruptable 5-4 Number of drives on device (0-3) 3 Driver supports format 2 Driver supports write 1 Driver supports read 0 Driver supports status call - This bit usage conforms to the information ProDOS keeps about disk drives. However, GEOS makes use of only bits 7 and 3.
- The only difference between drive types visible to GEOS is whether
their media is removable (floppy drives) or fixed (hard drives). The
bits of each byte have the following meanings:
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
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.
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:
- The current mouseXPos is left of mouseLeft or right of mouseRight, or
- The current mouseYPos is above mouseTop or below mouseBottom, or
- A menu is open, and the current pointer position is not within the menu.
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.
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.
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 - 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.
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.
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.
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:
Value | Meaning | |
---|---|---|
$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.
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.
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.
- When read: Bits 0-7 of the current raster scanline.
- When written: Bits 0-7 of the raster scanline on which the VIC will generate an IRQ, if enabled. See grirqen.
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:
- Set grcntrl1 bit 4 to blank the screen, then set clkreg bit 0 to start 2 MHz mode, and
- 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.
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.
- v1attdec bits 7-4 select the attack cycle duration (0-15).
- v1attdec bits 3-0 select the decay cycle duration (0-15).
- v1susrel bits 7-4 select the sustain cycle duration (0-15).
- v1susrel bits 3-0 select the release cycle duration (0-15).
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.
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.
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". |
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. |