This document is a work in progress based on the description and source code provided in the spr2gif utility written by ABel of TeamX. Spr2gif is written in Delphi (or a pascal variant?). However, here I will try to present the information in C style wherever possible.
I should point out that while I have written a loader that can parse all of the headers correctly, but I haven't yet implemented a decompression scheme needed for some .spr files, so my experience in some areas of this format is limited. I hope to document this page better once my loader is fully working.
It is my understanding that these sprites are not directly compatable with Fallout 1 & 2 because Fallout Tactics uses a different level orientation. Any effort to skew these images into a orientation suitable for Fallout 1 & 2 would result in a loss of quality (Bluring/Tearing).
Data types used in this document:[]
#define Uint32 unsigned integer // (4 bytes) #define Uint16 unsigned short integer // (2 bytes) #define Uint8 unsigned char // (1 byte) #define Sint32 signed integer // (4 bytes) #define Sint16 signed short integer // (2 bytes) #define Sint8 signed char // (1 byte) struct sString { Uint32 length; char *data; // no '\0' at end }; struct sPoint { Uint32 x; Uint32 y; }; struct sRect { Uint32 x1; // left Uint32 y1; // top Uint32 x2; // right Uint32 y2; // bottom };
Reading Strings:[]
in an .spr file, strings are stored in [pascal format?]. The string data is preceeded by a Uint32 containing the length of the string. There is no '\0' to terminate the string.
Sprite Header:[]
The sprite header is the first element in a .spr file. It is layed out as follows:
// SPR_HDR Uint8 [ 11 ] - '<sprite>' '\0' '4' '\0' - 11 bytes Uint8 [ 3 ] - unknown 3 bytes sPoint - centering coordinates Uint8 [ 3 ] - unknown 3 bytes Uint32 seq_count - sequence count SEQ_HDR[ seq_count ] - sequence headers Uint32 anm_count - animation count ANM_HDR[ anm_count ] - animaion headers IMG_HDR[ anm_count ] - image headers
Sequence Header:[]
// SEQ_HDR Uint32 itm_count - item count Sint16 [ itm_count ] - if this value is >= 0, it is the number of the frame in the ANM_HDR. values < 0 are unknown for now. Uint32 [ itm_count ] - unknown itm_count*4 bytes sString - sequence name Uint16 - ANM_HDR index containing the frames referenced by this sequence.
Animation Collection Header:[]
// ANM_HDR Uint8 [ 12 ] - '<spranim>' '\0' '1' '\0' Uint32 - .spr file offset of the image data, relative to the start of the .spr file. sString - animation collection name Uint32 frm_count - frame count Uint32 dir_count - directions per frame RECT [ frm_count * dir_count ] - bounding boxes for each frame of each direction
Parsing Image data:[]
At this point all of the headers should be fully parsed and we can proceed to load the image data. Each of the ANM_HDR structures in the SPR_HDR contains an offset in the file to some image data. The actual image data itself comes after a small header. This header is required because the image data is sometimes compressed.
Uint8 [ 14 ] - '<spranim_img>' '\0' Uint16 - if '1' '\0' - uncompressed - if '2' '\0' - compressed
Note that '1' and '2' are ascii characters, not data values. '1' in decimal is 49, and '2' is 50.
Compressed Image Data:[]
if the data is compressed the the header will continue like so:
Uint32 - data size after decompression Uint8 [ ... ] - raw, compressed image data
This is where the details get a little sparse since its not well documented, and im at this stage myself.
As far as I know there is no header entry to specify the size of the compressed data. Spr2Gif seems to infer the size of the compressed data by looking for the start of the next <spranim_img> entry and using the difference as the size.
Spr2Gif seems to use the ZLib library to 'inflate' the compressed data. I havent used ZLib before this project so until I can successfully decompress the image data there is not much more information I can provide. More information is availible by studying the source code for spr2gif.