RIFT64 // REMOTE_GATEWAY

VIC-II MEMORY

Video Bank Layouts, Pointer Offset Calculations, and Color Palettes

🖥️ V1 Protocol Beta
🏎️ SwiftLink 38400+ Baud
💾 Legacy C64/C128 & Replicas

VIC-II Bank Reference & Memory Map

Even though RIFT64 frees you from writing raw assembly, your backend program still needs to understand the structure and constraints of the C64's VIC-II (Video Interface Chip). Use this memory map reference to design graphics offsets, custom character sets, bitmaps, and sprites inside the four 16KB hardware chunks.

1. Visual 64KB System Memory Map

This visual representation illustrates the entire 64KB RAM layout of the Commodore 64, ordered from high-memory (top) to low-memory (bottom), color-coded by architecture layers:

8KB($E000-$FFFF) KERNAL ROM (Operating System Routines) Bank 3
4KB($D000-$DFFF) I/O Registers / Color RAM ($D800) Bank 3
4KB($C000-$CFFF) Free Upload RAM (Sprites & Tiles) Bank 3
8KB($A000-$BFFF) BASIC ROM (Unused / Save Buffers RAM) Bank 2
8KB($8000-$9FFF) Custom RAM / Char ROM Mirror ($9000) Bank 2
16KB($4000-$7FFF) High-Performance Free RAM (Bitmaps & Fonts) Bank 1
14KB($0800-$3FFF) Default BASIC Program RAM / Custom Fonts Bank 0
1KB($0400-$07FF) Screen Character RAM ($0400) / Sprite Pointers Bank 0
768B($0100-$03FF) System Stack / Cassette Buffer ($033C) Bank 0
256B($0000-$00FF) Zero Page registers (CPU only) Bank 0
Zero Page / Vectors
Active Screen RAM
Free RAM (Upload Zone)
System ROM / Buffers
I/O Registers / Color RAM

2. Active 16KB VIC-II Banks

The VIC-II chip can only access 16KB of RAM at once. The active bank is chosen using CIA 2 Register `$DD00` (bits 0 and 1):

Bank ID Memory Range `$DD00` Bit Layout Hex Value Default Usage & Layout Constraints
Bank 0 `$0000 - $3FFF` `%xxxxxx11` `$03` System default on boot. Contains default character ROM mapping.
Bank 1 `$4000 - $7FFF` `%xxxxxx10` `$02` Completely free RAM block. Excellent for custom graphics & bitmapped screens.
Bank 2 `$8000 - $BFFF` `%xxxxxx01` `$01` Contains character generator ROM mirror ($9000-$9FFF).
Bank 3 `$C000 - $FFFF` `%xxxxxx00` `$00` Free RAM block. Common destination for assembly programs and graphics.

3. Internal Offset Pointers (`$D018`)

VIC-II Register `$D018` defines where Screen Character RAM and Character Graphics RAM reside *within* the currently active 16KB bank:

$D018 = (Screen_RAM_Offset × 16) + (Char_RAM_Offset × 2)
  • High 4 Bits (7-4): Selects Screen Character RAM location (in steps of 1KB relative to the bank's base address).
  • Low 4 Bits (3-1): Selects custom Character Graphics/Font RAM location (in steps of 2KB relative to the bank's base address).

4. Visual 16KB Bank Memory Allocations

Below is a comprehensive textual breakdown of how the memory layout is segmented inside the four physical 16KB VIC-II banks:

Bank 0 ($0000 - $3FFF) - System Default Bank

$0000-$00FF
Zero Page: CPU hardware registers. Constraint: Keep clear of sprite/graphics assets; the VIC-II cannot read zero page memory safely due to system overlap.
$0100-$01FF
System Stack: Reserved for CPU stack calls.
$0200-$03FF
System Variables & Cassette Buffer: `$033C-$03FC` is the safe 102-byte cassette buffer, highly useful for staging small Machine Language copy or execution routines!
$0400-$07E7
Default Screen RAM: Standard 1000-character grid layout (40 columns by 25 rows).
$07F8-$07FF
Sprite Pointer Table: These 8 bytes point directly to your 64-byte sprite pixel data blocks relative to Bank 0 (e.g. `$07F8` is the pointer for Sprite 0).
$1000-$1FFF
Default Character ROM Mirror: Holds the mirror of C64 uppercase/lowercase character set glyphs. Seen by the VIC-II for character rendering on boot.
$2000-$3FFF
Free RAM Area: Standard free RAM space, excellent for storing custom graphics, bitmaps, sprite blocks, or game assembly routines.

Bank 1 ($4000 - $7FFF) - High-Performance Free RAM

$4000-$7FFF
Completely Free RAM: This entire 16KB bank is free from system or KERNAL ROM overlaps. It is the absolute ideal space for setting up double-buffered high-res bitmap pixel screens (requires 8KB) and mapping custom tiled character graphics at any 2KB boundary.

Bank 2 ($8000 - $BFFF) - System ROM Bank

$8000-$9FFF
Free RAM & Cartridge Space: Available RAM, often occupied by standard C64 memory-expanders or expansion cartridge ROMs.
$9000-$9FFF
Character ROM Mirror: Mirror of character sets seen by the VIC-II.
$A000-$BFFF
BASIC ROM (Banked Out): Banked out of system memory in the RIFT64 client. This frees up these 8KB of RAM, utilizing them as safe off-screen Save/Restore Screen Buffers!

Bank 3 ($C000 - $FFFF) - Code & Sprite Space

$C000-$CFFF
Free RAM Block: Excellent location to upload and stage custom sprite data banks or background tiles.
$D000-$DFFF
I/O Registers & Color RAM:
  • From the CPU's perspective, this space contains active hardware I/O registers (VIC-II, SID, CIAs) and Color RAM ($D800-$DBE7).
  • From the VIC-II's perspective, it sees raw RAM instead of registers, but reads Color RAM in a parallel dedicated data path to assign individual character colors!
$E000-$FFFF
KERNAL ROM: Active C64 operating system routines. Can be banked out for raw RAM if KERNAL system calls are not required by your programs.

5. VIC-II Hardware Graphics Modes

6. Sprite Memory Structure (64-Byte Grid)

Each C64 hardware sprite is represented in memory as exactly 64 bytes. The pixel layout is 24 pixels wide by 21 pixels high, which translates to 3 bytes per horizontal line over 21 lines:

21 Rows × 3 Bytes = 63 Bytes + 1 Trailing Padding Byte = 64 Bytes Total
Line 0:  [Byte 0: %00111100] [Byte 1: %01111110] [Byte 2: %00111100]  (24 Pixels)
Line 1:  [Byte 3: %01111110] [Byte 4: %11111111] [Byte 5: %01111110]  (24 Pixels)
Line 2:  [Byte 6: %11111111] [Byte 7: %11111111] [Byte 8: %11111111]  (24 Pixels)
...
Line 20: [Byte 60]           [Byte 61]           [Byte 62]            (24 Pixels)
Padding: [Byte 63: Unused / Stardust Padding Byte]
                

When in Standard High-Resolution mode (1 color), each active bit (1) represents a pixel drawn in the sprite's individual color register. In Multicolor mode (lower resolution), bits are parsed in pairs (00=Bg, 01=Sprite Multicolor 1, 10=Sprite Color, 11=Sprite Multicolor 2), doubling the pixel width.

7. Custom Character Set (8-Byte Font Grid)

The C64's custom character set glyphs are stored in memory as a series of 8-byte blocks. Each character in an 8x8 font grid is represented by exactly 8 consecutive bytes, where each byte dictates one horizontal pixel row:

8 Horizontal Rows × 1 Byte = 8 Bytes per Character
Row 0:  . . X X X . . .   Binary: %00111000 → Hex: $38  (Row Value)
Row 1:  . X . . . X . .   Binary: %01000100 → Hex: $44  (Row Value)
Row 2:  X . . . . . X .   Binary: %10000010 → Hex: $82  (Row Value)
Row 3:  X X X X X X X .   Binary: %11111110 → Hex: $FE  (Row Value)
Row 4:  X . . . . . X .   Binary: %10000010 → Hex: $82  (Row Value)
Row 5:  X . . . . . X .   Binary: %10000010 → Hex: $82  (Row Value)
Row 6:  X . . . . . X .   Binary: %10000010 → Hex: $82  (Row Value)
Row 7:  . . . . . . . .   Binary: %00000000 → Hex: $00  (Row Value)
                

To draw the letter "A" shown above, you stream the 8 hex bytes ($38, $44, $82, $FE, $82, $82, $82, $00) directly into your C64's Character Generator offset (at any 2KB boundary relative to your selected VIC bank) using client.StoreMemoryAsync()!

8. Official Commodore 64 Color Palette

Use these official C64 palette color codes (0-15 / $00-$0F) when sending color commands (like `K` and `Q` or sprite register values `CC`).

Black
ID: 0 ($00)
#000000
White
ID: 1 ($01)
#FFFFFF
Red
ID: 2 ($02)
#883932
Cyan
ID: 3 ($03)
#67B6BD
Purple
ID: 4 ($04)
#8B3F96
Green
ID: 5 ($05)
#55A049
Blue
ID: 6 ($06)
#40318D
Yellow
ID: 7 ($07)
#BFCE72
Orange
ID: 8 ($08)
#8B5429
Brown
ID: 9 ($09)
#574200
Pink
ID: 10 ($0A)
#B86962
Dark Grey
ID: 11 ($0B)
#505050
Grey
ID: 12 ($0C)
#787878
Lt Green
ID: 13 ($0D)
#94E089
Lt Blue
ID: 14 ($0E)
#7869C4
Lt Grey
ID: 15 ($0F)
#9F9F9F