Electronic Arts TGV

From MultimediaWiki
Jump to: navigation, search

TGV is a multimedia format used in various games published by companies under the Electronic Arts umbrella. It employs loss-less intra frame compression, and block-based motion and VQ for inter frames. The lossless compression algorithm is also used to compress game data files in Privateer 2 and StarLacer.

Definitions

le_16   16-bit value, little endian
le_uN   unsigned N-bits, where the buffer is processed lsb to msb bit
le_sN   signed N-bits, where the buffer is processed lsb to msb bit, and the sign bit is extended.
be_16   16-bit value, big endian
be_24   24-bit value, big endian

Chunk Types

See Electronic Arts Formats for file format description.

kVGT ("Intra-Frame")

Intra-frames begin with a header that describes the image dimensions and palette. Frame rate is not reported in the header. Need For Speed, NBA '96 and Cybermancer Demo samples were found to render correctly at 15 fps, while Privateer 2 samples render correctly at 12 fps.

Offset   Data_type   Name         Description
0x0000   le_16       width        image width (pixels)
0x0002   le_16       height       image height (pixels)
0x0004   le_16                    unknown
0x0006   le_16       pal_count    number of palette entries
0x0008   le_16                    unknown
0x000a   le_16                    unknown
For pal_count palette entries
   (u8) red_component
   (u8) blue_component
   (u8) green_component
 
(be_16) check
if (check & 0x0100)
    (be_u24) unknown, but possibly the size of the compressed buffer
 
(be_u24) uncompressed_buffer_size (bytes)

A compressed buffer immediately follows the header. When decompressed represents the intra-frame raster image. Pixels values are arranged in left to right, top to bottom raster order. The compressed buffer contains a series of variable length decompression statements. These statements are identified using a VLC and, are followed by parameter bits sequence of uncompressed bytes (that later only if required). The different statement types are described below. The decoder processes the compressed buffer until the size of the output buffer equals that reported by the uncompressed_buffer_size field.

VLC: 111111AA
  size1 = A
  append decompressed buffer with size1 bytes, fetched from the compressed buffer
 
VLC: 111AAAAA
  size1 = (A + 2) * 4
  append decompressed buffer with size1 bytes, fetched from the compressed buffer
 
VLC: 110CBBAA DDDDDDDD EEEEEEEE FFFFFFFF (four bytes)
  size1 = A
  size2 = (B<<8) + F
  offset = (C<<16) + (D<<8) + E + 1
  append decompressed buffer with size1 bytes, fetched from compressed buffer
  append decompressed buffer with size2 bytes, fetched from current buffer position less offset bytes
 
VLC: 10AAAAAA CCBBBBBB DDDDDDDD (three bytes)
  size1 = C
  size2 = A + 4
  offset = (B<<8) + D + 1
  append decompressed buffer with size1 bytes, fetched from compressed buffer
  append decompressed buffer with size2 bytes, fetched from current buffer position less offset bytes
 
VLC: 0CCBBBAA DDDDDDDD (two bytes)
  size1 = A
  size2 = B + 3
  offset = (C<<8) + D + 1
  append decompressed buffer with size1 bytes, fetched from compressed buffer
  append decompressed buffer with size2 bytes, fetched from current buffer position less offset bytes   

fVGT ("Inter-Frame")

Inter-frames are broken into 4x4 blocks, arranged in left to right, top to bottom order. Each block may be copied from the last frame using a motion vector, or from either a compressed or uncompressed code book entry. All samples file were found to use modulo 4 image dimensions.

Inter-frames begin with a header.

Offset   Data_type   Name         Description
0x0000   le_16       num_mvs      number of motion vector code book entries
0x0002   le_16       num_raw      number of uncompressed block code book entries
0x0004   le_16       num_packed   number of compressed block code book entries
0x0006   le_16       index_bits   number of mv/block index bits to read
0x0008   le_16                    unknown
0x000a   le_16                    unknown

The MV code book follows the header. The total length of the code book is padded to a 32-bit boundary.

for num_mvs
   (s10_lsb) mv_x
   (s10_lsb) mv_y
(padding bits)

The uncompressed block code book follow the MV code book. Blocks are addressed using left to right, top to bottom raster order.

for num_raw
   for address 0 through 15
      (u8) pixel

The compressed block code book follow the uncompressed block code book. These blocks are decompressed using a primitive VQ algorithm.

for num_packed
   (u8[4]) data array
   for address 0 through 15
      (le_u2) data array index  (algorithm: pixel = data[index])

An index table follows the compressed block code book, where the size of each index value is indicated by the index_bits header field.

for number of vertical blocks
for number of horizontal blocks
    (le_u<index_bits>) index

The table contains an index for each block within the inter-frame.

If index is less than num_mvs, it indicates a mv code book entry. Pixels for the current block are then fetched from the last frame, using the current block location offset by the motion vector.

Otherwise, num_mvs is subtracted from index. If index is less than num_raw, it indicates the uncompressed code book entry. Pixels values for the current block are fetched from this entry.

Otherwise, num_raw is subtracted from index, and index indicates the compressed code book entry from which to fetch pixels for the current block.

Games Using TGV

See Electronic Arts Formats for listing.