USB-NES Mapper Overrides

Mapper overrides are a scripting language and system tool built into USB-NES that provides end-users a way to patch in support for new games that otherwise can’t be auto-detected properly by a virgin unit. It also provides a convenient way to experiment with cartridge hardware to potentially develop patches for completely unknown or currently unsupported NES/Famicom boardsets.

This page details the legacy binary override mapper abstracts; the newer text-based scripts are 100% compatible with the documentation here.

Enable the Mapper Override Mode

After updating your USB-NES firmware to version 0.71, In the SETTINGS.TXT file go to the NES_2.0___Enable line and change the value assigned there to 2. Save the file and reset and/or remount the USB-NES drive to the host. In the root directory, this will expose the OVERRIDE.BIN file. Setting values (default_map_index + NES_2.0___Enable – 2) determine the mapper override offset in the file.

Note that you can always revert the USB-NES back to the autodetect mode by resetting the NES_2.0___enable setting back to 0 or 1 and saving the file.

Look in the root directory of USB-NES for SETTINGS.TXT.
Change the NES 2.0 setting to a 2, save it & reset the USB-NES.
OVERRIDE.BIN contains the entire the manual mapper mode interface for USB-NES.

Override Sequence Error Reporting

When the unit is configured to run in the mapper override mode, the DETECT.TXT and/or REPORT.TXT file will either report the override being used by the unit (as it normally does in autodetect mode), or it will report a syntax error indicating the problem with the mapper override abstract code.

Error CodeMeaning
ERR. 0Mapper abstract not found / unknown error
ERR. 1Header signature 1 not found
ERR. 2Header signature 2 not found
ERR. 3PRG-ROM size is set to zero
ERR. 4Bad initialization sequence
ERR. 5Bad power-down sequence
ERR. 6Bad PRG bankswitching sequence
ERR. 7Bad CHR bankswitching sequence
ERR. 8Bad SAV bankswitching sequence
ERR. 9Bad TEST sequence
ERR. 10Mapper abstract exceeds limit of OVERRIDE.TXT/BIN file

The mapper type abstracts have to be defined in a specific format using specific signatures to ensure the overall integrity of the sequence. Moreover, if there is an error, the indexed mapper abstract will be rejected and an error file will be generated. There are 11 possible error types to aid the user in troubleshooting mapper abstract sequences; the following paragraphs fully document the mapper abstracts.

When the selected mapper abstract sequence is valid, a proper ROM.NES file will be created as soon as the USB-NES is plugged in; this does not rely on reading the cartridge in any way to identify boardset parameters. Moreover, the USB-NES will remain in this “fixed” identification mode until the NES_2.0___Enable index value in SETTINGS.TXT changes or is reverted back to the normal autodetection mode. There also are no REPORT.TXT files generated in the manual override mode since this data echos that of OVERRIDE.BIN.

OVERRIDE.BIN File Format

Example of an OVERRIDE.BIN file describing 4 different mapper abstractions:
1. MMC1 with 128KB PRG + 128KB CHR + 8KB SAV file + write enable + write protect.
2. MMC3 with 256 KB PRG + 128 KB CHR.
3. UNROM with bankswitching table located at $FFD0.
4. BTTD Group NES-RED-PILL-02 with 512 KB PRG FLASH + 512 KB CHR FLASH.

Each USB-NES mapper descriptor contains one 32-byte header, and can contain additional 32-byte sequences that describe how bank address bits map to hardware registers specific to mapper bankswitching. Up to eight simultaneous mapper abstracts can be defined in a single OVERRIDE.BIN file composed of 512 bytes.

Mapper Abstracts

A mapper abstract is a method of connecting resources on the NES cartridge to the USB file system to provide a seamless data interface. Based on analyzing NES cart boardset tech for over 30 years, we can see the most essential resource abstracts required to describe nearly any NES/Famicom cartridge boardset:

  • PRG-ROM bank access
  • CHR-ROM bank access
  • SAV-RAM bank access (usually on the PRG side)
  • PRG bankswitching port access
  • CHR bankswitching port access
  • SAV bankswitching port access
  • Power-up policy (like disable write-protect on the SAV-RAM)
  • Shutdown policy (like write protect the SAV-RAM)
  • PRG.BIN flash write abstract file
  • CHR.BIN flash write abstract file

Mapper Header Descriptor Type

This defines the core layout of a single mapper override type, and indicates what related descriptor sequences are expected to follow.

OffsetSizeDescription
0x0016NES 2.0 spec1,7
0x102PRG-ROM bank offset address
0x122CHR-ROM bank offset address
0x142PRG-NVRAM bank offset address5,6
0x162CHR-NVRAM bank offset address5,6
0x181PRG ROM bank address bit count
0x191CHR ROM bank address bit count
0x1A1PRG NVRAM bank address bit count5,6
0x1B1CHR NVRAM bank address bit count5,6
0x1C1Sequence Flags2,8
—- -tsp

p: Mapper power-up sequence present

s: Mapper shutdown sequence present

t: Mapper test sequence present10,11
0x1D1Mode flags
MRB- –CP

P: Create a PRG-ROM FLASH3 abstraction file PRG.BIN

C: Create a CHR-ROM FLASH3 abstraction file CHR.BIN

B: Bankswitch helper flag12,13

R: Redirect9,10 CHR-ROM access to PRG-ROM port

M: MMC1 mode4
0x1E2End-of-descriptor header signature 2
Always CR+LF = 0x0A0D
0x20
1. Every size instance of PRG-ROM, CHR-ROM & NVRAM here that is larger than its corresponding second power functions of bank address bit counts in locations 0x18 – 0x1B, constitutes the expectation of related mapper descriptor sequence abstracts following this one in this exact order.

2. These descriptor sequences follow any PRG, CHR & NVRAM sections.

3. Byte program and sector erase protocol as per the SST39SF040 device.

4. Resets the MMC1 on power-up, and automatically serializes writes of bits D0-4 over D0 when A15=1 and D7=0.

5. USB-NES can only support one source of NVRAM and defaults to PRG-NVRAM in a simultaneous use case.

6. Do not use these parameters to describe any FLASH boardset chips (such as for PRG-ROM). Instead, set bit 0 of location 0x1D to create a write-only programming interface abstract file PRG.BIN in the root directory of USB-NES. Likewise, bit 1 can be set to abstract a theoretical CHR.BIN flash device.

7. Location 0x00 – 0x03 contains header signature 1.

8. Sequence order follows bit ordering here starting from the least significant bit.

9. Some newer NES carts have a large amount of CHR-RAM that emulates CHR-ROM after a boot loader loads the CHR graphics from the PRG-ROM after reset. In these cases, there may not be a currently known iNES or NES 2.0 mapper number to describe the PRG-ROM of this cart in its purely accurate state, but the cart can be functionally described as a simpler mapper type (usually MMC3) if the CHR-ROM is deferred to the PRG-ROM using this redirection flag.

10. With firmware version 0.70 or later.

11. Override test sequences are invoked following the completion of all other internal USB-NES auto-detection tests. These test sequences use equality comparisons statements to reject the mapper override selection in short-circuit evaluation style, otherwise this mapper override is used as default by USB-NES to access cart media

12. When the ROM contents are being read by the host, the bankswitch helper sends a bankswitch command to the boardset after every file sector transfer (512 bytes), as opposed to only when the ROM bank window changes (considerably less often). Some mappers require the constant refreshing of bankswitch registers as a copy-protection means when reading the ROM; this helper mechanism provides timely superfluous writes to the boardset during ROM access to more closely simulate operation as on a real console.

13. With firmware version 0.75 or later.

Mapper Sequence Descriptor Type

Following the mapper override header descriptor, any sequences that need to be defined to describe the bankswitching policy for access to PRG-ROM, CHR-ROM, NVRAM, as well as the INIT and SHUTDOWN abstracts are defined using one or more sequences of this descriptor type.

OffsetSizeDescription
0x001616-bit address map, MSB first2,6
16 alphanumeric text characters
are used to describe the map here.

“0”, “1”: map constant data

“a” … “z”: map a bank address line (bank_sel)5

“A” … “Z”: map a bank address line plus one3,5
0x101Sequence operation

“.” read cartridge operation7

“=” read1 + write-back operation

“?” compare for equality operation4,5,6
0x1188-bit data map, MSB first2
8 alphanumeric text characters
are used to describe the map here.

“-“: use original read data1,5

“0”, “1”: map constant binary data

“a” … “z”: map a bank address line (bank_sel)5,7

“A” … “Z”: map a bank address line inverted4,5,7
0x191Descriptor signature
Always = “.”
0x1A3Sequence write signature
This tag indicates the origin of
the ROM cartridge access.

“PRG”: CPU bus access

“CHR”: PPU bus access (A14-15 ignored)
0x1D1Sequence terminator

” “: another descriptor follows in this sequence

“!”: last descriptor in this abstraction sequence
0x1E2End-of-descriptor signature
Always CR+LF = 0x0A0D
0x20
1. If none of the 8 bits of the data map contain any “-” entries, no read cycle occurs.

2. “a” … “z” represent the bankswitching address lines used to access additional banks in the memory device, where “a” is the LSB line.

3. For carts that use bus-contention boardsets, occasionally it is necessary to add constant data to the bank select address when the bankswitching table in ROM is not 2n boundary-aligned.

4. With firmware version 0.70 or later.

5. Compare for equality will read the address formed by the 16-bit address map, and compare the data returned with the 8-bit data map excluding any bits where a “-” (dash) is present. If alphabet letters are present in the 16-bit address map or 8-bit data map, those letter variables will be iterated with all possible binary combinations once as a built-in looping function of the compare for equality operation. If the compare operation requires multiple compare iterations, they are evaluated short-circuit style and the loop exits early on the first data mismatch.

6. Compare for equality operations have access to a secret memory map located at PRG address range $0000 – $01FF, outlined later in this documentation.

7. When a read sequence is invoked, bank address lines mapped into the 8-bit data map are loaded with read data.

Mapper Footer Descriptor Type

Immediately following all the mapper sequence descriptors for an override, the footer descriptor may be optionally present to provide a name when reporting on the boardset info.

OffsetSizeDescription
0x0016Mapper override name in text
0x1012Reserved (all bytes = ” “)
0x1C2Signature “@!”
0x1E2Signature 0x0A0D
0x20
The footer descriptor is completely optional and merely adds a text-id string for the mapper override.

Secret Test Memory Map

This area contains the internally auto-detected mapper header descriptor type of the inserted cartridge boardset in the first 512 bytes starting @ PRG $0000, and can be used as a way for a mapper override test script to identify carts that are detected by USB-NES incorrectly. There is also access to the IRQ flag, VRAM A10 line, and a series of delay macros that permit the generation of semi-precise delays ranging from 1 uS to up to half a second. The secret test memory map is read-only and can only be accessed with compare for equality descriptor sequences.

PRG Address1SizeDescription
0x000032Mapper Header Descriptor Type

This auto-generated information can
be used by a mapper override test
sequence to help detect an
incorrectly identified boardset
0x0020224Reserved
0x01001IRQ Port
000 000i

i: Boardset IRQ line (cart pin 15)
0x01011NTRAM A10 Port
0000 000n

n: Boardset NTRAM A10 line (pin 22)
0x010214Reserved
0x0110240Time Delay Macros
dddd ssss (low 8 address bits)

dddd: Delay in microseconds (1-15)

ssss: Delay left shift bit count (0-15)

Access to any of these ports invoke
a delay based off the 8-bit address.
Note these macros always return 0.
0x0200
1. Only first 16 addresses avaliable with firmware predating version v0.75.

Custom Descriptor: Mapper 2 – UNROM Type

On the surface, the UNROM type is one of the simplest mapper types to implement. However, because it is a bus contention mapper type, it is necessary to know where a bankswitching table exists in the ROM before you can dump the game so easily.

In the case that the cart ROM data is unknown or cannot be referenced, the first dump of a cart like this will be wrong because you will have to take an educated guess at where the bankswitch table is. In this case, the banks will be mixed up in some way when read out, so you’ll have to manually identify the address of a parallel bankswitch table being used across ROM banks in the first dump, before subsequent reliable dumps can be easily acquired.

In this case, location $FFD0 is commonly used for bankswitching tables in Konami UNROM games from this era, such as with Top Gun and Double Dribble. However, there is no rule or specification whatsoever that says anything about how or where the developers of bus-contention NES software may allocate these kinds of bankswitching tables, or even if at all. A lot of them however, prefer to put bankswitch tables somewhere in the last 256 bytes of the PRG-ROM bank. Moreover, if the mapper sports any fixed PRG-ROM banks like the UNROM does at CPU address rage $C000-$FFFF, then there is a really high probability you will find a bankswitch table in this address range and won’t need to locate parallel tables used across all the banks either.

Developing a mapper abstract to dump unknown NES carts with bus-contention issues can be a difficult challenge. However if you figure out how to read a cart like this, you can share your OVERRIDE.BIN file with the USB-NES community so they may benefit from your work to read the same games much more easily now.

OVERRIDE.BIN with a simple mapper abstract description for UNROM.
Note that as no CHR-ROM is defined in this abstract (location 0x05 = 0), the value for the CHR ROM bank address bit count in location 0x19 is ignored.
OffsetSizeValueDescription
0x0410x08PRG-ROM 16KB chunk count
= 128 KB
0x0610x20Mapper number
= 2
0x1020x8000PRG-ROM bank offset
0x1810x0EPRG-ROM bank address bit count
214 = 16 KB bank size
0x20160xFFDxBankswitch table offset
Effective target address is:
0xFFD0 + (bank_sel & 7)
0x301“=”Indicates a write cycle to be invoked
0x318“——–“Write ROM data unaltered
Data at address is read in, and then
written back unaltered. This is standard
fare for handling all bus-contention
mapper types.
0x3D1“!”End of mapper abstraction sequence
Notable attributes of an UNROM mapper abstract implementation.
Close-up of UNROM override descriptor ASCII values.

Custom Descriptor: Mapper 1 – MMC1 Type

The MMC1 is second most popular mapper used on NES cart boardsets. The pain dealing with the MMC1 comes in its serial data interface; it only accepts one bit at a time and requires both a bus read cycle and write cycle. Moreover, defining an abstract to program one single 5-bit PRG bankswitching register takes 5 descriptor slots (with at least one bit in the data map marked as “-” to force a read cycle between writes). In retrospect, the OVERRIDE.BIN file has a maximum of 15 sequence descriptor slots available, and so this does not leave enough room to do a full-blown MMC1 mapper abstract implementation.

To solve this problem, the mapper descriptor has a flag in bit 7 of location 0x1D that when set, invokes a mode of serializing the data specified in the sequence descriptors so that one descriptor can now do the work that originally took five. Moreover, this automatic serialization only occurs for write cycles with data bit 7 clear to addresses in the $8000-$FFFF CPU (PRG) address range. Now it is possible to define a full-blown MMC1 abstract using only five additional sequence descriptors: a PRG and CHR bankswitch abstract, as well as a MMC1 mode set and NVRAM enable on power-up sequence and write-protect on power down sequence as well.

A full-boardset MMC1 mapper abstract consumes 6 descriptor slots in OVERRIDE.BIN.
OffsetSizeValueDescription
0x0410x08PRG-ROM 16KB chunk count
= 128 KB
0x0510x10CHR-ROM 8KB chunk count
= 128 KB
0x0610x12*Mapper number
= 1
*Battery flag set in D1.
0x0A10x70PRG-NVRAM size
2(7+6) = 8 KB
0x1020x8000PRG-ROM bank offset
0x1220x0000CHR-ROM bank offset
0x1420x6000PRG-NVRAM bank offset address
0x1810x0EPRG-ROM bank address bit count
214 = 16 KB bank size
0x1910x0DCHR-ROM bank address bit count
213 = 8 KB bank size
0x1A10x0DPRG-NVRAM bank address bit count
213 = 8 KB bank size
0x1C10x03*Sequence flags
*INIT sequence present
*SHUTDOWN sequence present
0x1D10x80#Mode flags
#MMC1 mode enabled
Notable attributes of an MMC1 mapper abstract header implementation.
Overview of PRG, CHR, INIT and SHUTDOWN sequences of an MMC1 mapper abstract. Bit 4 in the PRG bankswitch register is used as a SRAM chip disable, and must be cleared on power-up to allow access to the SRAM. Disabling the SRAM on power-down is a precautionary step to avoid the chance of save data corruption. Note that address line “e” is ignored in data bit 5 of the CHR descriptor.
OffsetSizeAddressDataDescription
0x200x200xE000bank_sel & 15PRG bankswitch
abstract
– set PRG bank
@ $8000
0x400x200xA000bank_sel << 1CHR bankswitch
abstract
– set CHR bank
@ $0000
0x600x400x8000
0xE000
0x0C*
0x00#
Power-up abstract
*16 KB PRG-ROM
@ $8000
*8KB CHR-ROM
@ $0000
#Enable SRAM
(D4 = 0)
0xA00x200xE0000x10Shutdown abstract
– Disable SRAM
Detailed attributes of an MMC1 mapper abstract implementation.

Custom Descriptor: Mapper 4- MMC3 Type

The MMC3 is the most common mapper type and is reasonably easy to implement an abstraction for. There are 2 main registers used for bankswitching on the MMC3 and as such, bankswitch abstracts for both ROM types require two descriptors each.

This MMC3 definition is only a basic type for reading PRG & CHR ROMs; it does not define any NVRAM (location 0x0A = 0), nor include any abstracts to enable the SRAM on the boardset.

OVERRIDE.BIN with a basic mapper abstract description for MMC3.
Note that as no PRG-NVRAM is defined in this abstract (location 0x0A = 0), the values for the PRG-NVRAM bank offset address (location 0x14) and address bit count (location 0x1A) are ignored.
OffsetSizeValueDescription
0x0410x10PRG-ROM 16KB chunk count
= 256 KB
0x0510x10CHR-ROM 8KB chunk count
= 128 KB
0x0610x40Mapper number
= 4
0x1020x8000PRG-ROM bank offset
0x1220x0000CHR-ROM bank offset
0x1810x0DPRG-ROM bank address bit count
213 = 8 KB bank size
0x1910x0BCHR-ROM bank address bit count
211 = 2 KB bank size
Notable attributes of an MMC3 mapper abstract header implementation.
Both PRG & CHR-ROM bankswitching abstract implementation for MMC3.
OffsetSizeAddressDataDescription
0x200x400x8000
0x8001
0x26
bank_sel
PRG bankswitch
abstract
– Set 8 KB PRG bank
@ $8000
0x600x400x8000
0x8001
0x20
bank_sel << 1
CHR bankswitch
abstract
– Set 2 KB CHR bank
@ $0000
Detailed attributes of an MMC3 mapper abstract implementation.

Custom Descriptor: Mapper 30 – FLASH Mode

When mapper 30 is configured to be self-flashable, there is no bus contention issue when writing to the mapper port and thus the requirement for a bankswitching table can be omitted in this mapper definition.

The main notes on this mapper are the UNROM-like characteristics it has; that is having a 16 KB swapable bank and a 16 KB fixed bank. The flashing is permitted only to the first swapable bank, and the bankswitch register can be written via the second fixed bank. In this case, this mapper uses bit 0 in the mode flags to create the PRG.BIN write-only abstraction file in the root directory of USB-NES.

Typical implementation of mapper 30 as a simple OVERRIDE.BIN descriptor sequence.
Note that the value in location 0x0A is not checked by USB-NES because the PRG-NVRAM bank address bit count in location 0x1A is set to 0.
OffsetSizeValueDescription
0x0410x20PRG-ROM 16KB chunk count
= 512 KB
0x0610xE2*Lo mapper number
*Battery flag set in D1.
0x0710x10Hi mapper number
(0x10 + 0xE) = 30
0x0A10xD0PRG-NVRAM size
2(13+6) = 512 KB
0x1020x8000PRG-ROM bank offset
0x1810x0EPRG-ROM bank address bit count
214 = 16 KB bank size
0x1D10x01#Mode flags
#Create PRG.BIN FLASH abstraction file
Notable attributes of a mapper 30 abstract header implementation.
Simple 1-line PRG-ROM bankswitching abstract.
OffsetSizeAddressDataDescription
0x200x200xC000bank_sel & 31PRG bankswitch
abstract
– Set 16 KB PRG bank
@ $8000
Detailed attributes of a mapper 30 abstract implementation.

Custom Descriptor: Mapper 111 – GTROM

GTROM is similar to Mapper 30 with few differences. It moves the bankswitch ports outside the PRG ROM address space so the FLASH chip can be allocated as a full 32 KB bank @ $8000-$FFFF. The main advantage of this comes when flashing the PRG: the flash protocol requires the back-to-back manipulation of fifteen address bits on the PRG-FLASH chip, and all 15 of these address bits are mapped directly to the PRG bank. Moreover, it is not necessary to constantly program the bankswitch register in this case and PRG flashing performance is improved as a result.

Typical implementation of mapper 111 as a simple OVERRIDE.BIN descriptor sequence.
Note that the value in location 0x0A is not checked by USB-NES because the PRG-NVRAM bank address bit count in location 0x1A is set to 0.
OffsetSizeValueDescription
0x0410x20PRG-ROM 16KB chunk count
= 512 KB
0x0610xF2*Lo mapper number
*Battery flag set in D1.
0x0710x60Hi mapper number
(0x60 + 0xF) = 111
0x0A10xD0PRG-NVRAM size
2(13+6) = 512 KB
0x1020x8000PRG-ROM bank offset
0x1810x0FPRG-ROM bank address bit count
215 = 32 KB bank size
0x1D10x01#Mode flags
#Create PRG.BIN FLASH abstraction file
Notable attributes of a GTROM mapper abstract header implementation.
Simple 1-line PRG-ROM bankswitching abstract.
OffsetSizeAddressDataDescription
0x200x200x5000bank_sel & 15PRG bankswitch
abstract
– Set 32 KB PRG bank
@ $8000
Detailed attributes of a GTROM abstract implementation.