This appendix explains how the NES’s 8-bit 6502 CPU uses memory-mapped I/O instead of dedicated port instructions, and outlines the complete memory and I/O layout of the original hardware. It summarizes how the 64k CPU address space is divided between internal CPU/PPU areas and cartridge-provided regions, and identifies the registers through which the CPU communicates with the PPU, APU, and external controllers. The goal is to provide a practical map and register list for building games that interact correctly with graphics, audio, and input on real NES/Famicom systems.
The 64k memory space is partitioned so that the lower 4k contains CPU-dedicated areas and the PPU’s memory-mapped registers, while the upper portion is largely cartridge-defined. Addresses $4020–$ffff are available to the cartridge for ROM, RAM, and mapper registers; commonly, $6000–$7fff is battery-backed or work RAM (WRAM/PRG-RAM), and $8000–$ffff holds ROM and mapper registers. Digital samples for DPCM must be placed at $c000–$fff1. The CPU expects interrupt vectors in fixed locations at the end of the address space: NMI at $fffa–$fffb, Reset at $fffc–$fffd, and IRQ/BRK at $fffe–$ffff.
I/O is achieved by reading and writing specific addresses. The PPU exposes eight registers at $2000–$2007 for control, status, scrolling, addressing, and data, plus an OAM DMA trigger at $4014. The APU provides 21 memory-mapped registers for the pulse, triangle, noise, and DMC channels, mostly write-only, with $4015 as read/write control/status and $4017 for frame sequencing. Controller and peripheral I/O use $4016/$4017: writing the low bits of $4016 drives a 3-bit output bus, while reading the low five bits of $4016 and $4017 returns input. Wiring differs across models: the NES, original Famicom, and AV Famicom connect different subsets of these data lines to controller and expansion ports.
Figure C.1 NES/Famicom Memory Map
FAQ
What CPU does the NES use and how much memory can it address?The NES uses an 8-bit 6502 CPU that can address 64 KB. It has no separate I/O instructions; external devices are accessed via memory-mapped addresses.How is the NES 64 KB memory space organized?The lower 4 KB contains dedicated CPU sections, followed by the PPU’s memory-mapped registers. The cartridge controls the upper space at $4020–$FFFF.Which cartridge address ranges are commonly used for RAM and ROM?$6000–$7FFF is typically battery-backed save/work RAM (WRAM/PRG-RAM). $8000–$FFFF holds ROM and mapper memory-mapped registers.Where must DPCM sample data be located?If using 1-bit DPCM samples, place the sample data at $C000–$FFF1.Where are the CPU interrupt vectors located?NMI: $FFFA–$FFFB. Reset: $FFFC–$FFFD. IRQ/BRK: $FFFE–$FFFF.Which PPU registers are exposed to the CPU and at what addresses?Eight registers at $2000–$2007: PPUCTRL ($2000), PPUMASK ($2001), PPUSTATUS ($2002), OAMADDR ($2003), OAMDATA ($2004), PPUSCROLL ($2005), PPUADDR ($2006), PPUDATA ($2007).What is OAMDMA ($4014) used for?It is the OAM DMA high address register, used to perform DMA transfers into sprite OAM.What does reading PPUSTATUS ($2002) do?It returns vblank (V), sprite 0 hit (S), and sprite overflow (O). Reading $2002 also resets the write pair toggle for $2005/$2006.How many APU registers are there, and which are readable?The APU exposes 21 memory-mapped registers. All are write-only except $4015, which is read/write.How do the controller I/O ports at $4016/$4017 work, and how do NES and Famicom wiring differ?Writing the bottom 3 bits of $4016 drives a 3-bit output (OUT0–OUT2). Reading the bottom 5 bits of $4016/$4017 returns input data and asserts /OE1 and /OE2. On the NES, only D0, D3, and D4 connect to the controller ports (all D0–D4 go to the expansion port). On the original Famicom, $4016 D0 and D2 and $4017 D0 are permanently connected to both controllers, while $4016 D1 and all of $4017’s D0–D4 go to the expansion port. On the AV Famicom, only D0 connects to the controller ports (expansion port unchanged).
pro $24.99 per month
access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!