September 21, 1998 The FLIC file format
The original
FLIC
file format was described by its author (Jim Kent) in Dr. Dobb's Journal, March 1993. The main purpose of this document is to document the modifications and extensions that EGI (a FLIC compiler and player engine) adds to theFLIC
file format, but since you may not have Jim Kent's article, all standard file information is included as well.There are two "official" types of
FLIC
files:FLI
andFLC
(the names of these types refer to the filename extensions). TheFLI
files are the older format and are limited to a resolution of 320*200. The EGI compiler only writesFLC
files, but the EGI players can read and play both formats.A
FLIC
file stores a number of frames. Every frame contains an image and possibly a palette, a label, or other data. A "compatible"FLIC
file contains a ring frame so that the animation can be played repeatedly without a perceptible pause between the last frame and the first (the unpacking of the first frame, a complete image, is generally slower than a delta frame update). AFLIC
file that contains segments optionally contains a ring frame per segment.
FLIC
files are structured in a hierarchy of chunks. A chunk contains a fixed part and a variable part. The fixed part of every chunk contains the type and the size of the chunk. The rest of the chunk has no fixed format; it all depends on the chunk type. The purpose of the chunked structure is to allow new chunks to be added without breaking existingFLIC
players. A reader that does not understand some chunk type can just skip it (using the information from the fixed part of the chunk). The figure below shows the hierarchy of chunks in aFLIC
file.All "word" (two bytes) or "double word" (four bytes) values are stored in Little Endian (this is the byte order used by the Intel 80x86 processor series).
Overview of the FLIC file structure File header general file information Prefix chunk FLC files only Cel data chunk CEL files (identical to FLC files) Segment table chunk EGI files only Segment chunk information of every segment Huffman table chunk EGI files only Frame chunk Postage stamp icon, FLC files only Image data compressed or uncompressed Palette chunk colour data Image data compressed in various ways Bitmap mask chunk EGI files only Multilevel mask chunk EGI files only Label chunk EGI files only Region chunk EGI files only Wave audio chunk EGI files only User string chunk EGI files only Key palette EGI files only Key image EGI files only Ring frame chunk Palette chunk see above Image data see above Bitmap mask chunk see above Multilevel mask chunk see above Label chunk see above Region chunk see above Wave audio chunk see above User string chunk see aboveThe file header
A
FLIC
file starts with a 128-byte header, see the figure below for a C structure. Thetype
field contains:
0xAF11
For FLI
files0xAF12
For standard FLC
files (with an 8-bit colour depth).0xAF44
For FLIC
files with a colour depth other than 8. Currently, the DTA program is the only utility that makesFLIC
files with a colour depth of 1, 15, 16 or 24 bits, and EGI is currently not compatible with theseFLIC
files.0xAF30
For FLIC
files that use Huffman or BWT compression.??? Password protected FLIC
files have a scrambled type field, so that previous versions of EGI and otherFLIC
readers will identify them as invalid (or unknown)FLIC
files.For
FLI
files, the delay between two frames is in increments of 1/70 second;FLC
files specify the speed in milliseconds. The header for aFLI
file does not contain the offset of the first and second frames; the first frame is assumed to start directly behind the file header (no "prefix", "segment table" or "Huffman table" chunks) and the offset to the second frame is easily computed once you read in the header of the first frame. The purpose of storing the offset to the second frame is that, after playing the ring frame, the next frame to display is the second frame of the animation.Autodesk Animator Pro also stores the MS-DOS formatted date and time stamps of the initial creation and last update of the
FLIC
file, as well as the serial number of the copy of the Animator Pro program that made/updated the file (in thecreator
andupdater
fields). Other utilities set thecreator
field to:
0
Unknown (Pro Motion, DTA, VFD or other) 0x45474900
EGI 0x464c4942
FlicLib 0x42494c46
FlicLib - release 2 0x41544542
Micrografx Simply3D 0x30314c46
Kinetix 3DStudio MAX The
frames
field in theFLIC
file header does not include the ring frame that loops back to the beginning of the animation.The
flags
field is used internally by Autodesk Animator Pro. If aFLIC
file is written to disk and closed correctly, Animator Pro sets this field to 3. Most other utilities set it to zero.
The FLIC file header typedef struct { DWORD size; /* Size of FLIC including this header */ WORD type; /* File type 0xAF11 or 0xAF12 */ WORD frames; /* Number of frames in first segment */ WORD width; /* FLIC width in pixels */ WORD height; /* FLIC height in pixels */ WORD depth; /* Bits per pixel (usually 8) */ WORD flags; /* Set to zero or to three */ DWORD speed; /* Delay between frames */ WORD reserved1; /* Set to zero */ DWORD created; /* Date of FLIC creation (FLC only) */ DWORD creator; /* Serial number or compiler id (FLC only) */ DWORD updated; /* Date of FLIC update (FLC only) */ DWORD updater; /* Serial number (FLC only), see creator */ WORD aspect_dx; /* Width of square rectangle (FLC only) */ WORD aspect_dy; /* Height of square rectangle (FLC only) */ WORD ext_flags; /* EGI: flags for specific EGI extensions */ WORD keyframes; /* EGI: key-image frequency */ WORD totalframes; /* EGI: total number of frames (segments) */ DWORD req_memory; /* EGI: maximum chunk size (uncompressed) */ BYTE reserved2[28]; /* Set to zero */ DWORD oframe1; /* Offset to frame 1 (FLC only) */ DWORD oframe2; /* Offset to frame 2 (FLC only) */ BYTE reserved3[40]; /* Set to zero */ } FLIC_HEADER;The modifications that EGI made to the
FLIC
file header are subtler. Not only are there a few added fields, but you must also decide whether the fields are valid:
- First verify that the
FLIC
file is created by EGI. The "creator
" field of theFLIC
file header is not equal to0x45474900
, theext_flags
field is not valid.- The
ext_flags
field indicates what extensions were used. If this value is zero (no extensions) the file is a "compatible"FLC
file.bit meaning0 file contains segments (segment table present) 1 file contains key images at regular intervals 2 all frames have an identity palette 3 file is Huffman compressed 4 file is BWT-Huffman compressed 5 bitmap masks are present 6 multilevel masks are present 7 region data is present 8 file is password protected 9 animation file contains digitized audio- If the script contains "
segment
" instructions, the EGI compiler produces a segment table. The segment table will come right after theFLIC
header. Bit 0 of the "ext_flags
" field indicates whether there is a segment table in the file.- In a segmented file, the "
frames
" field is set to the number of frames in the first segment (excluding the optional ring frame). Likewise, the fields for the offsets to the first and second frames ("oframe1
" and "oframe2
") are set to those of the first segment.- The
totalframes
field is the total number of frames in all segments, including all ring frames.Chunks and subchunks
Every chunk starts with a 6-byte header, that contains the size (four bytes) and the type (two bytes) for the chunk. All chunks sizes should be rounded up to an even number of bytes. The values of the main level chunks are above
0xF100
, values of the subchunks are below 100 (decimal). As you can see in figure "Overview of the FLIC file structure", nearly all of the subchunks appear in the "frame" chunk.Chunks types are indicated in the
FLIC
file with a two-byte value, but Jim Kent's article tagged names on those values (these names appear to be extracted from the Animator Pro source code). For ease of writing, I use the same names, in the same glorious "ALL UPPER CAPS
" that has become common in discussing theFLIC
file format.
Overview of all chunks 3 CEL_DATA position and transparency 4 COLOR_256 256-level colour palette 7 DELTA_FLC (FLI_SS2) delta image, word oriented RLE 11 COLOR_64 64-level colour palette 12 DELTA_FLI (FLI_LC) delta image, byte oriented RLE 13 BLACK full black frame (rare) 15 BYTE_RUN (FLI_BRUN) full image, byte oriented RLE 16 FLI_COPY uncompressed image (rare) 18 PSTAMP postage stamp (icon of the first frame) 25 DTA_BRUN full image, pixel oriented RLE 26 DTA_COPY uncompressed image 27 DTA_LC delta image, pixel oriented RLE 31 LABEL frame label 32 BMP_MASK bitmap mask 33 MLEV_MASK multilevel mask 34 SEGMENT segment information 35 KEY_IMAGE key image, similar to DELTA_FLC 36 KEY_PAL key palette, similar to COLOR_256 37 REGION region of frame differences 38 WAVE digitized audio 39 USERSTRING general purpose user data 0xF100 PREFIX_TYPE prefix chunk 0xF1FA FRAME_TYPE frame chunk 0xF1FB SEGMENT_TABLE segment table chunk 0xF1FC HUFFMAN_TABLE Huffman compression table chunkThe rest of the document discusses these chunks and subchunks in detail. On the right of the caption for each chunk type is the product for which this chunk is valid. Autodesk Animator is not mentioned explicitly, because there exist (to my knowledge) no chunks that only Animator supports.
The prefix chunk contains (undocumented) settings and cel data. It usually appears in
PREFIX_TYPE all .CEL
files.typedef struct { DWORD size; /* Size of the chunk, including subchunks */ WORD type; /* Chunk type: 0xF100 */ WORD chunks; /* Number of subchunks */ BYTE reserved[8]; /* Reserved, set to 0 */ } PREFIX_HDR;
CEL_DATA all typedef struct { DWORD size; /* Size of the chunk, including subchunks */ WORD type; /* Chunk type: 3 */ WORD center_x; /* coordinates of the cel centre */ WORD center_y; WORD stretch_x; /* stretch amounts */ WORD stretch_y; WORD rot_x; /* rotation in x-axis (always 0) */ WORD rot_y; /* rotation in y-axis (always 0) */ WORD rot_z; /* z-axis rotation, 0-5760=0-360 degrees */ WORD cur_frame; /* current frame in cel file */ BYTE reserved1[2]; /* Reserved, set to 0 */ WORD transparent; /* Transparent colour index */ BYTE reserved2[38] /* Reserved, set to 0 */ } CEL_DATA;The
CEL_DATA
chunk is usually not present inFLC
files. Intermediate files used by Autodesk Animator Pro with the.CEL
extension usually contain aCEL_DATA
in the prefix chunk. TheCEL
files have the same format asFLC
files.
SEGMENT_TABLE EGI 1+ typedef struct { DWORD size; /* Size of this chunk, including subchunks */ WORD type; /* Chunk type: 0xF1FB */ WORD segments; /* Number of SEGMENT chunks that follow */ } SEGMENT_TABLE;If a segment table is present, it overrules the values in the header (number of frames, offsets to the first and second frames).
SEGMENT EGI 1+ typedef struct { DWORD size; /* Size of this chunk (always 32 bytes) */ WORD type; /* Subchunk type: 34 */ WORD label; /* Label of the segment (user value) */ BYTE reserved1[2]; /* Reserved, set to zero */ WORD cont_image; /* "continued from" image id */ WORD last_image; /* id of the last image of this segment */ WORD flags; /* Flags */ WORD frames; /* Number of frames in the segment */ DWORD oframe1; /* File offset to frame 1 of the segment */ DWORD oframe2; /* File offset to frame 2 */ WORD next_segment; /* segment number of segment to proceed with */ WORD repeat; /* repeat count (0=indefinitely) */ BYTE reserved2[2]; /* Reserved, set to zero */ } SEGMENT;The
flags
field contains four bit flags:bit meaning0 the segment contains a ring frame 1 the first frame contains a full image 2 the "next_segment" field of the structure is valid 3 audio must be synchronized with the animationIf bit 1 is set, the first frame contains either a full image, or a delta image plus a key image. In other words, bit 1 indicates whether the segment is a "launch point". See the EGI compiler instruction
launch_point
for more details.The
frames
field does not include the ring frame (if a ring frame is present).In a
FLIC
file has multiple segments and some of the segments are "continued" from other segments (see the compiler instructioncontinued_from
), a frame may contain both a full image (the key image) and a delta image. The EGI player uses thecont_image
andlast_image
fields to determine whether it can use the delta image (whose decoding is usually quicker than a full image), or whether it must decode the full image instead.When creating the
FLIC
file, the EGI compiler assigns each picture a unique number. It stores the number of the last image in a segment in thelast_image
field of theSEGMENT
structure. When you add acontinued_from
instruction to the segment, the compiler copies thelast_image
field of the segment that was specified in thecontinued_from
instruction to thecont_image
field of the current segment. The compiler then proceeds to create a delta image given the first image of the current segment and the last image of the "continued from" segment. A segment that is not continued from another segment has a value of0xFFFF
in thecont_image
field.The EGI player goes the opposite route. Assuming that the player just displayed the last frame of a segment, and at that moment you switch to another segment: if the
last_image
field of the current segment is the same as thecont_image
of the next field, the player decodes the delta image of the new segment. Otherwise it decodes the key image.
HUFFMAN_TABLE EGI 1+ typedef struct { DWORD size; /* Size of this chunk */ WORD type; /* Chunk type: 0xF1FC */ WORD codelength; /* Maximum length of the Huffman codes */ WORD numcodes; /* The number of codes */ BYTE reserved[6]; /* Must be set to zero */ /* The following three fields are repeated "numcodes" times */ WORD code; /* Huffman code */ BYTE length; /* Length of the Huffman code */ BYTE value; /* Byte value represented by the Huffman code */ } HUFFMAN_TABLE;See the "Compression" paper for information on the Huffman compression algorithm. This chunk is only present if bit 3 of the
ext_flags
of theFLIC
file header is set.
FRAME_TYPE all This chunk is defined by Autodesk Animator, but Pro-Motion and EGI extend it.
typedef struct { DWORD size; /* Size of the chunk, including subchunks */ WORD type; /* Chunk type: 0xF1FA */ WORD chunks; /* Number of subchunks */ WORD delay; /* Delay in milliseconds */ BYTE reserved[6]; /* Reserved, set to 0 */ } FRAME_TYPE;The
delay
value overrules thespeed
field in theFLIC
header; a value of zero indicates that the normal speed (from theFLIC
header) applies. Thedelay
field is an extension to the FLIC format, introduced by Cosmigo's Pro Motion.
COLOR_256 and COLOR_64 all The two subchunks with types 4 and 11 are identical, except that the range of the RGB values is 0-63 for
COLOR_64
(type 11) and 0-255 forCOLOR_256
(type 4).The data in the chunk is organized in packets. The first word following the chunk header is the number of packets in the chunk. Each packet consists of a 1-byte skip count, a 1-byte copy count and a series of 3-byte RGB values (the "copy count" gives the number of RGB triplets). If the copy count is zero, there are 256 RGB triplets in the packet. For example, the data to change colours 2, 7, 8 and 9 would appear as:
2 /* two packets */ 2,1,r,g,b /* skip 2 entries, change 1 entry */ 4,3,r,g,b,r,g,b,r,g,b /* skip 4, change 3 */
BLACK all All pixels in the frame have colour 0. This chunk has no data following the chunk header.
FLI_COPY all The data that follows the chunk header are the pixels of an uncompressed image of the frame. The number of pixels (bytes) are exactly width*height of the frame. The first pixel is for the upper left corner of the frame.
BYTE_RUN (FLI_BRUN) all The data following the chunk header is a full image that is compressed with byte oriented RLE. The first image of a segment and key frames are usually stored in a
BYTE_RUN
chunk.Each line of the image is compressed separately, starting from the top of the image. The first byte of each line is the packet count, it is ignored (and set to zero) for
FLC
type files, because it is now possible to have more than 255 packets on a line. Instead, the width of the frame image now is the criterion for decoding: continue decompressing until the number of uncompressed pixels becomes equal to the image width.Each RLE packet consists of a count byte and one or more data bytes. If the count byte is negative, its absolute value is the number of data bytes (following the count byte) to copy to the image: a literal run. If the count byte is positive, the single data byte that follows must be replicated in the image "count" times: a replicate run.
DELTA_FLI (FLI_LC) all This chunk is used for
FLI
type files; the newerFLC
format replaces this chunk withDELTA_FLC
(see below). The chunk contains the differences (the "delta") between the current frame and the previous frame.The first 16-bit word behind the chunk header is the line number (starting from the top of the image) for the first line in the image that differs from the previous frame. In other words, it is a line skip count. The second word is the number of lines in the chunk. The data for the lines themselves follow these two words.
Each line starts with a packet count for the line. Unlike the
BYTE_RUN
chunk, this value is significant because the "delta" need not to store the complete width of the frame image. The packets themselves follow the packet count. Each packet consists of a column skip count, an RLE count byte and zero or more data bytes. The column skip count is the number of pixels to skip (the number of pixels that did not change between the current frame and the previous frame) from the current position in the line. It can have a value of zero. The RLE count byte and the data bytes are similar to theBYTE_RUN
encoding: if the count is positive, that number of bytes is to be copied from the data to the image (literal run); if the count is negative, its absolute value is the replication count of the one data byte that follows (replicate run).Two pitfalls:
- The negative/positive meaning of the RLE count byte is reversed from that of the
BYTE_RUN
encoding.- The RLE count byte can be zero. This occurs when the number of pixels to skip is more than 255. In this case, skip count is split over two packets. The first of these contains a skip count of 255, a RLE count of 0, and no data following the RLE count. The skip count of the second packet holds the remaining number of pixels to skip.
DELTA_FLC (FLI_SS2) all This chunk is similar to the
DELTA_FLI
chunk, but it compresses the delta image differently. The data following the chunk header is organized into lines and each line is organized into packets. Every line starts with one or more word-sized "opcodes".The first word following the chunk header is the number of lines in the chunk. This count does not include "skipped" lines. Each line starts with one or more opcodes. One of the opcodes (the last) is the packet count. The highest two bits of the opcode word give its type:
Bit 15 Bit 14 Description0 0 Packet count for the line, it can be zero 0 1 Undefined 1 0 Store the opcode's low byte in the last pixel of the line 1 1 The absolute value of the opcode is the line skip countThe RLE compression of
DELTA_FLC
is similar to that ofDELTA_FLI
, but it is word oriented. The first byte of each packet is the column skip count; the second byte is the RLE count byte. Zero or more data words follow the RLE count byte. If the count is positive, that number of words of data is copied to the image; if the count is negative, one data word follows and the absolute value of the count tells how many times that word must be replicated in the image.The two pitfalls from the
DELTA_FLI
chunk apply here too (see above). A third is:
- The packet count for a line can be zero. This occurs when the frame image has an odd width and only the last pixel of a line changes. In that case, there is a "last byte" opcode for the line, but no further packets.
PSTAMP all typedef struct { DWORD size; /* Size of this chunk */ WORD type; /* Chunk type: 18 */ WORD height; /* Height of the postage stamp */ WORD width; /* Width of the postage stamp */ WORD xlate; /* Colour translation, always 1 */ } LABEL;A "postage stamp" is a reduced image of the first frame of an animation. A postage stamp created by Autodesk Animator Pro has the preferred size of 100*63 (the actual size can vary) and uses a universal palette.
The palette is an RGB cube with 6 levels of each red, green and blue. This totals in 216 colours. An arbitrary RGB value (where each component is in the range of 0-255) is mapped into the six-cube space using:
((6*red)/256) * 36 + ((6*green)/256) * 6 + (6*blue)/256 The
PSTAMP
chunk embeds another chunk. This is usually aBYTE_RUN
chunk or aFLI_COPY
chunk (for compressed and uncompressed images respectively). If the type of the embedded chunk is 18 again (the type ofPSTAMP
is also 18), that chunk contains a 256-byte colour translation table. The translation table maps every palette index of the first frame to the universal six-cube colour space. To display the postage stamp, a program decodes the image of the first frame and maps every pixel of that image to the six-cube colour palette (using the translation table).
DTA_BRUN, DTA_COPY and DTA_LC DTA These chunks are generated by the DTA program by Dave K. Mason for
FLIC
files with 15-bit, 16-bit or 24-bit colour depth.FLIC
files with these formats usually have a.FLH
or a.FLT
extension.In 24-bit
FLIC
files, pixels are made up of three bytes in the order B,G,R. In 16-bit files the colour values are packed into words (two byte pairs)e in "rrrrrggg gggbbbbb
" format. 15-BitFLIC
files have pixels packed into the format "0rrrrrgg gggbbbbb
".The
DTA_BRUN
chunk is numbered 25 (instead of 15 for a standardBYTE_RUN
). The Repeat/Copy value is still a byte, but it refers to a number of pixels to copy or repeat, not bytes.The
DTA_LC
chunk is numbered 27. Internally it is like chunk type 7 (DELTA_FLC
). It starts with a number-of-lines value. For each line, the packet is a signed word value. If it is negative then it represents a lines-to-skip and does not count toward the number-of-lines. Each non-negative packet begins with a skip counter. This is still a byte, but it represents a number of pixels to skip, not bytes. Next comes a repeat/copy packet. It represents a number of pixels to copy or skip, not words. (Though in a 16-bitFLIC
file, the pixels are words.) The copy chunk is numbered 26, although the standard "copy" chunk type 16 (FLI_COPY
)would do equally well: there is no decoding for copy chunks.
LABEL EGI 1+ typedef struct { DWORD size; /* Size of this chunk */ WORD type; /* Chunk type: 31 */ WORD label /* Label of the frame (user value) */ BYTE reserved[2] /* Reserved, set to zero */ } LABEL;The EGI API function
FlicPlay
sends a notification message if it encounters a label subchunk in a frame. The message is sent (using SendMessage under Microsoft Windows) after decoding (and displaying) the frame.
KEY_IMAGE EGI 1+ The same as
BYTE_RUN
, but a frame that has aKEY_IMAGE
chunk also contains aDELTA_FLC
from a previous segment. A player can decide (based on the transition it makes from segment to segment) whether to decode theKEY_IMAGE
and skip theDELTA_FLC
, or to decode theDELTA_FLC
and skip theKEY_IMAGE
. See theSEGMENT
chunk for more information.
KEY_PAL EGI 1+ The same as
COLOR_256
, but it is only present for key images.
BMP_MASK and MLEV_MASK EGI 1+ and EGI 2+ The chunk
MLEV_MASK
is defined as of EGI version 2.0; the chunkBMP_MASK
exists since EGI 1.0.The chunk starts (right after the chunk header) with four 16-bit words that give the bounding box of the mask. You can use this bounding box to speed up drawing operations, because you do not have to draw anything outside this box (all pixels are transparent outside the bounding box). The values are stored in the following order:
x y width height
.The mask data starts behind the bounding box. Each line is encoded separately. A line starts with a "line skip count", which indicates how many lines remain unchanged from the previous mask. It is a two-byte value. It is zero for every line in a full mask.
The bitmap data (for the mask bitmap) comes after the line skip count. The bitmap data is compressed with the same RLE encoding as the
BYTE_RUN
image. This means that if the first (type) byte is positive, it is followed by a single pixel that must be replicated; if it is negative, it is followed by a series of bytes that must be copied literally. In contrast to theBYTE_RUN
compression, no "packet count" byte is stored at the beginning of a scan line. Each scan line of the mask is compressed individually. Huffman and BWT compression do not apply to masks.The data of a bitmap mask (after compression) is a 1 bit per pixel (8 pixels per byte) bitmap with the same size as the frame image. Each bit that is set ("1") represents a transparent pixel in the frame image. Each bit that is cleared ("0") represents an opaque pixel.
A multilevel mask is an 8 bits per pixel bitmap (with the same size as the frame image). Each byte in the mask represents the transparency level of the corresponding pixel in the frame image. A value of 255 is fully transparent, and 0 is fully opaque.
A frame can contain both a full image and a delta image. This occurs, for example when a segment in a
FLIC
file is both "continued_from
" another segment and a launch point, or when the "key_frames
" instruction is used. The mask for a frame that contains both a delta image and a full image is always a full mask.
REGION EGI 1+ typedef struct { DWORD size; /* Size of this chunk */ WORD type; /* Chunk type: 37 */ WORD number; /* Number of rectangles that form the region */ /* The following four fields are repeated "number" times */ WORD x; /* Pixel coordinates of a rectangle */ WORD y; WORD width; /* Size of the region in pixels */ WORD height; } REGION;The EGI compiler stores the region of frame differences (see the
dif_region
instruction of the compiler's script language) by means of a grid. In the current release, the grid is composed of square tiles of 16*16 pixels. When a single pixel in a tile changes, all 256 pixels in that tile are flagged as "modified".Two neighbouring tiles that are both flagged as "modified" are combined into a single new tile. The edges of the resulting rectangular tiles are always snapped to the grid points. Therefore, each rectangle in a region of frame differences needs not to enclose the object at pixel precision. However, no rectangle will exceed the bounding box of all differences between two frames.
The purpose of a coarse grid is to avoid a large amount of very small areas. The cost of the overhead for every call to the
BitBlt
function for all these areas might be higher than the cost of blitting several pixels too many.
WAVE EGI 2+ typedef struct { DWORD size; /* size of this chunk */ WORD type; /* Chunk type: 38 */ WORD flags; WORD samplefreq; /* sample frequency */ DWORD overlap; /* sample overlap (in bytes) */ BYTE reserved[6]; /* always zero */ } WAVE;The
flags
value is a bit field.Bit Description0 Sample size is 16-bit (otherwise 8-bit) 1 Format is signed PCM (otherwise unsigned PCM) 2 Audio is stereo 3 First block of the audio stream (open/reset sound card/driver) 4 Last block of the audio stream (close sound card/driver)The digitized audio data follows the chunk. The format depends on the various flags. If audio is 16-bit, there are two bytes per sample, in Little Endian (Intel format). In unsigned PCM, the "silence" level is 128 for 8-bit samples and 32768 for 16-bit samples. For stereo audio the samples for the left and right channels are interleaved; the sample for the left channel precedes the sample for the right channel.
Currently, EGI only supports 8-bit unsigned PCM or 16-bit signed PCM. These are the same formats as used in the
.WAV
and the.VOC
file formats.An audio stream is often be stored in a single block. The audio starts at the frame in which the block occurs, and it continues to "sound" during the displaying of the next frames. Audio and animation are not necessarily synchronized. For these single block audio streams, both bits 3 and 4 in the
flags
field are set, andoverlap
is always zero.The audio stream can also be cut in various blocks. The first block contains enough samples to get from the current frame to the first key frame. The key frame contains another audio block with enough samples to get to the next key frame, etc. Here, the bits 3 and 4 of the
flags
field help to glue the blocks together to a sequential audio stream. Audio and animation should be synchronized to play back correctly. (The EGI player synchronizes animation and sound by default if the sound is cut into blocks.)To avoid gaps in the audio when synchronization is not perfect, each block contains more samples than strictly necessary. In the current implementation, EGI adds enough samples to go to one frame after each key frame. When sending a (next) block to the audio device, you should ignore the first
overlap
bytes from the audio data.You can jump in the middle of an animation, and this way, you can also jump in the middle of a multiple block audio stream. In this case, to get a proper synchronization, ignore the
overlap
field for the first audio block that you encounter.
USERSTRING EGI 2+ A zero-terminated ASCII string follows the chunk header. The
USERSTRING
chunk allows an application to store general-purpose strings (both for copyright information as for references to other files or data) in a frame.
Frequent errors
Unfortunately, several utilities create
FLIC
files that do not completely comply with the standard. MostFLIC
players attempt to detect and silently correct these errors. Below is a list of frequent errors inFLIC
files.
- The colour depth is set to zero. The colour depth must usually be 8, only DTA supports
FLIC
files with a different colour depth.- The offsets to the first and second frames are zero in an
.FLC
file. In fact, it appears that these are.FLI
files with a.FLC
header.- The offset to the second frame is set to an incorrect value. I have seen
FLIC
files where the offset to the second frame was set to zero, to the offset to the first frame, to the offset to the ring frame, or to a random value.DELTA_FLC
chunks are present in files with a.FLI
header. Since most players are combined.FLI
/.FLC
players, this is usually not a problem. However, aFLIC
file withDELTA_FLC
chunks should have a.FLC
header.- Chunk sizes are not rounded to an even number of bytes.
- The sizes of all sub-chunks in a frame chunk do not add together to the size in the frame chunk header. Sometimes the frame chunk appears to be padded with extra data behind the last frame. Sometimes the size a subchunk is incorrect (I have seen this with the
FLI_COPY
chunk).DELTA_FLC
chunks with a "line count" of zero. This is essentially an 8-byte chunk: 6 bytes for the chunk header and two bytes for the count of lines in the chunk. Since this count is zero, no lines with compressed data follows. Although this is (or should be) valid, theAAPLAY
engine crashes when it encounters such blocks. Therefore, utilities should avoid creating these chunks.
References
Kent, J.; "The FLIC File format"; Dr. Dobb's Journal, March 1996 (Volume 18, issue 3).
© ITB CompuPhase, 1997-1998, The Netherlands
http://www.compuphase.com