Skip to content

MPKMeta block format

bryc edited this page Jul 17, 2022 · 29 revisions

MPKEdit supports a block-extension format to store additional metadata in .MPK files, mostly intended for adding user comments to save files, but may be extended in the future. When saving comments to .MPK files, the MPKMeta block is appended to the end of the .MPK.

The current MPKMeta version is 0x00. The format is described below.

This data may be stripped by emulators that aren't aware of its existence (although some emulators I tested leave it alone). It however will be stripped when transferring to a real MPK. It's mostly useful for adding comments to your saves and archiving online somewhere.

In the future it would be great if N64 emulators supported this format directly, to allow automatic note timestamps or in-app commenting. I'm still drafting the timestamp specs, but if you are an emulator author and think keeping track of each note index being written to is plausible for timestamping, please get in touch. :)

MPKMeta block - Revision 0

MPKMeta header

Offset Size Description
0x00 7 MPKMeta magic string
0x07 1 Format version code (Current = 0x00). Return an error for any unsupported version codes, because future versions may not be backwards compatible.
0x08 4 Hash of entire MPKMeta block, with hashfield always zero (using first 32-bit chunk of MurmurHash3_128).
0x0C 3 Unused
0x0F 1 Number of Metadata Entries (1-16)

When comments are present, a 16-byte header is expected to be at the end of a 32 KB .MPK file. A 32-bit hash is calculated from the start of this block, all the way to the end of the file. There is no "end of file" marker for MPKMeta, instead, the data length can be calculated through parsing the individual entries.

0x0F represents the number of Meta entries, a value between 1-16, which correspond to the Note slots. Meta entries are stored immediately after the 16-byte header.

Metadata Entry

Offset Size Description
0x00 1 Entry sanity byte (Result of XORing 0xA5 and offsets 1-4 of Note Entry)
0x01 1 IndexTable offset for specified note
0x02 3 Last 3 bytes of Game Code (eg. 'OPE' of NOPE)
0x05 2 Comment length in bytes (1-4080) (Ideally only use first 12 bits)
0x07 1-4080 Raw UTF-8 text comment data

The Entry sanity byte is computed as follows: It is the XOR sum of 0xA5 with bytes at offset 0x01, 0x02, 0x03 and 0x04 of the current entry. It's essentially a very simple checksum to let the parser know the Metadata Entry is valid. The second byte (offset 0x01) specifies the IndexTable location for the note in question. And bytes 2-4 specify the Note game code and region.

These 4 bytes (offset 0x1 and 0x2) are required for MPKEdit to pair comment data to actual save data in the .MPK file itself. If MPKEdit cannot find the data, the comment is discarded.

Note: The size of the comment cannot exceed 4080 bytes, and only 12 bits are required to store this number. It is possible that the upper 4 bits could be repurposed in a future format version.

Calculating the block length

Firstly, the header is 16 bytes, and stores the number of Meta Entries present. Each Meta entry consists of 7 bytes plus a variable-length comment (no more than 4080 bytes). The length of the comment is conveniently stored in the meta entry. The size of the meta entry (7 bytes) is subject to change if any new features get added, removed, or changed, in a future format revision. So that should be kept in mind when supporting multiple format variants.

Thus the formula for calculating the full block would be: 16 + EntryCount * (7 + commentLength).

One of course has to parse the full entry list to obtain and sum all the individual commentLength values.