Animation File Format for PC Animate Plus (ANI) Version 6.0 Last revised: February 7, 1992 Bill Marsh Presidio Software, Inc. Scope. The animation file format used by the animation programs from Presidio Software is described in detail herein so software developers can write compatible animation files. This description also promotes a better understanding of the animation techniques used in these products. Animation File Overview. Animations consists of a series of pictures (called frames) which, when shown in rapid succession, appear to have motion. Due to memory and hardware limitations, the animation file does not store each of the frames. It stores the first frame and the difference between each frame and the next (called the delta). The animation file consists of four parts: 1. The animation header contains information about the animation file. 2. The initialization section contains the first frame and other data. 3. The animation section contains the deltas of the other frames and other data. 4. The loop section contains the deltas from any loops in the animation. 5. The final section contains position information about all frames in the animation. Following the animation header, the remainder of the file is organized into data 'chunks.' The first byte of each chunk is the chunk type. The length of each chunk is determined by the chunk type and possibly other information contained in the chunk itself. This document describes version 6 of the animation file format. The changes from version 5 are a different animation file header and added data chunks. Readers should be able to read the old and new formats. Writers should only write the new format. The chunk types currently defined are: Type Definition ---- ---------- 00 Difference Chunk. This chunk contains data which describes the difference (delta) between two frames. The length of this chunk varies depending on the length of the delta and the video mode. This type of chunk is obsolete and should only be supported for playback, if at all. Use chunk type 09, Compressed Difference instead (see below). 01 End Frame. This chunk marks the end of the initialization section or the end of a frame of data. This chunk is always one byte long. 02 Palette Data. This chunk contains palette information used to set or update the display palette. The length depends on the number of palette entries. 03 First Frame Data. This chunk marks the beginning of the first frame picture. Data in the first frame is compressed, so the length of this frame varies. This chunk is only found in the initialization section. This chunk also serves as the end marker of the initialization section. If this chunk is present, there will be no End Frame chunk. 04 Frame Time. This chunk contains the number of vsync pulses to delay before moving to the next frame. This chunk is always three bytes long. 05 Sound File. This chunk defines the file name of a sound effects file. The length of this chunk depends on the filename. This chunk is only found in the initialization section. 06 Sound Play. This chunk starts a sound effect. This chunk is always 3 bytes long. 07 Volume Set. This chunk sets the volume and pan for a given sound channel. This chunk is always 4 bytes long. 08 Not Used, reserved for future usage. 09 Compressed Difference. This chunk contains data which describes the difference between two frames. The length of this chunk varies depending on the length of the delta and the video mode. This is the new style difference chunk and all future animations should be made with this definition. 10 Loop Definition. This chunk defines a loop in the animation, either a 'ping-pong' loop, or a 'run' loop, with the loop ending either by loop count or events (key press, mouse button press, or external event). The basic chunk length is 4 bytes. If a loop count is used, an extra 2 bytes are added. If the loop type is a 'run' loop, an additional 2 bytes are added. 11 External Event Trigger. This chunk specifies an external event is to be triggered during playback. This chunk is always 2 bytes long. 12 Frame Info. This is a special data chunk which follows the last loop frame. This chunk contains the starting offsets of each frame (including all loop frames) from the beginning of the animation file. This position is also given in the file header to enable readers fast access to frame data. 13 Repeated Sound. This chunk is like the sound play chunk (06), except that is has a repeat count to repeat the sound a given number of times. This chunk is always 4 bytes long. 14 File Memo. This chunk contains an ASCII string which can mean anything the creating application wants it to. A full description of the animation header and each chunk type and its data follows. Data Formats. The animation file consists of bytes, words, and double words, in addition to the animation header structure. In all cases, standard Intel byte and word ordering is used: Least significant byte is in the first (least) position: Least significant word is in the first (least) position. Animation Header. The animation header consists of information necessary for the playback of the animation. The format of the header is given by the 'C' structure below. typedef struct { unsigned short magic; /* Animation Header Magic Number*/ unsigned char mode; /* Mode animation was recorded */ unsigned char vers; /* Animation version number */ unsigned short playback; /* Preferred Playback Flags */ unsigned short time; /* Time constant for display */ unsigned short frames; /* Number of frames in animation*/ unsigned short loops; /* Number of loop frames */ unsigned short width; /* Width of animation */ unsigned short height; /* Height of animation */ unsigned short colors; /* Number of colors in animation*/ long length; /* Length (in bytes) of data */ long frame_info; /* File offset to frame info */ } ANI_HEADER; Member Usage ------ ----- magic Identifies the file as an animation file. The value, 0x4E41, makes the ASCII letters 'AN'. This should be checked by any animation player to make sure the indicated file is actually an animation file. mode Video mode in which the animation was recorded. For the Presidio software products the available modes are listed in the following table: PC Animate Resolution ---------- ---------- 5 640 x 350 x 16 7 320 x 200 x 256 11 640 x 480 x 16 13 VESA 640 x 400 x 256 Color 14 VESA 640 x 480 x 256 Color 15 VESA 800 x 600 x 16 Color 16 VESA 800 x 600 x 256 Color 17 VESA 1024 x 768 x 16 Color 18 VESA 1024 x 768 x 256 Color 19 VESA 1280 x 1024 x 16 Color 20 VESA 1280 x 1024 x 256 Color 21 TARGA 256 x 256 x 32K Color 22 TARGA 512 x 256 x 32K Color 23 TARGA 512 x 512 x 32K Color 24 HiColor 320 x 200 x 32K Color 25 HiColor 640 x 400 x 32K Color 26 HiColor 640 x 480 x 32K Color 27 HiColor 800 x 600 x 32K Color 28 HiColor 1024 x 768 x 32K Color 29 HiColor 1280 x 1024 x 32K Color vers Animation File Format version. Currently, this version number is 6. All animation readers should check this number to make sure the version of the animation file is correct, so that the reader will not encounter data streams that it doesn't understand. playback Preferred playback mode. This member tells the reader which mode of playback is preferred for this animation. The encoding is divided between the looping mode, and the starting flags for the animation. The definitions of the member is as follows: +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ | 15| 14| 13| 12| 11| 10| 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ | | | | | | | Leave Last Frame +-+-+ | Hide First Frame | Auto-Start Animation 0 Loop 1 Ping Pong 2 Once 3 Forward Only All other bits (2-12) are not used at this time and should be set to zero. A Forward Only animation file does not use XOR pixels, but rather stores the actual new value for the pixel. These animations may not be played backwards or have ping-pong loops in them. time Initial frame time. This number represents the number of vertical sync pulses should be counted before proceeding to the next frame. This value is only the default value and, while playing, individual frames can have their own specific values (See the FRAME TIME data chunk) frames The count of animation frames stored in the animation. There are actually more frames stored in the file, the extra being the "loop frames." Readers should use this value to determine when to stop reading the animation file. Simply using the End-Of-File is insufficient because some file transport protocols, like XMODEM, pad the end of file with garbage data. loops The count of loop frames stored in the animation. Readers should use this value to determine when to stop reading the animation file. width The width in pixels of the animation file. This can be smaller than the resolution permits. height The height in pixels of the animation file. This can be smaller than the resolution permits. colors The number of colors in the animation file. This can be smaller than the resolution permits. length Number of bytes in the animation file after the initialization information until the frame information. This is used by the animation player to allocate memory to hold the animation data. frame_info Offset in the file to the location of the frame info data chunk. This chunk must follow the last loop delta. Old Animation Header. Prior to version 6, the animation header consisted of the following header: typedef struct { unsigned short magic; /* Animation Header Magic Number */ unsigned char mode; /* Mode animation was recorded */ unsigned char vers; /* Animation version number */ unsigned short time; /* Time constant for display */ unsigned short frames; /* Number of frames in animation */ long length; /* Length (in bytes) of data */ } OLD_ANI_HEADER; Member Usage ------ ----- magic Identifies the file as an animation file. The value, 0x4E41, makes the ASCII letters 'AN'. This should be checked by any animation player to make sure the indicated file is actually an animation file. mode Video mode in which the animation was recorded. For the Presidio software products the available modes are listed in the following table: PC Animate Resolution ---------- ---------- 5 640 x 350 x 16 7 320 x 200 x 256 11 640 x 480 x 16 vers Animation File Format version. Currently, this version number is 5. All animation readers should check this number to make sure the version of the animation file is correct, so that the reader will not encounter data streams which it doesn't understand. time Initial frame time. This number represents the number of vertical sync pulses should be counted before proceeding to the next frame. This value is only the default value and, while playing, individual frames can have their own specific values (See the FRAME TIME data chunk) frames The count of animation frames stored in the file. There are actually 'frames + 1' frames of information in the file, the extra being the "loop frame." Readers should use this value to determine when to stop reading the animation file. Simply using the End-Of-File is insufficient because some file transport protocols, like XMODEM, pad the end of file with garbage data. length Number of bytes in the animation file after the initialization information. This is used by the animation player to allocate memory to hold the animation data. Animation Chunk Descriptions. The following sections describe in detail the format of the chunk data types currently used in animation files. The chunk descriptions detail the information which follows the chunk type. End Frame Chunk (Type 01). The end frame chunk marks the end of a frame of data or the end of the initialization section of the animation file. It consists of only one byte. +--------+ | 0x01 | End Frame Chunk Type. +--------+ Palette Chunk (Type 02). The palette chunk contains a new palette to be used in the current animation. This chunk can be located either in the initialization section or the animation section of the animation file. When located in the initialization section it establishes the palette for the animation. When located in the animation section, it changes the palette for the current frame, and remains in effect until changed by another palette chunk. The palette chunk is only used for video modes which use a palette. The palette chunk is not used for animations which use the 32K color video mode. The format of a palette chunk is as follows: +--------+ | 0x02 | Palette Chunk Type. +--------+ | Size | Number of Palette Entries. If 0, 256 are used. +--------+ | Red | Red, Green, Blue triplets follow for each palette +--------+ entry given above. Palette data always starts at | Green | color index #0. Each color component is left +--------+ justified in the byte. | Blue | +--------+ | etc. | First Frame Chunk (Type 03). The first frame chunk contains the picture information for the first frame. This chunk type can only be found in the initialization section of the animation file. The picture is stored using a run-length-encoded compression known as 'Pack-Bits'. This method was chosen due to the ease of encoding and decoding the information. Each row is compressed separately, thus allowing a simple test for errors (each row should expand to exactly one row of pixels). The data, when compressed, is organized in bytes for video modes with 256 or less colors, or short words for video modes with 32768 colors. The format of the chunk is as follows: +--------+ | 0x03 | First Frame Chunk Type. +--------+--------+ | Number of Cols. | Number of Pixel Columns. +-----------------+ | Number of Rows | Number of Rows. +-----------------+ After this header, the data is organized into a stream of bytes or words, depending on the video mode as described above. Data is organized into runs of the same pixels or runs of unique pixels, determined by the value specified by the first data item, the count. If the count byte is less than 128, then the run is of unique pixels of that length. If the count is greater than 127, then the run is of duplicated pixels, each equal to the next data item. Here is an example of a decoder (for 16 or 256 color mode). The only difference for a 32768 color mode is that the data being read should be short words rather than bytes. int cols, rows, xx; unsigned char *buf, *pixel, data; unsigned count; cols = getword(); /* read the number of columns */ rows = getword(); /* read the number of rows */ buf = malloc(cols); /* Allocate space for row storage */ for( ; rows > 0; rows--) { xx = cols; pixel = buf; while(xx > 0) { count = getbyte(); if(count > 128) { count |= 0xFF00; /* extend sign */ count = -count + 1; /* correct length */ data = getbyte(); while(count-- > 0) { *pixel++ = data; xx--; } } else { count++; while(count-- > 0) { *pixel++ = getbyte(); xx--; } } } if(xx < 0) { /* Error, too many bytes read in! */ } /* Write data to screen here */ } Difference Chunk (Type 00). This data chunk is obsolete. It is included here for compatibility purposes only. New applications should support it for playback only, if at all. New animations should be written with the Compressed Difference Chunk (Type 09). The difference chunk contains the data which is different between two frames. This data chunk should only be located in the animation section or the loop section of the animation file, and it must be the last chunk type of the frame. This data is stored as the XOR of the pixels in the two frames, thus forward and reverse playback is possible. Each difference chunk contains pixels from the same row of pixels, no difference chunk crosses into another row. There can be more than one difference chunk describing changes to the same row of pixels. Also, it is best to combine runs of differences using XOR pixels of value 0 between runs, if the number of pixels is less than the number of bytes in the difference chunk header. This will reduce the number of difference chunk headers, saving space in the animation file. The chunk has a screen offset and a count of pixels in the chunk, followed by a video mode specific data stream containing the XOR pixels. The offset portion is a long word indicating an offset into screen memory, to the byte where the difference begins (For 16 color mode, the actual 'pixel' offset is used instead, to indicate which pixel, odd or even, is first changed). The count is a short word specifying the number of pixels to change. XOR pixels are packed into bytes for 16 color modes, with the first pixel located in the lower nybble (bits 0-3) and the second pixel located in the upper nybble (bits 4-7). For 256 and 32768 color mode, the pixels are loaded into bytes or words, respectively. The format of the chunk is as follows: +--------+ | 0x00 | Difference Chunk Type. +--------+--------+-----------------+ | Offset into Screen Memory | Offset to Pixel. +-----------------+-----------------+ | Count of Pixels | Count of Pixels. +-----------------+ | XOR Pixels | XOR Pixels +-----------------+ (16 bit shown, 32K color) | etc. | Frame Time Chunk. The frame time chunk represents the number of vsync pulses to display the current frame. This value overrides the value located in the animation header if present, and remains in effect until changed by another frame time chunk. This chunk should only be located in the animation section of the animation file. A frame time chunk value of 0 is a pause; the animation does not proceed until the left mouse button is clicked or the Spacebar is pressed. New animations should use the Loop Definition Chunk to encode a pause, as this new chunk has many more options for terminating a pause. The format of the chunk is as follows: +--------+ | 0x04 | Frame Time Chunk Type. +--------+--------+ | Vsync Count | Frame Delay Time. +-----------------+ Sound File Chunk. The sound file chunk contains the filename of a sound effect file. This file is then loaded and made available for playback when triggered be a sound play chunk. This chunk can only be located in the initialization section of the animation file. The sound file is assumed to be located in the same directory as the animation file. The format of the chunk is as follows: +--------+ | 0x05 | Sound File Chunk Type. +--------+ | Index | Sound Index Number. +--------+ | name | File Name, with a null character (0x00) +--------+ termination. | ... | +--------+ (Max of 13 bytes including the null) | 0x00 | +--------+ Sound Play Chunk. This data chunk is obsolete. It is included here for playback purposes only. And new animations should be written using the Repeated Sound Play Chunk. The sound play chunk signals the playback of a sound effect. It contains the playback channel to use and the sound index number of the sound effect. This chunk can be located in the initialization section or the animation section of the animation file. The format of the chunk is as follows: +--------+ | 0x06 | Sound Play Chunk Type. +--------+ |Channel | Sound Channel to play sound effect on. +--------+ |Sound ID| Sound Index of sound effect to play. +--------+ Volume Set Chunk. The volume set chunk sets the volume of a sound channel. It contains the channel to set, the value to set for the volume, and the value to set for the pan. This value remains in effect until changed by another volume set chunk. This chunk can be located in the initialization section or the animation section of the animation file. The format of the chunk is as follows: +--------+ | 0x07 | Volume Set Chunk Type. +--------+ |Channel | Sound Channel to set volume. +--------+ | Volume | Volume value. 0 = minimum, 255 = maximum. +--------+ | Pan | Pan value. 0 = Left, 255 = Right. +--------+ Compressed Difference Chunk. The compressed difference chunk contains the data which is different between two frames. This data chunk should only be located in the animation section or the loop section of the animation file, and it must be the last chunk type of the frame. This data is normally stored as the XOR of the pixels in the two frames, thus forward and reverse playback is possible. If the forward only playback mode is selected, the data is stored as the pixels from the forward frame only, so no XOR is necessary, and the animation can not be played backwards. The ddifference is organized in a line-by-line basis, with a count of the number of skip-difference packets, followed by the actual packets themselves. If the count of packets is negative, the absolute value of the count is the number of lines to skip until the next change. If the count of packets is zero, it is the end of all delta information for this frame. The skip-difference packets consists of an unsigned single byte skip count, followed by a single byte difference count, followed by a variable number of XOR pixels. If the difference count is negative, it is followed by one XOR pixel which is repeated the absolute value of the count times. There is only one compressed delta chunk per frame. +--------+ | 0x09 | Compressed Delta Chunk +--------+--------+ | Packet Count | Packet Count +--------+--------+ | Skip | Count of Pixels to skip. +--------+ | Diff | Count of Differences. +--------+ | XOR | XOR Pixels +--------+ | etc... | +--------+--------+ | Packet Count | Packet Count, etc. +--------+--------+ | etc... | Loop Definition Chunk. The loop definition chunk defines a loop in the animation. This loop can be either a 'run' loop or a ping-pong loop. In all cases, the loop must be twords the beginning of the animation from the current frame, or magical and unexpected things may occur! The chunk defines a frame which is looped to (or twords in the case of a ping-pong loop), and a situation which will break out of the loop. This loop break can be a specified loop count, an external event, key press, or mouse click. +--------+ | 0x0A | Loop Definition Chunk +--------+--------+ | Flags | Loop Flags. +--------+--------+ | Loop Target Frm | Frame Target. +--------+--------+ | Loop Frame No. | Loop Frame to use ('run' loop only) +--------+--------+ | Loop Count | Loop Count (if present) +--------+--------+ Loop Flags: BIT 0 -- Run/Ping Pong Select. If 0, selects a 'ping-pong' loop. If 1, selects a 'run' loop, and specifies that a loop frame number will be present in the chunk. BIT 1 -- Break on Loop Count. If 1, it uses a loop count to stop the loop, and specifies that a loop count will be present in the chunk. BIT 2 -- Break on Left Mouse Click. If 1, will break out of the loop when the left mouse button is pressed. BIT 3 -- Break on Enter key press. If 1, will break out of the loop when the Enter key is pressed. BIT 4 - 14 -- Break on External Event. External Events are defined by the player. BIT 15 -- Reserved. Should always be zero. Note: Bits 1 through 14 can be combined to form an 'OR' condition. For example, if bits 2 and 3 are both set, the loop will break if either a left mouse click or enter key is pressed. If bit 1 is set also, it will loop the maximum times waiting for the enter key press or mouse click. If only bits 4 - 15 are set, the player may interpret this as bits 2 and 3 set. If no condition bits are set, it is an unconditional loop. Note: To cause a Pause, set the frame target to the current frame, select a 'ping-pong' style loop, and set the flags depending on the method you wish to exit the pause. This allows better selection of controls than using the frame time. If a 'count' is given, this sets up a maximum time to wait for the external event, basically a (count * frame time) amount of time. In this case only, the player should not accept an unconditional loop. If no bits are set, the player should assume that bits 2 and 3 are set. External Event Trigger Chunk. The external event trigger chunk causes the reader to trigger a reader defined external event. This can be used to trigger other peripherals. +--------+ | 0x0B | External Event Trigger Chunk. +--------+ | Event | Event number to trigger. +--------+ Frame Info Chunk. The frame info chunk defines the offsets of all frames in the animation file. This can be used by readers to quickly locate the beginning of any frame in the animation file. The length of this chunk is determined by the number of frame and loop deltas in the animation. This chunk follows the last loop delta at the end of the animation file, and it's offset in the file is also contained in the header. The length of each frame can be calculated from the next frames offset (use the frame info chunk offset in the header for the last loop frame length). +--------+ | 0x0C | Frame Info Chunk. +--------+--------+--------+--------+ | Frame 1 Delta Offset | Offset to frame 1 (32 bits) +--------+--------+--------+--------+ | Frame 2 Delta Offset | Offset to frame 2 (32 bits) +--------+--------+--------+--------+ | etc... | +--------+--------+--------+--------+ Repeated Sound Play Chunk. The sound play chunk signals the playback of a sound effect multiple times. It contains the playback channel to use and the sound index number of the sound effect. This chunk can be located in the initialization section or the animation section of the animation file. The format of the chunk is as follows: +--------+ | 0x0D | Repeated Sound Play Chunk Type. +--------+ |Channel | Sound Channel to play sound effect on. +--------+ |Sound ID| Sound Index of sound effect to play. +--------+ | Count | Number of times to play sound. +--------+ Animation Memo Chunk. The animation memo chunk contains a NULL terminated ASCII string. This string can contain up to 42 bytes of data plus one byte of NULL termination. This chunk can only be located in the initialization section of the animation file. The format of this chunk is as follows: +--------+ | 0x0E | Animation Memo Chunk Type. +--------+ | String | ASCII string, with a null character (0x00) +--------+ termination. | ... | +--------+ (Max of 43 bytes including the null) | 0x00 | +--------+