Original documentation: [[https://ext.3dodev.com/3DO/Portfolio_2.5/OnLineDoc/DevDocs/ppgfldr/smmfldr/cdmfldr/08CDM001.html|ppgfldr/smmfldr/cdmfldr/08CDM001.html]] ====== 3DO File Format ====== ---- %%The 3DO file format is a simple tagged format designed to be:%% * A target file format supporting the hardware features of the 3DO platform. * A common format for all available tools, allowing you to mix and match various tools on various platforms without running into file format incompatibilities. %%Each 3DO file consists of chunks. All chunks types (except one) are atomic, that is, they do not contain other chunks. Some chunks are, however, dependent on other chunks. This is explained in detail below.%% The 3DO file format currently defines chunks for images, cels, and simple flip-book type animations. It also defines several informational chunks for things like copyright notices. The one nonatomic chunk type is a wrapper type. An entire file (a concatenation of atomic chunks) can be "wrapped" in a single wrapper chunk. Wrapping is optional. Applications should be designed to handle either wrapped or unwrapped files. The 3DO Company plans to define additional chunk types in the future, including chunks for digital audio and for 3D objects. The 3DO Company intends to coordinate the process of defining new chunk types, and to maintain the central registry of chunk names and definitions. Developers are encouraged to define new chunk types and refine existing chunk types, since the entire development community benefits from having a common file format. ===== File Format Description ===== %%A file consists of one or more chunks. Each chunk contains:%% * The chunk header, which consists of a%% %%''chunk_ID''%% %%and the%% %%''chunk_size'' * The chunk body, containing the data. %%This section briefly discusses some special chunk types. The type definitions for all chunk types are listed in the next section. This%% ==== Wrapper Chunks ==== %%Wrapper chunks are the only chunks that can contain other chunks. A wrapper chunk must always be the first chunk in a file and must contain all other chunks in the file. The%%''chunk_size''%%of a wrapper chunk is therefore equal to the file size. A file need not be wrapped.%% * Unwrapped files are convenient because they can be concatenated to form new legal unwrapped files. * Wrapped files are convenient because they provide an easy way to check if a file is actually a 3DO file by looking for the%% %%''wrap_chunk''%% %%at the beginning of the file. On the Macintosh, you should give the file type `3DO ` to both wrapped and unwrapped 3DO files. ==== Packing of Data for Image Files ==== %%The native format for the target hardware is 555 chunky RGB. For all chunky files, numcomponents is 3 and numplanes is 1. The table below illustrates what happens with chunky files:%% Table 1: RGB chunky files (numplanes = 1) -------------------------------------------------------- File type |Discussion -------------------------------------------------------- 555 RGB |1 pixel is packed right-justified into 2 chunky |bytes. The value of the hvformat flag |determines the meaning of the |most-significant bit. -------------------------------------------------------- 24- bit |1 pixel is packed into 3 bytes. RGB chunky| | -------------------------------------------------------- 8-bit RGB |1 pixel is packed into 1 byte. The encoding chunky |is 332 RGB (or YUV); 3 bits of Red (or Y), 3 |bits of green (or U), and 2 bits of Blue (or |V). For display each component is expanded |into 5 bit quantities forming a 555 RGB (or |YUV) value. Red and Green are left-shifted |two bits, and Blue is left-shifted 3 bits. |The lower bits are 0-filled if hvformat = 0 |and copied from the high bits if hvformat = |1.Having hvformat = 1 allows you to represent |both pure white and pure black when going |from 332 to 555 mode. -------------------------------------------------------- For planar RGB files (numplanes =3), 1 component is stored right-justified in 1byte. For coded or color index images the data is packed as follows: Table 2: Packed data for coded images -------------------------------------------------------- Bits Per Pixel |Pixels Per Byte -------------------------------------------------------- 8 |1 -------------------------------------------------------- 6 |1 (right justified) -------------------------------------------------------- 4 |2 -------------------------------------------------------- 2 |4 -------------------------------------------------------- 1 |8 -------------------------------------------------------- A coded (color-indexed) image requires a PLUT (pixel lookup table) chunk containing at least 2**(bits per pixel) entries. ==== PLUT and Color Lookup Table Chunks ==== %%The PLUT (pixel lookup table) associates an entry in a color-indexed (coded) cel or image with a 555 RGB color value. The resulting 555 color is indexed once again through separate R, G, and B color lookup tables (CLUTs), which take a 5-bit index and yield an 8-bit color value. For more information, see the %%//3DO PortfolioGraphic's Programmer's Guide.// ===== Using Multiple Chunks ===== %%Information from more than one chunk may be needed to completely define an object. For example, a simple background image is defined by an image control chunk and a PDAT chunk.%% ''{image control chunk} {PDAT chunk containing the pixel values}''\\ %%The order of chunks in a file is important because several consecutive data chunks can share one preceding control chunk as follows:%% * Each chunk type has a%% %%//current value//. * When a file is read and a chunk is encountered, the chunk's values become the current value for that chunk type. * The current value for all chunk types is initialized to NULL at the beginning of a file. * When a data chunk is encountered, it is rendered in terms of the current values for all its components. %%Here are two examples of how multiple chunks are used in defining one object:%% Example 1: The 3DO format stores three separate backgrounds which share all image attributes (stored in the image control chunk): {image control chunk} {PDAT chunk} {PDAT chunk} {PDAT chunk} %%Example 2: 3DO format stores an animation using 10 cels, all the same size, and depth, half of which use one color table (PLUT) and the other half use another color table:%% {ANIM Control Chunk} {CEL Control Chunk} {PLUT Chunk} {PDAT} {PDAT} {PDAT} {PDAT} {PDAT} {PLUT Chunk} {PDAT} {PDAT} {PDAT} {PDAT} {PDAT} ==== Required and Optional Chunks ==== %%Data chunks have required chunks and optional chunks. If any required chunk has a current value of%%''NULL''%%the data chunk is undefined. For example a chunk of type cel data requires a cel control chunk and can optionally have a PLUT chunk.%% ===== 3DO File Format BNF ===== %%This section contains the BNF for the 3DO file format. If you're not familiar with that notation, you can also extract the information from the definition above and the chunk definitions below.%% {file} ::= {chunk} | {file}{chunk} {chunk} ::= {chunk_header}{chunk_body} {chunk_header} ::= {chunk_ID} {chunk_size} {chunk_ID} ::= `3DO ` | /* Optional wrapper chunk */ `IMAG' | /* Image Control chunk */ `CCB ` | /* CEL Control chunk */ `PDAT' | /* Pixel Data chunk */ `PLUT' | /* PLUT (Pixel Lookup Table) chunk */ `ANIM' | /* Animation Info */ `VDL ` | /* VDL (Video Display List) chunk */ `CPYR' | /* Copyright Notice */ `DESC' | /* Text description of image */ `KWRD' | /* Text Keywords for image */ `CRDT' /* Text credits associated with image */ {chunk_size} ::= /* Unsigned 32 bit integer */ /* Includes size of chunk_body plus size */ /* of chunk_header. chunk_size is 8 plus */ /* size of the chunk_body. */ /* Chunks must be Quad byte alligned. */ /* Chunks are padded with zeros to fill */ /* the quadword alignment. */ /* chunk_size does NOT include pad bytes */ {wrapped_file} ::= {wrap_chunk} {file} {wrap_chunk} ::= {wrap_chunk_ID}{chunk_size} {wrap_chunk_ID) ::= `3DO ` /* uppercase characters followed by one space */ ==== Storing Multibyte Numbers ==== %%The 3DO File Format uses big-endian format for storing multibyte numbers, which means that the most-significant byte is stored at the lowest address. This is the native byte order for the 68000 processor in the Macintosh and for the processor in the 3DO system.%% ===== Chunk Definitions ===== %%This section lists type definitions are used in chunk data structures.%% Integer types have the following definition: typedef signed char Int8; typedef unsigned char UInt8; typedef short Int16; typedef unsigned short UInt16; typedef long int32; typedef unsigned long UInt32; Fixed point types have the following definition: typedef Int32 Int1616; typedef UInt32 UInt1616; typedef Int32 Int1220; typedef UInt32 UInt1220; The following type describes a color in RGB 555 format typedef struct RGB555 { unsigned alpha : 1; unsigned red : 5; unsigned green : 5; unsigned blue : 5; } RGB555; The following types are also used by chunk definitions typedef unsigned char ubyte; typedef unsigned long ulong; typedef Int32 Color; typedef Int32 Coord; typedef Int32 CLUTEntry; typedef Int32 RGB888; ==== Chunk Structure Definitions ==== %%The wrapper chunk (see %%Wrapper Chunks %%above) has the following definition:%% typedef struct WrapperChunk /* Optional. Must be first if present */ { Int32 chunk_ID; /* `3DO ` Identifies wrapper chunk */ Int32 chunk_size; /* size of chunk including chunk_header */ ubyte data[1]; /* contains collection of atomic chunks */ } WrapperChunk; %%The image control chunk has the following definition.%% typedef struct ImageCC { /* `IMAG' Identifies image control chunk */ Int32 chunk_ID; /* size of chunk including chunk_header (24) */ Int32 chunk_size; /* width in pixels */ Int32 w; /* height in pixels */ Int32 h; /* may include pad bytes at end for alignment */ Int32 bytesperrow; /* 8,16,24 */ ubyte bitsperpixel; /* 3 => RGB (or YUV) , 1 => color index */ /* 3 => RGB (8 16 or 24 bits per pixel) */ /* 8 bit is 332 RGB (or YUV) */ /* 16 bit is 555 RGB (or YUV) */ /* 24 bit is 888 RGB (or YUV) */ /* 1 => coded meaning color index; */ /* Coded images require a Palette Chunk */ ubyte numcomponents; /* 1 => chunky; 3=> planar */ /* although the hardware does not support planar */ /* modes it is useful for some compression methods */ /* to separate the image into RGB planes or into */ /* YCrCb planes num components must be greater than */ /* 1 for planar to have any effect */ ubyte numplanes; /* 0 => RGB, 1 => YCrCb */ ubyte colorspace; /* compression type; 0 => uncompressed 1=Cel bit packed */ /* other compression types will be defined later */ ubyte comptype; /* 0 => 0555; 1=> 0554h; 2=> 0554v; 3=> v554h */ ubyte hvformat; /* 0 => (0,0), (1,0), (2,0) (x,y) is (row,column) */ /* 1 => (0,0), (0,1), (1,0), (1,1) Sherrie LRform */ /* 2 => (0,1), (0,0), (1,1), (1,0) UGO LRform */ ubyte pixelorder; /* image control chunk version identifier. 0 for now */ ubyte version; } ImageCC; %%The pixel chunk has the following definition:%% typedef struct PixelChunk { /* `PDAT' Identifies pixel data */ Int32 chunk_ID; /* size of chunk including chunk_header */ Int32 chunk_size; /* data. Semantics depend on previous chunks */ ubyte pixels[1]; } PixelChunk; ==== Cel Control Chunk ==== %%A Cel Control Chunk structure contains an actual CCB (cel control block) data structure, as required by the 3DO hardware. See the %%//3DO Portfolio Graphics Programmer's Guide //%%for descriptions of the fields in a CCB structure.%% typedef struct CCC { /* `CCB ` Identifies pixel data */ Int32 chunk_ID; /* size including chunk_header */ Int32 chunk_size; /* version number of struct. 0 now*/ ulong ccbversion; /* 32 bits of CCB flags */ ulong ccb_Flags; struct CCB *ccb_NextPtr; CelData *ccb_CelData; void *ccb_PLUTPtr; Coord ccb_X; Coord ccb_Y; long ccb_hdx; long ccb_hdy; long ccb_vdx; long ccb_vdy; long ccb_ddx; long ccb_ddy; ulong ccb_PPMPC; /* Cel Preamble Word 0 */ ulong ccb_PRE0; /* Cel Preamble Word 1 */ ulong ccb_PRE1; long ccb_Width; long ccb_Height; } CCC; %%An animation chunk describes the sequencing and timing the hardware should apply to a series of cels to create a flip-book animation. The %%''LoopRec ''%%structure is used by the %%''AnimChunk ''%%structure.%% typedef struct LoopRec { Int32 loopStart; /* start frame for loop in animation*/ Int32 loopEnd; /* end frame for loop in animation*/ Int32 repeatCount; /* repeats of looped portion*/ Int32 repeatDelay; /* number of 1/60s of a sec to delay each time thru loop */ } LoopRec; typedef struct AnimChunk { Int32 chunk_ID; /* `ANIM' Identifies ANIM chunk */ Int32 chunk_size; /* size including chunk_header */ Int32 version; /* current version = 0 */ Int32 animType; /* 0 = multi-CCB ; 1 = single CCB */ Int32 numFrames; /* number of frames for animation */ Int32 frameRate; /* number of 1/60s of a sec to display each frame */ Int32 startFrame; /* first frame. Can be non zero */ Int32 numLoops; /*number of loops in loop array. Loops execute serially */ LoopRec loop[1]; /* array of loop info. see numLoops */ } AnimChunk; %%The PLUT (pixel lookup table) associates an entry in a color indexed (coded) cel or image with a 555 RGB color value. The resulting 555 color is indexed once again through separate R, G, and B color lookup tables (CLUTs,) which take a 5- bit index and yield an 8-bit color value. For more information, see the%%//3DO Portfolio Graphics Programmer's Guide.// A PLUT chunk has the following definition: typedef struct PLUTChunk { Int32 chunk_ID; /* `PLUT' Identifies pixel data */ Int32 chunk_size; /* size of chunk including chunk_header */ Int32 numentries; /* number of entries in PLUT Table */ RGB555 PLUT[1]; /* PLUT entries */ } PLUTChunk; %%To construct a custom color lookup table, define a number of A_CLUT structures that are then pointed to by the CLUTCHUNK structure:%% typedef unsigned long vdlentry; /* contains RGB8 triple and control bits */ typedef struct A_VDL { Int32 palettePtr; Int32 dmaControl; vdlentry vdls[33]; /* VDL entries */ Int32 filler; /* 144 length for complex VDLs.*/ } A_VDL; typedef struct VDLCHUNK /* use for standard 33 entry vdl */ { Int32 chunk_ID; /* `VDL ` Identifies VDL chunk */ Int32 chunk_size; /* size including chunk_header */ Int32 vdlcount; /* number of vdls following */ A_VDL vdl[1]; /* VDL control words and entries */ } VdlChunk; %%There are several different text chunks:%% * CPYR-C String ASCII Copyright Notice * DESC-C String ASCII image description * KWRD-ASCII keywords, separated by `;' * KRDT-C String ASCII credits for image %%They have the following definition:%% typedef struct Cpyr { Int32 chunk_ID; /*`CPYR' Identifies pixel data */ Int32 chunk_size; /*size including chunk_header */ char copyright[1]; /*C String ASCII Copyright Notice*/ } Cpyr; typedef struct Desc { Int32 chunk_ID; /* `DESC' Identifies pixel data */ Int32 chunk_size; /* size including chunk_header */ char descrip[1]; /* C String ASCII image description*/ } Desc; typedef struct Kwrd { Int32 chunk_ID; /* `KWRD' Identifies pixel data */ Int32 chunk_size; /* size including chunk_header */ char keywords[1]; /* ASCII keywords, separated by `;' */ } Kwrd; typedef struct Crdt { Int32 chunk_ID; /* `CRDT' Identifies pixel data */ Int32 chunk_size; /* size including chunk_header */ char credits[1]; /* C String ASCII credits for image */ } Crdt;