6510: The C64's Custom Core
A 6502 with an I/O trick up its sleeve
The MOS 6510 added an integrated I/O port to the 6502, giving the Commodore 64 its signature memory banking and tape control.
The MOS 6510 is a 6502 with an integrated I/O port at addresses $00 and $01 — Commodore’s own datasheet says the internal architecture is identical, and the port is the whole of the difference. This seemingly minor addition gave the Commodore 64 its flexible memory mapping, allowing programmers to swap ROM in and out of the address space and control the datasette.
The port’s data and direction registers are both 8 bits wide internally, but the standard C64 6510 mask only bonds out P0–P5. Bits 6 and 7 still exist in the registers; they just drive no external pin. The 6510-1 and 6510-2 bond out all eight, and pay for the two extra pins by dropping RDY and NMI, which appear on neither variant’s pinout.
Fast facts
- Clock speed: 0.985 MHz (PAL) / 1.023 MHz (NTSC) in the C64; the part was sold in 1, 2 and 3 MHz grades.
- Compatibility: internal architecture identical to the 6502, for the same 56 instructions and thirteen addressing modes.
- I/O port: 8-bit registers at $00 (data direction) and $01 (data); 6 bits (P0–P5) bonded out on standard C64 mask.
- Pin count: 40-pin DIP package.
The I/O port
The magic lives at two special addresses:
| Address | Function |
|---|---|
| $00 | Data Direction Register (DDR) - 1=output, 0=input |
| $01 | Port data - controls memory mapping and tape |
Port bit assignments
| Bit | Function |
|---|---|
| 0 | LORAM - BASIC ROM visibility |
| 1 | HIRAM - KERNAL ROM visibility |
| 2 | CHAREN - Character ROM / I/O visibility |
| 3 | Cassette write line |
| 4 | Cassette sense (input) |
| 5 | Cassette motor control |
Bit 4 is the only input, which is why the C64 sets the DDR to %101111 — 47 decimal, $2F — automatically at reset.
Memory banking
By manipulating bits 0-2 of $01, programmers can:
- Hide BASIC ROM: gain 8KB at $A000-$BFFF for machine code.
- Hide KERNAL ROM: gain 8KB at $E000-$FFFF (requires custom IRQ handling). Taking HIRAM low removes BASIC as well, whatever LORAM is set to.
- Access character ROM: read font data at $D000-$DFFF instead of I/O.
- Full 64KB RAM: set LORAM and HIRAM low for complete RAM access.
The three port bits are not the whole story. The Programmer’s Reference Guide draws its maps against LORAM, HIRAM, GAME and EXROM together — the last two driven by the cartridge port — so a cartridge can select configurations software cannot reach on its own.
Common configurations
| $01 value | Configuration |
|---|---|
| $37 | Default: BASIC + KERNAL + I/O visible; 38K contiguous user RAM |
| $36 | BASIC hidden, KERNAL + I/O visible; 52K contiguous user RAM, intended for soft-loaded languages including CP/M |
| $35 | BASIC and KERNAL both hidden, I/O visible; 60K RAM, and you write your own I/O drivers |
| $34 | All 64KB RAM. CHAREN is set, but a map without I/O ignores it |
| $30 | All 64KB RAM — the same map as $34, reached with CHAREN clear |
Writing under ROM
A write to an address occupied by ROM always lands in the RAM beneath it, whatever the current bank. Commodore documents this as a feature rather than a hazard: a hi-res screen can sit under a ROM and be drawn into without banking it back in first. Reads still return the ROM.
Why it matters
The 6510’s I/O port let the C64 punch above its weight. Games could claim the full 64KB while still using ROM routines when convenient. This flexibility, combined with the VIC-II and SID, made the C64 the dominant gaming platform of the 8-bit era.
Capacitor decay quirk
A famous emulation gotcha, and one worth flagging as the weakest-sourced claim on this page: it rests on community measurement and emulator source, not on a Commodore document.
Drive a bit low (DDR=1, PORT bit=0), then switch it to input (DDR=0). The bit reads 0 briefly, then drifts to 1 over roughly 350 ms at room temperature — with significant variance — as the gate-input capacitance leaks. Drive the bit high first and there is no decay at all, because there is no charge to bleed off. On a C64 the effect is only observable on the unbonded bits 6 and 7: bits 0, 1, 2 and 5 carry external pull-ups, and bits 3 and 4 are pulled by the cassette interface.
Software that depends on this behaviour will misbehave in emulators that treat the bit as a plain register. Cycle-accurate emulators track a per-bit “last-driven value and timestamp” and time out reads to 1 after the decay window; VICE uses about 350,000 cycles at the PAL clock, some 355 ms.