Kernal Jump Table

AC6502 BIOS
Kernal · BIOS v2.0
The contract
Call the slot, never the implementation. 72 entry points, three bytes each, starting at $A000 and in an order that does not change. jsr $A000 prints a character on this ROM and on the next one. 6502-VDP.inc gives every slot its name, so you will write jsr Chrout.
Arguments go in registers. A, X and Y in, A, X, Y or the carry flag out. Nothing is passed on the stack.
The tail of the table. 13 slots from $A0D8 to $A0FE are reserved. Each is a real jump to a bare RTS, so calling one is harmless now and may do something later. Do not put your own code there.
Console
AddrNameIn / out
$A000ChroutOutput char (dispatched by IO_MODE)
in A = character to output
$A003ChrinInput char from buffer
$A090PrintStrPrint NUL-terminated string (A=lo, Y=hi); clobbers A,Y,STR_PTR
in A = string address low, Y = string address high · out A, Y clobbered; X preserved; clobbers STR_PTR (Chrout preserves it)
$A093PrintCRLFPrint CR+LF
$A096PrintDecU16Print unsigned 16-bit decimal (A=lo, X=hi), no leading zeros
in A = value low, X = value high
$A006WriteBufferWrite byte to input buffer
$A009ReadBufferRead byte from input buffer
$A00CBufferSizeGet buffer count
$A00FSetIOModeSet IO_MODE
in A = mode (bit 0: 0=video, 1=serial)
$A012GetIOModeGet IO_MODE
out A = current IO_MODE
The screen
AddrNameIn / out
$A015InitVideoText-mode console: registers, the card's font, palette row 0
$A018VideoClearClear video screen
$A01BVideoPutCharWrite char at cursor
in A = character to write
$A02AVideoChroutRawOutput char to video (raw, no control-code handling)
in A = character code (0-255)
$A01EVideoSetCursorSet cursor (X=col, Y=row)
in X = column (0-39), Y = row (0-23), on the screen as shown
$A021VideoGetCursorGet cursor position
out X = column (0-39), Y = row (0-23)
$A024VideoScrollScroll screen up one line
$A027VideoSetColorSet the pen and the border (A = fg<<4 | bg)
in A = fg<<4 | bg. VID_PEN = A, and register 7 = A, so the border follows
Sound
AddrNameIn / out
$A02DInitSIDInitialize SID
$A030BeepPlay beep tone
$A033SidPlayNotePlay note (A=voice, X=freqLo, Y=freqHi)
in A = voice (0-2), X = frequency low byte, Y = frequency high byte
$A036SidSilenceSilence all voices
$A039SidSetVolumeSet SID master volume (A=0-15)
in A = volume (0-15); upper nibble of SID_MODE_VOL is cleared (no filter)
Keyboard and sticks
AddrNameIn / out
$A045InitKBInitialize GPIO/VIA keyboard
$A048ReadJoystick1Read joystick 1
out A = joystick bitmask (active-low bits: R-L-D-U-Y-X-B-A)
$A04BReadJoystick2Read joystick 2
out A = joystick bitmask (active-low bits: R-L-D-U-Y-X-B-A)
$A099KBDisableRelease both encoders and settle; ports free for raw read
$A09CKBEnableRe-enable both encoders

Kernal Jump Table

AC6502 BIOS
Kernal · BIOS v2.0
Files
AddrNameIn / out
$A07EFsLoadFileAddrLoad named file to FS_IO_ADDR
in STR_PTR = filename, FS_IO_ADDR = destination address
$A081FsSaveFileAddrSave FS_FILE_SIZE bytes from FS_IO_ADDR to named file
in STR_PTR = filename, FS_IO_ADDR = source address, FS_FILE_SIZE = byte count
$A03CFsLoadFileLoad file from CF
in STR_PTR ($02-$03) points to null-terminated filename · out Carry clear = success, FS_FILE_SIZE = bytes loaded; Carry set = file not found or read error
$A03FFsSaveFileSave file to CF
in STR_PTR ($02-$03) points to null-terminated filename; FS_FILE_SIZE ($034A-$034B) = number of bytes to save · out Carry clear = success, Carry set = error (directory full or write error)
$A042FsDeleteFileDelete file from CF
in STR_PTR ($02-$03) points to null-terminated filename · out Carry clear = success, Carry set = file not found or error
$A084FsFormatDiskZero the current disk's directory sector
out Carry clear = success, Carry set = write error
$A087FsSetDiskSelect current CF disk (A=0-255)
in A = disk number (0-255)
$A08AFsGetDiskGet current CF disk (A=disk)
out A = current disk number
$A08DFsPrintDiskPrint "DISK n" + CRLF via Chrout
The card itself
AddrNameIn / out
$A06CStReadSectorRead CF sector
in CF_LBA ($26-$29) = LBA address, CF_BUF_PTR ($24-$25) = destination pointer · out Carry clear = success, Carry set = error; CF_BUF_PTR advanced by 512 bytes on success
$A06FStWriteSectorWrite CF sector
in CF_LBA ($26-$29) = LBA address, CF_BUF_PTR ($24-$25) = source pointer · out Carry clear = success, Carry set = error; CF_BUF_PTR advanced by 512 bytes on success
$A072StWaitReadyWait CF ready
out Carry clear = ready, Carry set = error or timeout
Serial
AddrNameIn / out
$A04EInitSCInitialize serial 6551
$A051SerialChroutDirect serial output (bypass IO_MODE)
$A054XModemLoadReceive binary via XModem
in XFER_PTR = destination address (set by caller) · out Carry clear = success, XFER_PTR past last byte written; XFER_REMAIN = total bytes received; Carry set = transfer failed
$A057XModemSaveSend binary via XModem
in XFER_PTR = source address, XFER_REMAIN = byte count (set by caller) · out Carry clear = success, Carry set = transfer failed
Clock and lasting memory
AddrNameIn / out
$A05ARtcReadTimeRead RTC time
out A = hours (binary), X = minutes (binary), Y = seconds (binary)
$A05DRtcReadDateRead RTC date
out A = day of month (binary), X = month (binary), Y = year (binary); RTC_BUF_CENT = century (binary)
$A060RtcWriteTimeSet RTC time
in A = hours (binary), X = minutes (binary), Y = seconds (binary)
$A063RtcWriteDateSet RTC date
in A = day of month (binary), X = month (binary), Y = year (binary); RTC_BUF_CENT = century (binary)
$A066RtcReadNVRAMRead NVRAM byte
in X = NVRAM address ($00-$FF) · out A = data byte
$A069RtcWriteNVRAMWrite NVRAM byte
in X = NVRAM address ($00-$FF), A = data byte
$A09FNvStatSlot status (X=slot) → A=status, Y=owner ID
in X = slot (0-15) · out A = NV_EMPTY / NV_VALID / NV_BAD, Y = owner ID, C clear; C set on no RTC or bad slot (A, Y undefined)
$A0A2NvReadCopy a valid slot's payload (X=slot, A/Y=dest lo/hi)
in X = slot (0-15), A/Y = destination lo/hi · out A = status, Y = owner ID; C clear and the buffer written only if A = NV_VALID; C set on no RTC or bad slot (A, Y undefined), or a slot that is not valid (A = its status, Y = its owner ID) — the buffer is untouched
$A0A5NvWriteWrite a slot (X=slot, A/Y=src lo/hi, NV_ID=owner ID)
in X = slot (0-15), A/Y = source lo/hi, NV_ID = owner ID ($01-$FF) · out C clear; C set on no RTC, bad slot, or NV_ID = 0 (nothing written)
$A0A8NvEraseZero all 16 bytes of a slot (X=slot)
in X = slot (0-15) · out C clear; C set on no RTC or bad slot
$A0ABNvFindLowest slot owned by A ($00 = first free) → X
in A = owner ID · out X = slot, C clear; C set if no slot matched (X undefined)
$A0AENvFormatErase all 16 slots
out C clear; C set on no RTC
The machine
AddrNameIn / out
$A075SysDelayDelay A=cnt_lo, X=cnt_hi centiseconds
in A = count low byte, X = count high byte
$A078KernalInitInitialize all hardware (caller must reset SP; no cli); rts when done
$A07BKernalVersionGet BIOS version (A=major, X=minor)
out A = major version, X = minor version

Kernal Jump Table

AC6502 BIOS
Kernal · BIOS v2.0
The PICOVDP
AddrNameIn / out
$A0B1VdpInfoCard found at boot → A=VDP_FW, X=VDP_CAPS, Y=$AC; carry set if none
out A = VDP_FW (STAT5), X = VDP_CAPS (STAT6), Y = VDP_ID ($AC); with no card A = X = Y = 0 and carry set
$A0B4VdpWriteRegWrite register (A=value, X=0-127), keeping VID_MODE and the LxCTRL shadows
in A = value, X = register (0-127) · out carry set, and nothing written, if no card or X > 127
$A0B7VdpSetModeWrite VMODE (A=1-4); carry set if out of range
in A = mode (1-4) · out carry set, and nothing written, if no card or A is out of range
$A0BAVdpPokeWrite VRAM byte A at X/Y = address lo/hi (all 64 KB)
in A = value, X = address low, Y = address high ($0000-$FFFF) · out carry set, and nothing written, if no card
$A0BDVdpPeekRead VRAM byte at X/Y = address lo/hi → A
in X = address low, Y = address high ($0000-$FFFF) · out A = the byte; carry set, and nothing read, if no card
$A0C0VdpSetPalettePalette entry X = 0-255 ← A = $0R, Y = $GB (at $FC00 + 2X)
in X = entry (0-255), A = $0R, Y = $GB · out carry set, and nothing written, if no card
$A0C3WaitVBlankReturn at the start of the next vertical blank (STAT0 untouched)
$A0C6VdpLoadFileLoad named file (STR_PTR) into VRAM at FS_IO_ADDR, exactly FS_FILE_SIZE bytes
in STR_PTR = filename, FS_IO_ADDR = VRAM address · out Carry clear = loaded, FS_FILE_SIZE = bytes written; Carry set = no video card (nothing read), or not found or read error
$A0C9VdpLoadFontCopy built-in font A into L0PAT and wait for it
in A = font ID · out carry set, and nothing written, if no card or A is not $00
$A0CCVdpSpriteSprite X = 0-63 ← VDP_P0-P3 = Y, X lo, pattern, attributes (table at $2000)
in X = sprite (0-63), VDP_P0 = Y, VDP_P1 = X bits 7:0, VDP_P2 = pattern,; VDP_P3 = attributes (b7 = X bit 8, b6 priority, b5:4 flips, b3:0 sub-palette; SPEC §10) · out carry set, and nothing written, if no card or X > 63
$A0CFVdpSetScrollLayer X = 0-1 scroll: A = x lo, Y = y, VDP_P0 = x bit 8
in X = layer (0-1), A = x bits 7:0, Y = y, VDP_P0 = x bit 8 (0 or not) · out carry set, and nothing written, if no card or X > 1
$A0D2VdpLayerLayer X = 0-1 off (A = 0) or on
in X = layer (0-1), A = 0 to hide, anything else to show · out carry set, and nothing written, if no card or X > 1
$A0D5VdpStatusRead status register X = 0-15 on port A → A
in X = status register (0-15) · out A = its value; carry set, and nothing read, if no card or X > 15