Outpost 2 File Formats · bei.pm
The file formats described on this page are based on the technical analysis of intellectual property by Dynamix, Inc. and Sierra Entertainment.
The intellectual property is now part of the Activision Publishing, Inc. / Activision Blizzard, Inc. estate and is currently owned by Microsoft Corp..
The information has been gathered through Reverse Engineering and Data Analysis for the purposes of archiving and interoperability with historical data.
No proprietary or confidential specifications were used.
The game is currently available for purchase as a download at gog.com.
The following series of articles documents my findings regarding the data formats in the real-time strategy game "Outpost 2: Divided Destiny", which was released by Sierra in 1997 and developed by Dynamix.
I focused primarily on analysing the game's data - and what to do with it - from around 1st November 2015 to 14th November 2015.
According to the information I have been able to gather so far, Dynamix - like many commercial companies - did not develop certain data formats specifically for Outpost 2, but also used them in other projects such as the Mechwarrior series (with modifications).
Regardless, it can also be noted that the innovative capacity of the file formats is quite limited and often builds on long-established concepts from common formats such as JFIF and RIFF.
Further information for interpreting the tables and data formats can be found under What is what?.
The data provided here is generally to be understood as Little Endian.
In conclusion, it can be said that reverse engineering was a lot of fun, even though it is not complete.
Of course, I can also only recommend playing the game yourself, as it offers interesting game mechanics.
Introduction
The data formats used by Outpost 2 have a structure reminiscent of JFIF/PNG - each data block always has an 8-byte header. Therefore, I will refrain from documenting the individual headers at the respective specific points and will only document deviations there.
The format is always as follows; the actual payload is then embedded within it:
Addr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | char | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Data type | Designation | Explanation |
---|---|---|---|
0x0000 | uint(32) | Magic Bytes | Contains information about what to expect in the next data block. Known values:
|
0x0004 | uint(24) | Block length | Contains information about the size (in bytes) of the following data block. This refers specifically to the raw payload data - the 8 header bytes are not included. |
0x0007 | uint(8) | Flags? | It is unknown what this block is specifically used for. In the volumes, this value is often 0x80, while in other files it is frequently 0x00. This suggests that it is a flag set. |
Volumes
The volumes are a data container for the game, similar to an archive format like a tarball. At least in Outpost 2, the format recognises only files - no folders. However, these could probably be simulated through appropriate filenames.
A volume consists of the volume header as well as several volume blocks that correspond to the actual files.
"Volumes" are the files with the extension 'vol'
in the game directory.
Addr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | char | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 56 | 4f | 4c | 20 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | V | O | L | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Data type | Designation | Explanation |
---|---|---|---|
0x0000 | uint(32) | Magic Bytes | |
0x0004 | uint(24) | Block length | |
0x0007 | uint(8) | Flags |
Volume Header
Addr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | char | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 76 | 6f | 6c | 68 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | v | o | l | h | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Data type | Designation | Explanation |
---|---|---|---|
0x0000 | uint(32) | Magic Bytes | |
0x0004 | uint(24) | Block length | |
0x0007 | uint(8) | Flags |
The Volume Header does not contain any user data.
It serves merely as a container.
The first entry in the Volume Header should be the Volume Strings, followed by the Volume Information.
Volume Strings
Addr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | char | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 76 | 6f | 6c | 69 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | v | o | l | i | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Data type | Designation | Explanation |
---|---|---|---|
0x0000 | uint(32) | Magic Bytes | |
0x0004 | uint(24) | Block length | |
0x0007 | uint(8) | Flags |
Addr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | char | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 76 | 6f | 6c | 73 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | v | o | l | s | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Data type | Designation | Explanation |
---|---|---|---|
0x0000 | uint(32) | Magic Bytes | |
0x0004 | uint(24) | Block length | |
0x0007 | uint(8) | Flags | |
0x0008 | uint(32) | Payload length | Indicates how many bytes of the following data are actually usable data. The remaining data in the volume strings list is evidently to be considered as garbage. In files with a later date, this 'remaining data' is 0x00, which could suggest shortcomings in the toolchain during the development of the game, meaning that a developer only addressed the proper initialisation of the buffers very late on, as it does not affect the game whether the data is initialised or not. |
0x000c | uint(8)[] | List of file names | This is a 0-byte terminated list of file names which, at least in the present data component, only expects ASCII characters. It is not necessary to analyse this data block in more detail when parsing the data, as the offsets of the file names are directly referenced in the volume information anyway. |
The volume strings refer to a list of file names that are contained within the volume.
Volume Information
Addr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | char | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 76 | 6f | 6c | 69 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | v | o | l | i | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Data type | Designation | Explanation |
---|---|---|---|
0x0000 | uint(32) | Magic Bytes | |
0x0004 | uint(24) | Block length | |
0x0007 | uint(8) | Flags |
The volume information contains more detailed information about the files. In a way, it is a sort of FAT directory entry (FAT = File Allocation Table).
The number of files is determined by dividing the block size by the length of the directory entries - 14 bytes.
The individual directory entries each have the following structure:
Addr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | char | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Data type | Designation | Explanation |
---|---|---|---|
0x0000 | uint(32) | Filename offset | Indicates at which offset (!) within the filename list (volume strings) the filename of the file is located. This refers to the beginning of the data block. |
0x0004 | uint(32) | File offset | Indicates the offset within the entire volume file where the file is located. |
0x0008 | uint(32) | File size | Indicates how large the file is in bytes. |
0x000c | uint(16) | Flags? | Apparently, it provides additional information about the file encoding.
|
Volume Block
Addr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | char | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 56 | 42 | 4c | 48 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | V | B | L | H | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Data type | Designation | Explanation |
---|---|---|---|
0x0000 | uint(32) | Magic Bytes | |
0x0004 | uint(24) | Block length | |
0x0007 | uint(8) | Flags |
A volume block is a container that holds files. It contains the file size redundantly once more - due to the block format - and is directly followed by the actual data.
Tiles
Addr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | char | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 50 | 42 | 4d | 50 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | P | B | M | P | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Data type | Designation | Explanation |
---|---|---|---|
0x0000 | uint(32) | Magic Bytes | |
0x0004 | uint(24) | Block length | |
0x0007 | uint(8) | Flags |
The tiles are a Bitmap graphic format specific to Outpost-2. They span 13 tilesets, referred to as "wells" (well0000.bmp
to well0012.bmp
), which are located within the volume maps.vol.
The tilesets / wells contain the following:
File Name | Content |
---|---|
well0000.bmp | A 32x32px blue graphic - ideal for testing whether your image loader works |
well0001.bmp | Contains light rock, mountain ranges on light rock, and countless variants of impact craters in light rock |
well0002.bmp | Contains light rock 'doodads' - elements that can be placed on light rock for decoration (or intentionally as structures, such as walls), including vegetation |
well0003.bmp | Contains a crust-like structure on light rock |
well0004.bmp | Contains dark rock, mountain ranges on dark rock, and countless variants of impact craters in dark rock |
well0005.bmp | Contains dark rock 'doodads' - elements that can be placed on dark rock for decoration (or intentionally as structures, such as walls) |
well0006.bmp | Contains a crust-like structure on dark rock, as well as transitions between light and dark rock |
well0007.bmp | Contains lava including 4-5 frames of animation for it |
well0008.bmp | Contains sand and countless variants of impact craters in sand |
well0009.bmp | Contains sand 'doodads' - elements that can be placed on sand for decoration (or intentionally as structures, such as walls) |
well0010.bmp | Contains 48 transitions from sand to light and dark rock |
well0011.bmp | Contains the polar caps of the map, with dark rock as the base |
well0012.bmp | Contains the polar caps of the map, with light rock as the base |
It is advisable for an accurate implementation not to render the tiles in advance for caching purposes, as the data for the day/night cycle still needs to be processed - and an enormous amount of data would accumulate.
The tiles are 8bpp graphics with an indexed palette, each with a resolution of 32x32 pixels, which are arranged in a grid. However, a tileset created in this way can accommodate far more.
The main container consists of 2 sections: head
and data
.
Tiles Header
Addr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | char | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 68 | 65 | 61 | 64 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | h | e | a | d | . | . | . | . | . | . | . | . | . | . | . | . |
0x0010 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Data type | Designation | Explanation |
---|---|---|---|
0x0000 | uint(32) | Magic Bytes | |
0x0004 | uint(24) | Block length | |
0x0007 | uint(8) | Flags | |
0x0008 | uint(32) | Version / Flags? | This could be a version indication of the file format; in all the files I have, the value |
0x000c | uint(32) | Width (Horizontal Resolution) | Indicates how wide the image file is (in pixels). For all wells in Outpost 2, the value |
0x0010 | uint(32) | Height (Vertical Resolution) | Indicates how tall the image file is (in pixels). In all wells of Outpost 2, the value |
0x0014 | uint(32) | Colour depth? | The meaning of this value is unknown. Since it contains the value |
0x0018 | uint(32) | Colour depth 2? | The meaning of this value is unknown. It may be a 'target' colour depth. |
Following this information, there will be a palette file available in the standardised RIFF format. The exact specification can be found - as the palettes appear elsewhere as well - under Palettes.
Tiles Data
Addr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | char | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 64 | 61 | 74 | 61 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | d | a | t | a | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Data type | Designation | Explanation |
---|---|---|---|
0x0000 | uint(32) | Magic Bytes | |
0x0004 | uint(24) | Block length | |
0x0007 | uint(8) | Flags |
Finally, the raw pixel data follows, line by line from the top left to the bottom right.
The data value for graphics, which are usually in 8bpp bitmap format, corresponds to the index of the colour in the colour palette.
The game engine likely renders the tiles *on demand*.
This seems to be partly due to the day-night cycle, which has 32 gradations of individual tiles. It appears that a 'little' is subtracted from the brightness value. Exact values have not yet been determined; I am working on the calculation basis
v *= (daylight / 48) + 0.25;
using the HSV data of the pixels, where daylight is a value from 0-31 and v is a value between 0-1. Furthermore, it should be noted that there is an additional margin of 16 tiles on each side of the map (which serves the invisible spawning of units).
Additionally, the day-night cycle only updates one column of the map per game cycle.
A sped-up day-night cycle therefore looks as follows:
PRT
Addr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | char | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 43 | 50 | 41 | 4c | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | C | P | A | L | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Data type | Designation | Explanation |
---|---|---|---|
0x0000 | uint(32) | Magic Bytes | |
0x0004 | uint(24) | Pallet length | Indicates, contrary to the normal block format, the number of palettes found in this file - not the length of the block in bytes. |
0x0007 | uint(8) | Flags | Probably, as usual, flags. However, I am not aware of any flags; since all the values I know correspond to |
I am not sure what PRT
stands for; one possibility might be 'Palette and Resource Table' - as this file, found as op2_art.prt in maps.vol, pertains to such a concept, or this would describe its function quite well.
This file contains a list of palettes, a table of all used bitmaps, all animation definitions, and a number of unknown data. It loosely follows the previous container format, as not all records adhere to this schema.
The CPAL
section (likely stands for Palette Container) encompasses only the palette data, indicating how many of the typically 1052-byte large 8-bit palettes are present.
The 1052-byte specification is not considered binding, as the palette format could potentially allow for different palette sizes. It only applies to the data set supplied with Outpost 2.
Following the palette lists, the bitmap list immediately follows without an introductory header; likewise, the animation lists follow directly after.
Both are each preceded by a uint(32) (or possibly uint24 + uint8 flags?) that contains the number of records.
Palettes
Addr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | char | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 50 | 50 | 41 | 4c | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | P | P | A | L | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Data type | Designation | Explanation |
---|---|---|---|
0x0000 | uint(32) | Magic Bytes | |
0x0004 | uint(24) | Pallet length | Indicates, contrary to the normal block format, the number of palettes found in this file - not the length of the block in bytes. |
0x0007 | uint(8) | Flags | Most likely, as usual, flags. However, I am not aware of any flags; since all the values I know correspond to |
The palette information is very straightforward to read.
It consists of a header and a data segment.
Palette Header
Addr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | char | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 68 | 65 | 61 | 64 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | h | e | a | d | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Data type | Designation | Explanation |
---|---|---|---|
0x0000 | uint(32) | Magic Bytes | |
0x0004 | uint(24) | Pallet length | Indicates, contrary to the normal block format, the number of palettes found in this file - not the length of the block in bytes. |
0x0007 | uint(8) | Flags | Most likely, as usual, flags. However, I am not aware of any flags; since all the values I know correspond to |
0x0008 | uint(32) | Pallet format version? | Probably defines which palette format version the palette follows. All Outpost2 palettes seem to have version |
Palette Data
Addr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | char | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | 64 | 61 | 74 | 61 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | d | a | t | a | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Data type | Designation | Explanation |
---|---|---|---|
0x0000 | uint(32) | Magic Bytes | |
0x0004 | uint(24) | Block length | |
0x0007 | uint(8) | Flags |
The data section includes the individual pallet entries. The number of pallet entries is determined by the block length / 4.
The individual entries have the following simple structure;
Addr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | char | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | -- | -- | -- | 04 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Data type | Designation | Explanation |
---|---|---|---|
0x0000 | uint(8) | Red component | Indicates the red component of the colour |
0x0001 | uint(8) | Green component | Indicates the green component of the colour |
0x0002 | uint(8) | Blue component | Indicates the blue component of the colour |
0x0003 | uint(8) | Unknown - Flags? | It is unclear what this value means, as it apparently is fundamentally |
Regarding the palettes, it can additionally be said that the following rules apply to palettes used for animations:
- The first colour is ALWAYS transparent, regardless of what value is specified there.
-
Palette entries 1-24 are to be considered as player colours in palettes 1-8.
Where the colours, apart from player 1, originate from is unclear to me.
I suspect that the remaining colours are hardcoded.
Bitmaps
Addr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | char | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
0x0010 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Data type | Designation | Explanation |
---|---|---|---|
0x0000 | uint(32) | Aligned width | Indicates the width of the pixel data rows in bytes - as they are aligned to 4-byte boundaries. This makes it quick to access a specific image row. It is unclear why this value is stored separately, even though it could be calculated. |
0x0004 | uint(32) | Offset | Indicates the offset of the first line in the bitmap |
0x0008 | uint(32) | Height | Specifies the height of the image in pixels |
0x000c | uint(32) | Width | Specifies the width of the image in pixels |
0x0010 | uint(16) | Type | Indicates the type of the image. It appears to be a bitmask:
|
0x0012 | uint(16) | Palette | Defines which palette from the PRT file should be used |
This data structure of the PRT file specifies how the bitmaps used for the sprites are constructed. These bitmaps serve as individual components, from which several are assembled into an animation frame of a sprite.
The actual image data, on the other hand, is hidden in the
op2_art.BMP in the game directory.
It is unclear why this bitmap file has a (mostly correct) RIFF bitmap header. It is likely that Outpost 2 uses system APIs to load the graphics by temporarily adopting this header and overwriting the relevant, varying fields.
The pixel data can be found in the BMP file at the position Offset + the uint32-offset, which can be found at address 0x000A in the BMP file (RIFF bitmap data offset), and again corresponds to the row-wise arrangement from the top left to the bottom right.
Monochrome 1bpp graphics can be drawn in such a way that colour 0 represents complete transparency, while colour 1 is a semi-transparent black/grey, as monochrome graphics are typically used for vehicle and building shadows in the animations.
This allows for a considerable amount of graphics to be assembled.
Animations
Now we come to the pinnacle of the disciplines within the Outpost 2 data formats:
The animations.
The animation lists begin with a global header, primarily serving data verification. Following this are the specific animation definitions, which are divided into three levels:
-
Animation
An animation is the highest instance; it represents the animation of a unit, a building, or a 'particle animation' (meteor impact, weather, explosion) in a specific starting condition. -
Frame
A frame is a single image within an animation. An animation can contain one or more frames. -
Subframe
A subframe is the information indicating that a specific bitmap should be drawn at a particular position of a frame under certain criteria. A frame can contain one or more subframes.
Next, we will directly follow with the individual animation definitions.
Addr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | char | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Data type | Designation | Explanation |
---|---|---|---|
0x0000 | uint(32) | Number of animations | How many animation data records are available? |
0x0004 | uint(32) | Number of frames | How many frames should there be in total? |
0x0008 | uint(32) | Number of subframes | How many subframes should be present in total? |
0x000c | uint(32) | Number of optional entries | How many "optional entries" are available. |
Animation
Addr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | char | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
0x0010 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
0x0020 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Data type | Designation | Explanation |
---|---|---|---|
0x0000 | uint(32) | Unknown 1 | Unknown information |
0x0004 | uint(32) | Bounding Box: Left | Specifies the left start (in pixels) of the Bounding Box. |
0x0008 | uint(32) | Bounding Box: Top | Indicates the upper start (in pixels) of the Bounding Box. |
0x000c | uint(32) | Bounding Box: Width | Indicates the width (in pixels) of the Bounding Box. |
0x0010 | uint(32) | Bounding Box: Height | Indicates the height (in pixels) of the Bounding Box. |
0x0014 | uint(32) | Offset: X | Indicates the horizontal midpoint of the animation |
0x0018 | uint(32) | Offset: Y | Specifies the vertical midpoint of the animation |
0x001c | uint(32) | Unknown 2 | Unknown Information |
0x0020 | uint(32) | Number of frames | Indicates how many animation frames are contained in this animation |
0x0024 | uint(32) | Number of windows | Indicates how many windows to apply when drawing |
The data from the top layer, the animation, primarily consists of administrative data - the Bounding box refers to the coordinates of the marker around the vehicle/building when it is selected and also indicates which area should be clickable.
The offset primarily determines the "zero point"; the point that needs to be added to or subtracted from the in-game coordinates. One could also say mathematically: the offset here refers to the origin of the coordinates.
The windows consist, just like the offset, of 4 uint(32) values per window, which specify an area that is considered usable for individual subframes. Drawing is not permitted outside the windows, unless it is specifically designated for the bitmap.
Frame
Addr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | char | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Data type | Designation | Explanation |
---|---|---|---|
0x0000 | uint(8) | Number of subframes and toggle for optional 1, 2 | This value contains:
|
0x0001 | uint(8) | Unknown 1 and toggle for Optional 3, 4 | This value contains:
|
0x0002 | uint(8) | Optional 1 | Unknown |
0x0003 | uint(8) | Optional 2 | Unknown |
0x0004 | uint(8) | Optional 3 | Unknown |
0x0005 | uint(8) | Optional 4 | Unknown |
Subframe
Addr | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF | char | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0x0000 | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . | . |
Offset | Data type | Designation | Explanation |
---|---|---|---|
0x0000 | uint(16) | Bitmap ID | Indicates which bitmap should be used for this subframe |
0x0002 | uint(8) | Unknown 1 | It is unknown - however, I strongly suspect that this relates to a render priority (Z-layer). |
0x0003 | uint(8) | Subframe ID | Indicates which subframe we are in |
0x0004 | sint(16) | Offset - Horizontal | Indicates where within the frame the subframe should be placed, or by how many pixels the bitmap should be shifted horizontally. |
0x0006 | sint(16) | Offset - Vertical | Indicates where within the frame the subframe should be placed, or by how many pixels the bitmap should be moved vertically. |
With this, we can now compose individual frames as well as complete animations accordingly, demonstrated here with a more complex animation, the animation with index 500.
Animation 500
Animation 500 shows how a Plymouth transporter, loaded with ordinary ore, is unloaded. This is one of the few animations that utilise the windowing functionality.
And so the complete animation can be assembled.
Unfortunately, there is still an issue with the upper loading hatch, as the corresponding bit in the graphic type information is not set.
Here are a few more beautifully animated sprites from the game:
User Interface
Now, what remains is the user interface of the game, which features a brushed metal look.
However, it is also evident that Dynamix did not need to reinvent the wheel; they are simply utilising the User32 and GDI32 APIs provided by Windows—particularly, they are employing the resource management capabilities of User32.
These can be extracted, for example, using programs such as Resource Hacker, developed as freeware by Angus Johnson, or - if one is hesitant to use Wine on Linux / Mac OS - with the wrestool included in icoutils.
Filename | Contents |
---|---|
Outpost2.exe | Contains only the game's icon, which depicts the space station in front of New Terra |
op2shres.dll | Includes graphics for UI elements such as borders, buttons, radio buttons, and checkboxes, as well as dialogue backgrounds, accompanying images for the story mission texts, and the main menu background graphic |
out2res.dll | Contains the in-game window decorations, icons for regular and special metal, the loading screen, graphics for dialogues, as well as additional cursor graphics, in addition to the animated ones in the game directory |