DPEG

From MultimediaWiki
Jump to navigation Jump to search
  • Company: Escal Software GmbH
  • Extension: .dpg

This is a rather simple video format with tile-based frames that employs motion compensation.

Container format

The file starts with 256-byte header followed by frames starting with 32-bit little-endian frame size and one byte flags (both being zero means end of stream) plus some information at the end. If container has audio then 16-bit audio size and payload follow, otherwise all of the payload is video frame data.

Known header fields:

 +00 - some string
 +28 - another string
 +50 - always seven?
 +5A - width
 +5C - height
 +6A - some audio-related value
 +6C - sampling rate
 +6E - audio channels
 +70 - some start value
 +74 - some end value
 +8C - offset to the information at the end

Frame flags:

 1 - probably audio data presence flag
 2 - intra frame (768-byte VGA palette precedes the data)
 4 - intra frame is scaled 2x horizontally (i.e. every pixel is repeated twice; should be used together with intra flag)
 8 - inter frame

Video coding is described below, audio coding is IMA ADPCM.

Video format

Frames are split into 8x8 tiles decoded in scanning order. Full intra frame is merely a raw frame, scaled intra frame (flags 6 or 7) have each pixel in them repeated twice, inter frame may code tiles in different ways.

Inter coding:

 for each 8x8 tile {
   op = *src++;
   if (op & 0xC0) != 0xC0 {
     offset = (int16_t)((op * 256 + *src++) << 2) >> 2;
   }
   switch (op >> 6) {
   case 0:
     copy tile contents from the previous frame with given offset
     break;
   case 1:
     run = *src++;
     for (y = 0; y < 8; y++) {
       for (x = 0; x < 8; x++) {
         if (run == 0) {
           frame[pos + x + y * width] = *src++;
           run = *src++;
         } else {
           frame[pos + x + y * width] = prev_frame[pos + x + y * width + offset];
           run--;
         }
       }
     }
     break;
   case 2:
     run = *src++;
     raw = 0;
     for (y = 0; y < 8; y++) {
       for (x = 0; x < 8; x++) {
         if (raw) {
            if (!run) {
              frame[pos + x + y * width] = prev_frame[pos + x + y * width + offset];
              run = *src++;
              raw = 0;
            } else {
              frame[pos + x + y * width] = *src++;
              run--;
            }
         } else {
            if (!run) {
              run = *src++;
              frame[pos + x + y * width] = *src++;
              raw = 1;
            } else {
              frame[pos + x + y * width] = prev_frame[pos + x + y * width + offset];
              run--;
            }
         }
       }
     }
     break;
   case 3:
     switch (op & 0x3F) {
     case 0x3F:
       read raw 8x8 tile
       break;
     case 0x0F:
       read raw 4x4 tile and scale it twice
       break;
     case 0x03:
       read raw 4x4 tile and scale it four times
       break;
     case 0x01:
       offset = (int16_t)((src[0] * 256 + src[1]) << 2) >> 2;
       delta  = (int16_t)(src[2] * 256 + src[3]);
       src += 4;
       for (y = 0; y < 8; y++)
         for (x = 0; x < 8; x++)
           frame[x + y * width] = clip8(prev_frame[x + y * width + offset] + delta);
     case 0x00:
       real fill value for the tile
       break;
     default:
       do nothing
     }
   }
 }

Audio coding

Audio is coded as IMA ADPCM in the following format:

 16-bit LE - number of samples coded (including the one used for prediction)
 8-bit - predictor value
 8-bit - initial step

Compressed data is coded in nibbles, low nibble first. Initial predictor value is derived as (src[2] - 0x80) * 256.

Games using this format

Bloodwings: Pumpkinhead's Revenge