Wing Commander III MVE

From MultimediaWiki
Jump to: navigation, search

This document is based on the document 'Description of the Wing Commander III MVE Movie File Format' by Mike Melanson and Mario Brito found at http://multimedia.cx/wc3movie.txt.

In 1994, Origin, a video game company best known for its Ultima and Wing Commander franchises, released a third installment of their Wing Commander series. Wing Commander III made liberal use of interactive cinema scenes in which real actors recited dialogue against computer-generated backgrounds. Many of the scenes seem to consist of Luke Skywalker (rather, Colonel Blair played by Mark Hamill) sighing heavily while being berated, scolded, and generally disapproved of by other characters in the story.

Each MVE file stores multiple variations of the same scene. For example, a file might begin with the multimedia data for a character telling Blair, "You are a terrible pilot." The file stores indexing information that the game's engine uses to locate the multimedia data for 2 or more possible responses that the player can choose. So the multimedia data for "Am not!" and "<sigh> I guess you have a point" would follow the initial setup for the scene.

MVE files also transport text subtitles in English, German, and French. This completes the great multimedia fusion of video, audio, text, and interactivity.

File Format

MVE files use a mixture of big endian and little endian formats to represent multi-byte numbers.

A MVE file is a concatenation of a series of chunks. Each chunk takes the form of:

bytes 0-3  human-readable four-character code (FOURCC) chunk type
bytes 4-7  chunk size (not including 8-byte preamble)
bytes 8..  chunk data

In this case, the data size is stored in big endian format.

Note that the chunks must be aligned on 16-bit offset boundaries, even when the data size of a previous chunk is odd. For example, if a FBAR (contrived) chunk begins at offset 0x124 and has a data size of 0x3F, the next chunk will actually begin at offset 0x164 instead of 0x163.

The general layout of the MVE file format is as follows:

FORM header
  [file header]
  _PC_
  SOND
  BNAM
  SIZE
  [palette chunks]
  PALT chunk 1
  ..
  ..
  PALT chunk n
  [branch index]
  INDX chunk
  [branch]
  BRCH chunk
  SHOT chunk
    [shot data]
    VGA  chunk
    TEXT chunk
    AUDI chunk
    VGA  chunk
    AUDI chunk
    ..
    ..
  [next branch]
  ..
  ..


A MVE file begins with a FORM chunk. The format of this chunk is:

bytes 0-3   'FORM' chunk identifier
bytes 4-7   total file size, not counting the first 8 bytes
bytes 8-11  'MOVE'

The second FOURCC in the header is probably a sub-identifier for the file type. The FORM header is a common occurrence in game data files. The second fourcc (MOVE) helps distinguish this format from others.

The next chunk in a MVE file is a _PC_ chunk. Very little is known about it except for the fact that it distinguishes the PC format variation from the variation found on the 3DO version of the game.

bytes 0-3    '_PC_' chunk identifier
bytes 4-7    chunk size (usually 12)
bytes 8-15   unknown
bytes 16-19  total number of PALT chunks in the file

The next chunk in a MVE file is a SOND chunk:

bytes 0-3   'SOND' chunk identifier
bytes 4-7   chunk size (usually 4)
bytes 8-11  chunk data (meaning unknown)

The SOND chunk always appears to contain 0x03 0x00 0x00 0x00. Again, the exact function of this chunk is unknown.

A MVE file may have a BNAM chunk in the general header:

bytes 0-3   'BNAM' chunk identifier
bytes 4-7   chunk size
bytes 8..   name of the file

This chunk carries the name of the file.

A MVE file may have a SIZE chunk in the general header:

bytes 0-3    'SIZE' chunk identifier
bytes 4-7    chunk size (usually 4)
bytes 8-11   video width in big endian notation
bytes 12-15  video height in big endian notation

A MVE file has a default video resolution of 320x165. If this chunk appears in the header, it overrides the default resolution with the width and height fields.

Next, a MVE file will store 1 or more PALT palette chunks. There is usually one PALT chunk for each SHOT in the movie. However, it appears that some files store one palette for all shots in the file. An individual PALT chunk stores 256 red-green-blue triplets in this format:

bytes 0-3    'PALT' chunk identifier
bytes 4-7    chunk size (should be 256 * 3 = 768)
bytes 8-775  palette data, 256 color triplets

See the section "Obtaining The Palette" to understand how the file format stores colors.

After the PALT chunks, a MVE file stores a INDX chunk which will contain an index of all possible BRCH (branch) offsets in the file. The format of an INDX chunk is:

bytes 0-3   'INDX' chunk identifier
bytes 4-7   chunk size (number of BRCH chunks * 4)
bytes 8..   BRCH offsets in little endian format

Note that while most of the multi-byte numbers in a MVE file are in big endian format, the BRCH offsets are in little endian format.

After the INDX chunk, a MVE file stores a number of branches (the number is derived from the INDEX chunk). Branches are denoted by a BRCH FOURCC. Branches are directions that a scene can take. A branch consists of one or more shots in a row. Individual shots are denoted by a SHOT FOURCC.

A BRCH chunk is an empty chunk. It only serves as a file marker. But it is included here for the sake of document consistency and completeness:

bytes 0-3   'BRCH' chunk identifier
bytes 4-7   chunk size (always 0)

A SHOT chunk delimits an individual scene in a MVE file. The SHOT chunk has the following format:

bytes 0-3   'SHOT' chunk identifier
bytes 4-7   chunk size (always 4)
bytes 8-11  palette number in little endian format

The palette number specified which palette to use when rendering the video frames in this particular shot.

Following a SHOT chunk is an arbitrary number of video, audio and multi-lingual text chunks.

A video chunk has the FOURCC 'VGA '. Note the trailing space (ASCII 0x20) needed to complete the four-character code. This chunk has the following format:

bytes 0-3   'VGA ' chunk identifier
bytes 4-7   chunk size
bytes 8..   compressed video data

The video coding method is described in Wing Commander III MVE Video Codec

An audio chunk has the FOURCC 'AUDI'. This chunk has the following format:

bytes 0-3   'AUDI' chunk identifier
bytes 4-7   chunk size
bytes 8..   audio data

MVE files store audio data as signed, 16-bit, little-endian, monaural PCM data.

A text chunk has the FOURCC 'TEXT'. This chunk has the following format:

bytes 0-3   'TEXT' chunk identifier
bytes 4-7   chunk size
bytes 8..   text data

The data in a TEXT chunk contains 3 strings in the following format:

byte 0     number (n) of characters (including null) in string
bytes 1..  text string

The first string is the English subtitle, the second is German, and the third is French.

Playing and Seeking Through MVE Files

AUDI chunks contain 2940 bytes. This corresponds to 1470 16-bit audio samples. Since MVE files have a sample rate of 22050 Hz:

22050 samples/second * (1 chunk / 1470 samples) = 15 chunks/second

MVE files maintain a precise interleaving of VGA and AUDI chunks: VGA - AUDI - VGA - AUDI, etc. This is in contrast to many multimedia files which store 0.25 - 0.5 seconds of audio in a single chunk and then store multiple video frames in a row. Therefore, the framerate appears to be 15 frames/second.

TEXT chunks occur randomly in shots between AUDI and VGA chunks. They should be placed on screen at a time corresponding with the nearest video frame.

Many game multimedia formats are not designed for random seeking. They usually carry no indexing or video keyframe information. A MVE file does carry an index at the start of the file. However, it is only an index of branches. A branch can have many different shots. Fortunately, the first VGA frame after a SHOT chunk can be considered a keyframe. Thanks to the tight interleaving of the audio and video chunks, it is possible to seek through a MVE file by traversing chunks until the beginning of a requested shot is located.

Obtaining The Palette

The 768 color components described in each PALT chunk do not represent red, green, and blue values. In order to obtain the actual RGB components, each PALT component must be rotated left by 2 (or right by 6, if you prefer). The rotated number is then used as an index into a table to obtain the actual red, green, or blue component value, which ranges from 0..255. The 256-element palette conversion table is:

unsigned char wc3_pal_lookup[] = {
 0x00, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0E,
 0x10, 0x12, 0x13, 0x15, 0x16, 0x18, 0x19, 0x1A,
 0x1C, 0x1D, 0x1F, 0x20, 0x21, 0x23, 0x24, 0x25,
 0x27, 0x28, 0x29, 0x2A, 0x2C, 0x2D, 0x2E, 0x2F,
 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x38, 0x39,
 0x3A, 0x3B, 0x3C, 0x3D, 0x3F, 0x40, 0x41, 0x42,
 0x43, 0x44, 0x45, 0x46, 0x48, 0x49, 0x4A, 0x4B,
 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53,
 0x54, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C,
 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64,
 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C,
 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74,
 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C,
 0x7D, 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83,
 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B,
 0x8C, 0x8D, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92,
 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x99,
 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1,
 0xA2, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
 0xA9, 0xAA, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
 0xB0, 0xB1, 0xB2, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6,
 0xB7, 0xB8, 0xB9, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD,
 0xBE, 0xBF, 0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4,
 0xC5, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB,
 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD0, 0xD1,
 0xD2, 0xD3, 0xD4, 0xD5, 0xD5, 0xD6, 0xD7, 0xD8,
 0xD9, 0xDA, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE4, 0xE5,
 0xE6, 0xE7, 0xE8, 0xE9, 0xE9, 0xEA, 0xEB, 0xEC,
 0xED, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF1, 0xF2,
 0xF3, 0xF4, 0xF5, 0xF6, 0xF6, 0xF7, 0xF8, 0xF9,
 0xFA, 0xFA, 0xFB, 0xFC, 0xFD, 0xFD, 0xFD, 0xFD
};

As an example, the number 0x68 is written in binary as 01101000. Rotating left by 2 yields 10100001 = 0xA1. Index 0xA1 in the above table is 0xB1 which would be the actual color component used.

3DO Variation

Wing Commander III was also released for the 3DO system. The game used the same multimedia files with a few variations:

  • the files bear an extension of .mov
  • the initial header contains the characters '3DO_' instead of '_PC_'
  • there is a chunk tagged 'FINL' with a 0x14-byte payload near the front of the file
  • some files use a video chunk tagged by 'DFCL'
  • files that use 'VGA ' chunks for video appear to start new SHOTs with a new type of chunk called 'CEL '