Electronic Arts TGV
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.
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
See Electronic Arts Formats for file format description.
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
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) 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.