Nintendo Entertainment System Architecture version 1.0 [06/06/1996] by Marat Fayzullin [fms@freeflight.com] WWW: http://www.freeflight.com/fms/ IRC: RST38h The following document describes the workings 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 in no way based on any official Nintendo information and may be incomplete and incorrect in many places. "Nintendo Entertainment System" and "Famicom" are registered trademarks of Nintendo. I would like to thank following people for their help in obtaining this information and writing a NES emulator, as well as the moral support from some of them: (sorted alphabetically) Pascal Felber Pan of Anthrox Marcel de Kogel John Stiles Alex Krasivsky Tink Patrick Lesaard Bas Vijfwinkel The current version of this file is missing some information, such as memory mappers. I will add these parts in later releases. If you have any information on NES, which is not in this manual, feel free to write to fms@freeflight.com. Your help will be appreciated. 0. Contents 1. General Architecture 2. Interrupts 3. I/O Ports 4. PPU Memory 5. HBlank/VBlank Bits 6. Joysticks 7. Sprites 1. General Architecture NES is based on the 6502 CPU, and a custom video controller known as PPU [Picture Processing Unit]. The PPU's video memory is separated from the main CPU memory and can be read/written via special ports. Cartridges may contain both ROM appearing in the main CPU address space at $8000-$FFFF, and VROM or VRAM appearing in the PPU address space at $0000-$1FFF and containing the Pattern Tables (aka Tile Tables). In smaller cartridges, which only have 16kB ROM, it takes place at $C000-$FFFF leaving $8000-$BFFF area unused. Internal NES VRAM is located at addresses $2000-$3FFF in the PPU memory. Some cartridges also have RAM at $6000-$7FFF, which may or may not be battery-backed. CPU Memory Map --------------------------------------- $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 2. Interrupts: NES uses non-maskable interrupts (NMIs) generated by PPU in the end of each frame (so-called VBlank interrupts). Maskable interrupts, or IRQs, can also be generated by circuitry in a cart, but most carts do not generate them. The VBlank interrupts can be enabled/disabled by writing 1/0 into 7th bit of $2000. When a VBlank interrupts occur, CPU pushes return address and the status register on stack, and 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. 3. I/O ports: NES internal I/O ports are mapped into the areas of $2000-$2007 and $4000-$4017. Some ports' usage is unknown or unclear, and any information is appreciated. I/O Ports Map ------+-----+--------------------------------------------------------------- $2000 | RW | PPU Control Register 1 | 0-1 | Name Table to show: | | | | +-----------+-----------+ | | | 2 ($2800) | 3 ($2C00) | | | +-----------+-----------+ | | | 0 ($2000) | 1 ($2400) | | | +-----------+-----------+ | | | | Remember, though, that because of the mirroring, there are | | only 2 real Name Tables, not 4. | 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 | HBlank Switch, 1 = generate HBlank (???) | 7 | VBlank Switch, 1 = generate 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 Switch, 1 = show picture, 0 = blank screen | 4 | Sprites Switch, 1 = show sprites, 0 = hide sprites | 5-7 | Unknown (???) ------+-----+--------------------------------------------------------------- $2002 | R | PPU Status Register | 0-5 | Unknown (???) | 6 | HBlank Flag, 1 = PPU is refreshing a scanline on display | 7 | VBlank Flag, 1 = PPU is generating a Vertical Blanking Impulse | | This flag resets to 0 when VBlank ends, or CPU reads $2002 | | (see "HBlank/VBlank Bits"). ------+-----+--------------------------------------------------------------- $2003 | W | Sprite Memory Address | | Used to set the address in the 256-byte Sprite Memory to be | | accessed via $2004. This address will increment by 1 after | | each access to $2004. The Sprite Memory contains coordinates, | | colors, and other attributes of the sprites (see "Sprites"). ------+-----+--------------------------------------------------------------- $2004 | RW | Sprite Memory Data | | Used to read/write the Sprite Memory. The address is set via | | $2003 and increments after each access. The Sprite Memory | | contains coordinates, colors, and other attributes of the | | sprites (see "Sprites"). ------+-----+--------------------------------------------------------------- $2005 | W | Background Scroll | | 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. The 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, though, that because of the mirroring, there are | | only 2 real Name Tables, not 4. ------+-----+--------------------------------------------------------------- $2006 | | PPU Memory Address | | See "PPU Memory". ------+-----+--------------------------------------------------------------- $2007 | | PPU Memory Data | | See "PPU Memory". ------+-----+--------------------------------------------------------------- $4000-$4013 | Sound Registers (usage unknown) (???) ------+-----+--------------------------------------------------------------- $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 | Usage unknown (???) ------+-----+--------------------------------------------------------------- $4016 | RW | Joystick 1 + Strobe | | See "Joysticks". ------+-----+--------------------------------------------------------------- $4017 | R | Joystick 2 | | See "Joysticks". ------+-----+--------------------------------------------------------------- 4. PPU Memory In a real NES, reading/writing PPU memory should only be attempted during VBlank period. Many smaller ROMs have read-only memory (VROM) for the Pattern Tables. In this case, you won't be able to write into this memory. The $3F00 and $3F10 locations in VRAM mirror each other [i.e. it is the same memory cell] and define the background color of the picture. 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. Then, the address will increment by 1 after each read. Name Table contains tile numbers organized into 25 rows of 32 bytes each. Tiles are 8x8 pixels each. Therefore, the screen is 32x25 tiles (256x240 pixels). In the American version of NES, upper and lower 8 pixels are not shown, therefore, the screen becomes 256x224 pixels. Pattern Table contains tile images in the following format: Character Colors Contents of Pattern Table ...o.... 00010000 00010000 $10 +-> 00000000 $00 ..O.O... 00202000 00000000 $00 | 00101000 $28 .0...0.. 03000300 01000100 $44 | 01000100 $44 O.....O. 20000020 00000000 $00 | 10000010 $82 ooooooo. -> 11111110 11111110 $FE | 00000000 $00 O.....O. 20000020 00000000 $00 | 10000010 $82 0.....0. 30000030 10000010 $82 | 10000010 $82 ........ 00000000 00000000 $00 | 00000000 $00 +---------+ Note that only two bits for each pixel of a character 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. The color attributes are stored in the Attribute Table as 16 rows of 15 bytes. Each byte contains 2-bit attributes for 4 tiles on the screen. After 2-bit values taken from the Pattern Table are appended to the attribute bits for a given position of the screen, we get a 4-bit reference into the Palette Table, from which contains the effective color number. There are two 16-byte Palette Tables: the one at $3F00, used for the picture, and another one at $3F10, containing the sprite palette. The $3F00 and $3F10 locations in VRAM mirror each other [i.e. it is the same memory cell] and define the background color of the picture. There is only enough VRAM for 2 Name Tables and Attribute Tables. Two others are going to be mirrors of the first two, i.e. exact copies of them. Which pages are mirrored depends on the cartridge circuitry. With vertical mirroring, tables 2 and 3 are the mirrors of pages 0 and 1 appropriately. With horizontal mirroring, pages 1 and 3 are the mirrors of pages 0 and 2 appropriately. PPU Memory Map --------------------------------------- $4000 Empty --------------------------------------- $3F20 Sprite Palette --------------------------------------- $3F10 Image Palette --------------------------------------- $3F00 Empty --------------------------------------- $3000 Attribute Table 3 --------------------------------------- $2FC0 Name Table 3 (32x25 tiles) --------------------------------------- $2C00 Attribute Table 2 --------------------------------------- $2BC0 Name Table 2 (32x25 tiles) --------------------------------------- $2800 Attribute Table 1 --------------------------------------- $27C0 Name Table 1 (32x25 tiles) --------------------------------------- $2400 Attribute Table 0 --------------------------------------- $23C0 Name Table 0 (32x25 tiles) --------------------------------------- $2000 Pattern Table 1 (256x2x8, may be VROM) --------------------------------------- $1000 Pattern Table 0 (256x2x8, may be VROM) --------------------------------------- $0000 5. HBlank/VBlank Bits: The VBlank flag is contained in the 7th bit of read-only location $2002. It indicates whether PPU is scanning the screen, or generating a vertical blanking impulse. It is set in the end of each frame (scanline 232), and stays on until the next screen refresh starts from the scanline 8. The program can reset this bit prematurely by reading from $2002. The HBlank flag is contained in the 6th bit of read-only location $2002. It is reset in the beginning of each scanline, when PPU starts to fetch the image data from its memory, and goes to 1 when PPU finishes fetching data. The HBlank flag is also set to 1 during the vertical blanking impulse, i.e. when VBlank is high, but reading from $2002 will not affect the HBlank flag. 6. Joysticks: There are two joysticks which are accessed via locations $4016 and $4017. To reset joysticks, write first 1, then 0 into $4016. This way, you will generate a strobe in the joystick circuitry. Then, read either from $4016 [for joystick 0] or from $4017 [for joystick 1]. Each read will give you the status of a single button in the 0th bit [1 if pressed, 0 otherwise]: Read # | 1 2 3 4 5 6 7 8 -------+--------------------------------------------------------- Button | A B SELECT START UP DOWN LEFT RIGHT Bits 6 and 7 of $4016/$4017 also seem to have some significance, which is not clear yet. 7. Sprites: There are 64 sprites, which can be either 8x8 or 8x16 pixels. Sprites patterns are stored in on of the Pattern Tables in the PPU Memory. Sprite attributes are stored in the Sprite Memory of 256 bytes, which is not a part of neither CPU nor PPU address space. The entire contents of Sprite Memory can be written via DMA transfer using location $4014 [see above]. Sprite Memory can also be accessed byte-by-byte by putting the starting address into $2003 and then writing/reading $2004 [the address will be incremented after each access]. The format of sprite attributes is as follows: 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 corner Sprite patterns are fetched in the exactly same way as the tile patterns for the background picture. The only difference occurs in the 16x8 sprites: the top half of the sprite is taken from the Sprite Pattern Table set in the $2000 port, while the bottom part is taken from the same location of the alternative Pattern Table. Therefore, if PPU is displaying a 16x8 sprite, and the Sprite Pattern Table is set to $1000, the bottom half of this sprite will be taken out of the $0000 Pattern Table, and vice versa. --------------------- Marat Fayzullin