Yaz0 compression is reportedly used in quite a few Nintendo datafiles.
I have seen it in SuperMario Sunshine's .szs files for example, and
I heard that it is used in Windwaker and Majoras Mask as well.
The first 16 bytes of a Yaz0-compressed data block are the data header.
The first 4 bytes of the header are 'Y', 'a', 'z', '0', so you can
easily see in your hex editor that there's a Yaz0 block waiting for
you :-) The second 4 bytes are a single uint32 (big-endian of course)
that tells you the size of the decompressed data, so you know how
large your working buffer has to be. The next 8 bytes are always zero.
Next comes the actual compressed data. Yaz0 is some kind of RLE compression.
You decode it as follows: First you read a "code"
byte that tells you for the next 8 "read operations"
what you have to do. Each bit of the "code" byte
represents one "read operation" (from left to right,
that is, 0x80 first, 0x01 last). If the bit is 1, copy one byte from
the input buffer to the output buffer. Easy. If the bit is 0, things
are a little bit more complicated, RLE compressed data is ahead. You
have to read the next two bytes to decide how long your run is and
what you should write to your output buffer.
15
8
7
0
a
b
The upper nibble of the first byte (a) contains the information you
need to determine how many bytes you're going to write to your output
buffer for this "read operation". if a == 0, then
you have to read a third byte from your input buffer, and add 0x12
to it. Otherwise, you simply add 2 to a. This is the number of bytes
to write ("count") in this "read operation".
byte2 and the lower nibble of byte1 (b) tell you from where to copy
data to your output buffer: you move (dist = (b < <
8) - byte2 + 1) bytes back in your outputBuffer and copy "count"
bytes from there to the end of the buffer. Note that count could be
greater than dist which means that the copy source and copy destination
might overlap.