Jazz Jackrabbit 2 J2V
Jump to navigation
Jump to search
This is an animation format used in Jazz Jackrabbit 2 game.
Header format:
8 bytes - "CineFeeed" 4 bytes - file size 4 bytes - CRC 4 bytes - width 4 bytes - height 2 bytes - depth (should be 8) 2 bytes - delay between frames in milliseconds 4 bytes - number of frames 20 bytes - some sizes
Frame data is split into four streams with different kinds of data (a la Smacker or Bink), each compressed with deflate independently and with chunks containing data for one or more frames being output time from time. Decoder needs to prefetch and unpack that data.
For that reason the rest of the file consists of variable-size repeat of data chunks for each stream prefixed with 32-bit size. Chunks may be empty.
Data streams are:
- stream 0 - opcodes
- stream 1 - X offsets
- stream 2 - Y offsets
- stream 3 - colour data
Frame decoding works in the following way:
pal_present = read_stream(OPCODES, 1);
if (pal_present) {
pal = read_stream(CLR, 1024); // in RGBA format
}
for each line {
pos = 0;
while (pos < width) {
op = read_stream(OPCODES, 1);
switch (op) {
case 0: // long copy
len = (uint16_t)read_stream(OPCODES, 2);
copy len pixels to the current line position from CLR stream
pos += len;
break;
case 0x01..0x7F: // short copy
len = op;
copy len pixels to the current line position from CLR stream
pos += len;
break;
case 0x80: // end of line
pos = width;
break;
case 0x81: // long copy of previous segment
len = (uint16_t)read_stream(OPCODES, 2);
xoff = (uint16_t)read_stream(XOFF, 2);
yoff = read_stream(YOFF, 1) - 127;
copy len pixels from (x, y + yoff) position in the previous frame
pos += len;
break;
default: // short copy of previous segment
len = op;
xoff = (uint16_t)read_stream(XOFF, 2);
yoff = read_stream(YOFF, 1) - 127;
copy len pixels from (x, y + yoff) position in the previous frame
pos += len;
}
}
}