Difference between revisions of "Image Formats (Apocalypse)"

From UFOpaedia
Jump to navigation Jump to search
m (categorizing)
(Graphic data update)
Line 9: Line 9:
 
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).
 
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).
+
==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.
  
When loading the following PCK archives (which contain terrain data), you must multiply the values of each TAB record by four:
+
==Image Header==
 
+
The first twelve bytes of each image in the PCK are a header:
* 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:
 
  
 
{| class="wikitable"
 
{| class="wikitable"
Line 53: Line 47:
 
|}
 
|}
  
It seems you can ignore the dimensions in the header, though you should probably expect them to be accurate.
+
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.
 
The image data then proceeds according to the compression mode used by the sprite.
Line 73: Line 68:
 
!0-3
 
!0-3
 
!0x00-0x03
 
!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.
+
|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).
(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).
+
To make the Y co-ordinate relative to the individual sprite, you can subtract the "Top-Most pixel" from the header.
 
 
If this is 0xFF FF FF FF, then stop rendering, you've hit the end of the sprite.
 
 
|- valign="top"
 
|- valign="top"
 
!4
 
!4
 
!0x04
 
!0x04
|The column to start rendering at (again).
+
|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.
 
|- valign="top"
 
|- valign="top"
 
!5
 
!5
Line 89: Line 83:
 
!6
 
!6
 
!0x06
 
!0x06
|Always 0 (probably part of the previous index).
+
|Always 0 (Assuming "Left Padding")
 
|- valign="top"
 
|- valign="top"
 
!7
 
!7
 
!0x07
 
!0x07
|Add one to this value then multiply by four to get the amount of pixels this record contains (... again).
+
|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)
 
|- valign="top"
 
|- valign="top"
 
!8 ...
 
!8 ...
 
!0x08 ...
 
!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.
+
|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
 
|-
 
|-
 
|}
 
|}
Line 161: Line 156:
 
==Compression mode: 128==
 
==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).
 
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).
 +
 +
=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
  
 
[[Category:Game Files]]
 
[[Category:Game Files]]
 
[[Category:Apocalypse]]
 
[[Category:Apocalypse]]

Revision as of 18:38, 16 July 2014

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.


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).

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