Some of the Redguard image data is stored in the TEXBSI.* files found in the FXART game directory. This document explains the format of these files as best that is known. It is assumed that you are at least slightly familiar with hex-editing and base-16 numbers. All of the texture files in the game and in the demo have been tested for any of the 'confirmed' markers.
Format Description
Each texture file is composed of multiple image structures, one following the other. The largest texture files in Redguard contain less than 100 images at the most. The image is always started with a 9 byte name identifier. If the image name is null (i.e., all 00h characters or 0 length) this indicates the end of a texture file. Following the name is a long integer representing the size in bytes the image takes up.
Size |
Type |
Info |
9 bytes |
string |
Name |
4 bytes |
long integer |
Image Size in bytes |
The size is not included for the last image in the file. The image size does not include the 13 bytes taken by name and size fields. The image is then divided into a number of sub-records, typically including the following in that order:
- Type
- Header
- Data
- End
The image sub-records have the following structure:
Size |
Type |
Info |
4 bytes |
string |
Name |
4 bytes |
long integer, Motorolal byte order |
Size in bytes |
The size of the sub-record again does not include the 8 bytes of header info. Please note that the sub-record size field is written with the Motorolalbyte order and not the usual Intel byte order. For instance, if we were writing the hex number AABBCCDDh to a file:
Intel Byte Order: |
DD |
CC |
BB |
AA |
Motorolal Byte Order: |
AA |
BB |
CC |
DD |
There are fields with a zero size indicating they contain no data. The possible image sub-records are described below.
Type: |
'BSIF' (this or IFHD are required) |
Size: |
Always 0 (Confirmed) |
Description: |
Appears to identify the image as a particular format. Perhaps the 'BattleSpire Image Format'? Requires a following 'BHDR' type sub-record. |
Type: |
'IFHD' (this or BSIF are required) |
Size: |
Always 44 (Confirmed) |
Description: |
This represents an 'Image Format Header' data structure containing header information for the current image. It appears that this and the 'BSIF' type sub-record cannot exist together.
short |
u1 |
always 0001h |
short |
u2[21] |
always 0000h |
|
Type: |
'BHDR' (Required) |
Size: |
Always 26 (Confirmed) |
Description: |
This is an image header structure for the 'BSIF' type image.
short |
x_offset |
} Most likely |
short |
y_offset |
} but unsure? |
short |
width |
|
short |
height |
|
char |
u1 |
(always 00h or 01h) |
char |
u2 |
(always 00/01/09h) |
short |
u3 |
(always 0000h) |
short |
u4 |
(always 0000h) |
short |
num_frames |
(always 0001-0010h) |
short |
u6 |
(0000-00FFh, 0041h occurs the most) |
short |
u7 |
(always 0000h) |
short |
u8 |
(always 0000h) |
char |
u9 |
(always 00/80/A3h, mostly 00h) |
char |
u10 |
(always 00/01/02h, mostly 01h) |
short |
u11 |
(always 0000/0004h, mostly 0000h) |
|
Type: |
'CMAP' (Optional) |
Size: |
768 (Confirmed) |
Description: |
A color map, or palette, for defining custom colors for the current image. The data is 256 colors written in RGB triplets. |
Type: |
'DATA' (Required) |
Size: |
Variable |
Description: |
This sub-record contains all the image data. If num_frames in BHDR is 1 then image data is array of width * height bytes (palette indices). If num_frames is >1 the there is first a list of height * num_frames offsets (each one is 32bit integer). Each group of height offsets points to rows of bytes (width in length) for one frame. Offset with value 0 would point at the beginning of the data in DATA sub-record, not the beginning of whole texture file. |
Type: |
'END ' (Required) |
Size: |
Always 0 (Confirmed) |
Description: |
Always the last sub-record in an image. Note that there is a space after the 'D'. |
Thus, a valid image format is composed of the following:
Image Header |
Required |
BSIF or IFHD |
Required |
BHDR |
Required |
CMAP |
Optional |
DATA |
Required |
END |
Required |
Texture Format Review
Here's a brief review of the texture format now that all the important stuff has been explained:
- Image #1
- Name (9 bytes)
- Size (4 bytes)
- Sub-Records ('BSIF', 'BHDR', 'END', etc...)
- Image #2
- Name
- Size
- Sub-Records
- ...
- Last Image
- Name (9 bytes) = (null or empty string)
Thus, if a texture file had no images it would just be 9 bytes in size, consisting of all 00h characters.