Commodore 64 memory map
The Commodore 64 memory map is the CPU-visible arrangement of the 6510's 16-bit, 64 KiB address space. It is not a one-to-one inventory of physical chips: the programmable logic array (PLA) can make RAM, firmware ROM, character ROM, I/O registers, or cartridge-selected resources answer at the same addresses. [1][2] The familiar power-on layout therefore describes a useful operating configuration, rather than a fixed division of the machine's RAM. [3][4]
CPU-visible regions
[edit | edit source]With the usual configuration, the CPU sees the following broad regions. The entries headed “selectable” have RAM underneath them; what a CPU read reaches depends on the processor-port configuration. [3][2]
| Addresses | Usual CPU-visible resource | Mapping significance |
|---|---|---|
| $0000–$00FF | Zero page | The first two bytes are 6510 port registers; much of the remainder is used by the system. [1][4] |
| $0100–$01FF | Hardware stack page | The 6510 places its stack in page 1. [1][3] |
| $0200–$9FFF | RAM, subject to cartridge controls | This is principally ordinary CPU RAM, although the PLA also receives cartridge-port control signals. [3][2] |
| $A000–$BFFF | BASIC ROM or underlying RAM | This 8 KiB window is controlled by the low RAM-select lines. [3][4] |
| $C000–$CFFF | RAM | This 4 KiB interval is not one of the standard BASIC, character/I/O, or KERNAL overlays. [3][2] |
| $D000–$DFFF | I/O, character ROM, or underlying RAM | This 4 KiB window is the central multiplexed region. [3][4] |
| $E000–$FFFF | KERNAL ROM or underlying RAM | This 8 KiB window contains KERNAL firmware in the ordinary start-up configuration. [3][4] |
This view avoids a common mistake: “ROM area” means that ROM is currently readable at that address, not that the address lacks RAM storage. A program that needs bytes hidden by an overlay must select a configuration in which the desired RAM is readable. [3][2]
The map is also conditional on the expansion port. The service documentation shows that the PLA receives cartridge-related signals as well as address and processor-port inputs, and the programmer’s guide reserves cartridge-oriented areas in its map. [5][3] Thus a cartridge can alter what the CPU sees without changing the CPU’s numerical address range. For ordinary software, the useful lesson is modest: do not assume that a machine with an attached cartridge has the same visible resources as an unexpanded start-up configuration. [5][4]
The ranges below $A000 and $C000–$CFFF are often the most straightforward places to put CPU code and data because the standard map does not overlay BASIC, KERNAL, character ROM, or the main I/O register block there. [3][2] “Straightforward” does not mean unrestricted: system software assigns documented purposes to portions of low RAM, and an expansion configuration can still affect the complete map. [4][5] The normal screen matrix is an example of RAM used by firmware and video hardware together. It begins at $0400 in the start-up display arrangement, while the VIC-II derives its display locations from its own controls. [3][6]
At the top of the address space, the processor’s reset and interrupt vectors are numerical locations in the $FFFA–$FFFF part of the KERNAL window in the ordinary configuration. The 6510 data sheet describes reset loading the program counter from $FFFC–$FFFD and an interrupt vector from $FFFE–$FFFF. [1] This makes the KERNAL overlay operationally important at system start: if a program deliberately changes the high-memory mapping, it must understand which vectors and code are visible for the mode it enters. [3][4]
Zero page and page 1
[edit | edit source]The 6510 reserves addresses $0000 and $0001 for its on-chip port's data-direction and data registers. The processor documentation also identifies zero-page addressing as a shorter, faster form of addressing, so zero page is valuable working space rather than simply the first 256 bytes of RAM. [1][4] Page 1, $0100–$01FF, is the processor stack, so subroutine calls, returns, interrupts, and explicit stack operations compete for that page. [1][3]
For machine-language programs, the practical rule is to treat both pages as shared infrastructure. The system's documented zero-page map assigns many bytes to BASIC and KERNAL work, while the stack is inherently live whenever normal control flow or interrupts use it. [4][3] A program should therefore choose its own zero-page locations deliberately, preserve any shared state it changes, and leave sufficient stack headroom for its calling and interrupt pattern. [1][4]
The benefit of zero-page allocation is architectural rather than a special C64 convention. The 6510 instruction set encodes zero-page operands with a one-byte address and provides indexed and indirect zero-page modes, while the data sheet notes the resulting code-size and execution-time advantage. [1] That benefit has a cost on a running C64: many low addresses have published system roles. [4][3] A routine intended to coexist with BASIC or KERNAL services therefore needs a chosen workspace convention, rather than treating every otherwise unused-looking low byte as private memory. [4][3]
Banking through the processor port
[edit | edit source]The C64 board connects port lines 0–2 to the PLA as /LORAM, /HIRAM, and /CHAREN. The PLA combines those lines with address and cartridge signals to select BASIC ROM, KERNAL ROM, character ROM, I/O decoding, RAM, or cartridge-related responses. [2][5] The normal port value is $37: its conventional result is BASIC ROM at $A000–$BFFF, I/O at $D000–$DFFF, and KERNAL ROM at $E000–$FFFF. [4][3]
The important distinction is that the two low selection bits govern the BASIC and KERNAL choices together, while bit 2 normally chooses I/O rather than character ROM at $D000–$DFFF. Some bit patterns expose all-RAM arrangements; the mapping table must be consulted rather than inferring that bit 2 alone always selects a device. [4][2] Because the same port also has cassette-related functions and a separately programmed data-direction register, robust code changes only the required bits and restores the prior state after a temporary bank switch. [4][5]
Banking changes what the CPU reads and executes. For example, code whose next instruction is fetched from an address normally covered by ROM cannot safely remove that ROM unless an appropriate RAM copy is visible at the same address or control has already moved elsewhere. This follows from the documented overlay alternatives, not from a separate instruction-memory space. [3][4] Similarly, a bank-switching routine should preserve the port’s data-direction state as well as its data state, because the 6510 uses separate registers for those functions. [1][4]
The character-ROM selection deserves separate attention. It is a read mapping for the CPU window, not a way to write new glyphs into ROM. A program that wants custom characters normally places the new patterns in RAM, makes the VIC-II use that RAM location, and selects its CPU mapping according to whether it also needs to read the built-in character shapes or I/O registers at that moment. [3][6] The published CPU map and video-bank discussion jointly support this workflow: the CPU can expose character ROM at $D000, while the VIC-II’s display source is constrained by its selected bank and register settings. [3][6]
The 6510 family documentation describes port variants with differing pin counts, whereas the C64 schematic and board-level accounts show the C64's relevant P0–P5 wiring. This is not a different C64 mapping: it is a distinction between the general processor-family datasheet and the machine's implemented connection. [1][5][2]
I/O, colour RAM, and the character generator
[edit | edit source]When I/O is selected, $D000–$D3FF reaches VIC-II registers and $D400–$D7FF is the SID register area, with repeated SID register images in the unused portion of that span. Colour RAM occupies $D800–$DBFF and stores only four data bits per location; $DC00–$DCFF and $DD00–$DDFF serve the two CIA chips. The $DE00–$DFFF blocks are expansion I/O regions. [3][4] When character ROM is selected instead, the same $D000–$DFFF CPU addresses supply the two 2 KiB character sets; with the relevant RAM configurations, RAM is visible there instead. [3][4]
This makes I/O banking a correctness issue, not only a memory-saving technique. A write intended for a hardware register requires I/O to be visible; a routine that needs the RAM beneath the I/O window must use a RAM-visible configuration and must not then attempt to access the device registers. [4][2]
The repeated register images in the SID portion are an address-decoding detail rather than additional sound chips. The technical map records the same 32-byte SID register set repeated through the otherwise unused part of the $D400–$D7FF allocation. [4] Colour RAM is different from the main 64 KiB RAM: its documented window contains the screen’s colour nibbles, and its four-bit data width is why a colour value has a narrower range than an ordinary byte. [3][4] These distinctions matter when reserving memory: screen codes, colour attributes, and bitmap or character data are related display inputs but occupy different storage resources. [3][6]
The VIC-II has a separate memory view
[edit | edit source]The CPU map does not fully describe graphics memory. The VIC-II has a 14-bit address space and works within one of four 16 KiB banks; CIA 2 port A at $DD00 selects the bank through active-low lines. [3][6] VIC-II register $D018 then chooses screen and character-data positions within that bank. [3][6] The character generator is visible to the VIC-II in two bank positions even though the CPU reaches it through the $D000 overlay, and colour RAM is separately wired to the video hardware. [3][6]
Graphics code consequently needs two maps in mind: the CPU configuration needed to read or write RAM and registers, and the VIC-II bank plus internal offsets from which the display fetches data. A location can be accessible to the CPU yet not be in the VIC-II's selected 16 KiB bank. [3][6]
The four banks are not a replacement for CPU banking. The video controller’s bank selector is on CIA 2, whereas the CPU overlay controls are on the 6510 port and feed the PLA. [3][2] Consequently, a display relocation normally has at least two parts: choosing the 16 KiB bank that contains the intended data, then selecting legal screen and character locations within it through the VIC-II control register. [3][6] A program may also need to consider whether the standard character shapes are available to the VIC-II in the chosen bank or whether it must first create a RAM-resident character set. [3][6]
The colour-memory path reinforces why a single linear-address diagram is incomplete. CPU code writes the colour attributes through the $D800 window when I/O is mapped, but the VIC-II receives those four-bit values through dedicated wiring irrespective of which 16 KiB display bank it is reading for screen codes and graphics data. [4][6] A layout decision that moves the screen matrix or bitmap therefore changes the VIC-II bank-and-offset planning, while the colour attributes retain their separate CPU-visible location. [3][6]
Programming implications
[edit | edit source]A reliable program establishes a known processor-port state before calling code that assumes ROM, I/O, or hidden RAM. It should save and restore the port around a temporary mapping change, keep its data and executable code readable in the configuration used during that change, and avoid relying on system-owned zero-page or stack state without a documented convention. [4][2] For video work, it must also coordinate CIA 2 bank selection and VIC-II register settings with the CPU-side I/O state. [3][6] These constraints explain why C64 programs often treat memory mapping as part of program state, alongside registers and interrupt state.
An effective debugging sequence is therefore to identify the CPU address first, determine which responder is selected there, and then, for display data, calculate the VIC-II bank and offset separately. This sequence follows directly from the documented CPU overlays and the independent VIC-II bank selection. [4][3][6] It also helps distinguish a banking fault from an ordinary addressing mistake: a byte may be at the intended numerical address but be hidden from the CPU, be a register rather than RAM, or fall outside the VIC-II bank currently used for display. [2][4][6]
The default map remains useful because it leaves the operating system firmware and devices directly reachable, but it is only one arrangement among the documented alternatives. [4][3] Programs that switch away from it should make the transition short, explicit, and reversible. They should also decide whether interrupts or calls into KERNAL are permissible while the relevant ROM or I/O window is hidden, since those operations depend on the same visible resources described by the map. [1][3][2] Treating the map this way lets a program use hidden RAM and custom video layouts without confusing an address with the device, ROM, or RAM that currently answers it. [4][6]
See also
[edit | edit source]- Commodore 64
- MOS Technology 6510
- VIC-II
- SID
- MOS Technology 6526 CIA
- Commodore 64 BASIC
- KERNAL
- Commodore 64 cartridge
- Zero page
References
[edit | edit source]- ↑ 1.00 1.01 1.02 1.03 1.04 1.05 1.06 1.07 1.08 1.09 1.10 “6510 Microprocessor with I/O”. Commodore Semiconductor Group. pp. 1, 6, 10. Accessed 2026-09-21.
- ↑ 2.00 2.01 2.02 2.03 2.04 2.05 2.06 2.07 2.08 2.09 2.10 2.11 2.12 2.13 “The 6510 Processor Port”. C64 OS. “The PLA” and CPU-view memory-region table. Accessed 2026-09-21.
- ↑ 3.00 3.01 3.02 3.03 3.04 3.05 3.06 3.07 3.08 3.09 3.10 3.11 3.12 3.13 3.14 3.15 3.16 3.17 3.18 3.19 3.20 3.21 3.22 3.23 3.24 3.25 3.26 3.27 3.28 3.29 3.30 3.31 3.32 3.33 3.34 3.35 3.36 “Commodore 64 Programmer's Reference Guide”. Commodore Business Machines. pp. 310–334. Accessed 2026-09-21.
- ↑ 4.00 4.01 4.02 4.03 4.04 4.05 4.06 4.07 4.08 4.09 4.10 4.11 4.12 4.13 4.14 4.15 4.16 4.17 4.18 4.19 4.20 4.21 4.22 4.23 4.24 4.25 4.26 4.27 4.28 “Commodore 64 memory map”. STA C64 Technical Archive. processor-port, ROM, and I/O-area entries. Accessed 2026-09-21.
- ↑ 5.0 5.1 5.2 5.3 5.4 5.5 “Service Manual, Model C64 Computer, Feb. 1985, PN-314001-02”. Commodore Business Machines; archived by Zimmers.NET. schematic 251138, sheets 1–2; 6510 and PLA pinout. Accessed 2026-09-21.
- ↑ 6.00 6.01 6.02 6.03 6.04 6.05 6.06 6.07 6.08 6.09 6.10 6.11 6.12 6.13 6.14 6.15 “VIC-II for Beginners Part 1 – When Visibility Matters”. Dustlayer(2013-04-22). “The Limited Power of Sight of the VIC-II”. Accessed 2026-09-21.
Automation and sourcing note
[edit | edit source]This candidate was independently synthesized from the cited sources under c64.wiki publication policy. It contains no copied manual text, scans, images, screenshots, or source-code extracts; cited historical manuals and schematics are used as citation-only evidence.