ROM header

From SNESdev Wiki
Jump to navigationJump to search

Nintendo required SNES developers to include a header in the game's data that describes what hardware the game cartridge contains. Emulators and flashcarts rely on this header to know how to emulate the game. Therefore, homebrew games also need to provide a header. lorom-template contains an example of how to set one up.

The header is located at the CPU address range $00FFC0-$00FFDF, right before the interrupt vectors, with an optional second header at $00FFB0-$00FFBF. This means that the location of the header within the actual ROM file will change based on the cartridge's memory map - with LoROM games placing it at $007Fxx, HiROM games placing it at $00FFxx, and ExHiROM games placing it at $40FFxx. Therefore, if it's correctly filled out, an emulator will have a higher chance of being able to figure out where the header is.

Things that increase an emulator's confidence include the checksum and checksum compliment adding up to $FFFF, the memory map value being correct for the header location, and the ROM and RAM size being reasonable values. If the first instruction in the reset routine is SEI then that increases confidence even further. At least one flash cart actually checks to see if the checksum is correct, so it's recommended to set a correct checksum.

Cartridge header

Header contents
First address Length Contents
FFC0 21 Cartridge title (21 bytes uppercase ASCII. Unused bytes should be spaces.)
FFD5 1 ROM speed and memory map (LoROM/HiROM/ExHiROM)
FFD6 1 Chipset (Indicates if a cartridge contains extra RAM, a battery, and/or a coprocessor)
FFD7 1 ROM size: 1<<N kilobytes, rounded up (so 8=256KB, 12=4096KB and so on)
FFD8 1 RAM size: 1<<N kilobytes (so 1=2KB, 5=32KB, and so on)
FFD9 1 Country (Implies NTSC/PAL)
FFDA 1 Developer ID
FFDB 1 ROM version (0 = first)
FFDC 2 Checksum
FFDE 2 Checksum compliment (Checksum ^ $FFFF)
FFE0 4 Unused
FFE4 2 COP vector (65C816 mode) (COP opcode)
FFE6 2 BRK vector (65C816 mode) (BRK opcode)
FFE8 2 ABORT vector (65C816 mode) (not used in SNES)
FFEA 2 NMI vector (65C816 mode) (SNES V-Blank Interrupt)
FFEC 2 Unused
FFEE 2 IRQ vector (65C816 mode) (SNES H/V-Timer or External Interrupt)
FFF0 4 Unused
FFF4 2 COP vector (6502 mode)
FFF6 2 Unused
FFF8 2 ABORT vector (6502 mode) (not used in SNES)
FFFA 2 NMI vector (6502 mode)
FFFC 2 RESET vector (6502 mode) (CPU is always in 6502 mode on RESET)
FFFE 2 IRQ/BRK vector (6502 mode)

$FFD5

Address $00FFD5 indicates the ROM speed and map mode.

001smmmm
   |++++- Map mode
   +----- Speed: 0=Slow, 1=Fast

Available modes include:

$FFD6

Address $00FFD6 indicates what extra hardware is in the cartridge, if any.

Possible values include:

  • $00 - ROM only
  • $01 - ROM + RAM
  • $02 - ROM + RAM + battery
  • $x3 - ROM + coprocessor
  • $x4 - ROM + coprocessor + RAM
  • $x5 - ROM + coprocessor + RAM + battery
  • $x6 - ROM + coprocessor + battery
  • $0x - Coprocessor is DSP (DSP-1, 2, 3 or 4)
  • $1x - Coprocessor is GSU (SuperFX)
  • $2x - Coprocessor is OBC1
  • $3x - Coprocessor is SA-1
  • $4x - Coprocessor is S-DD1
  • $5x - Coprocessor is S-RTC
  • $Ex - Coprocessor is Other (Super Game Boy/Satellaview)
  • $Fx - Coprocessor is Custom (specified with $FFBF)

When coprocessor is Custom, $FFBF selects from:

Expanded cartridge header

The expanded header's presence is indicate by putting $33 in $00FFDA, which is the developer ID. Some early games may indicate just $00FFBF by setting $00FFD4 to zero.

Expanded header contents
First address Length Contents
FFB0 2 ASCII maker code
FFB2 4 ASCII game code
FFB6 6 Reserved, should be zero
FFBC 1 Expansion flash size: 1 << N kilobytes
FFBD 1 Expansion RAM size: 1 << N kilobytes - for GSU?
FFBE 1 Special version (usually zero)
FFBF 1 Chipset subtype, used if chipset is $F0-$FF