Talisman ANI
- Company: Software 2000
- Extension: ani
- Game: Talisman
This is a rather peculiar video game format that uses frame data compression in addition to the frame coding.
The file consists of chunks of various types, each starting with 32-bit little-endian chunk type and 32-bit payload size (compressed payload will start with an additional 32-bit unpacked size).
Known chunks
0x1234
-- ANI header, should be 20 bytes long (always unpacked);0x4321
-- sync chunk, should be 16 bytes long (always unpacked);0x1111
-- Huffman codebooks data, always unpacked;0x2001
-- intra frame;0x2110
-- inter frame;0x2332
-- seems to always contain 32-value equal to one (obviously unpacked), probably skip frame signal;0x2553
-- probably the same, not encountered in game files;0x3456
-- unknown, might be related to audio data;0x5544
-- palette (unpacked), always 768 bytes;0xABCD
-- acknowledged by the decoder as unpacked but not encountered in game files.
Header chunk
The header chunk should be the first in the file, occur only once. It contains the following information:
- 32-bit image width
- 32-bit image height
- 32-bit value that is always zero
- 32-bit value that is always 300000
- 32-bit number of frames
Sync chunk
Sync chunks mark a sequence aka group of frames (an intra frame plus some inter frames).
- 32-bit offset to the next sync chunk
- 32-bit value that is always zero
- 32-bit value that looks like some suggested buffer size
- 32-bit number of video frames until next sync chunk
Codebooks data chunk
This chunk contains Huffman codebook definition.
First there may be a sequence of 0xFF
bytes that should be ignored.
The first byte with another value tells which Huffman tree should be used for the sequence.
The following data contains symbol values for the Huffman trees. It starts with an opcode telling what to do with the entries: 0xFF
means skip definition set, 0x00..0x7F
mean the next byte is the number of new symbols and the following N bytes are new symbol values, other values mean previously decoded definition with number in the low seven bits should be re-used (skipped ones included but should not be re-used).
See the next section on how that data is used.
Chunks unpacking
Chunks are packed using order-1 static Huffman codes with some predefined tables and per-sequence symbol values (defined in chunk 0x1111
). That means when the data is decoded, it reads the same code set but the symbol value depends on the definitions transmitted in the chunk so e.g. if symbol 011
meant 0 in one sequence, it may mean 4 in another.
First symbol is transmitted as is, then actual Huffman bitstream follows (packed in 16-bit words, MSB first). The first byte is transmitted as is since the symbol table is defined for the previously decoded symbol and newly decoded value from the stream. Chunk 0x1111
stores those context-dependent symbol definitions for each previously decoded value and all possible input values (i.e. first set is used when previous symbol value is 0, next set is used when previous symbol value is 1 and so on).
Video decoding
Video frames are split into 2x2 blocks and use motion value in byte form (low nibble - X offset, high nibble - Y offset) with nibble values being signed (e.g. nibble value 0x3
means offset 3 and nibble value 0xD
means offset -3).
Frame data is split into two parts, namely the motion vectors data (and run values) and pixel values. 32-bit value at the beginning tells where the pixel data starts (motion data always starts at offset 4).
Codes 0x00..0xF6
copy 2x2 block using the corresponding motion vector (0x00
- do nothing, 0x3D
- copy with 3,-3 offset).
Codes 0xF7..0xFA
read a motion vector byte and a pixel byte, copy block from the specified location and replace pixel 3..0 with the new pixel value.
Codes 0xFB..0xFD
read a motion vector byte and copy the source block rotated by 90/180/270 degrees counter-clockwise correspondingly.
Code 0xFE
reads a run value (that may be prefixed with several 0xFF
to add 255 to its value) from motion data section and skips the signalled number of blocks.
Code 0xFF
reads four pixel values for the block.
Inter frame seems to be the same but uses the intra frame as the reference.