Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!utgpu!water!watmath!clyde!rutgers!sri-spam!ames!amdahl!orandy From: orandy@amdahl.UUCP Newsgroups: comp.sys.amiga Subject: Initial posting of MandelVroom (8 of 8) Message-ID: <6770@amdahl.amdahl.com> Date: Tue, 19-May-87 21:27:19 EDT Article-I.D.: amdahl.6770 Posted: Tue May 19 21:27:19 1987 Date-Received: Thu, 21-May-87 03:07:26 EDT Organization: Amdahl Corporation, Sunnyvale, CA 94086 Lines: 1267 Keywords: Amiga Developers IFF includes. CPU-hours consumed. # This is a shell archive. Remove anything before this line, then # unpack it by saving it in a file and typing "sh file". (Files # unpacked will be owned by you and have default permissions.) # # This archive contains: # README compiler.h gio.h iff.h ilbm.h intuall.h packer.h putpict.h readpict.h remalloc.h echo x - README cat > "README" << '//E*O*F README//' This directory contains the include files off of Fish Disk 64. Fish Disk 64 contains the Amiga Developers IFF sources. //E*O*F README// echo x - compiler.h cat > "compiler.h" << '//E*O*F compiler.h//' #ifndef COMPILER_H #define COMPILER_H /*** compiler.h *********************************************************/ /* Steve Shaw 1/29/86 */ /* Portability file to handle compiler idiosyncrasies. */ /* Version: Lattice 3.03 cross-compiler for the Amiga from the IBM PC. */ /* */ /* This software is in the public domain. */ /* */ /************************************************************************/ #ifndef EXEC_TYPES_H #include "exec/types.h" #endif /* NOTE -- NOTE -- NOTE -- NOTE -- NOTE * Some C compilers can handle Function Declarations with Argument Types * (FDwAT) like this: * extern LONG Seek(BPTR, LONG, LONG) * while others choke unless you just say * extern LONG Seek() * * Comment out the #define FDwAT if you have a compiler that chokes. */ /* #define FDwAT COMMENTED OUT BECAUSE GREENHILLS CANT TAKE IT */ #endif COMPILER_H //E*O*F compiler.h// echo x - gio.h cat > "gio.h" << '//E*O*F gio.h//' #ifndef GIO_H #define GIO_H /*----------------------------------------------------------------------*/ /* GIO.H defs for Generic I/O Speed Up Package. 1/23/86 */ /* See GIOCall.C for an example of usage. */ /* Read not speeded-up yet. Only one Write file buffered at a time. */ /* */ /* Note: The speed-up provided is ONLY significant for code such as IFF */ /* which does numerous small Writes and Seeks. */ /* */ /* WARNING: If gio reports an error to you and you care what specific */ /* Dos error was, you must call IoErr() BEFORE calling any other gio */ /* functions. */ /* */ /* By Jerry Morrison and Steve Shaw, Electronic Arts. */ /* This software is in the public domain. */ /* */ /* This version for the Commodore-Amiga computer. */ /* */ /*----------------------------------------------------------------------*/ /* Use this file interface in place of ALL Open,Close,Read,Write,Seek DOS * calls for an optional i/o speed-up via buffering. You must use ONLY * these G routines for a file that is being buffered; e.g., call GClose * to Close the file, etc. * It is harmless though not necessary to use G routines for a file that * is not being buffered; e.g., GClose and Close are equivalent in that * case. * This Version only buffers one file at a time, and only for writing. * If you call GWriteDeclare for a second file before the first file * is GClosed, the first file becomes unbuffered. This is harmless, no * data is lost, the first file is simply no longer speeded-up. */ /* Before compiling any modules that make G calls, or compiling gio.c, * you must set the GIO_ACTIVE flag below. * * To omit the speed-up code, * #define GIO_ACTIVE 0 * * To make the speed-up happen: * 1. #define GIO_ACTIVE 1 * 2. link gio.o into your progrm * 3. GWriteDeclare(file, buffer, size) * after GOpening the file and before doing * any writing. * 4. ONLY use GRead, GWrite, GSeek, GClose -- do not use the DOS i/o * routines directly. * 5. When done, do GClose. Or to stop buffering without closing the * file, do GWriteUndeclare(file). */ #define GIO_ACTIVE 0 #ifndef COMPILER_H #include "iff/compiler.h" #endif #ifndef LIBRARIES_DOS_H #include "libraries/dos.h" #endif #ifndef OFFSET_BEGINNING #define OFFSET_BEGINNING OFFSET_BEGINING #endif #if GIO_ACTIVE #ifdef FDwAT /* Compiler handles Function Declaration with Argument Types */ /* Present for completeness in the interface. * "openmode" is either MODE_OLDFILE to read/write an existing file, or * MODE_NEWFILE to write a new file. * RETURNs a "file" pointer to a system-supplied structure that describes * the open file. This pointer is passed in to the other routines below.*/ extern BPTR GOpen(char * /*filename*/, LONG /*openmode*/); /* NOTE: Flushes & Frees the write buffer. * Returns -1 on error from Write.*/ extern LONG GClose(BPTR /*file*/); /* Read not speeded-up yet. * GOpen the file, then do GReads to get successive chunks of data in * the file. Assumes the system can handle any number of bytes in each * call, regardless of any block-structure of the device being read from. * When done, GClose to free any system resources associated with an * open file.*/ extern LONG GRead(BPTR /*file*/, BYTE * /*buffer*/, LONG /*nBytes*/); /* Writes out any data in write buffer for file. * NOTE WHEN have Seeked into middle of buffer: * GWriteFlush causes current position to be the end of the data written. * -1 on error from Write.*/ extern LONG GWriteFlush(BPTR /*file*/); /* Sets up variables to describe a write buffer for the file.*/ /* If the buffer already has data in it from an outstanding GWriteDeclare, * then that buffer must first be flushed. * RETURN -1 on error from Write for that previous buffer flush. * See also "GWriteUndeclare".*/ extern LONG GWriteDeclare(BPTR /*file*/, BYTE * /*buffer*/, LONG /*nBytes*/); /* ANY PROGRAM WHICH USES "GWrite" MUST USE "GSeek" rather than "Seek" * TO SEEK ON A FILE BEING WRITTEN WITH "GWrite". * "Write" with Generic speed-up. * -1 on error from Write. else returns # bytes written to disk. * Call GOpen, then do successive GWrites with GSeeks if required, * then GClose when done. (IFF does require GSeek.)*/ extern LONG GWrite(BPTR /*file*/, BYTE * /*buffer*/, LONG /*nBytes*/); /* "Seek" with Generic speed-up, for a file being written with GWrite.*/ /* Returns what Seek returns, which appears to be the position BEFORE * seeking, though the documentation says it returns the NEW position. * In fact, the code now explicitly returns the OLD position when * seeking within the buffer. * Eventually, will support two independent files, one being read, the * other being written. Or could support even more. Designed so is safe * to call even for files which aren't being buffered.*/ extern LONG GSeek(BPTR /*file*/, LONG /*position*/, LONG /*mode*/); #else /*not FDwAT*/ extern BPTR GOpen(); extern LONG GClose(); extern LONG GRead(); extern LONG GWriteFlush(); extern LONG GWriteDeclare(); extern LONG GWrite(); extern LONG GSeek(); #endif FDwAT #else /* not GIO_ACTIVE */ #define GOpen(filename, openmode) Open(filename, openmode) #define GClose(file) Close(file) #define GRead(file, buffer, nBytes) Read(file, buffer, nBytes) #define GWriteFlush(file) (0) #define GWriteDeclare(file, buffer, nBytes) (0) #define GWrite(file, buffer, nBytes) Write(file, buffer, nBytes) #define GSeek(file, position, mode) Seek(file, position, mode) #endif GIO_ACTIVE /* Release the buffer for that file, flushing it to disk if it has any * contents. GWriteUndeclare(NULL) to release ALL buffers. * Currently, only one file can be buffered at a time anyway.*/ #define GWriteUndeclare(file) GWriteDeclare(file, NULL, 0) #endif //E*O*F gio.h// echo x - iff.h cat > "iff.h" << '//E*O*F iff.h//' #ifndef IFF_H #define IFF_H /*----------------------------------------------------------------------*/ /* IFF.H defs for IFF-85 Interchange Format Files. 1/22/86 */ /* */ /* By Jerry Morrison and Steve Shaw, Electronic Arts. */ /* This software is in the public domain. */ /*----------------------------------------------------------------------*/ #ifndef COMPILER_H #include "iff/compiler.h" #endif #ifndef LIBRARIES_DOS_H #include "libraries/dos.h" #endif #ifndef OFFSET_BEGINNING #define OFFSET_BEGINNING OFFSET_BEGINING #endif typedef LONG IFFP; /* Status code result from an IFF procedure */ /* LONG, because must be type compatable with ID for GetChunkHdr.*/ /* Note that the error codes below are not legal IDs.*/ #define IFF_OKAY 0L /* Keep going...*/ #define END_MARK -1L /* As if there was a chunk at end of group.*/ #define IFF_DONE -2L /* clientProc returns this when it has READ enough. * It means return thru all levels. File is Okay.*/ #define DOS_ERROR -3L #define NOT_IFF -4L /* not an IFF file.*/ #define NO_FILE -5L /* Tried to open file, DOS didn't find it.*/ #define CLIENT_ERROR -6L /* Client made invalid request, for instance, write * a negative size chunk.*/ #define BAD_FORM -7L /* A client read proc complains about FORM semantics; * e.g. valid IFF, but missing a required chunk.*/ #define SHORT_CHUNK -8L /* Client asked to IFFReadBytes more bytes than left * in the chunk. Could be client bug or bad form.*/ #define BAD_IFF -9L /* mal-formed IFF file. [TBD] Expand this into a * range of error codes.*/ #define LAST_ERROR BAD_IFF /* This MACRO is used to RETURN immediately when a termination condition is * found. This is a pretty weird macro. It requires the caller to declare a * local "IFFP iffp" and assign it. This wouldn't work as a subroutine since * it returns for it's caller. */ #define CheckIFFP() { if (iffp != IFF_OKAY) return(iffp); } /* ---------- ID -------------------------------------------------------*/ typedef LONG ID; /* An ID is four printable ASCII chars but * stored as a LONG for efficient copy & compare.*/ /* Four-character IDentifier builder.*/ #define MakeID(a,b,c,d) ( (LONG)(a)<<24L | (LONG)(b)<<16L | (c)<<8 | (d) ) /* Standard group IDs. A chunk with one of these IDs contains a SubTypeID followed by zero or more chunks.*/ #define FORM MakeID('F','O','R','M') #define PROP MakeID('P','R','O','P') #define LIST MakeID('L','I','S','T') #define CAT MakeID('C','A','T',' ') #define FILLER MakeID(' ',' ',' ',' ') /* The IDs "FOR1".."FOR9", "LIS1".."LIS9", & "CAT1".."CAT9" are reserved * for future standardization.*/ /* Pseudo-ID used internally by chunk reader and writer.*/ #define NULL_CHUNK 0L /* No current chunk.*/ /* ---------- Chunk ----------------------------------------------------*/ /* All chunks start with a type ID and a count of the data bytes that follow--the chunk's "logicl size" or "data size". If that number is odd, a 0 pad byte is written, too. */ typedef struct { ID ckID; LONG ckSize; } ChunkHeader; typedef struct { ID ckID; LONG ckSize; UBYTE ckData[ 1 /*REALLY: ckSize*/ ]; } Chunk; /* Pass ckSize = szNotYetKnown to the writer to mean "compute the size".*/ #define szNotYetKnown 0x80000001L /* Need to know whether a value is odd so can word-align.*/ #define IS_ODD(a) ((a) & 1) /* This macro rounds up to an even number. */ #define WordAlign(size) ((size+1)&~1) /* ALL CHUNKS MUST BE PADDED TO EVEN NUMBER OF BYTES. * ChunkPSize computes the total "physical size" of a padded chunk from * its "data size" or "logical size". */ #define ChunkPSize(dataSize) (WordAlign(dataSize) + sizeof(ChunkHeader)) /* The Grouping chunks (LIST, FORM, PROP, & CAT) contain concatenations of * chunks after a subtype ID that identifies the content chunks. * "FORM type XXXX", "LIST of FORM type XXXX", "PROPerties associated * with FORM type XXXX", or "conCATenation of XXXX".*/ typedef struct { ID ckID; LONG ckSize; /* this ckSize includes "grpSubID".*/ ID grpSubID; } GroupHeader; typedef struct { ID ckID; LONG ckSize; ID grpSubID; UBYTE grpData[ 1 /*REALLY: ckSize-sizeof(grpSubID)*/ ]; } GroupChunk; /* ---------- IFF Reader -----------------------------------------------*/ /******** Routines to support a stream-oriented IFF file reader ******* * * These routines handle lots of details like error checking and skipping * over padding. They're also careful not to read past any containing context. * * These routines ASSUME they're the only ones reading from the file. * Client should check IFFP error codes. Don't press on after an error! * These routines try to have no side effects in the error case, except * partial I/O is sometimes unavoidable. * * All of these routines may return DOS_ERROR. In that case, ask DOS for the * specific error code. * * The overall scheme for the low level chunk reader is to open a "group read * context" with OpenRIFF or OpenRGroup, read the chunks with GetChunkHdr * (and its kin) and IFFReadBytes, and close the context with CloseRGroup. * * The overall scheme for reading an IFF file is to use ReadIFF, ReadIList, * and ReadICat to scan the file. See those procedures, ClientProc (below), * and the skeleton IFF reader. */ /* Client passes ptrs to procedures of this type to ReadIFF which call them * back to handle LISTs, FORMs, CATs, and PROPs. * * Use the GroupContext ptr when calling reader routines like GetChunkHdr. * Look inside the GroupContext ptr for your ClientFrame ptr. You'll * want to type cast it into a ptr to your containing struct to get your * private contextual data (stacked property settings). See below. */ #ifdef FDwAT typedef IFFP ClientProc(struct _GroupContext *); #else typedef IFFP ClientProc(); #endif /* Client's context for reading an IFF file or a group. * Client should actually make this the first component of a larger struct * (it's personal stack "frame") that has a field to store each "interesting" * property encountered. * Either initialize each such field to a global default or keep a boolean * indicating if you've read a property chunk into that field. * Your getList and getForm procs should allocate a new "frame" and copy the * parent frame's contents. The getProp procedure should store into the frame * allocated by getList for the containing LIST. */ typedef struct _ClientFrame { ClientProc *getList, *getProp, *getForm, *getCat; /* client's own data follows; place to stack property settings */ } ClientFrame; /* Our context for reading a group chunk. */ typedef struct _GroupContext { struct _GroupContext *parent; /* Containing group; NULL => whole file. */ ClientFrame *clientFrame; /* Reader data & client's context state. */ BPTR file; /* Byte-stream file handle. */ LONG position; /* The context's logical file position. */ LONG bound; /* File-absolute context bound * or szNotYetKnown (writer only). */ ChunkHeader ckHdr; /* Current chunk header. ckHdr.ckSize = szNotYetKnown * means we need to go back and set the size (writer only). * See also Pseudo-IDs, above. */ ID subtype; /* Group's subtype ID when reading. */ LONG bytesSoFar; /* # bytes read/written of current chunk's data. */ } GroupContext; /* Computes the number of bytes not yet read from the current chunk, given * a group read context gc. */ #define ChunkMoreBytes(gc) ((gc)->ckHdr.ckSize - (gc)->bytesSoFar) /***** Low Level IFF Chunk Reader *****/ #ifdef FDwAT /* Given an open file, open a read context spanning the whole file. * This is normally only called by ReadIFF. * This sets new->clientFrame = clientFrame. * ASSUME context allocated by caller but not initialized. * ASSUME caller doesn't deallocate the context before calling CloseRGroup. * NOT_IFF ERROR if the file is too short for even a chunk header.*/ extern IFFP OpenRIFF(BPTR, GroupContext *, ClientFrame *); /* file, new, clientFrame */ /* Open the remainder of the current chunk as a group read context. * This will be called just after the group's subtype ID has been read * (automatically by GetChunkHdr for LIST, FORM, PROP, and CAT) so the * remainder is a sequence of chunks. * This sets new->clientFrame = parent->clientFrame. The caller should repoint * it at a new clientFrame if opening a LIST context so it'll have a "stack * frame" to store PROPs for the LIST. (It's usually convenient to also * allocate a new Frame when you encounter FORM of the right type.) * * ASSUME new context allocated by caller but not initialized. * ASSUME caller doesn't deallocate the context or access the parent context * before calling CloseRGroup. * BAD_IFF ERROR if context end is odd or extends past parent. */ extern IFFP OpenRGroup(GroupContext *, GroupContext *); /* parent, new */ /* Close a group read context, updating its parent context. * After calling this, the old context may be deallocated and the parent * context can be accessed again. It's okay to call this particular procedure * after an error has occurred reading the group. * This always returns IFF_OKAY. */ extern IFFP CloseRGroup(GroupContext *); /* old */ /* Skip any remaining bytes of the previous chunk and any padding, then * read the next chunk header into context.ckHdr. * If the ckID is LIST, FORM, CAT, or PROP, this automatically reads the * subtype ID into context->subtype. * Caller should dispatch on ckID (and subtype) to an appropriate handler. * * RETURNS context.ckHdr.ckID (the ID of the new chunk header); END_MARK * if there are no more chunks in this context; or NOT_IFF if the top level * file chunk isn't a FORM, LIST, or CAT; or BAD_IFF if malformed chunk, e.g. * ckSize is negative or too big for containing context, ckID isn't positive, * or we hit end-of-file. * * See also GetFChunkHdr, GetF1ChunkHdr, and GetPChunkHdr, below.*/ extern ID GetChunkHdr(GroupContext *); /* context.ckHdr.ckID context */ /* Read nBytes number of data bytes of current chunk. (Use OpenGroup, etc. * instead to read the contents of a group chunk.) You can call this several * times to read the data piecemeal. * CLIENT_ERROR if nBytes < 0. SHORT_CHUNK if nBytes > ChunkMoreBytes(context) * which could be due to a client bug or a chunk that's shorter than it * ought to be (bad form). (on either CLIENT_ERROR or SHORT_CHUNK, * IFFReadBytes won't read any bytes.) */ extern IFFP IFFReadBytes(GroupContext *, BYTE *, LONG); /* context, buffer, nBytes */ /***** IFF File Reader *****/ /* This is a noop ClientProc that you can use for a getList, getForm, getProp, * or getCat procedure that just skips the group. A simple reader might just * implement getForm, store ReadICat in the getCat field of clientFrame, and * use SkipGroup for the getList and getProp procs.*/ extern IFFP SkipGroup(GroupContext *); /* IFF file reader. * Given an open file, allocate a group context and use it to read the FORM, * LIST, or CAT and it's contents. The idea is to parse the file's contents, * and for each FORM, LIST, CAT, or PROP encountered, call the getForm, * getList, getCat, or getProp procedure in clientFrame, passing the * GroupContext ptr. * This is achieved with the aid of ReadIList (which your getList should * call) and ReadICat (which your getCat should call, if you don't just use * ReadICat for your getCat). If you want to handle FORMs, LISTs, and CATs * nested within FORMs, the getForm procedure must dispatch to getForm, * getList, and getCat (it can use GetF1ChunkHdr to make this easy). * * Normal return is IFF_OKAY (if whole file scanned) or IFF_DONE (if a client * proc said "done" first). * See the skeletal getList, getForm, getCat, and getProp procedures. */ extern IFFP ReadIFF(BPTR, ClientFrame *); /* file, clientFrame */ /* IFF LIST reader. * Your "getList" procedure should allocate a ClientFrame, copy the parent's * ClientFrame, and then call this procedure to do all the work. * * Normal return is IFF_OKAY (if whole LIST scanned) or IFF_DONE (if a client * proc said "done" first). * BAD_IFF ERROR if a PROP appears after a non-PROP. */ extern IFFP ReadIList(GroupContext *, ClientFrame *); /* parent, clientFrame */ /* IFF CAT reader. * Most clients can simply use this to read their CATs. If you must do extra * setup work, put a ptr to your getCat procedure in the clientFrame, and * have that procedure call ReadICat to do the detail work. * * Normal return is IFF_OKAY (if whole CAT scanned) or IFF_DONE (if a client * proc said "done" first). * BAD_IFF ERROR if a PROP appears in the CAT. */ extern IFFP ReadICat(GroupContext *); /* parent */ /* Call GetFChunkHdr instead of GetChunkHdr to read each chunk inside a FORM. * It just calls GetChunkHdr and returns BAD_IFF if it gets a PROP chunk. */ extern ID GetFChunkHdr(GroupContext *); /* context.ckHdr.ckID context */ /* GetF1ChunkHdr is like GetFChunkHdr, but it automatically dispatches to the * getForm, getList, and getCat procedure (and returns the result) if it * encounters a FORM, LIST, or CAT. */ extern ID GetF1ChunkHdr(GroupContext *); /* context.ckHdr.ckID context */ /* Call GetPChunkHdr instead of GetChunkHdr to read each chunk inside a PROP. * It just calls GetChunkHdr and returns BAD_IFF if it gets a group chunk. */ extern ID GetPChunkHdr(GroupContext *); /* context.ckHdr.ckID context */ #else /* not FDwAT */ extern IFFP OpenRIFF(); extern IFFP OpenRGroup(); extern IFFP CloseRGroup(); extern ID GetChunkHdr(); extern IFFP IFFReadBytes(); extern IFFP SkipGroup(); extern IFFP ReadIFF(); extern IFFP ReadIList(); extern IFFP ReadICat(); extern ID GetFChunkHdr(); extern ID GetF1ChunkHdr(); extern ID GetPChunkHdr(); #endif /* not FDwAT */ /* ---------- IFF Writer -----------------------------------------------*/ /******* Routines to support a stream-oriented IFF file writer ******* * * These routines will random access back to set a chunk size value when the * caller doesn't know it ahead of time. They'll also do things automatically * like padding and error checking. * * These routines ASSUME they're the only ones writing to the file. * Client should check IFFP error codes. Don't press on after an error! * These routines try to have no side effects in the error case, except that * partial I/O is sometimes unavoidable. * * All of these routines may return DOS_ERROR. In that case, ask DOS for the * specific error code. * * The overall scheme is to open an output GroupContext via OpenWIFF or * OpenWGroup, call either PutCk or {PutCkHdr {IFFWriteBytes}* PutCkEnd} for * each chunk, then use CloseWGroup to close the GroupContext. * * To write a group (LIST, FORM, PROP, or CAT), call StartWGroup, write out * its chunks, then call EndWGroup. StartWGroup automatically writes the * group header and opens a nested context for writing the contents. * EndWGroup closes the nested context and completes the group chunk. */ #ifdef FDwAT /* Given a file open for output, open a write context. * The "limit" arg imposes a fence or upper limit on the logical file * position for writing data in this context. Pass in szNotYetKnown to be * bounded only by disk capacity. * ASSUME new context structure allocated by caller but not initialized. * ASSUME caller doesn't deallocate the context before calling CloseWGroup. * The caller is only allowed to write out one FORM, LIST, or CAT in this top * level context (see StartWGroup and PutCkHdr). * CLIENT_ERROR if limit is odd.*/ extern IFFP OpenWIFF(BPTR, GroupContext *, LONG); /* file, new, limit {file position} */ /* Start writing a group (presumably LIST, FORM, PROP, or CAT), opening a * nested context. The groupSize includes all nested chunks + the subtype ID. * * The subtype of a LIST or CAT is a hint at the contents' FORM type(s). Pass * in FILLER if it's a mixture of different kinds. * * This writes the chunk header via PutCkHdr, writes the subtype ID via * IFFWriteBytes, and calls OpenWGroup. The caller may then write the nested * chunks and finish by calling EndWGroup. * The OpenWGroup call sets new->clientFrame = parent->clientFrame. * * ASSUME new context structure allocated by caller but not initialized. * ASSUME caller doesn't deallocate the context or access the parent context * before calling CloseWGroup. * ERROR conditions: See PutCkHdr, IFFWriteBytes, OpenWGroup. */ extern IFFP StartWGroup(GroupContext *, ID, LONG, ID, GroupContext *); /* parent, groupType, groupSize, subtype, new */ /* End a group started by StartWGroup. * This just calls CloseWGroup and PutCkEnd. * ERROR conditions: See CloseWGroup and PutCkEnd. */ extern IFFP EndWGroup(GroupContext *); /* old */ /* Open the remainder of the current chunk as a group write context. * This is normally only called by StartWGroup. * * Any fixed limit to this group chunk or a containing context will impose * a limit on the new context. * This will be called just after the group's subtype ID has been written * so the remaining contents will be a sequence of chunks. * This sets new->clientFrame = parent->clientFrame. * ASSUME new context structure allocated by caller but not initialized. * ASSUME caller doesn't deallocate the context or access the parent context * before calling CloseWGroup. * CLIENT_ERROR if context end is odd or PutCkHdr wasn't called first. */ extern IFFP OpenWGroup(GroupContext *, GroupContext *); /* parent, new */ /* Close a write context and update its parent context. * This is normally only called by EndWGroup. * * If this is a top level context (created by OpenWIFF) we'll set the file's * EOF (end of file) but won't close the file. * After calling this, the old context may be deallocated and the parent * context can be accessed again. * * Amiga DOS Note: There's no call to set the EOF. We just position to the * desired end and return. Caller must Close file at that position. * CLIENT_ERROR if PutCkEnd wasn't called first. */ extern IFFP CloseWGroup(GroupContext *); /* old */ /* Write a whole chunk to a GroupContext. This writes a chunk header, ckSize * data bytes, and (if needed) a pad byte. It also updates the GroupContext. * CLIENT_ERROR if ckSize == szNotYetKnown. See also PutCkHdr errors. */ extern IFFP PutCk(GroupContext *, ID, LONG, BYTE *); /* context, ckID, ckSize, *data */ /* Write just a chunk header. Follow this will any number of calls to * IFFWriteBytes and finish with PutCkEnd. * If you don't yet know how big the chunk is, pass in ckSize = szNotYetKnown, * then PutCkEnd will set the ckSize for you later. * Otherwise, IFFWriteBytes and PutCkEnd will ensure that the specified * number of bytes get written. * CLIENT_ERROR if the chunk would overflow the GroupContext's bound, if * PutCkHdr was previously called without a matching PutCkEnd, if ckSize < 0 * (except szNotYetKnown), if you're trying to write something other * than one FORM, LIST, or CAT in a top level (file level) context, or * if ckID <= 0 (these illegal ID values are used for error codes). */ extern IFFP PutCkHdr(GroupContext *, ID, LONG); /* context, ckID, ckSize */ /* Write nBytes number of data bytes for the current chunk and update * GroupContext. * CLIENT_ERROR if this would overflow the GroupContext's limit or the * current chunk's ckSize, or if PutCkHdr wasn't called first, or if * nBytes < 0. */ extern IFFP IFFWriteBytes(GroupContext *, BYTE *, LONG); /* context, *data, nBytes */ /* Complete the current chunk, write a pad byte if needed, and update * GroupContext. * If current chunk's ckSize = szNotYetKnown, this goes back and sets the * ckSize in the file. * CLIENT_ERROR if PutCkHdr wasn't called first, or if client hasn't * written 'ckSize' number of bytes with IFFWriteBytes. */ extern IFFP PutCkEnd(GroupContext *); /* context */ #else /* not FDwAT */ extern IFFP OpenWIFF(); extern IFFP StartWGroup(); extern IFFP EndWGroup(); extern IFFP OpenWGroup(); extern IFFP CloseWGroup(); extern IFFP PutCk(); extern IFFP PutCkHdr(); extern IFFP IFFWriteBytes(); extern IFFP PutCkEnd(); #endif /* not FDwAT */ #endif IFF_H //E*O*F iff.h// echo x - ilbm.h cat > "ilbm.h" << '//E*O*F ilbm.h//' #ifndef ILBM_H #define ILBM_H /*----------------------------------------------------------------------* * ILBM.H Definitions for InterLeaved BitMap raster image. 1/23/86 * * By Jerry Morrison and Steve Shaw, Electronic Arts. * This software is in the public domain. * * This version for the Commodore-Amiga computer. *----------------------------------------------------------------------*/ #ifndef COMPILER_H /* #include "iff/compiler.h" */ #endif #ifndef GRAPHICS_GFX_H #include "graphics/gfx.h" #endif #include "iff/iff.h" #define ID_ILBM MakeID('I','L','B','M') #define ID_BMHD MakeID('B','M','H','D') #define ID_CMAP MakeID('C','M','A','P') #define ID_GRAB MakeID('G','R','A','B') #define ID_DEST MakeID('D','E','S','T') #define ID_SPRT MakeID('S','P','R','T') #define ID_CAMG MakeID('C','A','M','G') #define ID_BODY MakeID('B','O','D','Y') /* ---------- BitMapHeader ---------------------------------------------*/ typedef UBYTE Masking; /* Choice of masking technique.*/ #define mskNone 0 #define mskHasMask 1 #define mskHasTransparentColor 2 #define mskLasso 3 typedef UBYTE Compression; /* Choice of compression algorithm applied to * each row of the source and mask planes. "cmpByteRun1" is the byte run * encoding generated by Mac's PackBits. See Packer.h . */ #define cmpNone 0 #define cmpByteRun1 1 /* Aspect ratios: The proper fraction xAspect/yAspect represents the pixel * aspect ratio pixel_width/pixel_height. * * For the 4 Amiga display modes: * 320 x 200: 10/11 (these pixels are taller than they are wide) * 320 x 400: 20/11 * 640 x 200: 5/11 * 640 x 400: 10/11 */ #define x320x200Aspect 10 #define y320x200Aspect 11 #define x320x400Aspect 20 #define y320x400Aspect 11 #define x640x200Aspect 5 #define y640x200Aspect 11 #define x640x400Aspect 10 #define y640x400Aspect 11 /* A BitMapHeader is stored in a BMHD chunk. */ typedef struct { UWORD w, h; /* raster width & height in pixels */ WORD x, y; /* position for this image */ UBYTE nPlanes; /* # source bitplanes */ Masking masking; /* masking technique */ Compression compression; /* compression algoithm */ UBYTE pad1; /* UNUSED. For consistency, put 0 here.*/ UWORD transparentColor; /* transparent "color number" */ UBYTE xAspect, yAspect; /* aspect ratio, a rational number x/y */ WORD pageWidth, pageHeight; /* source "page" size in pixels */ } BitMapHeader; /* RowBytes computes the number of bytes in a row, from the width in pixels.*/ #define RowBytes(w) (((w) + 15) >> 4 << 1) /* ---------- ColorRegister --------------------------------------------*/ /* A CMAP chunk is a packed array of ColorRegisters (3 bytes each). */ typedef struct { UBYTE red, green, blue; /* MUST be UBYTEs so ">> 4" won't sign extend.*/ } ColorRegister; /* Use this constant instead of sizeof(ColorRegister). */ #define sizeofColorRegister 3 typedef WORD Color4; /* Amiga RAM version of a color-register, * with 4 bits each RGB in low 12 bits.*/ /* Maximum number of bitplanes in RAM. Current Amiga max w/dual playfield. */ #define MaxAmDepth 6 /* ---------- Point2D --------------------------------------------------*/ /* A Point2D is stored in a GRAB chunk. */ typedef struct { WORD x, y; /* coordinates (pixels) */ } Point2D; /* ---------- DestMerge ------------------------------------------------*/ /* A DestMerge is stored in a DEST chunk. */ typedef struct { UBYTE depth; /* # bitplanes in the original source */ UBYTE pad1; /* UNUSED; for consistency store 0 here */ UWORD planePick; /* how to scatter source bitplanes into destination */ UWORD planeOnOff; /* default bitplane data for planePick */ UWORD planeMask; /* selects which bitplanes to store into */ } DestMerge; /* ---------- SpritePrecedence -----------------------------------------*/ /* A SpritePrecedence is stored in a SPRT chunk. */ typedef UWORD SpritePrecedence; /* ---------- Viewport Mode --------------------------------------------*/ /* A Commodore Amiga ViewPort->Modes is stored in a CAMG chunk. */ /* The chunk's content is declared as a LONG. */ /* ---------- CRange ---------------------------------------------------*/ /* A CRange is store in a CRNG chunk. */ typedef struct { WORD pad1; /* reserved for future use; store 0 here */ WORD rate; /* color cycling rate, 16384 = 60 steps/second */ WORD active; /* nonzero means color cycling is turned on */ UBYTE low, high; /* lower and upper color registers selected */ } CRange; /* ---------- ILBM Writer Support Routines -----------------------------*/ /* Note: Just call PutCk to write a BMHD, GRAB, DEST, SPRT, or CAMG * chunk. As below. */ #define PutBMHD(context, bmHdr) \ PutCk(context, ID_BMHD, sizeof(BitMapHeader), (BYTE *)bmHdr) #define PutGRAB(context, point2D) \ PutCk(context, ID_GRAB, sizeof(Point2D), (BYTE *)point2D) #define PutDEST(context, destMerge) \ PutCk(context, ID_DEST, sizeof(DestMerge), (BYTE *)destMerge) #define PutSPRT(context, spritePrec) \ PutCk(context, ID_SPRT, sizeof(SpritePrecedence), (BYTE *)spritePrec) #ifdef FDwAT /* Initialize a BitMapHeader record for a full-BitMap ILBM picture. * This gets w, h, and nPlanes from the BitMap fields BytesPerRow, Rows, and * Depth. It assumes you want w = bitmap->BytesPerRow * 8 . * CLIENT_ERROR if bitmap->BytesPerRow isn't even, as required by ILBM format. * * If (pageWidth, pageHeight) is (320, 200), (320, 400), (640, 200), or * (640, 400) this sets (xAspect, yAspect) based on those 4 Amiga display * modes. Otherwise, it sets them to (1, 1). * * After calling this, store directly into the BitMapHeader if you want to * override any settings, e.g. to make nPlanes smaller, to reduce w a little, * or to set a position (x, y) other than (0, 0).*/ extern IFFP InitBMHdr(BitMapHeader *, struct BitMap *, /* bmHdr, bitmap */ int, int, int, WORD, WORD); /* masking, compression, transparentColor, pageWidth, pageHeight */ /* Masking, Compression, UWORD -- are the desired types, but get * compiler warnings if use them. */ /* Output a CMAP chunk to an open FORM ILBM write context. */ extern IFFP PutCMAP(GroupContext *, WORD *, UBYTE); /* context, colorMap, depth */ /* This procedure outputs a BitMap as an ILBM's BODY chunk with * bitplane and mask data. Compressed if bmHdr->compression == cmpByteRun1. * If the "mask" argument isn't NULL, it merges in the mask plane, too. * (A fancier routine could write a rectangular portion of an image.) * This gets Planes (bitplane ptrs) from "bitmap". * * CLIENT_ERROR if bitmap->Rows != bmHdr->h, or if * bitmap->BytesPerRow != RowBytes(bmHdr->w), or if * bitmap->Depth < bmHdr->nPlanes, or if bmHdr->nPlanes > MaxAmDepth, or if * bufsize < MaxPackedSize(bitmap->BytesPerRow), or if * bmHdr->compression > cmpByteRun1. */ extern IFFP PutBODY( GroupContext *, struct BitMap *, BYTE *, BitMapHeader *, BYTE *, LONG); /* context, bitmap, mask, bmHdr, buffer, bufsize */ #else /*not FDwAT*/ extern IFFP InitBMHdr(); extern IFFP PutCMAP(); extern IFFP PutBODY(); #endif FDwAT /* ---------- ILBM Reader Support Routines -----------------------------*/ /* Note: Just call IFFReadBytes to read a BMHD, GRAB, DEST, SPRT, or CAMG * chunk. As below. */ #define GetBMHD(context, bmHdr) \ IFFReadBytes(context, (BYTE *)bmHdr, sizeof(BitMapHeader)) #define GetGRAB(context, point2D) \ IFFReadBytes(context, (BYTE *)point2D, sizeof(Point2D)) #define GetDEST(context, destMerge) \ IFFReadBytes(context, (BYTE *)destMerge, sizeof(DestMerge)) #define GetSPRT(context, spritePrec) \ IFFReadBytes(context, (BYTE *)spritePrec, sizeof(SpritePrecedence)) /* GetBODY can handle a file with up to 16 planes plus a mask.*/ #define MaxSrcPlanes 16+1 #ifdef FDwAT /* Input a CMAP chunk from an open FORM ILBM read context. * This converts to an Amiga color map: 4 bits each of red, green, blue packed * into a 16 bit color register. * pNColorRegs is passed in as a pointer to a UBYTE variable that holds * the number of ColorRegisters the caller has space to hold. GetCMAP sets * that variable to the number of color registers actually read.*/ extern IFFP GetCMAP(GroupContext *, WORD *, UBYTE *); /* context, colorMap, pNColorRegs */ /* GetBODY reads an ILBM's BODY into a client's bitmap, de-interleaving and * decompressing. * * Caller should first compare bmHdr dimensions (rowWords, h, nPlanes) with * bitmap dimensions, and consider reallocating the bitmap. * If file has more bitplanes than bitmap, this reads first few planes (low * order ones). If bitmap has more bitplanes, the last few are untouched. * This reads the MIN(bmHdr->h, bitmap->Rows) rows, discarding the bottom * part of the source or leaving the bottom part of the bitmap untouched. * * GetBODY returns CLIENT_ERROR if asked to perform a conversion it doesn't * handle. It only understands compression algorithms cmpNone and cmpByteRun1. * The filed row width (# words) must agree with bitmap->BytesPerRow. * * Caller should use bmHdr.w; GetBODY only uses it to compute the row width * in words. Pixels to the right of bmHdr.w are not defined. * * [TBD] In the future, GetBODY could clip the stored image horizontally or * fill (with transparentColor) untouched parts of the destination bitmap. * * GetBODY stores the mask plane, if any, in the buffer pointed to by mask. * If mask == NULL, GetBODY will skip any mask plane. If * (bmHdr.masking != mskHasMask) GetBODY just leaves the caller's mask alone. * * GetBODY needs a buffer large enough for two compressed rows. * It returns CLIENT_ERROR if bufsize < 2 * MaxPackedSize(bmHdr.rowWords * 2). * * GetBODY can handle a file with up to MaxSrcPlanes planes. It returns * CLIENT_ERROR if the file has more. (Could be due to a bum file, though.) * If GetBODY fails, itt might've modified the client's bitmap. Sorry.*/ extern IFFP GetBODY( GroupContext *, struct BitMap *, BYTE *, BitMapHeader *, BYTE *, LONG); /* context, bitmap, mask, bmHdr, buffer, bufsize */ /* [TBD] Add routine(s) to create masks when reading ILBMs whose * masking != mskHasMask. For mskNone, create a rectangular mask. For * mskHasTransparentColor, create a mask from transparentColor. For mskLasso, * create an "auto mask" by filling transparent color from the edges. */ #else /*not FDwAT*/ extern IFFP GetCMAP(); extern IFFP GetBODY(); #endif FDwAT #endif ILBM_H //E*O*F ilbm.h// echo x - intuall.h cat > "intuall.h" << '//E*O*F intuall.h//' /* intuall.h */ #include "iff/compiler.h" #include "exec/types.h" #include "exec/io.h" #include "exec/memory.h" #include "graphics/gfxbase.h" #include "libraries/dos.h" #include "intuition/intuition.h" //E*O*F intuall.h// echo x - packer.h cat > "packer.h" << '//E*O*F packer.h//' #ifndef PACKER_H #define PACKER_H /*----------------------------------------------------------------------* * PACKER.H typedefs for Data-Compresser. 1/22/86 * * This module implements the run compression algorithm "cmpByteRun1"; the * same encoding generated by Mac's PackBits. * * By Jerry Morrison and Steve Shaw, Electronic Arts. * This software is in the public domain. * * This version for the Commodore-Amiga computer. *----------------------------------------------------------------------*/ #ifndef COMPILER_H #include "iff/compiler.h" #endif /* This macro computes the worst case packed size of a "row" of bytes. */ #define MaxPackedSize(rowSize) ( (rowSize) + ( ((rowSize)+127) >> 7 ) ) #ifdef FDwAT /* Compiler handles Function Declaration with Argument Types */ /* Given POINTERS to POINTER variables, packs one row, updating the source * and destination pointers. Returns the size in bytes of the packed row. * ASSUMES destination buffer is large enough for the packed row. * See MaxPackedSize. */ extern LONG PackRow(BYTE **, BYTE **, LONG); /* pSource, pDest, rowSize */ /* Given POINTERS to POINTER variables, unpacks one row, updating the source * and destination pointers until it produces dstBytes bytes (i.e., the * rowSize that went into PackRow). * If it would exceed the source's limit srcBytes or if a run would overrun * the destination buffer size dstBytes, it stops and returns TRUE. * Otherwise, it returns FALSE (no error). */ extern BOOL UnPackRow(BYTE **, BYTE **, WORD, WORD); /* pSource, pDest, srcBytes, dstBytes */ #else /* not FDwAT */ extern LONG PackRow(); extern BOOL UnPackRow(); #endif /* FDwAT */ #endif //E*O*F packer.h// echo x - putpict.h cat > "putpict.h" << '//E*O*F putpict.h//' #ifndef PUTPICT_H #define PUTPICT_H /** putpict.h ********************************************************* */ /* PutPict(). Given a BitMap and a color map in RAM on the Amiga, */ /* outputs as an ILBM. See /iff/ilbm.h & /iff/ilbmw.c. 23-Jan-86 */ /* */ /* By Jerry Morrison and Steve Shaw, Electronic Arts. */ /* This software is in the public domain. */ /* */ /* This version for the Commodore-Amiga computer. */ /* */ /************************************************************************/ #ifndef COMPILER_H #include "iff/compiler.h" #endif #ifndef ILBM_H #include "iff/ilbm.h" #endif #ifdef FDwAT /****** IffErr *************************************************************/ /* Returns the iff error code and resets it to zero */ /***************************************************************************/ extern IFFP IffErr(void); /****** PutPict ************************************************************/ /* Put a picture into an IFF file */ /* Pass in mask == NULL for no mask. */ /* */ /* Buffer should be big enough for one packed scan line */ /* Buffer used as temporary storage to speed-up writing. */ /* A large buffer, say 8KB, is useful for minimizing Write and Seek calls. */ /* (See /iff/gio.h & /iff/gio.c). */ /***************************************************************************/ extern BOOL PutPict(LONG, struct BitMap *, WORD,WORD, WORD *, BYTE *, LONG); /* file, bm, pageW,pageH,colorMap, buffer,bufsize */ #else /*not FDwAT*/ extern IFFP IffErr(); extern BOOL PutPict(); #endif FDwAT #endif PUTPICT_H //E*O*F putpict.h// echo x - readpict.h cat > "readpict.h" << '//E*O*F readpict.h//' #ifndef READPICT_H #define READPICT_H /** ReadPict.h **************************************************************/ /* */ /* Read an ILBM raster image file into RAM. 1/23/86. */ /* */ /* By Jerry Morrison, Steve Shaw, and Steve Hayes, Electronic Arts. */ /* This software is in the public domain. */ /* */ /* USE THIS AS AN EXAMPLE PROGRAM FOR AN IFF READER. */ /* */ /* The IFF reader portion is essentially a recursive-descent parser. */ /****************************************************************************/ /* ILBMFrame is our "client frame" for reading FORMs ILBM in an IFF file. * We allocate one of these on the stack for every LIST or FORM encountered * in the file and use it to hold BMHD & CMAP properties. We also allocate * an initial one for the whole file. */ typedef struct { ClientFrame clientFrame; UBYTE foundBMHD; UBYTE nColorRegs; BitMapHeader bmHdr; Color4 colorMap[32 /*1< "remalloc.h" << '//E*O*F remalloc.h//' /** RemAlloc.h **********************************************************/ /* ChipAlloc(), ExtAlloc(), RemAlloc(), RemFree(). */ /* ALLOCators which REMember the size allocated, for simpler freeing. */ /* */ /* Date Who Changes */ /* --------- --- -------------------------------------------------------*/ /* 16-Jan-86 sss Created from DPaint/DAlloc.c */ /* 22-Jan-86 jhm Include Compiler.h */ /* 25-Jan-86 sss Added ChipNoClearAlloc,ExtNoClearAlloc */ /* */ /* By Jerry Morrison and Steve Shaw, Electronic Arts. */ /* This software is in the public domain. */ /* */ /* This version for the Commodore-Amiga computer. */ /* */ /************************************************************************/ #ifndef REM_ALLOC_H #define REM_ALLOC_H #ifndef COMPILER_H #include "iff/compiler.h" #endif /* How these allocators work: * The allocator procedures get the memory from the system allocator, * actually allocating 4 extra bytes. We store the length of the node in * the first 4 bytes then return a ptr to the rest of the storage. The * deallocator can then find the node size and free it. */ #ifdef FDwAT /* RemAlloc allocates a node with "size" bytes of user data. * Example: * struct BitMap *bm; * bm = (struct BitMap *)RemAlloc( sizeof(struct BitMap), ...flags... ); */ extern UBYTE *RemAlloc(LONG, LONG); /* size, flags */ /* ALLOCator that remembers size, allocates in CHIP-accessable memory. * Use for all data to be displayed on screen, all sound data, all data to be * blitted, disk buffers, or access by any other DMA channel. * Does clear memory being allocated.*/ extern UBYTE *ChipAlloc(LONG); /* size */ /* ChipAlloc, without clearing memory. Purpose: speed when allocate * large area that will be overwritten anyway.*/ extern UBYTE *ChipNoClearAlloc(LONG); /* ALLOCator that remembers size, allocates in extended memory. * Does clear memory being allocated. * NOTICE: does NOT declare "MEMF_FAST". This allows machines * lacking extended memory to allocate within chip memory, * assuming there is enough memory left.*/ extern UBYTE *ExtAlloc(LONG); /* size */ /* ExtAlloc, without clearing memory. Purpose: speed when allocate * large area that will be overwritten anyway.*/ extern UBYTE *ExtNoClearAlloc(LONG); /* FREEs either chip or extended memory, if allocated with an allocator * which REMembers size allocated. * Safe: won't attempt to de-allocate a NULL pointer. * Returns NULL so caller can do * p = RemFree(p); */ extern UBYTE *RemFree(UBYTE *); /* p */ #else /* not FDwAT */ extern UBYTE *RemAlloc(); extern UBYTE *ChipAlloc(); extern UBYTE *ExtAlloc(); extern UBYTE *RemFree(); #endif /* FDwAT */ #endif REM_ALLOC_H //E*O*F remalloc.h// echo Possible errors detected by \'wc\' [hopefully none]: temp=/tmp/shar$$ trap "rm -f $temp; exit" 0 1 2 3 15 cat > $temp <<\!!! 10 20 133 README 32 123 1058 compiler.h 151 910 6100 gio.h 478 3249 20481 iff.h 261 1517 10909 ilbm.h 13 17 211 intuall.h 49 243 1706 packer.h 49 198 2110 putpict.h 62 313 2249 readpict.h 85 392 3182 remalloc.h 1190 6982 48139 total !!! wc README compiler.h gio.h iff.h ilbm.h intuall.h packer.h putpict.h readpict.h remalloc.h | sed 's=[^ ]*/==' | diff -b $temp - exit 0 -- UUCP: orandy@amdahl.amdahl.com or: {sun,decwrl,hplabs,pyramid,ihnp4,seismo,oliveb,cbosgd}!amdahl!orandy DDD: 408-737-5481 USPS: Amdahl Corp. M/S 249, 1250 E. Arques Av, Sunnyvale, CA 94086 [ Any thoughts or opinions which may or may not have been expressed ] [ herein are my own. They are not necessarily those of my employer. ]