2 Test read and write IFF-85, Interchange Format File
3 Copyright (c) 2008 Erwin Coumans http://bulletphysics.com
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the use of this software.
7 Permission is granted to anyone to use this software for any purpose,
8 including commercial applications, and to alter it and redistribute it freely,
9 subject to the following restrictions:
11 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
17 * IFF Support routines for writing IFF-85 files. 12/02/85
18 * (IFF is Interchange Format File.)
19 * By Jerry Morrison and Steve Shaw, Electronic Arts.
20 * This software is in the public domain.
28 IFFP MyReadICat(GroupContext *parent)
30 printf("Found and skipped a CAT\n");
34 IFFP MySkipGroup( GroupContext * )
36 printf("Found and skipped a LIST\n");
40 typedef UBYTE Masking; /* Choice of masking technique.*/
41 typedef UBYTE Compression; /* Choice of compression algorithm applied to
43 /* A BitMapHeader is stored in a BMHD chunk. */
46 UWORD w, h; /* raster width & height in pixels */
48 WORD x, y; /* position for this image */
49 UBYTE nPlanes; /* # source bitplanes */
50 Masking masking; /* masking technique */
51 Compression compression; /* compression algoithm */
52 UBYTE pad1; /* UNUSED. For consistency, put 0 here.*/
53 UWORD transparentColor; /* transparent "color number" */
54 UBYTE xAspect, yAspect; /* aspect ratio, a rational number x/y */
55 WORD pageWidth, pageHeight; /* source "page" size in pixels */
61 BYTE bodyBuffer[bufSz];
63 static void btSwap(char* a, char* b)
70 #define ID_ILBM MakeID('I','L','B','M')
71 #define ID_BMHD MakeID('B','M','H','D')
72 #define ID_CMAP MakeID('C','M','A','P')
73 #define ID_BODY MakeID('B','O','D','Y')
75 #define ID_DYNAWORLD MakeID('B','T','D','W')
76 #define ID_RIGIDBODY MakeID('B','T','R','B')
77 #define ID_SID MakeID('S','I','D',' ')
78 #define ID_MASS MakeID('M','A','S','S')
79 #define ID_SHAPE MakeID('S','H','A','P')
82 #define ID_COLOBJ MakeID('C','O','B','J')
83 #define ID_CUBE MakeID('C','U','B','E')
84 #define ID_DIMENSIONS MakeID('D','I','M','E')
87 IFFP MyProcessGroup(GroupContext *parent)
89 /*compilerBug register*/ IFFP iffp;
90 GroupContext rigidbodyContext;
92 BitMapHeader bmHeader;
93 bool foundBMHD = false;
96 if (parent->subtype != ID_ILBM)
97 return(IFF_OKAY); /* just continue scaning the file */
99 iffp = OpenRGroup(parent, &rigidbodyContext);
103 iffp = GetFChunkHdr(&rigidbodyContext);
104 if (iffp == ID_BMHD) {
105 printf("found ID_BMHD\n");
108 iffp = IFFReadBytes(&rigidbodyContext, (BYTE *)&bmHeader, (long)sizeof(BitMapHeader));
110 bmHeader.w = endianSwap16(bmHeader.w);
111 bmHeader.h = endianSwap16(bmHeader.h);
112 bmHeader.pageWidth = endianSwap16(bmHeader.pageWidth);
113 bmHeader.pageHeight = endianSwap16(bmHeader.pageHeight);
116 else if (iffp == ID_CMAP) {
117 printf("found ID_CMAP\n");
119 // ilbmFrame.nColorRegs = maxColorReg; /* we have room for this many */
121 // &rigidbodyContext, (WORD *)&ilbmFrame.colorMap, &ilbmFrame.nColorRegs);
124 else if (iffp == ID_BODY)
126 printf("found ID_BODY\n");
129 // if (!ilbmFrame.foundBMHD) return(BAD_FORM); /* No BMHD chunk! */
131 int moreBytes = ChunkMoreBytes(&rigidbodyContext);
134 int curRead = moreBytes > bufSz? bufSz : moreBytes;
136 iffp = IFFReadBytes(&rigidbodyContext, bodyBuffer, curRead);
137 moreBytes -= curRead;
140 printf("remaining=%d\n",moreBytes);
141 if (iffp == IFF_OKAY)
142 iffp = IFF_DONE; /* Eureka */
146 // nPlanes = MIN(ilbmFrame.bmHdr.nPlanes, EXDepth);
149 else if (iffp == END_MARK)
152 } while (iffp >= IFF_OKAY); /* loop if valid ID of ignored chunk or a
153 * subroutine returned IFF_OKAY (no errors).*/
155 if (iffp != IFF_DONE) return(iffp);
157 /* If we get this far, there were no errors. */
158 CloseRGroup(&rigidbodyContext);
164 #define CkErr(expression) {if (ifferr == IFF_OKAY) ifferr = (expression);}
167 int main(int argc, char* argv[])
172 //Create and write an IFF file from scratch
173 file = fopen("test.iff","wb");
175 GroupContext fileContext;
176 GroupContext catContext;
180 ifferr = OpenWIFF(file, &fileContext, szNotYetKnown) ;
181 //ifferr = StartWGroup(&fileContext, CAT, szNotYetKnown, ID_DYNAWORLD, &catContext);
182 ifferr = StartWGroup(&fileContext, LIST, szNotYetKnown, ID_DYNAWORLD, &catContext);
185 GroupContext rigidbodyPropContext;
186 ifferr = StartWGroup(&catContext, PROP, szNotYetKnown, ID_MASS, &rigidbodyPropContext);
188 PutCk(&rigidbodyPropContext, ID_MASS, 4,(char*)&mass);
189 ifferr = EndWGroup(&rigidbodyPropContext) ;
191 for (int i=0;i<3;i++)
193 GroupContext rigidbodyContext;
194 ifferr = StartWGroup(&catContext, FORM, szNotYetKnown, ID_RIGIDBODY, &rigidbodyContext);
195 char sidbuffer[]="rb1";
197 float dimensions[3] = {2,2,2};
198 PutCk(&rigidbodyContext, ID_SID, 3,sidbuffer);
200 GroupContext shapeContext;
201 ifferr = StartWGroup(&rigidbodyContext, FORM, szNotYetKnown, ID_SHAPE, &shapeContext);
202 PutCk(&shapeContext, ID_CUBE, 4,(char*)&mass);
203 PutCk(&shapeContext, ID_DIMENSIONS, sizeof(dimensions),(char*)&dimensions);
204 ifferr = EndWGroup(&shapeContext) ;
206 ifferr = EndWGroup(&rigidbodyContext) ;
210 ifferr = EndWGroup(&catContext) ;
211 ifferr = CloseWGroup(&fileContext);
217 //show a very simple way to skim through an ILBM or general IFF file
218 //for more verbose feedback, use iffcheck.c
220 //file = fopen("pe_3000_fall.iff","rb");
221 file = fopen("test.iff","rb");
223 ClientFrame clientFrame;
225 clientFrame.getList = MySkipGroup;
226 clientFrame.getProp = MySkipGroup;
227 clientFrame.getForm = MyProcessGroup;
228 clientFrame.getCat = MyReadICat ;
230 result = ReadIFF(file,&clientFrame);