Micro Machines Compression
| Format type | Compression algorithm |
|---|---|
| Type | Stream |
| I/O unit size | 1-byte |
| Games |
Micro Machines uses a single LZ77-style compression for all its packed files: the front-end graphics (COMPRESS.PI0-PI6), the tilesets (ROUNDnBR.PR0-PR2), the vehicles (ROUNDnBR.VH0) and BITSFILE.PH0. There is no header; the stream simply ends with an end marker.
Loading series
Most compressed data is split into several numbered files. The game replaces the last character of the file name with '0', '1', ... and loads files until one fails to open. Each file is decompressed and copied into memory 48 kB (0xC000 bytes) after the previous one, so every file except the last must decompress to exactly 0xC000 bytes.
A compressed file is read into the last 16 kB of a 64 kB work segment, so it must not be larger than 16384 bytes. The decompressed length should be even, as the result is copied with word moves.
Compression format
The stream is made of control bytes, each followed by 8 items. The bits of the control byte are read from the most significant bit down:
- Bit clear: copy one literal byte to the output.
- Bit set: read an opcode byte v (plus operand bytes b where listed) and act on it:
| Opcode | Operands | Meaning |
|---|---|---|
| 0x00-0x0E | - | Literal run: copy v+8 literal bytes. Another opcode follows immediately, without consuming a control bit. |
| 0x0F | b (or b, word) | Literal run of b+0x1E bytes. If b is 0xFF a 16-bit length follows. Another opcode follows immediately. |
| 0x10-0x1E | - | Repeat the previous output byte v-0x10+2 times |
| 0x1F | b | Repeat the previous output byte b+0x11 times |
| 0x20-0x4F | b | b, copying from pos-distance-2 |
| 0x50-0x5E | b1, b2 | b1, length b2+4, copying from pos-distance-1 |
| 0x5F | b0, b1, b2 | Long copy with the distance high byte read from the stream |
| 0x60-0x6F | b | Reversed copy: v-0x60+3 bytes read backwards, starting at pos-b-1 |
| 0x70-0x7E | - | Incrementing run of v-0x70+2 bytes, each one the previous byte plus 1 |
| 0x7F | b | Incrementing run of b+2 bytes (0 means 256) |
| 0x80-0xFE | - | Short copy: length ((v >> 5) & 3)+2, distance (v & 0x1F)+length, copying from pos-distance |
| 0xFF | - | End of stream |
All copies are made byte by byte, so a copy may overlap the bytes it is producing.
The shipped files never use the incrementing runs (0x70-0x7F) and use the literal runs only a few times. An encoder must take care not to emit a short copy of length 5 at distance 36, as it would encode as 0xFF, the end marker.
Decompressed sizes
| File | Decompressed size |
|---|---|
| COMPRESS.PI0-PI5 | 0xC000 each |
| COMPRESS.PI6 | 0xA000 |
| BITSFILE.PH0 | 0x65C0 (26048) |
| ROUNDnBR.PR0/PR1 | 0xC000 (the last file of a round may be shorter) |
| ROUNDnBR.PR2 | Remainder, the whole tileset is at most 0x20000 bytes |
| ROUNDnBR.VH0 | 0x2400-0x3600 (round 9: 0x5DC0) |
Credits
This compression algorithm was reverse engineered by VorticonCmdr. 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!)