Zork PMV

From MultimediaWiki
Jump to navigation Jump to search
  • Extensions: PMV
  • Decoder: [1]

This is a format used in MADE engine game Return to Zork.

Container format

Data is organised into chunks with 32-bit payload length following the 4-byte chunk identifier:

  • MOVE - root chunk
  • MHED - header
  • MFRM - frame chunk

Header contents:

2 bytes - delay between frames in milliseconds
4 bytes - always zero?
2 bytes - number of frames
4 bytes - always zero?
2 bytes - sample rate
44 bytes - unknown 16-bit words
768 bytes - palette

Frame chunk header:

8 bytes - unknown
4 bytes - audio data offset (from the chunk ID, not from payload start)
4 bytes - image data offset
4 bytes - palette data offset (if present)

Audio part header:

4 bytes - unknown
2 bytes - single chunk size in samples
2 bytes - number of chunks

Image part header:

4 bytes - image part size
4 bytes - unknown
2 bytes - width
2 bytes - height
2 bytes - block type data offset (from the image part start)
2 bytes - block types packed flag (0 or 1)
2 bytes - pixel data offset
2 bytes - pixel data packed flag (0 or 1)
2 bytes - mask data offset
2 bytes - mask data packed flag (0 or 1)
2 bytes - size of opcodes buffer for single image row (e.g. 20 for 320-pixel width)

Palette data starts with "PALT" and 32-bit data sized followed by updates telling at which offset and how many colours to update:

1 byte - number of colours minus one
1 byte - start colour
N*3 bytes - colour data

FF FF means end of palette data.

Frame data segments may be packed with simple RLE scheme signalled by the flag in the header. In that case positive byte value means number of byte to copy minus one and negative value means negated run length minus one (with the next byte being the colour value to repeat).

Video compression

Video is compressed using vector quantisation for 4x4 blocks with various data elements grouped together (command/block type, raw pixels, pixel masks).

Block types are stored in two-bit variables:

  • 0 - fill block (read one pixels from the pixel data part and fill block with it)
  • 1 - two-colour block (read 2 pixels from the pixel data part and 16-bit mask from the mask data part, arrange pixels using mask)
  • 2 - four-colour block (read 4 pixels and 32-bit mask for sixteen 2-bit colour indices)
  • 3 - skipped block

Masks are little-endian and read LSB first.

Audio compression

Each audio chunk starts with a byte telling how it should be decoded:

  • bits 0-3 - compression type
  • bits 6-7 - modifier (1 - decode every odd sample, linearly interpolate every even sample from them, 2 - decode and use for interpolation every fourth sample)

Compression types:

  • 0 - zero output
  • 1 - no change
  • 2-4 - read 2/4/16 U8 samples to delta buffer, for every sample read 1/2/4-bit index, use corresponding delta value to update the previous sample with clipping
  • 5 - raw unsigned 8-bit audio data