549 lines
24 KiB
Plaintext
549 lines
24 KiB
Plaintext
![]() |
|
||
|
Nintendo Entertainment System Architecture
|
||
|
version 1.4 [09/09/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 John Stiles
|
||
|
Kawasedo Patrick Lesaard Tink
|
||
|
Marcel de Kogel Paul Robson Bas Vijfwinkel
|
||
|
Alex Krasivsky Serge Skorobogatov
|
||
|
|
||
|
The current version of this file is missing some information, such as
|
||
|
sound hardware. 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.
|
||
|
|
||
|
|
||
|
******************************* Contents *******************************
|
||
|
|
||
|
1. General Architecture
|
||
|
2. Interrupts
|
||
|
3. I/O Ports
|
||
|
4. PPU Memory
|
||
|
5. Hit/VBlank Bits
|
||
|
6. Joysticks
|
||
|
7. Sprites
|
||
|
8. Memory Mappers
|
||
|
a) Sequential
|
||
|
b) Konami
|
||
|
c) VROM Switch
|
||
|
d) 5202 Chip
|
||
|
e) Others
|
||
|
9. Sound (to be written)
|
||
|
|
||
|
|
||
|
************************* 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
|
||
|
|
||
|
|
||
|
****************************** 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.
|
||
|
|
||
|
|
||
|
****************************** 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 | Hit Switch, 1 = generate interrupts on Hit (incorrect ???)
|
||
|
| 7 | VBlank Switch, 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 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 | Hit Flag, 1 = PPU refresh has hit sprite #0
|
||
|
| | This flag resets to 0 when VBlank starts, or CPU reads $2002
|
||
|
| | (see "Hit/VBlank Bits").
|
||
|
| 7 | VBlank Flag, 1 = PPU is generating a Vertical Blanking Impulse
|
||
|
| | This flag resets to 0 when VBlank ends, or CPU reads $2002
|
||
|
| | (see "Hit/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
|
||
|
| 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 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 | Joystick 1 + Strobe
|
||
|
| 0 | Joystick 1 data
|
||
|
| 1 | Joystick 1 presence, 0 = connected
|
||
|
| 2-5 | Unused, set to 0 (???)
|
||
|
| 6-7 | Unknown, set to 10 (???)
|
||
|
| | See "Joysticks".
|
||
|
------+-----+---------------------------------------------------------------
|
||
|
$4017 | R | Joystick 2
|
||
|
| 0 | Joystick 2 data
|
||
|
| 1 | Joystick 2 presence, 0 = connected
|
||
|
| 2-5 | Unused, set to 0 (???)
|
||
|
| 6-7 | Unknown, set to 10 (???)
|
||
|
| | See "Joysticks".
|
||
|
------+-----+---------------------------------------------------------------
|
||
|
|
||
|
|
||
|
****************************** 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 32 rows of 32 bytes
|
||
|
each. Tiles are 8x8 pixels each. Therefore, the whole Name Table is 32x32
|
||
|
tiles or 256x256 pixels. In the NTSC version of NES, upper and lower 16
|
||
|
pixels are not shown, thus, the screen becomes 256x224 pixels. In the PAL
|
||
|
version of NES, upper and lower 8 pixels are not show, thus, the screen
|
||
|
becomes 256x240 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.
|
||
|
|
||
|
Each byte in the Attribute Table represents a 4x4 group of tiles on the
|
||
|
screen, which makes an 8x8 attribute table. Each 4x4 tile group is
|
||
|
subdivided into four 2x2 squares as follows:
|
||
|
|
||
|
(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)
|
||
|
|
||
|
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
|
||
|
|
||
|
|
||
|
*************************** Hit/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 Hit flag is contained in the 6th bit of read-only location $2002.
|
||
|
It goes to 1 when PPU starts refreshing the first scanline where sprite#0
|
||
|
is located. For example, if sprite#0's Y coordinate is 34, the Hit flag
|
||
|
will be set in scanline 34. The Hit flag is reset when vertical blanking
|
||
|
impulse starts. The program can reset this bit prematurely by reading from
|
||
|
$2002.
|
||
|
|
||
|
|
||
|
******************************* 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 joysticks' 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
|
||
|
|
||
|
Bit 1 indicates whether joystick is connected to the port or not. It is
|
||
|
set to 0 if the joystick is connected, 1 otherwise. Bits 6 and 7 of
|
||
|
$4016/$4017 also seem to have some significance, which is not clear yet.
|
||
|
The rest of bits is set to zeroes. Some games expect to get *exactly* $41
|
||
|
from $4016/$4017, if a button is pressed, which has to be taken into
|
||
|
account.
|
||
|
|
||
|
|
||
|
******************************* 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.
|
||
|
|
||
|
|
||
|
**************************** Memory Mappers ****************************
|
||
|
|
||
|
There are many diffirent memory mappers (aka MMCs) used in the NES
|
||
|
cartridges. They are used to switch ROM and VROM pages, and do some other
|
||
|
tasks. I will only describe the MMCs I'm familiar with. Any new
|
||
|
information on these and other MMCs is highly appreciated. The MMC
|
||
|
numbers are given in terms of the .NES file field "Mapper Type".
|
||
|
|
||
|
|
||
|
1. Mapper #1, Sequential
|
||
|
|
||
|
This is a sequential mapper used in many 256kB cartridges, such as
|
||
|
Bomberman 2, Destiny Of The Emperor, Megaman 2, Airwolf, Operation Wolf,
|
||
|
Castlevania 2, Silk Worm, Yoshi, Break Thru. It may be used to switch ROM
|
||
|
and VROM. If there is no VROM, 8kB of VRAM is present at $0000. In some
|
||
|
cases (mostly RPG games) such cartridges also contain battery-backed RAM
|
||
|
at $6000-$7FFF. The mapper has four 5bit registers, which are accessed via
|
||
|
following addresses:
|
||
|
|
||
|
Register Address Range Function
|
||
|
---------------------------------------------------------------------------
|
||
|
0 $8000-$9FFF Mirroring and VROM Page Size select
|
||
|
The 0th bit of this register selects the mirroring type (1 for
|
||
|
horizontal, 0 for vertical). The 4th bit selects the size of
|
||
|
VROM pages. When it is 1, two 4kB VROM pages can be switched
|
||
|
independently at $0000 and $1000. Otherwise, there is a single
|
||
|
8kB VROM page at $0000.
|
||
|
|
||
|
1 $A000-$BFFF VROM page select
|
||
|
This register sets either 8kB or 4kB VROM page at $0000,
|
||
|
depending on the page size selected via register 0.
|
||
|
|
||
|
2 $C000-$DFFF Second VROM page select for 4kB pages
|
||
|
If 4kB VROM pages selected via register 0, this register sets
|
||
|
the VROM page at $1000. Otherwise, its value is ignored.
|
||
|
|
||
|
3 $E000-$FFFF ROM page select
|
||
|
This register sets 16kB ROM page at $8000. The page at $C000 is
|
||
|
always hardwired to the last ROM page in the cartridge. The
|
||
|
cartridge starts with page 0 at $8000.
|
||
|
---------------------------------------------------------------------------
|
||
|
|
||
|
In order to write to a mapper register, write $80 into any of the
|
||
|
locations first. This will reset the mapper. Then write the value bit by
|
||
|
bit into an appropriate address range. For example, the following assembly
|
||
|
code will write $0C into register 3:
|
||
|
|
||
|
lda #$80 ; Resetting mapper
|
||
|
sta $8000 ;
|
||
|
lda #$0C ; This is our value
|
||
|
sta $EFD9 ; Writing bit 0
|
||
|
lsr a ; Shifting
|
||
|
sta $EFD9 ; Writing bit 1
|
||
|
lsr a ; Shifting
|
||
|
sta $EFD9 ; Writing bit 2
|
||
|
lsr a ; Shifting
|
||
|
sta $EFD9 ; Writing bit 3
|
||
|
lsr a ; Shifting
|
||
|
sta $EFD9 ; Writing bit 4
|
||
|
|
||
|
|
||
|
2. Mapper #2, Konami
|
||
|
|
||
|
This is a quite simple mapper used in most Konami (Life Force,
|
||
|
Castlevania, Metal Gear) and some other cartridges. It only switches the
|
||
|
ROM. All cartridges with this mapper have 8kB VRAM at $0000 (i.e. no
|
||
|
VROM). The mapper has a single 8bit register which can be written via
|
||
|
locations $8000-$FFFF. It contains a number of 16kB ROM page at $8000.
|
||
|
The page at $C000 is always hardwired to the last ROM page in the
|
||
|
cartridge. The cartridge starts with page 0 at $8000.
|
||
|
|
||
|
There is one more thing to note about this mapper: although any address
|
||
|
in the $8000-$FFFF range can be used to access the mapper, most games
|
||
|
prefer to use the address with the last digit equal to the value they
|
||
|
write out. Thus, $07 can be written to $9FF7, $05 to $9FF5, and so forth.
|
||
|
The reason for this is unknown.
|
||
|
|
||
|
|
||
|
3. Mapper #3, VROM Switch
|
||
|
|
||
|
Mapper #3, also known as a VROM switch, is used in the Goonies series
|
||
|
and many Japanese-only games. It only allows you to switch 8kB pages of
|
||
|
VROM. The ROM is either 16kB or 32kB and is not paged. The mapper has a
|
||
|
single 8bit register which can be written via locations $8000-$FFFF. It
|
||
|
contains a number of 8kB VROM page at $0000.
|
||
|
|
||
|
As with mapper #2, many games use locations with the last digit equal to
|
||
|
the value being written. I do not know why.
|
||
|
|
||
|
|
||
|
4. Mapper #4, 5202 Chip (???)
|
||
|
|
||
|
This mapper (or should I say 'an expansion chip'?) is used in many
|
||
|
recent cartridges, such as Batman Returns, Super Contra, Vindicators,
|
||
|
Silver Surfer, etc. It is an extremely complicated device, which is able
|
||
|
to generate its own interrupts via IRQ line, and has a set of commands to
|
||
|
switch ROM and VROM. VROM pages are 1kB, ROM pages appear to be 8kB. I do
|
||
|
not completely understand how this mapper works, so any information is
|
||
|
appreciated.
|
||
|
|
||
|
The chip is controlled via following locations:
|
||
|
|
||
|
Address Function
|
||
|
---------------------------------------------------------------------------
|
||
|
$8000 A command number (0-7) is written here. Also, write to this
|
||
|
register appears to reset the change made by a write into $E000.
|
||
|
$8001 An value for command is written here.
|
||
|
$A000 The 0th bit controls mirroring (1 = horizontal mirroring).
|
||
|
$A001 Same as $8001 (???)
|
||
|
$C000 Unknown
|
||
|
$C001 Unknown
|
||
|
$E000 The 5th bit appears to swap memory at $8000-$8FFF and
|
||
|
$A000-$AFFF, when set to 1.
|
||
|
$E001 Unknown
|
||
|
---------------------------------------------------------------------------
|
||
|
|
||
|
In order to use the mapper, you should first write a command number
|
||
|
into $8000, and then a value (page number) into $8001. Following commands
|
||
|
exist:
|
||
|
|
||
|
Cmd Function
|
||
|
---------------------------------------------------------------------------
|
||
|
0 Select 2 consequent 1kB VROM pages at $0000. The 0th bit of a value
|
||
|
written into $8001 does not matter, i.e. 5 will always select pages
|
||
|
4 and 5.
|
||
|
1 Select 2 consequent 1kB VROM pages at $0800. The 0th bit of a value
|
||
|
written into $8001 does not matter, i.e. 5 will always select pages
|
||
|
4 and 5.
|
||
|
2 Select a 1kB VROM page at $1000.
|
||
|
3 Select a 1kB VROM page at $1400.
|
||
|
4 Select a 1kB VROM page at $1800.
|
||
|
5 Select a 1kB VROM page at $1C00.
|
||
|
6 Select a 8kB ROM page at $8000. The initial value seems to be 0.
|
||
|
7 Select a 8kB ROM page at $A000. The initial value seems to be 1.
|
||
|
---------------------------------------------------------------------------
|
||
|
|
||
|
Note that the ROM pages at $C000 and $E000 are hardwired to the last
|
||
|
pages of the ROM, and can not be switched (they can be swapped via
|
||
|
$E000 though).
|
||
|
|
||
|
|
||
|
5. Other mappers
|
||
|
|
||
|
There are several other mappers, some of them very sophisticated. iNES
|
||
|
partially supports them, but as this support either doesn't work
|
||
|
correctly, or the mappers are uncommon (such as 100-in-1 cartridge mapper,
|
||
|
I don't cover them here.
|
||
|
|
||
|
|
||
|
******************************** Sound *********************************
|
||
|
|
||
|
To be written.
|
||
|
|
||
|
|
||
|
|
||
|
---------------------
|
||
|
Marat Fayzullin
|