Skip to content

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.