PAA File Format: Difference between revisions
mNo edit summary |
m (paa moved to PAA File Format: naming consistence) |
(No difference)
|
Revision as of 14:12, 22 November 2008
PAA texture file structure
Introduction
Of the many image file formats 'out there', such as jpeg, such as gif. BI choose to use a specially developed file format (paa) as the base texture file for all engine types.
The reason for this is the raw data within the file can be passed directly to Microsoft's Direct X as a DXT1 picture (eg) without further massaging.
While all engines except Elite also support JPG files, PAA files can result in much better performance.
Main Format
Overall structure of a Paa file is
struct overall { ushort TypeOfPaa; struct HeaderTags {...}; // OPTIONAL ushort EndofTags; // always zero struct MipMap_DataBlocks{....}; byte EndOfMaps[6]; // always zero };
Every PAA file starts with a TypeOfPaa
ushort TypeOfPaa; // type of texture, known values are // 0xFF01 DXT1 compressed texture (may have 1 bit alpha map, check MSDN documentation for details) // 0x1555 Uncompressed RGBA 5:5:5:1 texture // 0x4444 Uncompressed RGBA 4:4:4:4 texture // 0x8080 Uncompressed Luminosity/Alpha map. Actual color of texture is derived from AVGCTAGG tag? // 0xFF03 XBox & ArmA only. DXT3 compressed texture // 0xFF05 XBox & ArmA only. DXT5 compressed texture // 0x4747 Uncompressed Index Palette texture(P8) SPECIAL CASE see notes // added TypeOfPaa working in Oxygen 2 Full: // 0xFF02 DXT2 compressed texture // 0xFF04 DXT4 compressed texture // 0x8888 RGBA 8:8:8:8 texture
followed by optional header tags
struct PAA_Tag { byte name[8]; // name of tag is actually reversed when written in file, // so OFFSTAGG would be written as GGATSFFO. See below for known tags. ULONG tag_size; // size of this tag byte data[tag_size]; // size * bytes of actual data }
followed by an EndofTags ushort of zero, indicating, no more tags !!
Special Case
TypeOfPaa 0x4747 Uncompressed Index Palette texture
This is a corrupt entry in the sense that it does not have a TypeOfPaa !!!!! It is the lead in bytes to a standard AVCGTAGG. The next block of data is, the palette. Followed by 'standard' mip-data blocks. Urrrrgh.
Indecipherable commentary from Feersum
If format not 0x4747 then end of header tag data is marked by UWORD 0x0000, else this is a `size of palette` and next block it`s a palette(sizeof = `size of palette` * 3) Palette storeg in BGR format.
HexDump
Known header tags
There are several knowns header tags.
OFFSTAGG
Sizeof Data (16 x ULONGS) Example: GGATSFFO = 6 entries 256 x 128 Size=16384 128 x 64 Size=4096 64 x 32 Size=1024 32 x 16 Size=256 16 x 8 Size=64 8 x 4 Size=16
MipMap data is presented in 'blocks'. One or more 'blocks' exist in a paa file.
This is a pointless and redundant tag that declares where each of these blocks are in the file, relative to start of file.
The location of each block is already known, relative to the size of the previous block (if any). So, although almost always present in paa files, it's use, is redundant.
This tag always contains 16 ULONG offsets. Each one is a hard offset to actual mipmap data relative to start of file.
Not all entries are used (obvuously) since most paa files contain less than 16 mipmaps. Unused offsets contain the value 0x00000000. There are no known examples of splattered offset entries. All offsets after the first 0 entry are 0 as well.
AVGCTAGG
Average Colour
Sizeof Data (1 x ULONG) example: GGATCGVA = FF443D39
This tag contains average color of texture, probably used in rendering 8:8 luminosity/alpha textures.
FLAGTAGG
Sizeof Data (1 x ULONG) example: GGATGALG = 0 // range, 0 to 2
Marks if texture contains transparency. Value 1 means basic transparency, 2 means alpha channel is not interpolated. This flag should be always present in LOD textures with 1-bit alpha with value of 2 or there will be "ghost outlines" on LOD textures when viewed from distance. Note that this flag must be present in texture file when binarizing model, because Binarize stores information about how to render textures in actual P3D file.
ArmA / Elite
Purpose of these tags are not yet known.
MAXCTAGG
Sizeof Data (1 x ULONG) example: GGATCXAM = FFFFFFFFF // no other value seen so far
Contains color of brightest pixel in texture?
SWIZTAGG
Sizeof Data (1 x ULONG) example: GGATZIWS = 0x05040203
Swizzle is apparently used to modify texture components processing like swizzle modifiers in pixel shaders. For example ArmA sky texture has green channel stored in alpha channel and inversed to take advantage from feature that in DXT5 64 bits are used for alpha channel in each block and 64 bits for RBG, giving double the accuracy to green channel as opposed to storing texture just normally.
Exact format of swizzle data is still unknown. swizzle data: char channelSwizzleA; char channelSwizzleR; char channelSwizzleG; char channelSwizzleB;
format of swizzle char: bits 7-4 = 0; bit 3 - "1" flag. All channel data must be set to 0xff; bit 2 - "negate flag". Channel data must be negated. bit 1-0 - number of color channel: 00 - Alpha channel 01 - Red channel 10 - Green channel 11 - Blue channel
for example (*_nohq.paa textures) swizzle data is: 0x05 - Alpha, Negated, stored in Red; 0x04 - Red, Negated, stored in Alpha; 0x02 - Green, Stored as is; 0x03 - Blue, Stored as is;
Mipmap data
After end-of-header marker, actual mipmap data follows. Tag OFFSTAGG (if supplied) contains (up to) 16 offsets. Each offset points to the following struct type (relative to start of the file).
struct Mipmap_Data { UWORD width; // width of this mipmap UWORD height; // height of this mipmap UCHAR size[3]; // size of compressed texture data. this is 24-bit unsigned integer. UCHAR data[size]; // actual texture data };
If OFFSTAGG is not supplied, then the next mipmap block is indicated by the size of the previous one.
Note that the size reflects the size of data in the file not the actual size if that data if is compressed.
The size of output data for Dct1 format is (width*height / 2)
Size of output data for Dct5 format is (width*height)
Texture types 0x4444,0x4747,0x1555, 0x8080 and 0x8888, ie, non DXT, are always stored in compressed format. See Example above for detailed look .
DXT1 textures are stored "as is" ( see ->DXTn compress/decompress).
Decompression Code
/* by Flea */ int LZSSDecode(unsigned char * in,unsigned char * out,int szin,int szout) { szin = szin > 0? szin: 0x7fffffff; int i, j, k, r = 0, pr, pi = 0,po = 0; unsigned int flags = 0; unsigned char buf[0x100F], c; for (i = 0; i < 0x100F; buf[i] = 0x20, i++); while (pi < szin && po < szout) { if (((flags >>= 1) & 256) == 0) { if(pi >= szin)break; c = in[pi++]; flags = c | 0xff00; } if (flags & 1) { if(pi >= szin || po >= szout)break; c = in[pi++]; out[po++] = c; buf[r++] = c; r &= 0xfff; } else { if(pi + 1 >= szin)break; i = in[pi++]; j = in[pi++]; i |= (j & 0xf0) << 4; j = (j & 0x0f) + 2; pr = r; for (k = 0; k <= j; k++) { c = buf[(pr - i + k) & 0xfff]; if(po >= szout)break; out[po++] = c; buf[r++] = c; r &= 0xfff; } } } return pi; }
End of Mipmap(s)
After last mipmap, there are six (6) bytes set to 0x00 to mark end of texture data. And,consequently, end of file. No further data is known to occur after this End mark.
Alpha channel interpolation
These two images visualize difference between alpha channel interpolation (FLAGTAGG header tag value).
FLAGTAGG = 1, interpolated alpha channel (default behaviour)
FLAGTAGG = 2, alpha channel interpolation disabled
Bibliography
Feersum's original posting on BIS forums: Paa/pac texture format documentation MSDN documentation on DXT1 textures: DirectX: Opaque and 1-Bit Alpha Textures Squish Compression DXTn compress/decompress