Nintendo header
From NESdev Wiki
Jump to navigationJump to search
About 33% of licensed Nintendo NES games have an header present at their last bank, at addresses $FFE0-$FFF9, right before the interrupt vectors. The FamicomBox reads this header to determine the title of the inserted game.
The info in them is frequently incomplete and/or inaccurate. When info on a particular filed is not present, a byte $00 or $FF is used for padding.
- $FFE0-$FFEF : Name of the game, in ASCII. (sometimes the name is abbreviated or replaced by Nintendo's code). ASCII codes 20h-5Ah allowed. Should be right-justified.
- $FFF0-$FFF1 : PRG checksum (either the last 16k bank, or the whole PRG-ROM). Sum of all bytes in the relevant area, excluding the two checksum bytes. Big-endian.
- $FFF2-$FFF3 : CHR checksum. 0x00 if RAM. Big-endian.
- $FFF4 : Data sizes. Values: 0 = 8 KiB or 64 KiB based on board type, 1 = 16 KiB, 2 = 32 KiB, 3 = 128 KiB, 4 = 256 KiB, 5 = 512 KiB
- D7-D4: PRG size
- D3: 0 = CHR ROM, 1 = CHR RAM
- D2-D0: CHR size
- $FFF5 : Board Type.
- D7: 0 = Horizontal nametable arrangement, 1 = Vertical arrangement (inverse of iNES mirroring bit)
- D6-D0: 0 = NROM, 1 = CNROM, 2 = UNROM/AOROM, 3 = GNROM, 4 = MMC (any). Determines which area to checksum.
- $FFF6 : Title encoding : 0 = No title entered, 1 = ASCII, 2 = Another encoding
- $FFF7 : Valid Title Length - 1. 0 if no title entered.
- $FFF8 : Maker's code, the same used for the FDS, GB, GBC and SNES headers : 1 = Nintendo, 2-254 = everyone else. 255 must be reserved.
- $FFF9 : Header Validation Byte. 8-bit checksum of $FFF2-$FFF9 should = 0
Calculating the checksum
Everynes claims that the FamicomBox system software applies these rules:
- NROM and CNROM
- Sum of $E000-$FFFF, $C000-$FFFF, or $8000-$FFFF. The system software detects the size.
- UNROM/AOROM
- Sum of $8000-$BFFF in banks 0-7.
- GNROM
- Each bank has a header with its own checksum of $8000-$FFFF. All checksums must pass.
- MMC
- Sum of $C000-$FFFF, as if NROM-128. No bank switching is attempted.
A checksum passes if the sum of bytes, minus the bytes at $FFF0 and $FFF1, matches the big-endian value at $FFF0.
Caveats for particular mappers, to be verified:
- UNROM
- The checksum routine avoids bus conflicts by searching ROM for the first byte in $8000-$FFFF whose low bits match the low bits of the bank number, reading that byte, and writing it back. This causes problems with UOROM, as this a write with low nibble as a write intended to set bank 0 may instead set bank 8.
- For a 64 KiB UNROM, such as 240p Test Suite, the checksum routine reads each of the four banks twice. Thus it double-counts most bytes and (net) single-counts the bytes at $FFF0-$FFF1 because they also appear at $BFF0-$BFF1. A ROM will usually need an extra byte somewhere (such as at $FFDF) whose value is chosen to cancel the lower byte of the checksum of the rest of the ROM.
- AxROM and BxROM
- 128 KiB ROM has four banks and thus has a similar double-counting caveat to 64 KiB UNROM. The checksum is in the last bank (bank 3 or bank 7) and, as usual, both bytes are subtracted before comparison despite not having been included in the original sum.
- MMC1
- Sum of $C000-$FFFF at power on, as if NROM-128. No bank switching is attempted. Any 16 KiB bank that can be switched into $C000-$FFFF needs its own header with a checksum of that bank.
- MMC3, most VRCs, FME-7
- Sum of $C000-$FFFF at power on, as if NROM-128. These mappers have a fixed bank at $E000-$FFFF and an unpredictable switchable bank at $C000-$DFFF. In order to get the checksum to match regardless of state, the sum of bytes in all 8 KiB banks other than the last must be identical. Given the overall lack of mapper IRQ support in the FamicomBox, we seek evidence of games on these mappers having been released for FamicomBox at all.