YAZ0 (File Format)

From Custom Mario Kart
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

Yaz0 is a run length encoding (RLE compression) method. In Mario Kart Wii most of the SZS files are Yaz0 compressed U8 files. See »File format: U8 archives« for details.



Data structure

Header

The header of a Yaz0 file is always 16 bytes long. All numeric values are stored as big endian.

Offset Type Description
0x00 Char[4] magic. Always Yaz0 in ASCII.
0x04 UInt32 Size in bytes of the uncompressed data.
0x08 UInt32[2] Reserved for special use. Always 0 in Mario Kart Wii.
GNU C example
typedef struct yaz0_header_t
{
    char	magic[4];		// always "Yaz0"
    be32_t	uncompressed_size;	// total size of uncompressed data
    be32_t	reserved[2];		// two unsigned integers reserved for special use
}
__attribute__ ((packed)) yaz0_header_t;

Data Groups

The complete compressed data is organized in data groups. Each data group consists of 1 group header byte and 8 chunks.

N Size Description
1 1 byte the group header byte
8 1-3 bytes 8 chunks

Each bit of the group header corresponds to one chunk:

  • The MSB (most significant bit, 0x80) corresponds to chunk 1
  • The LSB (lowest significant bit, 0x01) corresponds to chunk 8

A set bit (=1) in the group header means, that the chunk is exact 1 byte long. This byte must be copied to the output stream 1:1. A cleared bit (=0) defines, that the chunk is 2 or 3 bytes long interpreted as a backreference to already decompressed data that must be copied.

Size Data Bytes Size Calculation
2 bytes NR RR N = 1..f SIZE = N+2 (=3..0x11)
3 bytes 0R RR NN N = 00..ff SIZE = N+0x12 (=0x12..0x111)
  • RRR is a value between 0x000 and 0xfff. Go back RRR+1 bytes in the output stream to find the start of the data to be copied.
  • SIZE is calculated from N (see above) and declares the number of bytes to be copied.
  • It is important to know, that a chunk may reference itself. For example if RRR=1 (go back 1+1=2) and SIZE=10 the previous 2 bytes are copied 10/2=5 times.

Decoding data groups and chunks is done until the end of the destination data is reached.

Examples

Decompression

GNU C example
const u8 * src      = // pointer to start of source
const u8 * src_end  = // pointer to end of source (last byte +1)
u8 * dest           = // pointer to start of destination
u8 * dest_end       = // pointer to end of destination (last byte +1)

u8  group_head      = 0; // group header byte ...
int group_head_len  = 0; // ... and it's length to manage groups

while ( src < src_end && dest < dest_end )
{
    if (!group_head_len)
    {
	//*** start a new data group and read the group header byte.

        group_head = *src++;
        group_head_len = 8;
    }

    group_head_len--;
    if ( group_head & 0x80 )
    {
        //*** bit in group header byte is set -> copy 1 byte direct

        *dest++ = *src++;
    }
    else
    {
        //*** bit in group header byte is not set -> run length encoding

	// read the first 2 bytes of the chunk
        const u8 b1 = *src++;
        const u8 b2 = *src++;
        
	// calculate the source position
        const u8 * copy_src = dest - (( b1 & 0x0f ) << 8 | b2 ) - 1;

	// calculate the number of bytes to copy.
        int n = b1 >> 4;

        if (!n)
            n = *src++ + 0x12; // N==0 -> read third byte
        else
            n += 2; // add 2 to length
        ASSERT( n >= 3 && n <= 0x111 );

	// a validity check
        if ( copy_src < szs->data || dest + n > dest_end )
            return ERROR("Corrupted data!\n");

	// copy chunk data.
        // don't use memcpy() or memmove() here because
        // they don't work with self referencing chunks.
        while ( n-- > 0 )
            *dest++ = *copy_src++;
    }

    // shift group header byte
    group_head <<= 1;
}

// some assertions to find errors in debugging mode
ASSERT( src <= src_end );
ASSERT( dest <= dest_end );

This code example is taken from Wiimms SZS Tools: SVN repository lib-szs.c line 162

Tools

The following tools can handle compressed U8 files (=SZS files):

Wexos's Toolbox and Wiimms SZS Tools can (de)compress any kind of Yaz0-compressed files. CTools and SZS Modifier can only handle U8 files.