DPEG

From MultimediaWiki
Revision as of 09:36, 29 September 2022 by Kostya (talk | contribs) (Created page with "* 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 dat...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
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 format

Frames are split into 8x8 tiles decoded in scanning order. Full intra frame is merely a raw frame reorganised in tiles, scaled intra frame (flags 6 or 7) has 4x8 tiles with 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) {
              frame[pos + x + y * width] = *src++;
              run = *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
     }
   }
 }

Games using this format

Bloodwings: Pumpkinhead's Revenge