Adeline XCF

From MultimediaWiki
Jump to navigation Jump to search

This is a mixed format used for game cutscenes as well as providing some in-game animations e.g. demo runs.

Overall the XCF file consists of chunks with 8-character chunk tag (padded with spaces if needed) and 32-bit size. The first chunk in the file should be "FrameLen" chunk.

Some known chunks are:

  • "Camera " - some game engine command (probably telling how to orient 3D scene to match animation as the background)
  • "Format " - chunk with video parameters, there may be more than one of those in the file
  • "FrameLen" - first chunk in the file, often contains copyright notice about XCF at the end;
  • "DltFrame" - inter (delta) frame
  • "End " - file end marker
  • "KeyFrame" - intra (key) frame
  • "NulChunk"
  • "Palette " - palette
  • "Recouvre" - some game engine command
  • "SAL_STRT", "SAL_PART", "SAL_END " - some demo-related chunks
  • "SoundBuf" - initial segment of audio
  • "SoundEnd" - end of audio data marker
  • "SoundFrm" - subsequent segment(s) of audio

Format chunk

While usually its size is reported as 128 bytes, only part of it is used:

 4 bytes - actual chunk size (usually 28 or 44)
 4 bytes - width
 4 bytes - height
 4 bytes - some size
 4 bytes - some size (recommended video buffer size?)
 4 bytes - unknown
 4 bytes - frames per second
 if actual size is 44 bytes
   4 bytes - sampling rate
   4 bytes - audio channels

Video compression

Video compression scheme employed by XCF is overcomplicated. It splits frame into 8x8 blocks and applies one of 64 possible operations to it. Frame data is divided into three parts - opcodes (packed bitstream, 6 bits per block), part 1 starting immediately after it and part 2, 32-bit offset to which is the first item in frame data. Different opcodes may read colour and mask values from either part, often without any apparent logic.

Some opcodes actually consist of doing two things: base operation (e.g. fill block with one colour or copy block from certain position) and refining operation. There are four refining operations - do nothing, update arbitrary four pixels, update arbitrary eight pixels, update arbitrary pixels. So when opcode lists e.g. "21-24 - fill" it means fill as the base operation plus one of four refining operations, so 23 is fill block and then update arbitrary eight pixels. Four- or eight-pixel refinement means reading those pixel values and packed 6-bit indices for the positions where to put those colours. Arbitrary pixels means reading 64 bits of mask and new pixel values for the positions for which the mask is present.

Additionally when opcode uses a motion vector, that vector originates from the block centre so you have to add (4,4) to the full block or (2,2) for sub-block MV in order to find out the real displacement.

Possible opcodes are:

  • 0 -- raw block
  • 1-4 -- skip block (with refinement of course)
  • 5-8 -- motion compensation using one byte for motion vector (its nibbles are signed vector components)
  • 9-12 -- motion compensation using 16-bit offset from the frame start
  • 13-16 -- motion compensation for each of 4x4 sub-blocks using one byte for motion vector
  • 17-20 -- motion compensation for each of 4x4 sub-blocks using 16-bit absolute offset
  • 21-24 -- fill
  • 25-28 -- fill each sub-block with its own colour
  • 29 -- two-colour pattern
  • 30 -- four-colour pattern
  • 31 -- eight-colour pattern
  • 32 -- sixteen-colour pattern
  • 33 -- two-colour pattern per each sub-block
  • 34 -- four-colour pattern per each sub-block
  • 35 -- eight-colour pattern per each sub-block
  • 36 -- special four-colour pattern where half of the pixels have fixed colours and for the others only two options are available
  • 37 -- the same as 24 (fill with arbitrary pixels refinement)
  • 38 -- block is represented as the base colour plus 4-bit deltas at each position
  • 39 -- block is represented as two base colours (defining high nibbles of the pixel colour) plus 5-bit values telling which base colour to select for the current pixel and what its low nibble is
  • 40-43 -- RLE represented by mask telling at which positions to read a new colour value; here different opcodes are used for different scans - per-line, per-column, zigzag and mirrored zigzag correspondingly;
  • 44-47 -- similar to the previous but high nibble remains the same and only low nibble changes;
  • 48-51 -- motion compensation with 16-bit signed offset (relative to the centre of the block of course);
  • 52-55 -- motion compensation with motion vector components as signed bytes;
  • 56-59 -- same as 48-51 but for each sub-block;
  • 60-63 -- same as 52-55 but for each sub-block.