JV
From MultimediaWiki
- Extension: jv
- Company: Bitmap Brothers
- Samples: http://samples.ffmpeg.org/game-formats/jv/
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.
Contents |
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.
