Wiki: USF Format Specification

Revision as of 16:50, 18 January 2010 by Djpretzel (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Mirror of http://hcs64.com/usf/usf.txt.

USF specification v1.2
9/19/04 - v1.0 - First official version
10/10/04 - v1.1 - Removed bug tags, added _enablecompare tag
1/14/06 - v1.2 - added _enableFIFOfull tag

--- Structure of a USF file

A USF file may contain an N64 save state and/or ROM image. The structure is that
of a PSF file with version code 0x21. The save state and ROM are stored in the
reserved area of the PSF file. The compressed program section is not used, thus
the program size and CRC should both be zero.
The organization of the reserved area is:

SR64 ROM image (stored as little endian 4 byte words) or 4 zero bytes (signifying no ROM)
  then
SR64 Project 64 v1.4 save state (format below) or 4 zero bytes (signifying no save state)

--- Definition of SR64 Format

SR64 is a sparse storage scheme. Instead of storing an entire file SR64 makes
it possible to store only those parts which are important. USF uses this format
to store the ROM and save state.

SR64 format is:
4 byte identifier: "SR64"
each chunk:
4 byte little endian chunk length n (if 0 this ends the sparse segment)
4 byte little endian chunk offset
n bytes data

--- Loading a USF or USFlib/miniUSF

1. initialize the ROM and save state to zero.
2. if the USF contains a _lib tag (_libn not supported as of this version)
recursively load the specified file starting from step 2
3. load the ROM and save state, replacing any data with the same addresses that
may have already been loaded

By convention a file that includes a _lib tag is named with a .miniusf extension
and a file that is included via a _lib tag is name with a .usflib extension.

--- Definition of Project 64 v1.4 save state

(DWORD is 4-byte little endian, _int64 is 8-byte little endian)
0x000: DWORD: 0x23D8A6C8, identifier
0x004: DWORD: RDRAM size in bytes
0x008: ROM header, first 0x40 bytes of ROM stored as DWORDs
0x048: DWORD: VI timer (PJ64 internal)
0x04c: DWORD: PC
0x050: 32 _int64: CPU General Purposes Registers
0x150: 32 _int64: Floating Point Registers
0x250: 32 DWORD: COP0 Registers
0x2d0: 32 DWORD: Floating Point Control Registers
0x350: _int64: HI
0x358: _int64: LO
0x360: 10 DWORD: RDRAM Registers
0x388: 10 DWORD: SP Registers
0x3b0: 10 DWORD: DP Registers
0x3d8: 4 DWORD: MI Registers
0x3e8: 14 DWORD: VI Registers
0x420: 6 DWORD: AI Registers
0x438: 13 DWORD: PI Registers
0x46c: 8 DWORD: RI Registers
0x48c: 4 DWORD: SI Registers
0x49c: 32 TLB entries (20 bytes each), see PJ64 source for format
0x71c: PIF RAM, 0x40 bytes stored as DWORDs
0x75c: RDRAM, stored as DWORDs, whatever size specified by 0x004.
0x75c+RDRAM size: 0x1000 bytes RSP DMEM, stored as DWORDs
0x175c+RDRAM size: 0x1000 bytes RSP IMEM, stored as DWORDs

Most of these values are relatively straightforward and would be a component of
any N64 emulator.

--- _enablecompare tag

A MIPS processor has an exception triggered when the Count register equals the
Compare register. The Count register is always incrementing, and many games that
don't even need this register leave it enabled anyway. This causes a slight
problem with USFs, because it is possible that this exception will not be
triggered during the logging of the USF. This results in USFs that crash many
minutes into the track when the exception handler is not found. The initial
solution was to disable this exception in 64th Note, but it has since been
discovered that several games do require this exception for sound generation.
In order to preserve compatibility with the old sets this exception is disabled
by default. It can be enabled by including the _enablecompare tag in the
affected miniUSF or USFlib (which will affect the entire set). Note that the
value of the tag is unimportant, it can be _enablecompare=1,
_enablecompare=true, or _enablecompare=false if you want to be confusing.
This feature was introduced in 64th Note v0.06.

--- _enableFIFOfull tag

The FIFO full flag in the AI status register is set when a buffer has been sent and
cleared when it is done playing. Some games rely on this behavior, and expect the
playback to take a real number of cycles. Initially 64th Note never set the FIFO
full flag, but once a game was encountered that needed it this feature was added
and it broke some games, so it must be enabled by the individual game.
Without this tag 64th Note never sets the FIFO full flag. If this tag is found
(regardless of its value, as with _enablecompare) the flag will be set for
approximately the playback time of the buffer.
This feature was introduced in 64th Note v1.0 beta 23.

Promotion

Latest Albums

Latest ReMixes

Navigation

  • This page was last edited on 18 January 2010, at 16:50.