What's new

File spec for N64 ROM formats?

janzdott

New member
Hello. I've written an NES emulator, and was able to do so because of the vast amount of information about the NES I was able to find online. All of the hardware details were very well documented, and there is a specification for the ROM file format(sorry it wouldn't let me post a link, google "NES ROM format"). I would like to start working on an N64 emulator. I am well aware that it is not an easy task (probably an order of magnitude more difficult than writing an NES emulator) and I certainly won't finish it, but I'm fine with that. I'm an experienced programmer and I'm no stranger to getting in over my head.

With that said, onto my question... Is there anywhere I can find a file spec for any of the N64 ROM formats? I've looked and looked, and found no information. People created the file formats and people wrote emulators that read them, so the information must be available somewhere. I'm assuming the ROMs have a header and the contents are stored in a file structure or archive inside the ROM. I can't exactly figure this out by looking at dozens of ROMs in a hex editor by hand. Is someone willing to share this information, or at least point me in the right direction?
 

talker

New member
Checkout Maratonman's thread about his emulator (CEN64) and also ask him or maybe zilmar (project 64) if he's online.
 
Disclaimer: I know nothing technical about what I am about to say

I do believe n64 ROMs have headers, the way the header is saved depends on what was used to dump the ROM with though, this is why there are multiple file extensions (.v64, .n64,.z64 maybe more) on most n64 ROMs. The difference is in the endianness, I belive that .v64 is little-endian (Edit: byte swapped), .n64 is middle-endian (Edit: little endian), and .z64 is big-endian.

Edit: Mah sources tell me this:

http://forum.pj64-emu.com/showthread.php?t=2239
 
Last edited:

zoinkity

New member
N64 headers are part of the ROM. There was some idiot on a crusade to remove them and obviously wasn't bright enough to realize this breaks them.
The first 0x40 is the internal header, but you can only rely on the first 0x18 being set. Prototypes don't always set an internal name or ID, as the IDs were provided by Nintendo when accepting them for release. In fact, there's a fairly good chance the protos you see with complete headers were added by the people who clean the dumps so certain HLE emus can run them.

From after the 0x40 header until 0x1000 is the bootstrap, which you'll find is remarkably similar between games. I'll get into that in a minute. Generally the game executable follows, but this isn't mandatory. Otherwise, there's no standard format for N64 data like with NES carts. They can put whatever data they want wherever they want. It's just a big block of free memory.

Depending on how you plan for your emulator to work, you may or may not need to parse the header at all. If you're using a PIFrom, the header will be unpacked without any real effort on your part and the bootstrap will be automatically copied. PIFrom is copied to BFC00000 at boot and the PIF is responsible for forcing the video mode. You're expected to provide a few other values though, which would normally be provided by the CIC chip (and maybe system, not 100% clear on the particulars):
Code:
BFC007E4: device state flags
	00080000	S3: osRomType	(True boots from IPL, not cartridge)
	00040000	S7: osVersion
	00020000	S5: osResetType
	0000FF00	S6: CIC seed value
	000000FF	mirror of CIC seed value, unread
From there, PIFrom automatically passes control to the bootstrap, and this in turn passes control to the main game executable.

If you aren't using PIFrom you'll have to do what it does manually. Firstly, you'll need to copy the bootstrap to A4000040, which you'll recognize as being SP memory. Set S3 = osRomType, S4 = osVideoMode, S5 = osResetType, S6 = CIC seed value, and S7 = osVersion. You'll also have to do the register initialization the PIF usually does, but that's involved enough to make this post a bit messy. Either way, the bootstrap will boot the game as normal.

You can thank Intel for little-endian ROMs. The native format is big-endian, but one common copier switched them around. You can't rely on any file extension to determine endianess. As an example, .n64, which in the previous post was listed as little endian, was the registered extension for N64 ROMs in the Monegi Multi Viewer. It expected them to be big-endian. The N64 is locked into big-endian as far as I can tell, but technically the endianess would be determined by whether the high bit (0x80) of the first or second byte is set.

Despite several popular emulators using the internal region code to determine the region of the game, the N64 never looks at it. Of course, an individual game may, but the system is blind to all header data beyond the first 0x18.
You shouldn't need it for emulation purposes, but this is a slightly amended table of the header, stolen from somebody at Dextrose ages ago. If I knew who it was I'd give them credit, but alas, I do not. Fairly certain Release is not properly subdivided.
Code:
0000h             (1 dword): initial PI_BSD_DOM1 REG settings
	80000000	indicator for endianess
	00F00000	initial PI BSD Domain 1 Release reg
	000F0000	initial PI BSD Domain 1Pages reg
	0000FF00	initial PI BSD Domain 1Pulse Width reg
	000000FF	initial PI BSD Domain 1Latency reg
0004h - 0007h     (1 dword): ClockRate
	FFFFFFF0	ClockRate override
	0000000F
0008h - 000Bh     (1 dword): Program Counter (PC)
000Ch - 000Fh     (1 dword): Release
0010h - 0013h     (1 dword): CRC1
0014h - 0017h     (1 dword): CRC2
0018h - 001Fh    (2 dwords): Unknown (0x0000000000000000)
0020h - 0033h    (20 bytes): Image name
                             Padded with 0x00 or spaces (0x20)
0034h - 0037h     (1 dword): Unknown (0x00000000)
0038h - 003Bh     (1 dword): Media format ('N' for carts, 'D' for disk, 'E' for expandable carts)
003Ch - 003Dh      (1 word): Cartridge ID
003Eh - 003Fh      (1 byte): Country code
003Fh - 0040h      (1 byte): Version (i.e.: 00 = 1.0, 15 = 2.5)
0040h - 0FFFh (1008 dwords): Boot code
 

Top