C64 Memory Map: A Programmer’s Reference
The 64K Address Space
The C64 has 64K of RAM, but the 6510 processor sees a layered memory map where RAM, ROM, and I/O registers overlap. The processor port at $0001 controls which layers are visible at any address. Understanding this banking system is essential for advanced C64 development.
Default Memory Layout
$0000-$00FF Zero Page (fast access, 256 bytes)
$0100-$01FF Processor Stack
$0200-$03FF System variables, BASIC input buffer
$0400-$07FF Default Screen Memory (1024 bytes)
$0800-$9FFF BASIC program area / Free RAM
$A000-$BFFF BASIC ROM (or RAM underneath)
$C000-$CFFF Free RAM (4K, ideal for code)
$D000-$DFFF I/O registers (VIC-II, SID, CIA) or Char ROM or RAM
$E000-$FFFF KERNAL ROM (or RAM underneath)
Banking with $0001
The processor port at $0001 has three relevant bits:
- Bit 0 (LORAM): BASIC ROM at $A000 (1=ROM, 0=RAM)
- Bit 1 (HIRAM): KERNAL ROM at $E000 (1=ROM, 0=RAM)
- Bit 2 (CHAREN): I/O vs. Character ROM at $D000 (1=I/O, 0=Char ROM)
For games, the typical setup is LDA #$35 : STA $01 — this banks out all ROM, giving you the full 64K of RAM with I/O still visible at $D000. When you need character data, briefly flip bit 2 to read the character ROM.
VIC-II Banks
The VIC-II can only see 16K at a time, selected by bits 0–1 of CIA2 port A ($DD00):
Bank 0: $0000-$3FFF (default)
Bank 1: $4000-$7FFF
Bank 2: $8000-$BFFF
Bank 3: $C000-$FFFF
Within the selected bank, VIC-II register $D018 controls where screen memory and character/bitmap data are located. The bank-switched double buffer technique exploits this by alternating between two VIC banks to achieve flicker-free full-screen scrolling.
Zero Page Strategy
Addresses $00–$01 are the processor port. BASIC and KERNAL use $02–$8F. If you bank out ROM, everything from $02 to $FF is available — 254 bytes of the fastest memory on the system.
Allocate zero page carefully: reserve $FB–$FE for temporary pointers (4 bytes = 2 pointers), dedicate fixed locations for your most critical variables (player position, scroll counters, frame flags), and leave a block free for the music player.
Screen and Colour RAM
Screen memory (default $0400, 1000 bytes) is relocatable within the VIC bank. Colour RAM at $D800–$DBE7 is fixed — it always occupies those 1000 nybbles regardless of banking configuration. This is a common source of confusion and bugs.
I/O Register Map
$D000-$D02E VIC-II (video controller)
$D400-$D41C SID (sound synthesizer)
$D800-$DBE7 Colour RAM (fixed location)
$DC00-$DC0F CIA1 (keyboard, joystick, timer)
$DD00-$DD0F CIA2 (serial, VIC bank, timer)
The VIC-II registers at $D000 are where all the visual magic happens — from raster interrupt setup to sprite control and the colour palette registers that define the C64’s distinctive look.
Practical Layout for Games
A typical game memory plan:
- $0800–$0FFF: Music player + data
- $1000–$1FFF: Sprite data (up to 64 sprites)
- $2000–$3FFF: Bitmap or character set
- $4000–$7FFF: VIC bank 1 — screen + charset for double buffer
- $8000–$BFFF: Level data, lookup tables
- $C000–$CFFF: Game engine code
- $E000–$FFFF: More code or compressed data (with KERNAL banked out)
For scrolling games using the Wild Wood parallax approach, careful memory layout is essential to fit multiple scroll layers, tile maps, and animation data within the 64K limit.