This might not paste so well, so let me know if you want the text file.
Edit: Nope. It kinda didn't. All the tabs are lost so it's harder to tell where the loops are that read the data. (Triply nested loops in some parts). There are a few other misc notes I can include, as well as code locations, and decriptions of what the functions do. This should be enough to display all images and animations though. Certainly enough detail has been filled in to process the entire file and duplicate the functionality of the art viewer Cynex made. All that's really left is a few unknown fields to give proper names/descriptions too. I've also got a test VB app that parses through the whole file and can display the still images. I haven't really gotten around to using the animation data yet though.
Outpost 2 unit graphics file format
--------------------------------
Note: This format refers to OP2_ART.PRT.
Note: The pixel data for the unit graphics resides in OP2_ART.BMP
and the indexing information is found in OP2_ART.PRT (in maps.vol).
The .prt file contains the indexing information for the graphics
in the .bmp file. The .bmp file contains the pixel data for all the
unit graphics. It is structured like a regular Windows bitmap file
except that the palette section consists of all zeros. The palettes
are found in the .prt file.
Note: The pixel format and palette to use for a given images is
determined by the indexing structure found in the .prt file.
Typical image formats are 8 bpp, and 1 bpp (unit shadows/etc.)
The images also have variable size, which is specified in the
indexing structure.
Note: The palettes use the same loading code as is used for the
tileset files (well00??.bmp). The begining of this file is very
similar in structure to the tileset files.
Offset Size Description
------ ---- -----------
0x0 4 "CPAL" - Palette array section tag
0x4 4 (9) numPalettes
- - - - - - - - - - - - - -
0x8 1052*numPalettes An array of palettes is read from the file (numPalettes elements)
- - - - - - - - - -
4 "PPAL" - Palette section tag
4 (1048) sectionSize (including this int)
- - - - - - - - - -
4 "head" - section header tag (used to control the second level parser)
4 (4) sectionSize
- - - - - - - - - -
4 (1) numTagsLeft - number of tags left to expect at this level of parsing
- - - - - - - - - -
4 "data" - palette data section tag
4 (1024) sectionSize
- - - - - - - - - -
1024 paletteData - 256 palette entries of 4 byets each (RGBA format, reversed from what Windows uses by default for GDI)
- - - - - - - - - - - - - -
0x2504 4 (5390) numImages
- - - - - - - - - - - - - -
0x2508 20*numImages An array of image info structures (numImages elements of 20 bytes each)
- - - - - - - - - -
4 ScanlineByteWidth - number of bytes in each scanline of the image (this should be the width of the image rounded up to a 32 bit boundary)
4 DataPtr - The offset of the pixel data into the .bmp file
4 Height - height of the image in pixels
4 Width - width of the image in pixels
2 Type - type of image (also controls bit depth)
2 PaletteNum - index of the palette to use for this image (see palette section above)
- - - - - - - - - - - - - -
0x1CA20 4 (2079) numAnimations - how many times to loop in the next section
0x1CA24 4 (24185) numFrames (14 byte structures) - made up of overlayed frame component images
0x1CA28 4 (160922) numFrameComponents (6 byte structures) - components of a frame
0x1CA2C 4 (6012) numFrameOptional? (4 byte structures) - optional data associated with a frame
- - - - - - - - - - - - - -
0x1CA30 ... and the loading code gets really weird here
The following animation records are loaded in a loop
(Animation sequence data)
4 (0x1)
4 selectionBox.left (pixelX coordinate)
4 selectionBox.top (pixelY coordinate)
4 selectionBox.right (pixelX coordinate)
4 selectionBox.bottom (pixelY coordinate)
4 pixelXDisplacement (reverse direction from an offset, origin is center of tile)
4 pixelYDisplacement (reverse direction from an offset, origin is center of tile)
4 (0x0)
(0x3C CC/DIRT/Garage/Std. Lab construction/dock, 0x0D spider walking)
4 numFrames - number of frames in this animation
- - - - - - - - - -
The following is loaded from a loop
(Frame data)
1 numFrameComponents (if most significant bit is set then read first two optional bytes
1 (if most significant bit is set then read second two optional bytes)
- - - - - - - - - -
Load values into the 4 byte structure
(Conditionally load these bytes)
(FrameOptionalInfo)
1
1
- - - - - - - - - -
1
1
- - - - - - - - - -
The following is loaded from a loop
(Frame Component data)
2 imageInfoIndex (struct6.word3)
1 (0xFF) (unused/ignored)
1 frameComponentIndex (out of order components? why?)
2 pixelXOffset (left, struct6.word1)
2 pixelYOffset (top, struct6.word2)
- - - - - - - - - -
4 num???
- - - - - - - - - -
The following is loaded from a loop
(16 byte structure)
4
4
4
4
---------------------------
Note: The pixelXDisplacement/pixelYDisplacement in the Animation data gives a global displacement for all animation frames. It is in the reverse direction of a displacement and the origin is the center of the tile. Positive values will move the unit to the left and up from the center. Values of 0 will have the upper left corner of the unit start in the middle of the tile. Keep in mind that the pixelX and pixelY coordinates of the unit are stored relative to the middle of the tile it occupies. These displacement values are subtracted from the pixelX and pixelY values to find the location of the upper left corner of the image being drawn. Also keep in mind the space used for the hitpoint bar that appears above the unit. (Consider the hitpoint bar to be the top of the unit when determining placement).
Note: The pixelXDisplacement/pixelYDisplacement will affect all images draw using the animation sequence. This includes the icon of the unit in it's command pane when it is selected. (But only ever uses the first frame of the animation sequence where the unit is facing right).
Note: The selection box coordinates are given relative to the upper left corner of the unit. This is done after the displacement values are applied. Positive values are down and to the right.
Structures Used By Outpost 2
----------------------------
These structures were used by Outpost 2 during the load process. They don't really relate to the file format, but rather how Outpost 2 stores the data in memory after it's been loaded.
AnimationSequence
Size: 14 bytes
Offset Size Description
------ ---- -----------
0x0 2 0x7FFE (hardcoded initialization)
0x2
0x8 2 numFrameComponents - in this frame of animation (first single byte read AND 0x7F)
0xA 4 &(current 6 byte structure)
---------------------------
FrameComponentInfo
Size: 6 bytes
Offset Size Description
------ ---- -----------
0x0 2 pixelXOffset (Left)
0x2 2 pixelYOffset (top)
0x4 2 imageInfoIndex (Image to display in the frame at the given offsets)
FrameOptionalInfo?
Size: 4 bytes
Offset Size Description
------ ---- -----------
0x0 1
0x1 1
0x2 1
0x3 1