Zone 66 Compression
Format type | Compression algorithm |
---|---|
Type | Stream |
I/O unit size | 1-bit |
Games |
Zone 66 files are compressed with a variant of the LZW algorithm, with a few tricks to make reverse engineering a little more difficult.
File structure
Files begin with the decompressed size, followed by compressed data.
Data type | Name | Description |
---|---|---|
UINT32LE | decompressedSize | Size of file after decompression |
BYTE[] | data | Compressed data |
The decompressed size does not need to be used to limit the decompression in any way (the file is fully decompressed when the end of the compressed data is reached) however the game no doubt uses the field to allocate sufficient memory in advance to hold all the data.
Compression algorithm
The algorithm is LZW, but the way it is implemented is significantly different. Codewords start at 9 bits in length and extend to 12 bits, and after the last 12-bit codeword is used the codeword length is reset back to 9 bits in length, and the dictionary index is reset to 64 (i.e. the first 64 entries in the dictionary are kept over a reset.) After each codeword is read in, a further 8-bits are read in and output after the codeword.
Some files (tpal.z66) contain codewords that have not yet been added into the dictionary, so the dictionary should be initialised with all entries containing the value 0x00 before decompression starts. These invalid codewords should be treated as codeword 0x100 when being added to the dictionary (otherwise e.g. tpal.z66 will have extra 0x2A bytes at offset 0x2A0.)
Example code
- john_doe's code on the XeNTaX forum
- filter-zone66.cpp from Camoto's libgamearchive
Credits
The compression algorithm was reverse engineered by john_doe, with a couple of bugfixes by Malvineous. If you find this information helpful in a project you're working on, please give credit where credit is due. (A link back to this wiki would be nice too!)