Yaz0 (Compression)
Yaz0 is a RLE compression (run-length encoding). It has been used in lots of games and platforms since its introduction on the Nintendo 64 console. It has been used in games like Mario Kart Wii, Super Mario Odyssey and many more. Note that Yaz0-compressed files are not affected by the endianness of the CPU. All fields will always be stored as big endian.
Header
A Yaz0-compressed file starts with the following header:
Offset | Type | Description |
---|---|---|
0x00 | String | File magic. Always Yaz0 in ASCII. |
0x04 | UInt32 | Size of the uncompressed data in bytes. |
0x08 | UInt32 | Reserved for special use within a game. Super Mario Odyssey uses this field as the file alignment. |
0x0C | UInt32 | Reserved for special use within a game. Only seen as 0. |
Chunks
The data is then stored into different chunks. Each chunk starts with a chunk header, which consist of a Byte. It obviously contains 8 bits, and each bit specifies the mode for one copy command, meaning there will be 8 copy commands per chunk. The MSB bit is the first command, and the LSB bit corresponds to the last command. Chunks are read until the size of the output is the same as specified in the header.
- Direct Copy
If a bit is 1, then one byte is copied directly from the input to the output data.
- Run-length
If a bit is 0, then this group will contain run-length encoded data. In order for this to work, a UInt16 (B) has to be read from the input. The data is copied from the output, at a specific address, to the output. To calculate the address to copy the data from, perform this calculation:
CopyOffset = CurrentOffset - (A & 0xFFF) - 1
Then the number of bytes to copy needs to be calculated. The run-length command supports two different size mode, and first the following calculation is performed:
B = (A >> 12) & 0b1111
If B is zero, then another byte is read. The number of bytes to copy is then calculated by adding 0x12 to the read byte. If B is not zero, then the number of bytes to copy is by adding 2 to B.