The RIFT64 Wire Protocol
The RIFT64 protocol is an optimized, unframed, byte-stream protocol designed specifically for low-bandwidth, high-speed serial links (such as SwiftLink cartridges operating at 38.4kbps). By utilizing a compact character-prefix format followed by hexadecimal arguments, RIFT64 achieves extreme parsing efficiency directly on the C64's 8-bit 6502 microprocessor.
Status: V1 Feature Complete (Active Beta). Future development goals include: Mouse input routing, direct SID register streams, dynamic connection/crash recovery, and client-side custom ML execution.
! Write Text
Streams ASCII text directly at the current cursor offset using the active default foreground color. The stream terminates as soon as a Carriage Return (`$0D`) or Line Feed (`$0A`) is parsed. Letters are dynamically converted from ASCII to native C64 screen codes on-the-fly.
// Example: Write "RIFT64 ACTIVE" and wrap cursor
!RIFT64 ACTIVE<CR>
@ Batch Sprite Position
A high-speed shortcut command that updates the position of one or more sprites without altering pointers, colors, or other configurations. `MM` is an 8-bit mask whose set bits select which of the 8 sprites are being updated; the client then reads one 6-hex-digit `XHXLYY` block per set bit, in ascending sprite-ID order. `XH` carries the X-MSB bit (used when X > 255), `XL` is the low byte of X, and `YY` is the Y coordinate.
// Example: Move Sprite 0 to (X=300, Y=150) and Sprite 2 to (X=80, Y=200)
// Mask = %00000101 = $05; entries follow in ID order (0, then 2)
@05 012C96 0050C8
~ Framed Command
Invokes a framed, checksum-verified packet. `C` is a one-byte framed command ID (e.g. `L` for length text, `C` for clear). `LL` is the payload length. `SS` is an additive checksum calculated over the entire packet: `SS = (C + LL + sum(data)) & $FF`.
// Example: Send a framed text packet with checksum verification
~L13FRAMED TEXT PAYLOAD5F
? Capabilities Query
Instructs the Commodore 64 client to write its features/capabilities string back upstream. Useful on connection handshakes to detect compatibility and the set of supported command opcodes. The C64 client immediately streams back a CR-terminated response listing the supported command letters, terminated by an `ACK` token: RIFT64 CKPLQXZ~FIDY@UGHNA ACK<CR>.
// Example: Send query to the C64
?
A Audio Module Control
Drives the resident SID music-module player. The first byte `S` is an ASCII subcommand digit selecting the operation; remaining hex bytes are subcommand-specific arguments. Most subcommands return `A` (ACK) on success or `N` (NAK) on failure; A7 returns a single state byte instead.
A0— Stop playback.A1 TT— Start playback of subtuneTT(1..127).A2— Pause playback.A3— Resume playback.A4 TT— Set playback tempoTT.A5 LLHH— Bind the music module installed at address$HHLL.A6 0V— Set master volumeV(low nibble, 0..F).A7— Query state; the client streams back a single status byte (no ACK).
// Example: Bind a music module previously uploaded to $C000, then start subtune 1
A500C0
A101
B Draw Border
Automatically draws a rectangular border outline on the C64 screen starting from the current cursor coordinates. `WW` is the width, and `HH` is the height. The 9-byte configuration payload contains the raw C64 character codes representing corners and vertical/horizontal bars.
// Example: Draw a 10x10 border outline using custom corners and line characters
B0A0A[9 bytes of layout config]
C Clear Screen
Clears the 40x25 character matrix back to spaces (`$20`), resets the cursor position to column 0, row 0, and hides the hardware cursor. To avoid a jarring visual flash, the border and background colors are preserved during this clear step.
// Example: Clears screen instantly
C
D Draw Metatile
Renders a rectangular window of a tile-id map into screen RAM in a single round-trip. Supports three tile modes (1 = raw 1×1 char, 2 = 2×2 metatiles, 3 = 3×3 metatiles), arbitrary target stride, sub-tile scroll offsets (offX/offY) for smooth scrolling, an edge fill character, and a configurable colour-RAM pass (cMode: 00=NONE, 01=FILL, 02=MAP, 03=PERCELL). PERCELL is mode-2 only and uses a 1 KB page-aligned bank of 4 parallel slot pages, indexed by tile id, giving a distinct colour to each child cell of every metatile (mode 3 transparently falls back to MAP). The renderer ACKs with A after the entire window is drawn. See the metatile guide for the full payload layout and SDK helper.
// Payload (each field is one hex pair):
// mode mapLo mapHi mapW mapH metaHi tgtLo tgtHi stride winW winH x y offX offY fill cMode cTgtLo cTgtHi cSrcLo cSrcHi cFill
D[20 hex bytes]
E Erase Run
Writes exactly `LL` spaces (`$20`) starting from the current cursor offset. When complete, the cursor position automatically restores to its starting offset. Ideal for erasing lines, status displays, or rendering clear space runs.
// Example: Erase 40 ($28) cells (a full row) from current cursor
E28
F Charset Bank Swap
Alters the active VIC-II bank and character memory offset mapping. Allows developers to toggle live between uppercase, lowercase, and custom uploaded fonts/tile matrices. The client responds with `A` (ACK) after register swapping.
// Example: Switch charset bank register offsets
F[Hex Nibble + Hex Byte]
G Scroll Region
Executes hardware subregion shifting of width `WW` and height `HH` from coordinate `XXYY`. Direction `D` controls the shift: `0` Up, `1` Down, `2` Left, `3` Right. Shshifted lines automatically preserve color RAM values. Newly exposed row/column slots are cleared to spaces using the default background/foreground colors.
// Example: Scroll a 40x10 region from column 0, row 5 upwards
G0005280A0
H Cursor Visibility
Controls whether the C64 client actively renders and flashes the text cursor. Hiding the cursor (`H0`) is highly recommended during game loops or graphic rendering to prevent visual glitches. Show the cursor (`H1`) when waiting for text inputs.
// Example: Hide the cursor
H0
I Display Mode
Switches the active VIC-II graphics mode. Allows the host to switch the screen from standard text mode into multicolor bitmap, standard bitmap, or extended color modes. Returns `A` (ACK) on successful transition.
// Example: Set screen to Multicolor Bitmap Mode
I[Mode parameters]
J Telemetry Control
Controls the upstream telemetry generator. The first byte `S` is an ASCII subcommand digit. J1 additionally takes a 1-byte hex divider DD (frames between sends) and a 1-byte hex channel mask MM selecting which hardware sources to sample.
J0— Disable telemetry.J1 DD MM— Enable periodic streaming.DD= frame divider;MM= channel mask (bit 0 Joy port 2, bit 1 Joy port 1, bit 2 Sprite-Sprite collision$D01E, bit 3 Sprite-Background collision$D01F).J2— Send a single one-shot telemetry packet immediately.
// Example: Enable telemetry every 3 frames, sampling both joysticks + sprite collisions
J1030F
K Set Colors
Sets the background and border color registers to the hex color value `B`, and sets the default text foreground write color to `F`. Both `B` and `F` must be lowercase or uppercase hex digits (0-F).
// Example: Set background/border to Black ($00), and foreground to White ($01)
K01
L Length-Prefixed Text
Writes exactly `LL` bytes of text. Safe for streaming raw strings containing control characters, escape sequences, or binary formatting bytes that would prematurely terminate a standard `!` command. The client returns `A` (ACK) once the exact byte length is consumed.
LL = 01toFF→ Represents 1 to 255 bytes of text payload.LL = 00→ Special case representing exactly 256 bytes of payload.
// Example: Write exactly 12 ($0C) bytes of raw text
L0CHELLO WORLD
M Store Memory
Writes binary bytes directly to C64 RAM starting at destination address `AAAA` for length `LL` (where `00` represents 256 bytes). This is highly powerful, allowing you to stream custom sprite bitmaps, font banks, or raw 6502 Machine Language code directly to the C64.
- Length Range:
LL = 01toFFwrites 1 to 255 bytes of binary data. - Special Case (256 Bytes): Setting
LL = 00is a special case representing exactly 256 bytes of payload. - System Safety: Writing to zero page (
$0000-$00FF), stack pointer ($0100-$01FF), or RIFT64's dynamic ACIA serial receive buffer (allocated at the end of the client code, usually around$2B00-$2BFF) will cause immediate connection drops or system crashes.
// Example: Upload 64 ($40) bytes of sprite data to $3E00
M3E0040[64 bytes of raw sprite binary]
N Raster Split
Configures a horizontal raster split line. Highly advanced, this enables split-screen graphics—for example, rendering a full-color bitmap image at the top of the screen while preserving a standard character text terminal at the bottom! Returns `A` (ACK) on completion.
// Example: Configure a raster split at horizontal line 150
N[Split parameters]
O Custom Restore
Signals a custom, client-side visual restoration routine. Used to return from heavy custom graphics or raster split interfaces back to standard boot screen matrices.
// Example: Invoke client custom restore
O
P Set Cursor Position
Positions the hardware cursor on the screen. `XX` represents the column offset (clamped to 0-39) and `YY` represents the row offset (clamped to 0-24). Decoding is performed on the C64 dynamically to calculate the absolute RAM writing index.
// Example: Move the cursor to Column 10 ($0A), Row 5 ($05)
P0A05
Q Color RAM Block
Directly updates the color RAM matrix for a rectangular region of width `WW` and height `HH` from coordinate `XXYY` without changing any text character codes on the screen. Each color is a single low-nibble byte. Returns `A` (ACK) on completion.
- Payload Size: Exactly
WW × HHbytes must follow. - Color RAM In C64: Modifies standard color attributes at
$D800 + YY * 40 + XX.
// Example: Paint a 10x2 block at (2, 5) with custom colors
Q02050A02[20 color bytes]
R Restore Screen Buffer
Restores the complete 1000-character screen and color RAM grids back from one of the off-screen backup slots (0 or 1) on the C64. This is extremely fast (virtually instantaneous), allowing you to draw temporary popups, overlay menus, or dialogs, and then dismiss them instantly without stream overhead!
// Example: Restore the screen from Slot 0
R0
S Save Screen Buffer
Saves the entire current screen RAM (`$0400-$07E7`) and color RAM (`$D800-$DBE7`) matrices into a local backup buffer slot (0 or 1) residing in upper C64 RAM. Essential for preserving the screen state before loading overlays or menus.
// Example: Save screen to Slot 0
S0
T Write Colored Text
Sets the active default foreground text color to `F` (low nibble), then writes the text exactly like the `!` write text command. Terminated by a Carriage Return or Line Feed.
// Example: Write "ONLINE" in Cyan ($03) text
T3ONLINE<CR>
U Sprite Multicolor
Configures the VIC-II's sprite multicolor state. Allows you to toggle individual sprites between standard (high resolution, 1 color) and multicolor (lower resolution, 4 colors) modes, and configure the two shared multicolor registers (`$D025` and `$D026`).
// Example: Configure sprite multicolor registers
U[Multicolor registers]
V Write Colored Window
Sets the active default foreground text color to `F` (low nibble), then writes a window block exactly like the standard `W` draw window command.
// Example: Draw a 10x2 window in Orange ($08) foreground
V80A02[20 bytes of raw data]
W Draw Window
Writes a rectangular grid of raw characters of width `WW` and height `HH`. The current cursor position forms the top-left boundary of the window. After each row of size `WW` is written, the cursor position dynamically resets to the starting column and advances down by one row, allowing rapid batch painting.
- Payload Length: Exactly
WW × HHbytes of screen data must be sent. - Screen Bounds Clamping: Width
WWis clamped to 1-40. HeightHHis clamped to 1-25.
// Example: Render a 4x2 ($0402) block of filled blocks (8 bytes)
W0402[8 bytes of raw data]
X Checked Window
Buffered window block render verified by an 8-bit additive checksum `SS`. The C64 client reads the incoming character stream first into an internal, 256-byte staging buffer named `MemoryStoreBuffer` (located in the client's memory copying module, memory_store.asm). It then validates the checksum. If the checksum matches, the block is dynamically copied row-by-row to the screen matrix; if it fails, the C64 drops the data and returns `N` (NAK).
- Payload Length: Exactly
WW × HHbytes of screen data must follow. - Hardware Clamping: Width
WWis clamped to 1-40. HeightHHis clamped to 1-25. - Critical Buffer Limit: Because the
Xcommand stages data inside the 256-byteMemoryStoreBuffer, the productWW × HHmust not exceed 256 bytes, or memory overflow/corruption will occur on your Commodore!
// Example: Write a verified 4x2 window with checksum (8 bytes + 1 checksum byte)
X0402[8 bytes of raw data]5A
Y Set Sprite
Configures one of the 8 built-in C64 hardware sprites. `II` selects the sprite ID (0-7). `XH` handles the Sprite X-MSB bit (controls if X is > 255). `XL` is the X position (0-255). `YY` is the Y position. `CC` controls the sprite color. `PP` is the sprite memory block pointer (relative to VIC Bank). `BB` controls the active 16KB VIC bank. `EE` toggles the sprite's enable status (`00` is off, `01` is on).
// Example: Enable Sprite 0 at X=150, Y=120, Color Green ($05), Pointer $3E
Y00009678053E0301
Z Checked Memory Store
Identical to the `M` memory copy command, but validated via an 8-bit additive checksum `SS`. If the checksum fails, the write is aborted, and `N` is returned, preventing code or memory corruption in noisy serial environments.
- Length Range:
LL = 01toFFwrites 1 to 255 bytes.LL = 00writes exactly 256 bytes. - Checksum Math: The 1-byte hex checksum
SSmust equal the 8-bit sum of all raw data bytes:SS = sum(data) & $FF. - Memory Protection: Aborts writes if a transmission error occurs, shielding sensitive assembly pointers from corruption.
// Example: Upload checked binary blocks to RAM (64 bytes + 1 checksum byte)
Z3E0040[64 bytes of raw sprite binary]AF
Upstream Telemetry Packets (J Command)
The RIFT64 terminal client on the Commodore 64 doesn't just receive rendering data; it also acts as an active telemetry source, pushing real-time hardware status (joystick ports and VIC-II collision latches) back upstream to your backend server.
Whenever telemetry is enabled (J1) or one-shot (J2), the C64 client emits a fixed-length 8-byte packet over the same SwiftLink stream. Channels masked off by the MM argument are reported as zero. Keyboard input continues to use the existing inline upstream byte path and is not framed by this packet.
| Offset | Byte | Field | Description |
|---|---|---|---|
| 0 | $7E | SYNC | Fixed sync marker. |
| 1 | $55 | TYPE | Packet type id ('U' = upstream telemetry v1). |
| 2 | seq | Sequence | Rolling 0..255 counter for loss detection. |
| 3 | joy1 | Joystick (Port 2) | CIA1 $DC00, low 5 bits inverted to active-high (0 if channel disabled). |
| 4 | joy2 | Joystick (Port 1) | CIA1 $DC01, low 5 bits inverted to active-high (0 if channel disabled). |
| 5 | spr_spr | Sprite-Sprite Collisions | Latched VIC-II $D01E (0 if channel disabled). |
| 6 | spr_bg | Sprite-Background Collisions | Latched VIC-II $D01F (0 if channel disabled). |
| 7 | cksum | Checksum | (seq + joy1 + joy2 + spr_spr + spr_bg) & $FF. |