Origin Xan Codec
- FourCC: Xxan
- Company: Origin Systems
- Samples: http://samples.mplayerhq.hu/game-formats/wc4-xan/
The Xan codec is a codec used in various multimedia-heavy titles from early in the FMV-era of PC computer games. The video was packaged in AVI files along with a custom DPCM audio codec.
While not all of the details have been reverse engineered, the Xan codec is known to use the same byte unpacking algorithm as used in the custom video codec developed for Wing Commander III. Further, it uses Huffman coding and bit packing, though using a slightly different algorithm than its predecessor codec, and it appears to have been designed to easily accommodate a number of video output and scaling modes.
Trivia: All Xan-encoded AVI files contain very interesting comment string inside. 'Xxan video stream, Blue Mu Productions.' What could possible that Blue Mu be? A subdivision of Origin or real codec authors?
Format
This codec is similar to Wing Commander III MVE Video Codec and employs the same packing algorithm. The main difference is that this codec stores information in YUV colorspace (6 bits for Y component, 5 bits for U and V components).
Frame format:
header: bytes 0-3 - frame type bytes 4-7 - offset to chroma data bytes 8-11 - offset to some luma differences?
bytes 12-? - luma Huffman-coded data for frame type 0 or bytes 12-15 - offset to chroma differences bytes 16-? - luma Huffman-coded data for frame type 1
chroma data: bytes 0-1 - chroma data is YUV420 or YUV410 bytes 2-3 - offset to Huffman-coded chroma indexes bytes 4-? - possible chroma values
Luma data is packed with left-to-right Huffman codes, chroma data is packed with the same wc3_unpack
.
Intra frame (type 0)
Luma reconstruction
Reconstruction of the first line:
byte_l = *unpacked++; byte_h = byte_l; byte_l *= 2; *out++ = byte_l; width_counter = (width - 2) / 2; while (width_counter--) { byte_l = byte_h; byte_h += *unpacked++; byte_h &= 0x1F; byte_l += byte_h; *out++ = byte_l; byte_l = byte_h; byte_l *= 2; *out++ = byte_l; } *out++ = byte_l;
Reconstruction of the rest of the lines:
while (height_counter--) { byte_l = out[-width]; byte_l /= 2; byte_l += *unpacked++; byte_l &= 0x1F; byte_h = byte_l; byte_h *= 2; *out++ = byte_h; byte_h = byte_l; mod_width = (-width + 2) >> 1; while (mod_width < 0) { byte_l = out[-width + 1]; byte_l /= 2; byte_l += *unpacked++; byte_l &= 0x1F; byte_h += byte_l; *out++ = byte_h; byte_h = byte_l; byte_l *= 2; *out++ = byte_l; mod_width++; } *out++ = byte_l; }
Chroma reconstruction
while (bytes_decoded--) { current_values = LE_16(&mem34) * 2; if (current_values != 0) { byte_l = (current_values & 0xFF); byte_l += mem2C[0]; byte_l &= 0x3F; mem2C[0] = byte_l; byte_l = ((current_values >> 8) & 0xFF); byte_l += mem2C[2]; byte_l &= 0x3F; mem2C[2] = byte_l; } mem34 += 2; mem2C += 4; }
Inter frame (type 1)
Luma reconstruction
while (height_counter--) { byte_l = *mem34++; byte_l *= 2; byte_l += *mem2C; byte_l &= 0x3F; *mem2C++ = byte_l; width_counter = (s->avctx->width - 1) / 2; while (width_counter--) { byte_h = *mem34++; byte_h *= 2; byte_h = mem2C[1]; byte_h &= 0x3F; mem2C[1] = byte_h; byte_l /= 2; mem2C[0] = byte_l; mem2C += 2; byte_l = byte_h; } *mem2C++ = byte_l; }
Chroma reconstruction
There are two possible modes - in one mode single chroma differences buffer is unpacked, in another mode two buffers are unpacked and their contents are added together before using in unpacking.
while (input_size > 0) { *mem2C++ = (((*mem34++) << 1) + *mem2C) & 0x3F; mem2C++; input_size--; }
Games Using Xan Video
- Crusader: No Regret (DOS)
- Crusader: No Remorse (DOS)
- Pandemonium! (note: not an Origin's game!)
- Wing Commander IV