HNM4

From MultimediaWiki
Jump to navigation Jump to search

HNM4 is the third generation of the Cryo HNM video format. At least two decoder-incompatible variation of this format is known. The main version operates in 320x200x256 resolution. A simplified version operates in 640x480x256; this is used in "Aliens: A Comic Book Adventure". Both formats share the same container structure.

File Format

File header:

 dword signature     - file signature, "HNM4"
 dword unknown1      - probably format version
 word  width         - width of the frame
 word  height        - height of the frame
 dword filesize      - size of the entrie hnm file
 dword frames        - number of frames
 dword taboffset     - offset of the TAB chunk
 word  bits          - sound sample resolution
 word  channels      - number of sound channels
 dword framesize     - frame allocation size (width * height)
 byte  unknown2[16]  - seems to be unused
 byte  copyright[16] - "-Copyright CRYO-"

The rest of the file organized on manner similar to HNM (1) format. All single-frame related chunks combined to superchunks, where each superchunk starts with 32-bit value, lower 24 bits of it indicates superchunk size and highest 8 bits - flags (unknown). Each chunk starts with another 24+8 bits length header followed by 4 bytes of chunk ID (where only 2 bytes can be actually used), and chunk data. Near the end of file usually TAB chunk located, it doesn't have an upper-level superchunk.

PL Chunk

Palette. Stored in same format as used in HNM (1).

  • ALIENS: However, non-zero bit 23 of ChunkId indicates that palette stored in complete 8-bits-per-component format, unlike regular 6-bits otherwise.

IZ Chunk

Keyframe. See video decompression below.

IU Chunk

Interframe. See video decompression below.

SD Chunk

Sound data. DPCM-encoded sound fragment.

Decoding Video

Intraframes

Intraframe decompression is simialar to HNM (1) 0xFE frames. But with a few changes. Chunk data starts with small 4-bytes header:

 word width  - width of the frame
 byte height - height of the frame (only lower byte of it)
 byte mode   - rendering mode (always 0xFE ?)

Then immediately followed by LZ-packed raster (without 6-byte compression header as was used before). LZ decompression algorithm remains the same, but bitreader use 32-bits queue and processing bits from highest to lowest.

  • You can safely ignore width/height/mode fields of the frame header as original decoder always renders whole frame regardless specified values.

Interframes

HNM4 Interframe

Packed interframe consist of one or more compression codes. Depending on the code's count field following cases possible:

 bits
   0..4 : count = 0
   5..7 : tag:
           0: copy next two bytes of input to the output
           1: skip (next byte of input) * 2 bytes of output
           2: skip (next word of input) * 2 bytes of output
           3: fill (next byte of input) * 2 of output with (next byte of input)
        else: finish the unpacking

  - or -

   0..4 : count <> 0
      5 : previous
      6 : backline
      7 : backward
      8 : swap
  9..23 : offset

In this case for (count) pixel pairs, copy them from the (output + offset * 2 - 32768) of the current frame to the output. Flag bits modify various parameters of this scheme (multiple flags can be used):

  • previous - copy pairs from the previous frame
  • backline - first pixel located 2 lines above + (swap)
  • backward - advance source pixel pairs in backward order
  • swap - swap pair's pixels

Since the original decoder uses double buffering, "previous frame" refers to the other buffer. Buffers are flipped after each frame. Intraframes are copied to both buffers. HNM4 (but not HNM4A): All Interframe operations are performed on non-postprocessed data.

HNM4A Interframe

HNM4A interframe is a simplified version of the HNM4 interframe. Code format:

 bits
   0..5 : count = 0
   6..7 : tag:
           0: skip (next byte of input) bytes of output
           1: draw 1x2 column of the output with next 2 bytes of input
           2: advance to the next line of output (but keep current x position)
           3: finish the unpacking

  - or -

   0..5 : count <> 0
      6 : previous
      7 : delta
  8..23 : offset

For (count) 1x2 columns copy them from the (output + offset) to the output.

  • previous - copy column from the previous frame
  • delta - copy column from (output + offset - 65536)

Postprocessing

For HNM4 (but not HNM4A movies) you need to perform extra frame postprocessing by swapping pixels using following self-explaining example (assuming 4xN image):

 Just unpacked frame       Final frame
     p0 p1 p2 p3    ==>    p0 p2 p4 p6
     p4 p5 p6 p7           p1 p3 p5 p7
         ...                   ...

This applies to both intraframes and interframes.

Decoding Audio

TODO

Games Using HNM4