From MultimediaWiki
Jump to navigation Jump to search

JV is a multimedia format developed by the Bitmap Brothers and is used in the DOS game Z. No other games are known to use this format. Carries palettized video using BTC encoding and PCM audio.

File Format

Files consist of a fixed-length header, followed by an index table, and then frame chunks. All numbers are little-endian.

File header (0x68 bytes):

 u8  sig[2]             -- File signature, "JV"
 u8  palmode1           -- Initial palette mode. 'W' - all White, '0' (or any
                           other value) - Black. (Un)used for fade-in effect
 u8  palmode2           -- Final palette mode. Same as above, but fade-out
 u8  copyright[0x4C];   -- "Compression by John M Phillips"... bla-bla
 s16 width;             -- Frame width
 s16 height;            -- Frame height
 s16 frames;            -- Number of frames
 s16 rate;              -- Frame rate. Delay between successive frames in ms
 s32 maxchunk;          -- Maximal size of a single frame chunk
 s32 freq;              -- Audio frequency
 u8  flags0:1;          -- ?
 u8  volume:7;          -- Default sound volume (0 - max)
 u8  unused[6];
 u8  flags1:3;          -- Number of fade-in frames?
 u8  flags2:3;          -- ?
 u8  flags3:1;          -- ?
 u8  flags4:1;          -- ?

File header is followed by frame index table, one entry per frame.

Table entry format (0x10 bytes):

 s32 chunk_size;        -- Size of the chunk data
 s32 audio_size;        -- Size of the audio portion of the frame
 s32 video_size;        -- Size of the video portion of the frame
 s8  has_palette;       -- New palette is present
 s8  audio_type;        -- Audio format. Always 0 - mono, 8-bit PCM
 s8  video_type;        -- Video compression method (see below)
 s8  unused;

Finally, frame chunks follows.

Frama chunk format:

 s8  audio[audio_size]; -- Audio data
 RGB palette[256];      -- New palette (present only if has_palette flag is set)
 s8  video[video_size]; -- Video data
 s8  padding[];         -- sizeof(audio + palette + video + padding) == chunk_size 

Video compression

Depending on video_type value, frame can be encoded using the following way:

Type 0: Raw frame

Paint frame using the video data and continue with Type 1 decoding. Apparently, someone forgot to put the "break" keyword here because additional decoding of the raw data seems redundant. Or perhaps it was originally planned to (losely) compress this block data somehow.

Type 1: BTC frame

Initialize a bit-reader using video data. Fill it with 8-bit values, fetch bits starting from the highest. Multi-byte values are read as byte0 = GetByte(), byte1 = GetByte(), etc.

Frame is encoded as a series of 8x8 blocks. To decode single block:

 Read 2-bit block type:
 0: End. End of (sub)block decoding.
 1: Fill. Read 8 bits and use them to fill the (sub)block.
 2: BTC. Read color0 and color1, 8 bits each. Read mask. For each pixel of
    (sub)block, if mask bit is set - paint it using color1. Use color0 if bit
    is clear. Complete mask read first (4/16/64 bits) and processed from
    its highest bit to lowest.
 3: Subblock. Split the block on 4 equal subblocks and process each one
    separately using the same scheme recursively. If the subblock size is
    already 2x2, paint it using the next 2 * 2 * 8 bits.

Type 2: Solid frame

Read 8-bit pixel value from video data and use it to fill the whole frame.