User:Tepples/Multi-discrete mapper

From Nesdev wiki
Jump to: navigation, search

The Action 53 mapper allows making a multicart of games that use multiple discrete mappers. As a random sample, it'd support 1943: The Battle of Midway/Valhalla (UNROM), 3-D Battles of Worldrunner (UNROM), Battle City (NROM-128), Battle Kid: Fortress of Peril (UOROM), Battle Tank (CNROM), Battleship (CNROM), Battletoads (AOROM), and Gekitotsu Yonku Battle (UNROM). iNES Mapper 028 has been assigned.


Register select
Register value

$5000: Register select

7654 3210
S       R
|       +- Select register
+--------- 0: User registers; 1: Supervisor registers

In a multicart, registers $00 and $01 change the bank within a game, and registers $80 and $81 remain constant throughout a given game's execution. Some games ported from SGROM may rewrite register $80, usually to change mirroring.

$00: CHR bank

7654 3210
   M   BB
   |   ++- Set CHR RAM A14-A13
   +------ Set CIRAM A10 if H/V mirroring is disabled

$01: Inner bank

7654 3210
   | ++++- Set current PRG ROM bank
   +------ Set CIRAM A10 if H/V mirroring is disabled

If the current mirroring mode is one of the 1-screen modes (0 or 1), writes to registers $00 and $01 change bit 0 of the mirroring mode to D4 of the written value. (This simulates the mirroring control of AxROM.) If the current mirroring mode is vertical or horizontal (2 or 3), D4 is ignored.

$80: Mode

7654 3210
  || ||++- Nametable mirroring mode
  || ++--- PRG bank mode
  ++------ PRG outer bank size
Mirroring modes
Mode Effect Effect of write to register $00 or $01
0 1-screen lower bank D4 changes bit 0 of the mirroring mode
1 1-screen upper bank D4 changes bit 0 of the mirroring mode
2 Vertical D4 is ignored
3 Horizontal D4 is ignored

While the mirroring mode is 0 or 1 (1-screen), bit 0 is accessible in three places: bit 0 of $80, bit 4 of $00, or bit 4 of $01.

Logic table, with o = $81 value and i = $01 value
PRG bank mode
Mode Simulates Effect
0, 1 BNROM/AOROM Current 32 KiB bank in $8000-$FFFF
2 UNROM (#180) Fixed bottom half of outer bank in $8000-$BFFF
Current bank in $C000-$FFFF
3 UNROM (#2) Current bank in $8000-$BFFF
Fixed top half of outer bank in $C000-$FFFF

When the fixed bank ($8000-$BFFF in mode 2 or $C000-$FFFF in mode 3) is accessed, it treats accesses to the fixed bank the same way as accesses in mode 0 with 32K: the outer bank bits are passed straight through. For example, this would allow the fixed $C000 bank in mode 3 128K to be set to 16K bank 7 (as in mapper 2) or 1, 3, or 5. In mode 2 128K, the fixed $8000 bank could be configured as 16K bank 0 (as in mapper 180) or 2, 4, or 6.

PRG outer bank size
Size Effect
0 A20-A15 controlled by outer bank (32 KiB)
1 A20-A16 controlled by outer bank (64 KiB)
2 A20-A17 controlled by outer bank (128 KiB)
3 A20-A18 controlled by outer bank (256 KiB)

Again, when a fixed bank is being accessed, this is temporarily forced to 32K, allowing all outer bank bits to come through.

These are the outputs on A20-A14 in each of the 12 combinations of mode and size, with o used for outer bank bits and i used for inner bank bits:

Mode value PRG bank mode Outer bank size Bank in $8000 Bank in $C000
$00-$07 32 KiB 32 KiB oooooo0 oooooo1
$08-$0B Fixed $8000 32 KiB oooooo0 ooooooi
$0C-$0F Fixed $C000 32 KiB ooooooi oooooo1
$10-$17 32 KiB 64 KiB oooooi0 oooooi1
$18-$1B Fixed $8000 64 KiB oooooo0 oooooii
$1C-$1F Fixed $C000 64 KiB oooooii oooooo1
$20-$27 32 KiB 128 KiB ooooii0 ooooii1
$28-$2B Fixed $8000 128 KiB oooooo0 ooooiii
$2C-$2F Fixed $C000 128 KiB ooooiii oooooo1
$30-$37 32 KiB 256 KiB oooiii0 oooiii1
$38-$3B Fixed $8000 256 KiB oooooo0 oooiiii
$3C-$3F Fixed $C000 256 KiB oooiiii oooooo1

For all of these cases, the "o"s come from the topmost outer bank bits and the "i"s come from the bottommost inner bank bits.

$81: Outer bank

7654 3210
  ++-++++- Set outer PRG ROM bank

Only 6 bits are defined currently for two reasons: parallel flash memory pricing and the practical limit of 2 MiB in an iNES ROM image. In fact, the PowerPak uses only the low 4 bits, as it has only 512 KiB of RAM for PRG ROM. Once emulators support NES 2.0 large ROMs, an implementation may add bits 6 and 7 to this register, resulting in an oversize extension to 8 MiB.

When the outer bank size is set greater than 32K, the bank number is not barrel shifted. Instead, the least significant bits are ignored. Bits 5 through 3, for example, always control PRG ROM A20 through A18.

Power up state

At power on, the last 16 KiB of the ROM is mapped into $C000-$FFFF. The rest of the state is unspecified. The mapper state is unchanged on reset.

Non-normative: One possible init sequence involves setting reg $81 = $FF and reg $80 = $02 to get into oversize-BNROM mode.

Non-normative: If desired, games in a multicart can be patched with an appropriate reset stub to allow returning to the menu. The Action 53 build tool does this semi-automatically for NROM games.


NROM-128 (#0)
Outer bank size 0, PRG mode 2 or 3, mirroring H or V, select $01
NROM-256 (#0)
Outer bank size 0, PRG mode 0, mirroring H or V, select $01
CNROM (#3)
Outer bank size 0, PRG mode 0, mirroring H or V, select $00
BNROM (#34)
Outer bank size 1-3, PRG mode 0, mirroring H or V, select $01
BNROM oversize (#34 as emulated)
Outer bank size 0, PRG mode 0, mirroring H or V, select $81, and modify bus-conflict-avoidance table for position within multicart
UNROM (common) (#2)
Outer bank size 1-3, PRG mode 3, mirroring H or V, select $01
UNROM (Crazy Climber and MGC 2011) (#180)
Outer bank size 1-3, PRG mode 2, mirroring H or V, select $01
AOROM (#7)
Outer bank size 1-3, PRG mode 0, mirroring 1-screen, select $01

Reference implementations

See /Reference implementations for functions in Python and 6502 assembly language that calculate the bank number output to PRG ROM A20-A14 as described above. These may be used to verify emulator or hardware implementations.

Hardware implementations

Two implementations in Verilog are designed for use on a CPLD. One has been tested on a PowerPak as MAP1C.MAP.

The MiST FPGA computer includes an implementation in Verilog.

Implementation notes

Input pins: 2 power, 16 signal

  • Power and ground
  • CPU D7, D5-D0 (D6 used only in 4-8 MB version)
  • CPU A14-A12, /PRGSEL, M2, R/W
  • PPU A12-A10

Output pins: 12 signal

  • CHR RAM A14-A13
  • CIRAM A10
  • PRG ROM A20-A14, /CE
  • Optional PRG RAM enable ($6000-$7FFF)

A CPLD requires one macrocell per bit of state and one for each output pin controlled by a multiplexer, plus possibly a couple more for more complex operations. When configured for PRG ROM up to 2 MB, this mapper requires 20 bits of state and 7 multiplexed outputs, which fits comfortably in a 32- or 36-cell CPLD.

  • Register select: 2 bits
  • Register $00: 2 bits (D4 is directed to register $80)
  • Register $01: 4 bits (D4 is directed to register $80)
  • Register $80: 6 bits
  • Register $81: 6 bits
  • A17-A14: 4 multiplexed outputs
  • CIRAM A10: 1 multiplexed output
  • PRG ROM /CE: 1 multiplexed output
  • PRG RAM /CE: 1 multiplexed output

After synthesizing and laying fitting within a XC9536XL CPLD 27/36 Macrocells were consumed (75%). Additionally this design requires 25/34 available pins on the XC9536XL.

Adding WRAM control requires 2 Macrocells and 2 pins.

Lowering to 1 MB by shaving off PRG ROM A20 would save 1 Macrocell and 1 pin, if desired.

External links

  • test28, a comprehensive test ROM