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; } } }