JV
From MultimediaWiki
| Revision as of 21:31, 29 March 2008 Suxen drol (Talk | contribs) (cat) ← Previous diff |
Revision as of 14:30, 6 March 2011 VAG (Talk | contribs) (rewrite) Next diff → |
||
| Line 3: | Line 3: | ||
| * Samples: TBD | * Samples: TBD | ||
| - | JV is a multimedia format developed by the Bitmap Brothers and is used in the DOS game [http://www.mobygames.com/game/dos/z Z]. No other games are known to use this format. | + | JV is a multimedia format developed by the Bitmap Brothers and is used in the DOS game [http://www.mobygames.com/game/dos/z Z]. No other games are known to use this format. Carries palettized video using [[BTC]] encoding and [[PCM]] audio. |
| - | ==File Structure== | + | == File Format == |
| - | Files consist of a fixed-length header, followed by an index table, and the | + | |
| - | 0x0000 70 bytes ASCIIZ "JV00 Compression by John M Phillips Copyright (C) 1995 The Bitmap Brothers Ltd." | + | Files consist of a fixed-length header, followed by an index table, and then frame chunks. All numbers are little-endian. |
| - | 0x0050 le_u16 frame width (pixels) | + | |
| - | 0x0052 le_u16 frame height (pixels) | + | |
| - | 0x0054 le_u16 total frame count | + | |
| - | 0x0056 le_u16 always 0x50 | + | |
| - | 0x0058 le_u16 always 0x01 | + | |
| - | 0x005a le_u16 always 0x02 | + | |
| - | 0x005c le_u16 audio samples per second (22050 observed) | + | |
| - | 0x0060 7 bytes always zero | + | |
| - | 0x0067 u8 always non-zero | + | |
| - | The frame index table begins at offset 0x68, and contains an index record for each frame. The size of the table can be calculated using the total frame count field. | + | File header (0x68 bytes): |
| - | le_u32 - total frame length (octets) | + | u8 sig[2] -- File signature, "JV" |
| - | le_u32 - audio chunk length (octets) | + | u8 palmode1 -- Initial palette mode. 'W' - all White, '0' (or any |
| - | le_u32 - video chunk length (octets) | + | other value) - Black. (Un)used for fade-in effect |
| - | le_u16 - unknown | + | u8 palmode2 -- Final palette mode. Same as above, but fade-out |
| - | le_u16 - unknown | + | 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; -- ? | ||
| - | Frame data is stored immediately follows the header, where each frame corresonds to an entry in the index table. Each frame comprises an audio chunk followed immediately by a video chunk. The length of the audio and video data corresponds to the value indicated in the index record. Video chunks may sometimes be zero length. Frames sometimes contain additional unknown data (suspected to be padding), therefore the "total frame length" field must considered when parsing each frame. | + | File header is followed by frame index table, one entry per frame. |
| - | ==Audio Chunk== | + | Table entry format (0x10 bytes): |
| - | Each audio chunk contains mono unsigned 8-bit PCM audio samples. | + | 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; | ||
| - | ==Video Chunk== | + | Finally, frame chunks follows. |
| - | The compression algorithm is unknown. | + | 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. | ||
| [[Category:Game Formats]] | [[Category:Game Formats]] | ||
| [[Category:Undiscovered_Video_Codecs]] | [[Category:Undiscovered_Video_Codecs]] | ||
Revision as of 14:30, 6 March 2011
- Extension: jv
- Company: Bitmap Brothers
- Samples: TBD
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.
