This page is a mirror of Tepples' nesdev forum mirror (URL TBD).
Last updated on Oct-18-2019 Download

Headers at the end of commercial roms

Headers at the end of commercial roms
by on (#56884)
I've spend the afternoon heavily studying the header hidden in some commecial ROMs to see if I could make a sense out of it.
This header is commonly located at $ffe0 at the end of the last PRG-ROM bank.

- About half of games I've checked actually have such an header
- The header contains the name of the game and some other information
- Not all games that have an header have a complete header. Some only have the name, some only the information, some have incomplete information (with either $00 of $ff filling the gaps).
- Dragon Warrior 3, 4 and Dragon Quest 4 are special : They have headers in all of their 32 PRG banks. The headers of banks 7, 15, 23 and 31 are unique, and all the other banks shares the same header.
- The names can also be shorted, or even be replaced by their Nintendo's code.
- Information found in headers is not always correct. SMB3 and Earthbound prototype has incorrect PRG/CHR size, and SSome Konami games, Castlevania 2, Gradius 2, Contra (J) and maybe more says they have CHR-RAM when in fact they have CHR-ROM.

Name is commonly located at $ffe0-$ffef, but it sometimes starts sooner (Dragon Warrior II), and when less than 16 bytes it can be aligned either left or right and gaps are filled with $00s or $20s.

At $fff0 and $fff1 appear to be some kind of checksums. This is the only bytes that changes between the header in Faxanadu (J), Faxananu (U) and Faxanadu (E) which is what leads me to that conclusion.

$fff2 and $fff3 are most often $00, but not always.

$fff4 seems to indicate the PRG and CHR size of the game. Altough some games from Nintendo (SMB2, SMB3, Startropics 1 and 2) have incorrect info, it would work for all other games I checked.
Code:
$fff4 High nybble = prg size (0=64kb, 2=32kb, 3=128kb, 4=256kb or 512kb, 5=512kb)
$fff4 Low nybble = chr size (0 or 8 = 8kb of RAM, 1=16kb, 2=32kb 3=128kb, 4=256kb)
$fff5 = Mirroring. ($04 = mapper controlled, $02 = hardwired to vertical, $81 or $82 = harwired to horizontal
$fff8 = maker's code, the same used for the FDS, GB, GBC and SNES headers. $01 = Nintendo, $08 = Capcom, etc...

I suspect $fff6 is a version number or something, as it's always $01 (when it's not $ff). Nintendo didn't change the header between the (PRG0) and (PRG1) version of SMB3, but it may be their lazyness - like for SMB2.

$fff2, $fff3, $fff6, $fff7, and $fff9 seems to contain other game-specific info, but I have no idea what it is yet. I'm currently inverstigating it, it seems $fff6 = 04 or 02, and $fff7 = 01 comes most often, no matter the mapper or size of the games.

EDIT : I'm editing this post as I make new discoverings, and I might continue to edit it.
EDIT 2 : About SMB2 being called Zelda, it's fun, but it has the exact same header as zelda, INCLUDING the Reset & IRQ vectors (but it's a different NMI vector, and it's the only difference between both headers).

by on (#56885)
Thanks, that's really interesting. I've noticed the game name aswell in a few ROMs.
To people who have access to the old devkit, does it mention anything about this header?

by on (#56886)
That's pretty cool, I didn't know there was a "header" like that. I wonder why SMB2 has "ZELDA" in its name field? :)

by on (#56893)
thefox wrote:
That's pretty cool, I didn't know there was a "header" like that. I wonder why SMB2 has "ZELDA" in its name field? :)

In one of the videos/interviews someone posted on here from S. Miyamoto [sp] regarding New Super Mario Bros Wii he revealed that Zelda/Mario were originally the same "quest". I think it was in something I read off of the thread where people were discussing the original artwork of Zelda.

by on (#56894)
thefox wrote:
That's pretty cool, I didn't know there was a "header" like that. I wonder why SMB2 has "ZELDA" in its name field? :)

Intelligent Systems started as the team porting games from FDS to NES. The first such games ended up on the SNROM board: Metroid, Kid Icarus, and (yes) The Legend of Zelda. Originally Doki Doki Panic was slated to be ported the same way, but it ended up getting a much bigger expansion as it became SMB2 (U), including a 7-step tile animation, more detailed slot machine graphics, and a new ending. I'm guessing the "ZELDA" came because someone at IS cribbed the project template and various FDS-mapper-hack-support subroutines from LoZ.

by on (#56900)
Well I think I figured out everything I could.
$fff9 seems to contain a completely random number, but in the same series can share this number.
$fff7 also seems completely random to me but it only contains low numbers (the highest I've seen was $10).

It would be great to find how they computed the checksum at $ffff0/1 so it would be possible to see which headers are "valid" and which are "invalid".

by on (#56902)
Anyone has any speculations about the purpose of this header?

by on (#56911)
oRBIT2002 wrote:
Anyone has any speculations about the purpose of this header?

Required for Nintendo Seal of Approval that Nintendo themselves did not police effectively?

by on (#56914)
Is there a breakdown of header vs. no header by copyright year? Perhaps it was done around the introduction of the Super Famicom, which does a lot more with the header.

by on (#56921)
The oldest ROMs always have no header, and the first appeared arround 1987. For later ROMs, there is about 50% of chances that there is a header, and some companies seems to like headers more than others.

by on (#56923)
Among companies that liked headers vs. companies that didn't, which of them were also SNES developers?

by on (#56925)
SNES ROMs, when assembled/submit to Nintendo (usually in EPROM form), most definitely contain an in-ROM header. The format is fully documented. I can provide those details when I get back home.

I wouldn't be surprised if the same applied to NES ROMs back in the day.

by on (#56928)
It seems that the only headers with any real force behind them are the GB/GBC headers.

by on (#56929)
tepples wrote:
Among companies that liked headers vs. companies that didn't, which of them were also SNES developers?

Well Rare and Sunsoft seems to never put headers in their ROMs, for other companies it varies. But headers already appears in 1987 ROMs, before they were made for GB cartridge (1989) or SNES cartridge (1990).

by on (#56942)
I wrote a little tool to go through ROMs and print info about the "header" (maybe it should be called footer instead?). It's not very intelligent (yet), it simply seeks to -32 bytes from the end of the last PRG bank and reads the data and interprets it according to what Bregalad posted in the first message. It also displays some info from iNES header for comparison.

In case anybody is interested I made the output available here:

http://thefox.aspekt.fi/hdrinfos-europe.txt
http://thefox.aspekt.fi/hdrinfos-usa.txt
http://thefox.aspekt.fi/hdrinfos-japan.txt

EDIT #2: cksum endianess is now correct

by on (#56959)
So here's the data for SNES ROMs -- sure, not the same, but might give folks reverse-engineering said NES headers some ideas of what values could be. Note that these are stored in the equivalent of PRG.

Bank $00 (or $C0 if Mode 21 in use):

Code:
$FFC0-FFD4 = Title Registration Area (ASCII, 0x20 for space)
$FFD5      = Mode and ROM Speed
$FFD6      = Cartridge Type
$FFD7      = ROM Size
$FFD8      = RAM Size
$FFD9      = Destination Country Code
$FFDA      = Maker Code
$FFDB      = Mask ROM Version Number
$FFDC-FFDD = Complement Check (order: low, high)
$FFDE-FFDF = Checksum (order: low, high)


And for the possible values for each...

Code:
Mode and ROM Speed
  $20 = Mode 20, standard speed (2.68MHz access cycle)
  $21 = Mode 21, standard speed (2.68MHz access cycle)
  $30 = Mode 20, high speed (3.58MHz access cycle)
  $31 = Mode 21, high speed (3.58MHz access cycle)

Cartridge Type
  $00 = ROM
  $01 = ROM + RAM
  $02 = ROM + Back-up RAM
  $03 = ROM + DSP
  $04 = ROM + DSP + RAM
  $05 = ROM + DSP + Back-up RAM
  (Note: I assume "Back-up RAM" means battery-backed RAM)

ROM Size
  Value "n" of formula 8 * (2^n).  Examples:
  $09 = 4096  = 4mbit
  $0A = 8192  = 5-8mbit
  $0B = 16384 = 9-16mbit

RAM Size
  Value "n" of formula 8 * (2^n), in kilobits.  Examples:
  $00 = RAM not used
  $01 = 16Kbit
  $03 = 64Kbit
  $05 = 256Kbit

Destination Country Code
  $00 = SHVC = Japan
  $01 = SNS  = North America
  $02 = SPAL = Europe, Oceania, Asia
  $03 = SSWE = Sweden
  $04 = SFIN = Finland
  $05 = SDEN = Denmark
  $06 = SFRA = France
  $07 = SHOL = Netherlands
  $08 = SESP = Spain
  $09 = SFRG = Germany, Austria, Switzerland
  $0A = SITA = Italy
  $0B = SCHN = China, Hong Kong
  $0C = SINA = Indonesia
  $0D = SKOR = Korea

Maker Code
  Presumably per-manufacturer code.  No examples given, but
  it's safe to say every manufacturer has their own value.

Mask ROM Version Number
  Version number; start at $00 and increment after each revision
  is submit.

Complement Check
  Calculate the ones-complement of each byte of the checksum
  upper value and lower value (see below).

Checksum
  1. Write $FF for 2 bytes to Complement Check, and $00 for 2 bytes
     to Checksum.
  2. Calculate the checksums of all areas (1/2/4/8...mbit).  Use $FF
     to fill unused areas of the ROM.
  3. Write the value calculated in step 2 to the Checksum section,
     and write each ones-complement value in the upper and lower
     Complement Check section.


I should probably move this post to the SNES forum, but I'll let tepples et al decide what to do with that. :-) HTH!

by on (#56964)
I tried to figure out the checksum stuff ($FFF0/$FFF1 and $FFF2/$FFF3), seems it's very inconsistent like everything else with this header.

In some games, at least "Double Dribble (U) (PRG0) [!].nes", "Dr. Mario (U) (PRG0) [!].nes", "Dragon Fighter (U) [!].nes" checksum seems to be sum of all bytes in the last 16K PRG bank of the ROM (checksum bytes themself should be set to 0 when calculating). In PRG1 revisions of those games the checksum either is incorrect or is calculated differently.

In at least "Times of Lore (U) [!p].nes" and "Isolated Warrior (U) [!].nes" checksum is sum of ALL bytes in the PRG ROM.

In "Duck Tales 2 (U) [!].nes" checksum is sum of all bytes, but the checksum bytes are in little endian order. :roll:

The bytes at $FFF2/$FFF3 are the CHR ROM checksum. It's also simply the sum of all bytes in the CHR ROM.

So all in all, very inconsistent stuff, and hardly useful for anything. But fun nevertheless.

EDIT: In fact the DT2 checksum is in little endian order (lobyte, hibyte), unlike most of the other ones which are big endian (hibyte, lobyte).

by on (#56981)
Oh this is an awesome find !!
I was going to try and do a program that tries to compute the checksum but it seems you beat it to me. I'm not surprised that (PRG1) ROMs have incorrect checksums - likely they kept headers from PRG0 version, at least like they did on SMB3.

I also wonder about how they are calculated in Dragon Warrior games that have an header in each bank. It would make sense it it the sum of the bytes in the bank where the header is placed, but some banks shares an identical header.

by on (#56988)
Bregalad wrote:
Oh this is an awesome find !!
I was going to try and do a program that tries to compute the checksum but it seems you beat it to me. I'm not surprised that (PRG1) ROMs have incorrect checksums - likely they kept headers from PRG0 version, at least like they did on SMB3.

Heh, funnily just noticed right now, in Dr. Mario PRG 0 the checksum is sum of the bytes in the last 16K bank, but in PRG 1 it's the sum of all bytes in the PRG ROM :) Very strange they have been changing that around.

Anyways, I updated the text files that I posted in the earlier message. They now contain also the calculated checksums for comparison.

by on (#57043)
What about improving your program and ignore ROMs that obviously have no header (if all fields are all wrong) that is still the majority of games (sorry it seems I was wrong before sayings 1/2 of games have an header it seems more like 1/4 now, it's just I've checked the good ones).

Sorry for giving you request like that... but it would clear things up.

Also maybe one of the unknown bytes tells how the checksum is calculated ?

by on (#57045)
Bregalad wrote:
What about improving your program and ignore ROMs that obviously have no header (if all fields are all wrong) that is still the majority of games (sorry it seems I was wrong before sayings 1/2 of games have an header it seems more like 1/4 now, it's just I've checked the good ones).

Sorry for giving you request like that... but it would clear things up.

Also maybe one of the unknown bytes tells how the checksum is calculated ?

Hey no problem, I was going to do that anyways at some point. Just need to think of a good way to detect when there's no header.

by on (#57046)
thefox wrote:
Just need to think of a good way to detect when there's no header.

Divide the bytes in the title portion into three categories: ASCII printable ($20-$7E), nulls ($00 and $FF), and everything else. If there are at least twice as many "ASCII printable" as "everything else", assume a header.

by on (#57050)
No...
I've found many games, mostly from Rare and Koei, that have text instead of the header, but it's obviously not a header as the text starts before $ffe0 and ends where there would be the other info instead.

Also most later Capcom tiltles have no "name", but have other info here in the header.

I'm not too sure about it tough - it'd seem hard to tell apart a game with incorrect header from one which have no header at all.

Once thing which is sure is that when all the entiere header is filled with a constant value, it is no header. This should eliminate quite some headerless games.

After that, I think the most reliable way would be to ignore games which have "inconsistant" mirroring byte OR "inconsistant" PRG/CHR sizes (by inconsistant I mean the nybble greater than 5, not incorrect by not being correct, because many headers have it "incorrect") AND which have no ASCII letters in the title.

That way later Capcom games would pass the check as they have "correct" mirroring, PRG & CHR sizes, and Rare/Koei games wouldn't pass because they have both incorrect mirroring and PRG/CHR bytes.

by on (#57051)
I did modify my app to try to ignore invalid headers. It tries to check the name field (it'll give false positive on some Rare games at least). It also checks PRG and CHR checksum. If it detects any of these fields as valid it assumes the header is valid. So it's not foolproof.

Out of the 240 ROMs in "Europe" directory 91 (38%) detected as valid:
http://thefox.aspekt.fi/hdrinfos-europe-valid.txt

Out of the 732 ROMs in "USA" directory 242 (33%) detected as valid
http://thefox.aspekt.fi/hdrinfos-usa-valid.txt

Out of the 1071 ROMs in "Japan" directory 463 (43%) detected as valid
http://thefox.aspekt.fi/hdrinfos-japan-valid.txt

Of course being detected valid doesn't mean that the header is complete and as said there are some false positives in there too. But surprisingly many Japanese titles contain a header of some sort.

EDIT: Found a bug, some ROMs like Spot (J).nes are detected as valid because CHR checksum is 0 in the header and the game uses CHR-RAM. Will fix this later.

EDIT: Here are working links:
https://www.dropbox.com/s/ufl154069isek ... d.txt?dl=0
https://www.dropbox.com/s/1b3u62yk12qrq ... d.txt?dl=0
https://www.dropbox.com/s/7he8dhfd7wun0 ... d.txt?dl=0

by on (#57052)
I think the best way to detected validity would probably be to:

1) check if PRG/CHR checksum is correct, if so mark header as valid
2) if PRG/CHR checksum is $0/$FFFF mark header as valid only if name seems to be valid too

by on (#57060)
I talked to kevtris about this today, and he said the Famicombox (http://kevtris.org/mappers/famicombox/index.html) actually uses the title and checksum from this 'header'. I believe he said the checksum is supposed to be of the last bank, not the whole ROM. That makes sense now that I think about it, as it would make for a nice automated sanity/bad connection check. Considering the Famicombox has what, 16 cart slots? One would get a headrush from blowing all those out, heheh.

by on (#57068)
Memblers wrote:
Considering the Famicombox has what, 16 cart slots? One would get a headrush from blowing all those out, heheh.

Which is why Nintendo produced an official cleaning kit for 72-pin connectors.