![]() |
![]() |
ADDRESS | FUNCTION |
---|---|
$0000-$07FF | RAM |
$2000-$2007 | PPU communication registers |
$4000-$4013 | pAPU communication registers |
$4014-$4017 | Miscellaneous registers |
$5000-$5FFF | MMC5 Expansion RAM and registers |
$6000-$7FFF | Save RAM |
$8000-$FFFF | ROM |
$FFF9-$FFFF | (6502 vectors) |
ADDRESS | USAGE | FUNCTION |
---|---|---|
$0000-$07FF | Read/ Write | RAM You are given a mere Two Kilobytes of RAM to work with (and an eighth of it is stack space). Use it well! |
$0800-$1FFF | n/a | Shadow RAM Every $400 bytes of this is simply a duplicate of $0000-$07FF. Yes, it's stupid. |
The following are used to communicate with the PPU | ||
$2000 | Write | PPU Control Register #1 This is used to control PPU Functions. It is a bitwise register. NMSbsATT ||||||++--- Name Table Address |||||| (I'm not sure what this represents) |||||+----- PPU Address Increment (on read/write of $2007) ||||| 0 = Increment by 1 ||||| 1 = Increment by $20 (32) ||||+------ Sprite Pattern Table Address |||| 0 = VRAM $0000 ("left" half) |||| 1 = VRAM $1000 ("right" half) |||+------- Background Pattern Table Address ||| 0 = VRAM $0000 ("left" half) ||| 1 = VRAM $1000 ("right" half) ||+-------- Sprite Size || 0 = 8x8 pixels || 1 = 8x16 pixels |+--------- (unused; leave it at 0) +---------- Execute NMI on VBlank 0 = Disabled 1 = Enabled |
$2001 | Write | PPU Control Register #2 This is used to control display settings CCCSBsbT |||||||+--- Colour mode ||||||| 0 = Colour (normal palette) ||||||| 1 = Monochrome (all palette entries mapped to $x0) ||||||+---- Background Clipping |||||| 0 = BG not displayed in left-/right-hand 8-pixel column |||||| 1 = No clipping |||||+----- Sprite Clipping ||||| 0 = (as above, but for Sprites) ||||| 1 = No clipping ||||+------ Background visibility |||| 0 = Background not displayed (all black) |||| 1 = Background visible |||+------- Sprite visibility ||| 0 = Sprites invisible ||| 1 = Sprites visible +++-------- CMYK colour mask 000 = do not alter colours 001 = darken Magenta (make palette Greener) 010 = darken Yellow (make palette Bluer) 100 = darken Cyan (make palette Redder)Notes:
|
$2002 | Read |
PPU Status Register This register reports the PPU Status V08W.... |||+------- VRAM Write Flag ||| 0 = Writes to VRAM Respected ||| 1 = Writes to VRAM Ignored ||+-------- Scanline sprite count || 0 = Eight or fewer Sprites are on the current scanline || 1 = More than eight Sprites on the current scanline |+--------- Sprite #0 Occurence | 0 = Sprite #0 not found | 1 = PPU Has hit Sprite #0 | (see below) +---------- Vertical Blanking Impulse (VBlank) status 0 = Not occuring 1 = PPU is in VBlankNotes:
|
$2003 | Write | Sprite-RAM Address Register Use this to set the address to start I/O for Sprite-RAM. |
$2004 | Write | Sprite-RAM I/O Register This is where you write data to Sprite-RAM (set the starting address via $2003). I do not know if you can also read data through this. I've never needed to. |
$2005 | Write x2 | VRAM Address Register #1 This controls PPU Addressing lines. It is generally used (by you) to pan/scroll the background display. The first write is Horizontal, and the second write is Vertical. I do not completely understand this register, so I will leave it at that. For more information, consult the NESDEV site. |
$2006 | Write x2 | VRAM Address Register #2 This is used to specify the 16-bit address in VRAM to access via $2007. It also controls PPU Addressing Lines, so unless you know what you're doing, you should first wait for VBlank before setting this. You write the high byte FIRST, and then the low byte. |
$2007 | Read/ Write | VRAM I/O Register This is where you will access VRAM (read/write). The VRAM address is auto-incremented (by either 1 or 32, set via $2000) upon each access. Notes:
|
$2008-$3FFF | n/a | Shadow PPU Registers Every eight bytes is a mirror of $2000-$2007. Yes, it's stupid. |
The following are pAPU (audio) registers. This information taken nearly verbatim from Y0sHi's document. | ||
$4000 | Write | Pulse #1 Control Register |
$4001 | Write | Pulse #1 Ramp Control Register |
$4002 | Write | Pulse #1 Fine-Tune Register |
$4003 | Write | Pulse #1 Coarse-Tune Register |
$4004 | Write | Pulse #2 Control Register |
$4005 | Write | Pulse #2 Ramp Control Register |
$4006 | Write | Pulse #2 Fine-Tune Register |
$4007 | Write | Pulse #2 Coarse-Tune Register |
$4008 | Write | Triangle Control Register #1 |
$4009 | "?" | Triangle Control Register #2 |
$400A | Write | Triangle Frequency Register #1 |
$400B | Write | Triangle Frequency Register #2 |
$400C | Write | Noise Control Register #1 |
$400D | ??? | "Unused (???)" |
$400E | Write | Noise Frequency Register #1 |
$400F | Write | Noise Frequency Register #2 |
$4010 | Write | Delta Modulation Control Register |
$4011 | Write | Delta Modulation "D/A" Register |
$4012 | Write | Delta Modulation Address Register |
$4013 | Write | Delta Modulation Data Length Register |
The following are "miscellaneous" registers. | ||
$4014 | Write | Sprite-RAM DMA Register This is a very handy way to deal with Sprites. When you write a value here, 256 bytes are automagically transferred to Sprite-RAM. The address read from is $xx00-$xxFF, where xx is the value written. You can make the most of this by setting aside $100 bytes of RAM (such as $0700-$07FF) as a Sprite DMA table. You can then modify the data there instead of manually via $2003/$2004. When everything's ready, just write the page number (in this case, $07) to $4014. Einfach! (Nothing to it!) |
$4015 | Read/ Write | pAPU Master Control On read: ..IDNT21 |||||+--- Pulse #1 ---------+ ||||+---- Pulse #2 | |||+----- Triangle +-- 0 = Not in use ||+------ Noise | 1 = In use |+------- Delta Modulation -+ +-------- "Vertical Clock Signal IRQ Avaliability" 0 = One frame occuring, thus IRQ cannot occur 1 = One frame is being interrupted via IRQOn write: ...DNT21 ||||+--- Pulse #1 ---------+ |||+---- Pulse #2 | ||+----- Triangle +-- 0 = Disabled |+------ Noise | 1 = Enabled +------- Delta Modulation -+(This information taken nearly verbatim from Y0sHi's NESTECH.TXT document) |
$4016 | Read/ Write | Joystick #1 On read: ...TS..D || +--- Joystick data (see below) |+------ Zapper Sprite Detection | 0 = Sprite not in position | 1 = Sprite in front of cross-hair +------- Zapper Trigger 0 = Pulled 1 = ReleasedOn write: .......S +--- Joystick strobe 0 = Clear strobe 1 = Reset strobeNotes:
a.read = $00 b.read = $01 . . . right.read = $07 readjoy: LDX #$01 STX $4016 DEX STX $4016 LDY #$00 do_readjoy: LDX $4016 STX a.read,Y INY CPY #$08 BNE do_readjoy RTS |
$4017 | Read/ Write | Joystick #2 This works essentially the same as for Joystick #1. |
$5000-$5FFF | Read/ Write | MMC5 Registers and Expansion RAM This section of memory is only used with the Nintendo MMC5 memory mapper. |
$6000-$7FFF | Read/ Write | Save-RAM This is where saved games live and frolick and make merry, assuming the cardridge supports it. If it does, you may as well use this as an extension to the regular work RAM. I mean, you're born with 2K, and here's 8K of space (minus whatever you use for the actual saved games) right here! |
$8000-$FFFF | Read | ROM This is the area in which the game ROM is loaded. Notes:
|
The following are 6502 Vectors. | ||
$FFFA-$FFFB | n/a | Non-Maskable Interrupt (NMI) Vector This contains the address to jump to when the PPU generates a Vertical Blanking Impulse. Notes:
|
$FFFC-$FFFD | Reset Vector This contains the address to jump to when the 6502 hardware is initialized. This occurs when you first turn on the power, or when you press the Reset button. In other words, this contains the address of the "start" of the program. | |
$FFFE-$FFFF | Interrupt Request / CPU Break (IRQ/BRK) Vector This contains the address to jump to when a hardware interrupt (IRQ) or software interrupt (BRK) is executed. |
ADDRESS | FUNCTION |
---|---|
$0000-$1FFF | Pattern Tables This is where the graphic tiles are stored. You can view these in NESticle by pressing F2. Notes:
|
$2000-$23BF | Name Table #0 (lower-left) The Name Table data controls which tiles go where in the Background. It starts with the upper-left tile, and each successive byte represents the next tile. Each byte represents the tile number in the pattern tables ($0xx0 or $1xx0 depending on PPU Control Register #1 ($2000)). The background (per name table) is 32x30 tiles in size. |
$23C0-$23FF | Attribute Table #0 (lower-left) The Attribute Table data controls which set of colours is used where. Each Attr. Table byte covers a 4x4-tile area, and these areas are laid out left-to-right, top-to-bottom. Each such section is divided into 2x2-tile areas, which is the finest resolution of Attribute Table data. Now, for each byte: 44332211 ||||||++--- Upper-left 2x2-tile section ||||++----- Upper-right 2x2-tile section ||++------- Lower-left 2x2-tile section ++--------- Lower-right 2x2-tile sectionFor each: 00 = First set of four colours (of the BG palette) 01 = Second set of four colours 10 = Third set of four colours 11 = Fourth set of four coloursNotes:
|
$2400-$27BF | Name Table #1 (lower-right) |
$27C0-$27FF | Attribute Table #1 (lower-right) |
$2800-$2BBF | Name Table #2 (upper-left) |
$2BC0-$2BFF | Attribute Table #2 (upper-left) |
$2C00-$2FBF | Name Table #3 (upper-right) |
$2FC0-$2FFF | Attribute Table #3 (upper-right) |
$3000-$3EFF | Unknown This is probably mirrored from something. Whoever laid out the NES memory map sure likes to waste space with "mirroring", doesn't he? |
$3F00-$3F0F | Background Colour-Index Array (ie. Palette) Each byte written here is not an absolute colour value, but rather an offset in the colour index used by the PPU to draw the screen. This image will serve as a very valuable reference: ![]() Feel free to download and save that image. Right-click on it and select "Save Image As...". Notes:
|
$3F10-$3F1F | Sprite Colour-Index Array (ie. Palette) This is the same as the Background palette, except it's used for Sprites. Notes:
|
$3F20-$3FFF | Shadow Palette Every $20 bytes of this is simply a mirror of $3F00-$3F1F. |
$4000-$FFFF | Shadow VRAM Every $4000 bytes of this is simply a mirror of $0000-$3FFF. |