FVF
Jump to navigation
Jump to search
FVF is a format used for cutscenes in Star Trek: The Next Generation - "A Final Unity" game.
File structure
All data is little-endian. Data is grouped into frames that are grouped into blocks aligned to at least 2048 bytes. Audio is stored as unpacked PCM, video is compressed with its own method.
Header:
4 bytes - "FVF " 4 bytes - unknown 4 bytes - unknown 4 bytes - unknown 4 bytes - first block offset 4 bytes - last block offset 4 bytes - image header (should be 0x60) 4 bytes - audio header (usually 0xB5) 64 bytes - unknown
Image header:
2 bytes - header size? (usually 40) 2 bytes - always 1? 2 bytes - always 16? 2 bytes - width 2 bytes - height 4 bytes - delay in milliseconds 4 bytes - unknown 4 bytes - number of frames 4 bytes - unknown 2 bytes - unknown 1 byte - palette something 1 byte - number of palette entries (usually 15) 4 bytes - palette offset (usually 0x88) 6 bytes - unknown
Audio header:
2 bytes - compression? (usually it's 1 and raw PCM) 2 bytes - number of channels? 2 bytes - bits per sample (usually 8) 2 bytes - sampling rate 8 bytes - unknown
Block header:
2 bytes - header size (should be 16) 2 bytes - flags 4 bytes - previous block size 4 bytes - current block size 4 bytes - next block size
Frame header:
2 bytes - header size (should be 24) 4 bytes - full size 4 bytes - always 24? 4 bytes - video part size 4 bytes - audio part size 6 bytes - unknown
Video frame part
Video frame part starts with 32-bit size and two 16-bit fields (one of those is used to signal palette change, another one is for motion vector table size). Compression method seems to work by painting tiles using RGB555 colour combinations generated from the palette colours. Bitstream is little-endian, low three bits signal tile opcode and it's aligned to the byte boundary before each next opcode:
- code 0 -- get 7-bit value for palette LUT offset, get 14-bit value for source data offset, copy 4x4 block from the source applying palette LUT;
- code 1 -- the same as above but tile is flipped horizontally;
- code 2 -- same as code 0 but tile is flipped vertically;
- code 3 -- same as above but tile is flipped horizontally as well;
- code 4 -- get 5-bit run value, copy the provided amount of 4x4 tiles from the previous frame (presumably);
- code 5 -- get 1-bit run flag and then 4-bit MV table index. Run flags means reading 8-bit run value and performing the operations that many additional times, zero flag means doing motion compensation on 4x4 tile just once (motion vector table is stored at the beginning of the frame);
- code 6 -- skip 5 bits (to byte align) and copy 16 bytes from the input to the tile data;
- code 7 -- this is large tile mode, the next 4 bits signal the operation:
- case 0 -- skip 1 bit, get 7-bit palette LUT index, get 1-bit flag, get 14-bit source offset index, paint 8x8 tile;
- cases 1-7 -- same but with various flipping modes;
- cases 8-11, 13-14 -- should not be present;
- case 12 -- special 4x4 tile copy run with long values (either 8-bit run value + 32 or 16-bit run value + 288 depending on flag);
- case 14 -- raw 2x2 tile.