The following document describes the hardware architecture of Nintendo Entertainment System videogame console, also known as Famicom in the East (Korea, Japan), and Dandy in Europe (Russia, etc.). Note that this document is mainly based on experimentation and may be incomplete and incorrect in many places. "Nintendo Entertainment System", "Famicom", and (most likely) "Dandy" are registered trademarks of Nintendo.
This document has also been translated to Japanese by Bero. French translation by Guillaume Tuloup is also available.
I would like to thank following people for their help in obtaining this
information and writing a NES emulator, as well as moral support from
some of them:
(sorted alphabetically)
Pascal Felber Patrick Lesaard Tink
Goroh Pan of Anthrox Bas Vijfwinkel
Kawasedo Paul Robson
Marcel de Kogel Serge Skorobogatov
Alex Krasivsky John Stiles
The 6502 CPU used in NES is not covered in this document though, as there is enough information on it in other literature. You are assumed to know how 6502 works.
Also not covered are some more exotic memory mappers, Famicom DiskSystem, and some other esoteric pieces of hardware, as I don't have enough information about them. If you have any information on NES which is not in this manual, feel free to write to fms@cs.umd.edu. Your help will be appreciated.
In this manual, you may encounter notation of the form "Nth bit" (5th, 3rd, etc.). Bits are counted from the least significant (0th) to the most significant (7th).
All hexadecimal numbers are prepended with a dollar sign ($2002, $4016, etc.) which is a common notation used in 6502 CPU assembler.
Cartridges may contain both ROM appearing in the CPU address space at $8000-$FFFF, and VROM or VRAM appearing in the PPU address space at $0000-$1FFF.
In smaller cartridges, which only have 16kB ROM, it takes place at $C000-$FFFF leaving $8000-$BFFF area unused. In cartridges with >32kB ROM, it is paged into address space with special circuitry (see "Mappers"). Some cartridges also have RAM at $6000-$7FFF which may or may not be battery-backed.
Cartridge VROM (VRAM) is used for Pattern Tables (aka Tile Tables, Character Generators, etc.). The usual amount is 8kB which contain 2 Pattern Tables. In cartridges with >8kB VROM (VRAM), it is paged into address space with special circuitry (see "Mappers").
Internal NES VRAM is located at addresses $2000-$3FFF in the PPU memory and used to store Name Tables (aka Screen Buffers, etc.). Although PPU supports 4 Name Tables, there is only enough memory for two of them. Other two mirror the first two (see "PPU Details").
--------------------------------------- $10000 Upper Bank of Cartridge ROM --------------------------------------- $C000 Lower Bank of Cartridge ROM --------------------------------------- $8000 Cartridge RAM (may be battery-backed) --------------------------------------- $6000 Expansion Modules --------------------------------------- $5000 Input/Output --------------------------------------- $2000 2kB Internal RAM, mirrored 4 times --------------------------------------- $0000
--------------------------------------- $4000 Empty --------------------------------------- $3F20 Sprite Palette --------------------------------------- $3F10 Image Palette --------------------------------------- $3F00 Empty --------------------------------------- $3000 Attribute Table 3 --------------------------------------- $2FC0 Name Table 3 (32x30 tiles) --------------------------------------- $2C00 Attribute Table 2 --------------------------------------- $2BC0 Name Table 2 (32x30 tiles) --------------------------------------- $2800 Attribute Table 1 --------------------------------------- $27C0 Name Table 1 (32x30 tiles) --------------------------------------- $2400 Attribute Table 0 --------------------------------------- $23C0 Name Table 0 (32x30 tiles) --------------------------------------- $2000 Pattern Table 1 (256x2x8, may be VROM) --------------------------------------- $1000 Pattern Table 0 (256x2x8, may be VROM) --------------------------------------- $0000
------+-----+--------------------------------------------------------------- $2000 | RW | PPU Control Register 1 | 0-1 | Name Table Address: | | | | +-----------+-----------+ | | | 2 ($2800) | 3 ($2C00) | | | +-----------+-----------+ | | | 0 ($2000) | 1 ($2400) | | | +-----------+-----------+ | | | | Remember that because of the mirroring there are only 2 | | real Name Tables, not 4. Also, PPU will automatically | | switch to another Name Table when running off the current | | Name Table during scroll (see picture above). | 2 | Vertical Write, 1 = PPU memory address increments by 32: | | | | Name Table, VW=0 Name Table, VW=1 | | +----------------+ +----------------+ | | |----> write | | | write | | | | | | V | | | | 3 | Sprite Pattern Table Address, 1 = $1000, 0 = $0000. | 4 | Screen Pattern Table Address, 1 = $1000, 0 = $0000. | 5 | Sprite Size, 1 = 8x16, 0 = 8x8. | 6 | PPU Master/Slave Mode, not used in NES. | 7 | VBlank Enable, 1 = generate interrupts on VBlank. ------+-----+--------------------------------------------------------------- $2001 | RW | PPU Control Register 2 | 0 | Unknown (???) | 1 | Image Mask, 0 = don't show left 8 columns of the screen. | 2 | Sprite Mask, 0 = don't show sprites in left 8 columns. | 3 | Screen Enable, 1 = show picture, 0 = blank screen. | 4 | Sprites Enable, 1 = show sprites, 0 = hide sprites. | 5-7 | Background Color, 0 = black, 1 = blue, 2 = green, 4 = red. | | Do not use any other numbers as you may damage PPU hardware. ------+-----+--------------------------------------------------------------- $2002 | R | PPU Status Register | 0-5 | Unknown (???) | 6 | Hit Flag, 1 = Sprite refresh has hit sprite #0. | | This flag resets to 0 when screen refresh starts | | (see "PPU Details"). | 7 | VBlank Flag, 1 = PPU is in VBlank state. | | This flag resets to 0 when VBlank ends or CPU reads $2002 | | (see "PPU Details"). ------+-----+--------------------------------------------------------------- $2003 | W | Sprite Memory Address | | Used to set the address of the 256-byte Sprite Memory to be | | accessed via $2004. This address will increment by 1 after | | each access to $2004. Sprite Memory contains coordinates, | | colors, and other sprite attributes (see "Sprites"). ------+-----+--------------------------------------------------------------- $2004 | RW | Sprite Memory Data | | Used to read/write the Sprite Memory. The address is set via | | $2003 and increments by 1 after each access. Sprite Memory | | contains coordinates, colors, and other sprite attributes | | sprites (see "Sprites"). ------+-----+--------------------------------------------------------------- $2005 | W | Screen Scroll Offsets | | There are two scroll registers, vertical and horizontal, | | which are both written via this port. The first value written | | will go into the Vertical Scroll Register (unless it is >239, | | then it will be ignored). The second value will appear in the | | Horizontal Scroll Register. Name Tables are assumed to be | | arranged in the following way: | | | | +-----------+-----------+ | | | 2 ($2800) | 3 ($2C00) | | | +-----------+-----------+ | | | 0 ($2000) | 1 ($2400) | | | +-----------+-----------+ | | | | When scrolled, the picture may span over several Name Tables. | | Remember that because of the mirroring there are only 2 real | | Name Tables, not 4. ------+-----+--------------------------------------------------------------- $2006 | W | PPU Memory Address | | Used to set the address of PPU Memory to be accessed via | | $2007. The first write to this register will set 8 lower | | address bits. The second write will set 6 upper bits. The | | address will increment either by 1 or by 32 after each | | access to $2007 (see "PPU Memory"). ------+-----+--------------------------------------------------------------- $2007 | RW | PPU Memory Data | | Used to read/write the PPU Memory. The address is set via | | $2006 and increments after each access, either by 1 or by 32 | | (see "PPU Memory"). ------+-----+--------------------------------------------------------------- $4000-$4013 | Sound Registers | See "Sound". ------+-----+--------------------------------------------------------------- $4014 | W | DMA Access to the Sprite Memory | | Writing a value N into this port causes an area of CPU memory | | at address $100*N to be transferred into the Sprite Memory. ------+-----+--------------------------------------------------------------- $4015 | W | Sound Channel Switch | 0 | Channel 1, 1 = enable sound. | 1 | Channel 2, 1 = enable sound. | 2 | Channel 3, 1 = enable sound. | 3 | Channel 4, 1 = enable sound. | 4 | Channel 5, 1 = enable sound. | 5-7 | Unused (???) ------+-----+--------------------------------------------------------------- $4016 | RW | Joystick1 + Strobe | 0 | Joystick1 Data (see "Joysticks). | 1 | Joystick1 Presence, 0 = connected. | 2-5 | Unused, set to 000 (???) | 6-7 | Unknown, set to 10 (???) ------+-----+--------------------------------------------------------------- $4017 | RW | Joystick2 + Strobe | 0 | Joystick2 Data (see "Joysticks). | 1 | Joystick2 Presence, 0 = connected. | 2-5 | Unused, set to 000 (???) | 6-7 | Unknown, set to 10 (???) ------+-----+---------------------------------------------------------------
When a VBlank interrupt occurs, CPU pushes return address and the status register on stack, then jumps to the address stored at location $FFFA (ROM in NES).
The interrupt handler is supposed to finish its execution with RTI command which returns CPU to the main program execution. More information on the interrupt handling can be found in a decent book on 6502 CPU.
Maskable interrupts (aka IRQs) can be generated by external circuitry on the cart (see "Mappers"), but most carts do not generate them.
Read # | 1 2 3 4 5 6 7 8 -------+--------------------------------------------------------- Button | A B SELECT START UP DOWN LEFT RIGHT1st bit indicates whether joystick is connected to the port or not. It is set to 0 if a joystick is connected, 1 otherwise. 6th and 7th bits of $4016/$4017 also seem to have some significance. The rest of bits appear to return zeroes. Some games expect to get exactly $41 from $4016/$4017 if a button is pressed.
Many smaller ROMs have read-only memory (VROM) for the Pattern Tables.
In this case, you won't be able to write into this part of PPU address
space, only read from it.
Writing to PPU memory:
a) Write upper address byte into $2006
b) Write lower address byte into $2006
c) Write data into $2007. After each write, the
address will increment either by 1 (bit 2 of
$2000 is 0) or by 32 (bit 2 of $2000 is 1).
Reading from PPU memory:
a) Write upper address byte into $2006
b) Write lower address byte into $2006
c) Read data from $2007. The first byte read from
$2007 will be invalid (see "PPU Details"). Then,
the address will increment by 1 after each read.
It is necessary to say that although PPU supports 4 Name Tables, NES only has enough internal VRAM for 2 Name Tables. Two others are mirrored.
Character Colors Contents of Pattern Table ...*.... 00010000 00010000 $10 +-> 00000000 $00 ..O.O... 00202000 00000000 $00 | 00101000 $28 .#...#.. 03000300 01000100 $44 | 01000100 $44 O.....O. 20000020 00000000 $00 | 10000010 $82 *******. -> 11111110 -> 11111110 $FE | 00000000 $00 O.....O. 20000020 00000000 $00 | 10000010 $82 #.....#. 30000030 10000010 $82 | 10000010 $82 ........ 00000000 00000000 $00 | 00000000 $00 +---------+Note that only two bits for each pixel of each tile are stored in the Pattern Table. Other two are taken from the Attribute Table. Thus, the total number of simultaneous colors on the NES screen is 16, although each tile has only 4 colors.
(0,0) (1,0) 0| (2,0) (3,0) 1 (0,1) (1,1) | (2,1) (3,1) --------------+---------------- (0,2) (1,2) 2| (2,2) (3,2) 3 (0,3) (1,3) | (2,3) (3,3)The attribute byte contains upper two bits of the color number for each 2x2 square (the lower two bits are stored in the Pattern Table):
Bits Function Tiles -------------------------------------------------------------- 7,6 Upper color bits for square 3 (2,2),(3,2),(2,3),(3,3) 5,4 Upper color bits for square 2 (0,2),(1,2),(0,3),(1,3) 3,2 Upper color bits for square 1 (2,0),(3,0),(2,1),(3,1) 1,0 Upper color bits for square 0 (0,0),(1,0),(0,1),(1,1)
Which pages are mirrored depends on the cartiridge circuitry. Each
cartridge has control of the PPU address bits A10 and A11. It may set them
in one of four possible ways:
A11 A10 Effect
----------------------------------------------------------
0 0 All four screen buffers are mapped to the same
area of memory which repeats at $2000, $2400,
$2800, and $2C00.
0 x "Upper" and "lower" screen buffers are mapped to
separate areas of memory at $2000, $2400 and
$2800, $2C00.
x 0 "Left" and "right" screen buffers are mapped to
separate areas of memory at $2000, $2800 and
$2400,$2C00.
x x All four screen buffers are mapped to separate
areas of memory. In this case, the cartridge
must contain 2kB of additional VRAM.
The Hit Flag allows to implement both horizontal and vertical screen splits, as well as variety of other interesting effects. It is not reset by reading from the PPU Status Register. Instead, it appears to go down on its own every time PPU starts refreshing screen.
The idea behind this trick is that PPU uses the VRAM address register to store current address during screen refresh. By writing into $2006 you effectively modify this address and make PPU continue screen refresh from a different location. Details on how $2007 affects screen refresh are unknown.
While it is not clear how exactly values written into $2006
relate to the screen locations, they seem to follow this diagram:
Address Written into $2006
xxYYSSYYYYYXXXXX
| | | |
| | | +---- Horizontal scroll in tiles (i.e. 1 = 8 pixels)
| | +--------- Vertical scroll in tiles (i.e. 1 = 8 pixels)
| +------------ Number of Name Table ($2000,$2400,$2800,$2C00)
+-------------- Additional vertical scroll in pixels (0..3)
Sprite Attribute RAM: | Sprite#0 | Sprite#1 | ... | Sprite#62 | Sprite#63 | | | +---- 4 bytes: 0: Y position of the left-top corner - 1 1: Sprite pattern number 2: Color and attributes: bits 1,0: two upper bits of color bits 2,3,4: Unknown (???) bit 5: if 1, display sprite behind background bit 6: if 1, flip sprite horizontally bit 7: if 1, flip sprite vertically 3: X position of the left-top cornerSprite patterns are fetched in the exactly same way as the tile patterns for the background picture. The only difference occurs in 8x16 sprites: the top half of a sprite is taken from the Sprite Pattern Table at $0000 while the bottom part is taken from the same location of $1000 Sprite Pattern Table.
To be written
--------------------------------------- $10000 8kB FDS BIOS ROM --------------------------------------- $E000 32kB Program RAM --------------------------------------- $6000 Expansion Modules --------------------------------------- $5000 Input/Output --------------------------------------- $2000 2kB Internal RAM, mirrored 4 times --------------------------------------- $0000The Famicom Disk System also adds some I/O ports into $4000-$40FF range to control the disk drive, the sound hardware, and the IRQ counter built into FDS:
------+-----+--------------------------------------------------------------- $4020 | W | Lower Byte of IRQ Counter ------+-----+--------------------------------------------------------------- $4021 | W | Upper Byte of IRQ Counter ------+-----+--------------------------------------------------------------- $4022 | W | Enable/Disable IRQs | 2 | \ = Stop IRQ counter and reset its interrupt request. | | / = Load IRQ counter with a value from $4020-$4021 and | | start it. ------+-----+--------------------------------------------------------------- $4024 | W | Data Write Register | | To write data to the disk, output it into this register. ------+-----+--------------------------------------------------------------- $4025 | W | Control Register | 0 | Drive Motor, 0 = on, 1 = off. | 1 | \ = Set drive head to the start of the first track. | 2 | Disk Write, 0 = enabled, 1 = disabled. | 3 | Screen Mirroring, 0 = vertical, 1 = horizontal. | 4-6 | Unknown (???) | 7 | Disk IRQs, 0 = disabled, 1 = enabled. ------+-----+--------------------------------------------------------------- $4026 | W | ExPort Output (???) ------+-----+--------------------------------------------------------------- $4030 | R | Disk Status Register 0 | 4 | Unknown (???) | 6 | Unknown (???) ------+-----+--------------------------------------------------------------- $4031 | R | Data Read Register | | To read data from the disk, input it from this register. ------+-----+--------------------------------------------------------------- $4032 | R | Disk Status Register 1 | 0 | Disk Presence, 0 = inserted, 1 = not inserted. | 1 | Disk Ready, 0 = ready, 1 = not ready. | 2 | Write Protection, 0 = unprotected, 1 = protected. ------+-----+--------------------------------------------------------------- $4033 | R | ExPort Input | 7 | Battery Status, 0 = ok, 1 = low. ------+-----+---------------------------------------------------------------
[1,2,3,4,3,4,...3,4]
where
------------------------------------------------------ 1. Side Header Block (56 bytes) 0 $01 1-14 "*NINTENDO-HVC*" 15 Maker ID 16-19 Side Name 20 Version Number 21 Side Number $00 = Side A $01 = Side B 22-24 Additional Disk Data 25 $08 26-56 Reserved Space (not used by BIOS) ------------------------------------------------------ 2. File Number Block (2 bytes) 0 $02 1 Number of Files on this side ------------------------------------------------------ 3. File Header Block (16 bytes) 0 $03 1-2 File Number (not used by BIOS?) 3-10 File Name (not used by BIOS?) 11-12 Starting Address in memory 13-14 File Size 15 File Type $00 = Program Data $01 = Character Data $02 = Screen Data ------------------------------------------------------ 4. File Data Block (variable length) 0 $04 1-... Data (see File Header Block for size) ------------------------------------------------------All two-byte fields are written with the most significant byte first. Side names may be different for different sides of the same game floppy, but they are usually the same. Starting addresses are actual addresses in RAM or VRAM where files are loaded.
READ: $4025| A | B | C | D || E | A) Initialization 7bit |___|______|___|---||------___| B) Motor on 6bit |___|______|---|---||------___| C) Read start mark 5bit |---|------|---|---||---------| D) Enable IRQs 4bit |___|______|___|___||___---___| E) Read end mark 2bit |---|------|---|---||---------| 1. Read data, ($4030)=[xx0xxxxx] 1bit |---|---___|___|___||_________| 2. Read data, ($4030)=[xxx0xxxx] 0bit |___|------|---|---||------___| Note | | | | || 1 2 | WRITE: $4025| A | B | C | D || E | A) Initialization 7bit |___|______|______|---||------___| B) Motor on 6bit |___|______|___---|---||------___| C) Write start mark 5bit |---|------|------|---||---------| D) Enable IRQs 4bit |___|______|______|___||___---___| E) Write end mark 2bit |---|------|______|___||______---| 1. Delay, write [00000000] 1bit |---|---___|______|___||_________| 2. Write [10000000] 0bit |___|------|------|---||------___| 3. Write data, ($4030)=[xx0xxxxx] Note | | | 1 | 2 || 3 4 | 4. DelayIt is not clear from the diagrams how actual reading and writing is done. It is quite clear though that FDS generates an IRQ every time a byte is read from the disk. FDS IRQ handler (which is a part of the FDS BIOS) reads this byte from $4031 while the head is advanced to the next byte.
ERR.01 No disk ERR.02 No power ERR.03 Broken prong on the disk ERR.04 Wrong maker ID ERR.05 Wrong game name ERR.06 Wrong game version ERR.07 Wrong side number (flip the disk) ERR.08 Wrong disk #1 ERR.09 Wrong disk #2 ERR.10 Wrong disk #3 ERR.20 Allows it to recognize screen data differs (???) ERR.21 Wrong Side Header Block ("*NINTENDO-HVC*") ERR.22 Wrong Side Header Block ID ($01) ERR.23 Wrong File Number Block ID ($02) ERR.24 Wrong File Header Block ID ($03) ERR.25 Wrong File Data Block ID ($04) ERR.26 Error writing data to the disk ERR.27 Block ends prematurely ERR.28 The disk unit and the same period can't take it (???) ERR.29 The disk unit and the same period can't take it (???) ERR.30 Disk full ERR.31 Data number of a disk doesn't match up (???)
Byte Contents --------------------------------------------------------------------------- 0-3 String "NES^Z" used to recognize .NES files. 4 Number of 16kB ROM banks. 5 Number of 8kB VROM banks. 6 bit 0 1 for vertical mirroring, 0 for horizontal mirroring bit 1 1 for battery-backed RAM at $6000-$7FFF bit 2 1 for a 512-byte trainer at $7000-$71FF bit 3 1 for a four-screen VRAM layout bit 4-7 Four lower bits of ROM Mapper Type. 7 bit 0-3 Reserved, must be zeroes! bit 4-7 Four higher bits of ROM Mapper Type. 8-15 Reserved, must be zeroes! 16-... ROM banks, in ascending order. If a trainer is present, its 512 bytes precede the ROM bank contents. ...-EOF VROM banks, in ascending order. ---------------------------------------------------------------------------Note that this format will most likely expand in future, therefore do not take it for something permanent. All new additions are guaranteed to be compatible with the older versions of a format though.
The 8 bits allocated for the mapper number give us a total of 256 possible mapper types. If you happen to find a new type of a memory mapper, please, email me its description and several sample ROMs and I will allocate and announce a new number for it. Do not pick the number yourself, as this will cause a general mess.
Following is a table of assigned mapper types. The ones with the "-"
sign are not currently supported by iNES in a
proper way.
Mapper# Name Examples
---------------------------------------------------------------------------
0 No mapper All 32kB ROM + 8kB VROM games
1 Nintendo MMC1 Megaman2, Bomberman2, etc.
2 Simple ROM switch Castlevania, LifeForce, many games
hacked for use with FFE copier
3 Simple VROM switch QBert, PipeDream, Cybernoid, many
Japanese games
4 Nintendo MMC3 SilverSurfer, SuperContra, Immortal, etc.
5 Nintendo MMC5 Castlevania3
6 FFE F4xxx F4xxx games off FFE CDROM
7 32kB ROM switch WizardsAndWarriors, Solstice, etc.
8 FFE F3xxx F3xxx games off FFE CDROM
9 - Nintendo MMC2 Punchout
10 Nintendo MMC4 Punchout2
11 ColorDreams chip CrystalMines, TaginDragon, etc.
12 - FFE F6xxx F6xxx games off FFE CDROM
15 100-in-1 switch 100-in-1 cartridge
16 Bandai chip Japanese DragonBallZ series, etc.
17 FFE F8xxx F8xxx games off FFE CDROM
18 Jaleco SS8806 chip Japanese Baseball3, etc.
19 Namcot 106 chip Japanese GhostHouse2, Baseball90, etc.
20 Nintendo DiskSystem Reserved. Don't use this mapper!
21 Konami VRC4 Japanese WaiWaiWorld2, etc.
22 Konami VRC2 (a) Japanese TwinBee3
23 Konami VRC2 (b) Japanese WaiWaiWorld, MoonWindLegend, etc.
24 - Konami VRC6 ???
32 Irem G-101 chip Japanese ImageFight, etc.
33 Taito TC0190/TC0350 Japanese PowerBlazer
34 32kB ROM switch ImpossibleMission2 and DeadlyTowers
---------------------------------------------------------------------------