IBM PhotoMotion

From MultimediaWiki
Jump to navigation Jump to search

This page is originally based on a document entitled 'Description Of The American Laser Games "MM" File Format/Video Codec' by Peter Ross.

This is a multimedia format developed by IBM and licensed to American Laser Games. There is no known information whether ALG introduced new half-resolution compression methods but the known version of IBM PhotoMotion player does not support them. Known PhotoMotion samples use only frame types 0x0002 and 0x0005, and player additionally supports frame type 0x0004.

In the early 1990s American Laser Games released several of their arcade shooting game titles on IBM-PC CD-ROM. The games feature hundreds of full motion video scenes, where each scene accounts for different actions taken by the player, namely when you shoot the bad guy and he falls dead, or when the bad guy shoots you.

The games were intended for 286/386 hardware. Video sequences were presented at 10 fps, using VGA (~320x200x256) resolutions and accompanied by 8-bit mono sound.

Trivia: The original game relied upon the intra/inter pixel refresh to clear away bullet hole marks drawn directly on the output buffer.

The game was developed to run smoothly on a single-speed CD-Drives. Thus, assuming 10 fps playback rate, each frame size may not exceed 15kb (not including it's sound portion), while full VGA screen takes 320*200 = 64k of data. Due to this speed limits, video becomes very lossy/blocky in the fast-changing scenes. Authors even included separate video files for double-speed CD-ROMs with a bit improved picture quality.


Acronyms

  • u16_le unsigned 16-bit integer, little endian
  • u32_le unsigned 32-bit integer, little endian

MM File Format/Video Codec

The MM file consists of data chunks in the following form:

 | preamble data |  preamble data | ...

The preamble:

 (u16_le)  type      data type identifier for the data.
 (u32_le)  length    length of chunk data in bytes (not including this preamble)

MM Chunk Type 0x0000 ("Header")

The length of the header chunk can be either 0x16, 0x18 or 0x1a bytes, where the latter two indicate the presence of audio samples.

Header structure:

 (u16_le)  num_chunks      total number of chunks in the mm file excluding header chunk
 (u16_le)  frame_rate      frame rate (frames per second, always set to 10)
 (u16_le)  video_mode      IBM-PC video bios mode (always set to 0x13 for 320x200x256 colors)
 (u16_le)  width           image width (pixels)
 (u16_le)  height          image height (pixels)
 (u16_le)  type_raw        raw video chunk type (always set to 0x2)
 (u16_le)  type_inter      inter video chunk type (always set to 0x5)
 (u16_le)  type_intra_hh   intra_hh video chunk type (always set to 0xc)
 (u16_le)  type_inter_hh   inter_hh video chunk type (always set to 0xd)
 (u16_le)  type_intra_hhv  intra_hhv video chunk type (always set to 0xe)
 (u16_le)  type_inter_hhv  inter_hhv video chunk type (always set to 0xf)

 (u16_le)  type_audio      chunk type of "audio sample" only present when header chunk length is 0x18

 (u16_le)  unknown         only present when header chunk length is 0x1a

Notes:

  • The type_xxx fields (with exception of type_audio) are interesting in that the games evaluted did not honour the values placed in these fields.

MM Chunk Type 0x0030 ("Video Palette Full")

 for all 256 palette entries starting from the beginning
    (u8)   blue_component
    (u8)   green_component
    (u8)   red_component

The palette values are VGA DAC colors in range 0..63, you'll probably need to multiply them by 4 to get more common 0..255 range.

MM Chunk Type 0x0031 ("Video Palette Partial")

 (u16_le)  start_color
 (u16_le)  count_colors
 for count_color palette entries starting from start_color
    (u8)   blue_component
    (u8)   green_component
    (u8)   red_component

The palette values are VGA DAC colors in range 0..63, you'll probably need to multiply them by 4 to get more common 0..255 range.

MM Chunk Type 0x0014

The chunk seems to be another audio stream, probably PWM data for being played on PC speaker. It accompanies 8kHz audio stream in some of the original IBM PhotoMotion files and corresponds to about 5000 bytes per second rate.

MM Chunk Type 0x0015 ("Audio Sample 8kHz")

The audio chunk contains unsigned 8-bit PCM audio samples, sampled at 8000 Hz.

MM Chunk Type 0x0016 ("Audio Sample 11kHz")

The audio chunk contains unsigned 8-bit PCM audio samples, sampled at 11000 Hz.

MM Chunk Type 0x0008 ("Intra Video")

Intra-frames are decompressed using the following run length algorithm. Intra-frames must be applied to the output buffer of the previous frame, as there is an opaque (inter-frame) capability.

 x,y = (0,0)
 i = 0
 while i < chunk_length

   if chunk_data[i] & 0x80
     run_length = 1
     color = chunk_data[i]
     i++
   else
     run_length = (chunk_data[i] & 0x7f) + 2
     color = chunk_data[i]
     i += 2

     if color > 0 
        write run_length at the x,y position
     increment x position by run length
     if x now exceeds the video width, increment y position

MM Chunk Type 0x000c ("Intra Half-Horiz Video")

Identical to type 0x0008, except each compressed sample is refers to two horizontal (across) pixels.

MM Chunk Type 0x000e ("Intra Half-Horiz Half-Vertical Video")

Identical to type 0x0008, except each compressed sample refers to two horizontal (across) and two vertical (down) pixels.

MM Chunk Type 0x0005 ("Inter Video")

Inter-frames are decompressed using a strip copy algorithm. Inter-frames are applied to the output buffer of the previous frame.

The chunk is broken into two portions, where the first describes the strip location and which pixels are to be replaced, whereas the second contains the replacement video samples.

Decoding algorithm:

The initial two bytes of the chunk indicate byte offset (u16_le; relative to the start of the chunk + 2) of the first replacement sample

 x,y = (0,0)
 d = first_sample_offset
 r = 2
 while r < first_sample_offset
   length = buf[r] & 0x7f
   x = buf[r+1] + ((buf[r] & 0x80) << 1)
   r += 2

   if length == 0
      skip x number of rows

   else
      for length number of bytes
         test each bit (start with msb)
         if bit is set then
            replace pixel at x,y with chunk_data[d] 
            d++
         x++
      y++

MM Chunk Type 0x0004 ("Masked Inter Video")

Inter-frames are decompressed the same as in chunk type 0x0005 case but first part of the data contains only mask bytes but for the whole frame.

MM Chunk Type 0x000d ("Inter Half-Horiz Video")

Identical to type 0x0005, except each compressed sample refers to two horizontal (across) pixels.

MM Chunk Type 0x000f ("Inter Half-Horiz Half-Vertical Video")

Identical to type 0x0005, except each compressed sample refers to two horizontal (across) and two vertical (down) pixels.

MM Chunk Type 0x0002 ("Raw Video")

The raw video chunk is not used by the games evaluated, but was found to be a a working feature of the game engine (decoder). It was stumbled across when testing how the game engine handled unsupported chunk types.

Decoding algorithm:

 for each horizontal pixel
   for each vertical pixel
     (u8)  palette_index

CDs Using This Format

PC Games Using This Format

The following IBM-PC CD-ROM games are known to use the MM format:

It should be noted that many of these games have since been re-released on Win32 CD-ROM and DVD-ROM (using MPEG-1/2).