Image Formats (Apocalypse)

From UFOpaedia
Jump to: navigation, search
Image file formats used by X-COM: Apocalypse.


PCK

An advancement on the version used by the previous games, which can now use a variety of different compression methods on different sprites within the same image archive.

Most images are about 48x64 (the bounds of a single tile), but the format leaves itself open to much larger dimensions (for example, the giant Megaspawns aren't split up into multiple "tiles" like the large units in the previous games (such as the Cyberdiscs) - they nearly double the average sprite dimensions as a result).

As before, the image data indexes into an palette consisting of 256 colours. There is a unique palette stored for every terrain, but they're mostly similar (after all, your units need to look the same regardless of where you send them).

TAB

Each PCK file is again accompanied by a TAB file. The TAB file contains a 32bit integer (4 bytes, little endian) per image. This value needs to be multipled by 4 to get the file offset in the PCK of the image header.

Image Header

The first twelve bytes of each image in the PCK are a header:

Offset
(Decimal)
Offset
(Hex)
Usage
0 0x00 Compression mode. If 0, stop reading, there's no image to load and even the header won't be complete.
1-3 0x01-0x03 Unknown, usually blank (unless the compression mode is 128).
4-5 0x04-0x05 Left-most pixel within the sprite. No data should be rendered further left of this point.
6-7 0x08-0x09 Right-most pixel within the sprite. No data should be rendered at this point or further.
8-9 0x08-0x09 Top-most pixel within the sprite. No data should be rendered higher above this point.
10-11 0x0A-0x0B Bottom-most pixel within the sprite. No data should be rendered at this point or lower.

Width = Right-Most pixel - Left-ost pixel Height = Bottom-Most pixel - Top-Most pixel

The image data then proceeds according to the compression mode used by the sprite.


Compression mode: 0

No image, don't render anything.


Compression mode: 1

RLE compression, but opaque pixels aren't compressed at all. The concept is fairly similar to that of the old PCK format (though it's been expanded out a bit). Keep reading & rendering records according to this pattern:

Offset
(Decimal)
Offset
(Hex)
Usage
0-3 0x00-0x03 Amount of pixels to skip from co-ordinate (0, 0). If this is 0xFF FF FF FF, then stop rendering, you've hit the end of the sprite.

You can calculate the Y co-ordinate for your row by taking the integer value of this divided by 640 (rounding down). To make the Y co-ordinate relative to the individual sprite, you can subtract the "Top-Most pixel" from the header.

4 0x04 Quick access to the X co-ordinate (so you don't have to calculate the modulus of the pixels to skip).

To make the X co-ordinate relative to the individual sprite, you can subtract the "Left-Most pixel" from the header.

5 0x05 The amount of pixels this record contains.
6 0x06 Always 0 (Assuming "Left Padding")
7 0x07 Right Padding. This is the number of pixels in the row you don't need to draw.

Pixels To Draw = (Amount Of Pixels) - (Right Padding)

8 ... 0x08 ... From this point, read the amount of pixels specified by index 5 and render then left to right on the display. Palette Index 0 is transparent


Compression mode: 2

Uncommon, not entirely certain it's used at all...


Compression mode: 3

I guess you could describe this as LZ77 compression. Start out by loading the contents of TacData\XCOM.BLK into RAM - this contains all the actual pixel data used by sprites via this mode. Keep reading & rendering records according to the below pattern.

If a given record starts with 0xFF FF FF FF, then stop rendering, you've hit the end of the sprite.

Offset
(Decimal)
Offset
(Hex)
Usage
0 0x00 The amount of sub-records to render on this row.
1 0x01 Usually, this is 128 minus the amount of pixels drawn by the first sub-record rendered on the previous row. I'm not strictly sure what this means or why it's there.
2 0x02 Unknown
3 0x03 The row this record is to be rendered on.
4 0x04 Sub-records. Read & render however many index 0 specified, on the current row:
Offset
(Decimal)
Offset
(Hex)
Usage
0 0x00 Column to start rendering, relative to where the last sub-record finished (or relative to column 0, if this is the first sub-record on the row).
1 0x01 Amount of pixels to render.
2-4 0x02-0x04 A three byte value that indexes into TacData\XCOM.BLK. Starting from this location, read however many bytes index 1 specified and render them left-to-right on the display.

Shadow sprites

These files contain a transparent 'dither' mask to render shadows etc. NOTE - These files do not seem to have the same first two bytes so that cannot be used solely to decide which 'compression format' each file is encoded with - for example 'tacdata/aliens/alien/poppers.pck (popper shadows) is this format with the first two bytes as '0x00 0x6e'. Which files are in this format may be 'baked in' to the executable, or it's a 'none of the above' clause.

It starts with an 8 byte header

Offset
(Decimal)
Offset
(Hex)
Usage
0 0x00 Compression format header (Always seems to be either '0x0' or '0x80')
1 0x01 Unknown - multiple different values seen
2-3 0x02-0x03 Unknown - always seems to be zero?
4-5 0x04-0x05 Width of the sprite
6-7 0x06-0x07 Height of the sprite

Following this are a number of 2-byte pairs implementing a RLE-like encoding, encoding pixels as a lookup into a 4 pixel wide lookup table of if each pixel is occluded or not

Offset
(Decimal)
Offset
(Hex)
Usage
0 0x00 Repeat count - the number of repeated 4-pixel units - if 0xFF (255) stop as you've reached the end of the image.
1 0x01 Index into a 7-entry lookup table for 4-pixel values

The stride of these images always seems to be 640 pixels (140 4-pixel units) - IE each row contains 640 total pixel values, but only the width specified in the header are actually drawn.

The lookup table looks like this:

Index
(Decimal)
Pixel value (0 = transparent, 1 = opaque)
0 0 0 0 0 (All transparent)
1 1 0 1 0
2 0 1 0 1
3 1 0 0 0
4 0 1 0 0
5 0 0 1 0
6 0 0 0 1

I do not know where the colour for the pixel is selected, maybe always black?

Strategic map tiles

These images are always 8x8 pixel format, they used to draw strategic maps:

Offset
(Decimal)
Offset
(Hex)
Usage
1-2 0x00-0x02 Pixel skip. If this is 0xFF FF, then stop rendering, you've hit the end of the sprite.You can calculate the Y coordinate for your row by taking value divided by 640.
3-4 0x03-0x04 The number of visible pixels in a row (the others are transparent).
5... 0x05 ... From this point, read the amount of pixels specified by 3 and 4 byte of header and render then left to right on the display. Palette Index 0 is transparent.

PCX

There are a number of images in PCX format, these are standard and most graphic packages can read them

MOUSE.DAT

This file contains 9 images with a resolution of 24 x 24 pixels, using 8bpp with a palette index