Legend Entertainment Q
- Company: Legend Entertainment
The format stores paletted video and raw audio stream for some game cutscenes or animations (while others may be stored in FLIC format). The format consists of 26-byte header followed by a series of 6-byte chunk headers and optional chunk payload. All data is little-endian.
File header
2 bytes - magic 0x6839 1 byte - version 1 byte - ignored 2 bytes - width in blocks 2 bytes - height in blocks 1 byte - block width (should be 4) 1 byte - block height (should be 4) 2 bytes - number of frames 4 bytes - offset to the frame data (palette and optional method signalling chunks are stored before that offset) 1 byte - frames per second 1 byte - ignored 2 bytes - some audio flags 2 bytes - unknown 4 bytes - audio chunk size
Chunk types
Chunk header consists of 16-bit chunk type and 32-bit chunk size.
Chunk types:
0xFFFF
- end of stream0
- audio1
- VGA palette2
- video frame3
- video frame (with additional coordinates to update just the part of image)4
- video frame (with additional coordinates to update just the part of image)5
- up to 128 most common 16-bit patterns used by the following frames6
- a marker signalling different decoding algorithm (chunk size should be ignored)7
- a marker signalling different decoding algorithm (chunk size should be ignored)8
- RIFF WAV header9
- first part of interlaced frame (version 5 only)10
- padding?11
- second part of interlaced frame (version 5 only)
Video compression
Video frame is compressed as a sequence of 4x4 blocks using mainly Block Truncation Coding and reusing other frame blocks (either by not updating it or by copying some other frame block). The compressed data is essentially a stream of opcodes that tell how to decode the following block (or several blocks).
Opcodes (version 3):
xx xx (xx < 0xF8)
- fill the block withxx
valuexx yy pppp (xx < 0xF8)
- fill the block using the 16-bit patternpppp
(top bit first) and coloursxx
andyy
0xF8
- TODO0xF9 nn
- depending on previous block type either repeat previous blocknn
times or skip blocknn
times0xFA nnnn
- copy the block after the current one using offsetnnnn
0xFB nnnn
- copy the block before the current one using offsetnnnn
0xFC yx
- copy the block using the motion vector with each nibble corresponding to the value in this table:{ 0, 4, 8, 12, 16, 20, 24, 28, -32, -4, -8, -12, -16, -20, -24, -28 }
0xFD nn
- copy the block after the current one using offsetnn
0xFE nn
- copy the block before the current one using offsetnn
0xFF
- leave the block unchanged
Opcodes (version 4, 5 and 7):
xx xx (xx < 0xF8)
- fill the block withxx
valuexx yy ii (xx < 0xF8, ii < 0x80)
- fill the block using the pattern from chunk type 5 with indexii
(top bit first) and coloursxx
andyy
xx yy pppp (xx < 0xF8, pppp >= 0x8000)
- fill the block using the 16-bit patternpppp
(top bit first) and coloursxx
andyy
0xF8
- compact mode (see below)0xF9 nn
- depending on previous block type either repeat previous blocknn
times or perform the same motion compensation as the previous block0xFA nnnn
- copy the block at absolute 16-bit positionnnnn
0xFB
- see below0xFC mm
- copy the block using the motion vectormm
from the table below0xFD nn
- copy the block after the current one using offsetnn
0xFE nn
- copy the block before the current one using offsetnn
0xFF
- leave the block unchanged
0xF8 opcode
This opcode is used for compact colour representation: F8 0x
introduces a new table with up to 15 colours and fill/two-colour patterns use nibbles for colour indices until another F8
opcode is encountered and this mode is switched off. Also the table may be reused later and F8 NN
with NN ≥ 0x10
is used to recall a previous table with an index equal to NN - 0x10
(and for some reason this table should be added to the list again).
0xFB opcode methods
Depending on initialisation chunk or version and frame type (version 4 with chunk type 7 being present in the beginning or version 5 for frame types 9 and 11 for mode 7, mode 6 otherwise) this opcode has a different meaning.
In either case it contains a number of blocks to process (two or more) and each block is processed in the same way.
It also seems to depend on frame type, e.g. in version 7 frame type 9 uses mode 6 while frame type 11 uses mode 7.
Repeat block type sequence (mode 6)
Depending on previously decoded block type a different action should be taken:
- fill block - read a one byte fill value for the current block
- 8-bit pattern block - read 8- or 16- pattern for the current block, reuse colours from the reference block
- 16-bit pattern block - read 16-bit pattern for the current block, reuse colours from the reference block
- various motion compensation block types - read the same data type (1-byte offset, 2-byte index, 1-byte motion vector code) and perform motion compensation
Raw blocks sequence (mode 7)
If the data starts with byte value less than 0xF8
then the following 16 bytes are copied into the output block, otherwise fill block with several colours depending on the code:
0xF8
- should not happen, skip0xF9
- fill the block using 32-bit pattern (with 2 bits per pixel) and following 3 colours0xFA
- fill the block using 32-bit pattern (with 2 bits per pixel) and following 4 colours0xFB
- fill the block using 2x24-bit pattern (3 bits per pixel, each 4x2 block has its own 24-bit pattern) and following 5 colours0xFC
- fill the block using 2x24-bit pattern and following 6 colours0xFD
- fill the block using 2x24-bit pattern and following 7 colours0xFE
- fill the block using 2x24-bit pattern and following 8 colours0xFF
- should not happen, skip
Motion vectors table
Motion vectors are also used with the whole blocks so e.g. (-5, 8)
means taking 4x4 block that is 5 blocks to the left and eight blocks down from the current one.
( 0, 8), ( 1, 8), ( 2, 8), ( 3, 8), ( 4, 8), ( 5, 8), ( 6, 8), ( 7, 8), (-8, 8), (-1, 8), (-2, 8), (-3, 8), (-4, 8), (-5, 8), (-6, 8), (-7, 8), ( 0, 9), ( 1, 9), ( 2, 9), ( 3, 9), ( 4, 9), ( 5, 9), ( 6, 9), ( 7, 9), (-8, 9), (-1, 9), (-2, 9), (-3, 9), (-4, 9), (-5, 9), (-6, 9), (-7, 9), ( 0, 2), ( 1, 2), ( 2, 2), ( 3, 2), ( 4, 2), ( 5, 2), ( 6, 2), ( 7, 2), (-8, 2), (-1, 2), (-2, 2), (-3, 2), (-4, 2), (-5, 2), (-6, 2), (-7, 2), ( 0, 3), ( 1, 3), ( 2, 3), ( 3, 3), ( 4, 3), ( 5, 3), ( 6, 3), ( 7, 3), (-8, 3), (-1, 3), (-2, 3), (-3, 3), (-4, 3), (-5, 3), (-6, 3), (-7, 3), ( 0, 4), ( 1, 4), ( 2, 4), ( 3, 4), ( 4, 4), ( 5, 4), ( 6, 4), ( 7, 4), (-8, 4), (-1, 4), (-2, 4), (-3, 4), (-4, 4), (-5, 4), (-6, 4), (-7, 4), ( 0, 5), ( 1, 5), ( 2, 5), ( 3, 5), ( 4, 5), ( 5, 5), ( 6, 5), ( 7, 5), (-8, 5), (-1, 5), (-2, 5), (-3, 5), (-4, 5), (-5, 5), (-6, 5), (-7, 5), ( 0, 6), ( 1, 6), ( 2, 6), ( 3, 6), ( 4, 6), ( 5, 6), ( 6, 6), ( 7, 6), (-8, 6), (-1, 6), (-2, 6), (-3, 6), (-4, 6), (-5, 6), (-6, 6), (-7, 6), ( 0, 7), ( 1, 7), ( 2, 7), ( 3, 7), ( 4, 7), ( 5, 7), ( 6, 7), ( 7, 7), (-8, 7), (-1, 7), (-2, 7), (-3, 7), (-4, 7), (-5, 7), (-6, 7), (-7, 7), ( 0, -8), ( 1, -8), ( 2, -8), ( 3, -8), ( 4, -8), ( 5, -8), ( 6, -8), ( 7, -8), (-8, -8), (-1, -8), (-2, -8), (-3, -8), (-4, -8), (-5, -8), (-6, -8), (-7, -8), ( 0, -9), ( 1, -9), ( 2, -9), ( 3, -9), ( 4, -9), ( 5, -9), ( 6, -9), ( 7, -9), (-8, -9), (-1, -9), (-2, -9), (-3, -9), (-4, -9), (-5, -9), (-6, -9), (-7, -9), ( 0, -2), ( 1, -2), ( 2, -2), ( 3, -2), ( 4, -2), ( 5, -2), ( 6, -2), ( 7, -2), (-8, -2), (-1, -2), (-2, -2), (-3, -2), (-4, -2), (-5, -2), (-6, -2), (-7, -2), ( 0, -3), ( 1, -3), ( 2, -3), ( 3, -3), ( 4, -3), ( 5, -3), ( 6, -3), ( 7, -3), (-8, -3), (-1, -3), (-2, -3), (-3, -3), (-4, -3), (-5, -3), (-6, -3), (-7, -3), ( 0, -4), ( 1, -4), ( 2, -4), ( 3, -4), ( 4, -4), ( 5, -4), ( 6, -4), ( 7, -4), (-8, -4), (-1, -4), (-2, -4), (-3, -4), (-4, -4), (-5, -4), (-6, -4), (-7, -4), ( 0, -5), ( 1, -5), ( 2, -5), ( 3, -5), ( 4, -5), ( 5, -5), ( 6, -5), ( 7, -5), (-8, -5), (-1, -5), (-2, -5), (-3, -5), (-4, -5), (-5, -5), (-6, -5), (-7, -5), ( 0, -6), ( 1, -6), ( 2, -6), ( 3, -6), ( 4, -6), ( 5, -6), ( 6, -6), ( 7, -6), (-8, -6), (-1, -6), (-2, -6), (-3, -6), (-4, -6), (-5, -6), (-6, -6), (-7, -6), ( 0, -7), ( 1, -7), ( 2, -7), ( 3, -7), ( 4, -7), ( 5, -7), ( 6, -7), ( 7, -7), (-8, -7), (-1, -7), (-2, -7), (-3, -7), (-4, -7), (-5, -7), (-6, -7), (-7, -7)