FAS is a file format used by @Oska's DeskMates for storing information about frames and sequences. An FAS file consists of the main header, the touch reaction bitmap, and "Sequences" and "Frames" sections, in that exact order. The format has four revisions: 0, 1, 2, 3. The differences between four revisions will be talked about later on. The values are labelled by myself. FAZ is just the FAS file but zlib-compressed with the DEFLATE algorithm at the default compression level. All integers in the file are in x86-style little-endian order. By default, they're signed unless specified otherwise.
Header
An FAS file always starts with a 68-byte header. It contains several values:
- name (length: variable, max length: 50) - A nul-terminated, variable ASCII string defining the file's name.
- revision (length: 2) - An unsigned integer specifying the revision number of the file.
- frameIDFirst (length: 2) - An unsigned integer representing the number of the first frame.
- frameIDLast (length: 2) - An unsigned integer representing the number of the last frame.
- frameWidth (length: 4) - An integer specifying the width of every frame in pixels.
- frameHeight (length: 4) - An integer specifying the height of every frame in pixels.
- frameSizeLow (length: 2) - An unsigned integer specifying the size, in bytes, of every frame, but restricted to lower 2 bytes of the 4-byte value. It is calculated as: (frameWidth * BPP + 31) // 32 * 4 * frameHeight
- dblHeaderCount (length: 2) - An unsigned integer specifying the number of unique pairs of BitmapInfo structures (each consisting of the bitmap information header and the color table): one for color, and one for masking.
- bitmapInfos (count: dblHeaderCount * 2)
Extra Information
- charNameXOR (length: 1) - An unsigned integer representing the XOR of ASCII values of the uppercased character name, used for verifying the character name. Revisions 1 and higher only.
- extraFilesEndOffset (length: 4) - An unsigned integer specifying the sum of lengths of this very variable, extraSprCount and the extraFiles array. Revisions 2 and higher only.
- extraSprCount (length: 2) - An unsigned integer specifying the number of additional FAS files to be listed. Revisions 2 and higher only.
- extraFiles (array length: extraSprCount): An array of nul-terminated, variable ASCII strings defining names of additional FAS files to be loaded. Revisions 2 and higher only.
- frameSizeHigh (length: 2) - The missing upper 2 bytes of frameSizeLow. It was done to accommodate bigger sprites. Revision 3 only.
- touchColors (length: 2) - An unsigned integer specifying the number of colors for the touch reaction bitmap.
- colTable (length: touchColors) - Functionally the same as the bmiColors member, but for the touch reaction bitmap.
- touchWidth (length: 4) - An integer specifying the width of the touch reaction bitmap, in bytes. It is calculated as: (frameWidth * log2(touchColors-1)/8)
- touchBitmap - The touch reaction bitmap itself.
Sequences
Header
The section always starts with an 8-byte header. It contains two values:
- dataLength (length: 4) - An integer representing the size of the section in bytes.
- sequenceCount (length: 4) - An integer specifying the number of sequences in the file.
Directory
The directory associates names of sequences with the textual data, that belong to them. It consists of a number of entries, each with a length of 8 bytes. The length of the directory is determined by the number given in the section. The structure of each entry is as follows:
nameOffset (length: 4) - An integer holding a pointer to the start of the sequence’s name in the file, relative to the beginning of lumps.
dataOffset (length: 4) - An integer holding a pointer to the start of the sequence's data in the file, relative to the beginning of lumps.
String data lumps
This is the meat of the section. It consists of a number of sequences, each with a corresponding name and a data lump (which is the formatted string). The structure of each entry is as follows:
- name (length: variable, presumable max length: 64) - A variable ASCII string defining the sequence's name. The name must be nul-terminated if less than 64 characters.
- data (length: variable) - A variable, nul-terminated ASCII string, representing a sequence of frame numbers, weighted random choices, shortcuts to play sound effects located in WAS/WA3 files, other sequences, FAS files in the demand_load_only_list.txt file, moving and fencing sprites, giving sprites other properties (like flipping and masking), etc. These parts in sequences are documented in the ReadMe for PyDeskMates, which I'm currently developing. (shameless plug)
Following the entries, on revisions 1 and higher, it has the new value:
- checksum (length: 1) - An unsigned integer representing a checksum of ASCII values of the uppercased file name (not the "name" variable) truncated to the lowest byte.
Frames
The following section contains values:
- frameCount (length: 4) - An integer specifying the number of frames in the file.
- frameIDs (array length: frameCount; length: 2) - An array of unsigned integers specifying individual numbers of every frame.
- frameHeaderIDs (array length: frameCount; length: 1) - An array of unsigned integers, assigning pairs of BitmapInfo structures to specific frames.
- frameBitmaps (array length: frameCount) - An array of frame bitmaps.