Difference between revisions of "Image Formats (Apocalypse)"
Bomb Bloke (talk | contribs) (Created page with "{{tocright}}Image file formats used by X-COM: Apocalypse. <br clear=all> =PCK= An advancement on the version used by the previous games, whi...") |
m (categorizing) |
||
Line 163: | Line 163: | ||
[[Category:Game Files]] | [[Category:Game Files]] | ||
+ | [[Category:Apocalypse]] |
Revision as of 12:49, 23 July 2013
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).
Each PCK file is again accompanied by a TAB file. Every image gets a four-byte record in the TAB which indicates where the image data for that sprite starts in the PCK; the image data ends where the next image begins (or EOF, whichever comes first).
When loading the following PCK archives (which contain terrain data), you must multiply the values of each TAB record by four:
- Ground (contains, um, ground tiles)
- Left (contains west walls)
- Right (contains north walls)
- Feature (contains "object" tiles)
- Animate (doors opening, etc)
The first twelve bytes of each record 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. |
It seems you can ignore the dimensions in the header, though you should probably expect them to be accurate.
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, relative to where the tile is supposed to be rendered (ignore what the header has to say about the image dimensions and assume co-ord 0x0). Divide this by 640 and round down to get the row to start rendering at. Take the modulo of this and 640 to get the column to start rendering at.
(If this sounds needlessly confusing, at run time the game doesn't need to think in terms of rows and columns and so doesn't bother with the math - it just jumps to the exact address in the display memory to start dumping the sprite at and offloads it. This value is a shortcut). If this is 0xFF FF FF FF, then stop rendering, you've hit the end of the sprite. |
4 | 0x04 | The column to start rendering at (again). |
5 | 0x05 | The amount of pixels this record contains. |
6 | 0x06 | Always 0 (probably part of the previous index). |
7 | 0x07 | Add one to this value then multiply by four to get the amount of pixels this record contains (... again). |
8 ... | 0x08 ... | From this point, read the amount of pixels specified by index 5 and render then left to right on the display. Skip any values of 0 encountered. |
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:
|
Compression mode: 128
I haven't looked into this one as of yet, but the context this mode is used in suggests it's mainly used for smoke clouds (which'd use lots of transparent pixels).