Magic Pockets RNC Compression

From ModdingWiki
Jump to navigation Jump to search

The binary assets in Magic Pockets use RNC ProPack method 1. This is a compression wrapper, not an archive: each file decompresses to one payload interpreted by its own graphics, map, event, sound or driver format. All 60 binary files in the analysed data directory have this wrapper; install.txt does not.

File format

Header

Offset Data type Name Description
0 BYTE[4] signature 52 4E 43 01: ASCII RNC followed by method 1
4 UINT32BE unpacked length Size of the decoded payload
8 UINT32BE packed length Size of the compressed data after the header
12 UINT16BE unpacked CRC CRC-16/ARC of the decoded payload
14 UINT16BE packed CRC CRC of the packed payload
16 UINT8 leeway Workspace/leeway field; not used by the repo decoder
17 UINT8 chunks Number of compressed chunks

The compressed stream starts at byte 18. Numeric header fields are big-endian, whereas the bit reader consumes little-endian 16-bit words, least significant bit first. The decoded payload's own byte order is independent of the wrapper.

Huffman tables

Discard the first two stream bits during initialisation. Each chunk begins with three fresh Huffman tables, in order: literal-run length, match distance and match length.

For each table, read a 5-bit symbol count and then one 4-bit code length per symbol. A zero length means an unused symbol. Assign canonical codes in increasing code-length and symbol order, reversing the code bits for the LSB-first reader.

The decoded symbol number is a value class. Classes 0 and 1 return those values directly. For class s of 2 or more, read s - 1 extra bits and return:

value = (1 << (s - 1)) | extra_bits

Chunk body

After the tables, read a 16-bit group count. Copy a literal run decoded from the literal-length table. For each remaining group, decode a match distance and match length, copy the match, then copy the next literal run.

match distance = decoded distance + 1
match length = decoded length + 2

Match copies are byte-by-byte and may overlap their own output. A chunk with n groups contains n literal runs and n - 1 matches.

Literal bytes are read directly from the source pointer rather than as Huffman bits. After a literal copy, rebuild the bit window from the new source position while retaining the already-valid unconsumed bits. Simply byte-aligning or clearing the bit reader loses data. The source code implements the original two-word window and this resynchronisation explicitly.

Checksums

The decoded checksum uses reflected CRC-16/ARC, polynomial 0xA001, initial value zero. All 60 checked assets decode to the declared length and match their embedded unpacked CRCs. The implementation comes from the original game's Rnc_Depack routine and helpers at 1000:FCC4, FEC2, FE86 and FF22.

Notes

  • This page records the method-1 variant used by the game, not support for every RNC method.
  • The EJWLIB logo resources use LZHUF instead. Executable packing and asset packing are separate concerns.
  • Matching an unpacked CRC validates the decompressed bytes; it does not by itself identify the payload format.

Source code

From re-magicpockets, the open-source browser port and reverse-engineering project:

Credits

This file format was reverse engineered by VorticonCmdr. Please credit this work in projects that use it; a link back to this wiki is appreciated.