[net.micro.amiga] New IFF header files

page@ulowell.UUCP (Bob Page) (03/20/86)

# Here are the latest header files for IFF.  Most of the files are
# dated.  I recently posted new IFF spec documents for ILBM, FTXT,
# 8SVX and SMUS.  Contact me by mail (don't post to the net)
# if you didn't receive them and you want them.
#
# I will post the IFF source code in a few days.
#
# Bob Page, ulowell!page (preferred) or page@ulowell.csnet
#
#########################################################
#                                                       #
# This is a shell archive file.  To extract files:      #
#                                                       #
#    1)	Make a directory for the files.                 #
#    2) Write a file, such as "file.shar", containing   #
#       this archive file into the directory.           #
#    3) Type "sh file.shar".  Do not use csh.           #
#                                                       #
#########################################################
#
#
echo x - compiler.h:
cat >compiler.h <<\STUNKYFLUFF
#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. */



		/* Greenhills can't take it */
		/* Aztec C can't take it */
#define FDwAT	/* OK for Lattice */



#endif COMPILER_H

STUNKYFLUFF
set `sum compiler.h`
if test 20345 != $1
then
echo compiler.h: Checksum error. Is: $1, should be: 20345.
fi
#
#
echo x - gio.h:
cat >gio.h <<\STUNKYFLUFF
#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
STUNKYFLUFF
set `sum gio.h`
if test 22472 != $1
then
echo gio.h: Checksum error. Is: $1, should be: 22472.
fi
#
#
echo x - iff.h:
cat >iff.h <<\STUNKYFLUFF
#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
STUNKYFLUFF
set `sum iff.h`
if test 16961 != $1
then
echo iff.h: Checksum error. Is: $1, should be: 16961.
fi
#
#
echo x - ilbm.h:
cat >ilbm.h <<\STUNKYFLUFF
#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
STUNKYFLUFF
set `sum ilbm.h`
if test 64527 != $1
then
echo ilbm.h: Checksum error. Is: $1, should be: 64527.
fi
#
#
echo x - intuall.h:
cat >intuall.h <<\STUNKYFLUFF
/*** intuall.h **********************************************************/
/*  intuall.h, Include lots of Amiga-provided header files. 1/22/86 */
/*  Plus the portability file "iff/compiler.h" which should be tailored */
/*  for your compiler.                                 */
/*                                                                      */ 
/* By Jerry Morrison and Steve Shaw, Electronic Arts.                   */ 
/* This software is in the public domain.                               */ 
/*                                                                      */ 
/* This version for the Commodore-Amiga computer.                       */
/*                                                                      */ 
/************************************************************************/

#include "iff/compiler.h"     /* COMPILER-DEPENDENCIES */

/* Dummy definitions because some includes below are commented out.
 * This avoids 'undefined structure' warnings when compile.
 * This is safe as long as only use POINTERS to these structures.
 */

struct Region { int dummy; };
struct VSprite { int dummy; };
struct collTable { int dummy; };
struct CopList { int dummy; };
struct UCopList { int dummy; };
struct cprlist { int dummy; };
struct copinit { int dummy; };
struct TimeVal { int dummy; };

#include "exec/types.h"
#include "exec/nodes.h"
#include "exec/lists.h"
#include "exec/libraries.h"
#include "exec/ports.h"

#include "exec/tasks.h"
#include "exec/devices.h"


#include "exec/interrupts.h"

#include "exec/io.h"
#include "exec/memory.h"
#include "exec/alerts.h"

/* ALWAYS INCLUDE GFX.H before any other amiga includes */

#include "graphics/gfx.h"
/*#include "hardware/blit.h"*/

/*****
#include "graphics/collide.h"
#include "graphics/copper.h"
#include "graphics/display.h"
#include "hardware/dmabits.h" 
#include "graphics/gels.h"
***/

#include "graphics/clip.h"

#include "graphics/rastport.h"
#include "graphics/view.h"
#include "graphics/gfxbase.h"
/*#include "hardware/intbits.h"*/
#include "graphics/gfxmacros.h"

#include "graphics/layers.h"

#include "graphics/text.h"
#include "graphics/sprite.h"
/*#include "hardware/custom.h"*/

/*#include "libraries/dos.h"*/
/*#include "libraries/dosextens.h"*/

#include "devices/timer.h"
#include "devices/inputevent.h"
#include "devices/keymap.h"

#include "intuition/intuition.h"

/*#include "intuitionbase.h"*/
/*#include "intuinternal.h"*/
STUNKYFLUFF
set `sum intuall.h`
if test 01286 != $1
then
echo intuall.h: Checksum error. Is: $1, should be: 01286.
fi
#
#
echo x - packer.h:
cat >packer.h <<\STUNKYFLUFF
#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
STUNKYFLUFF
set `sum packer.h`
if test 55164 != $1
then
echo packer.h: Checksum error. Is: $1, should be: 55164.
fi
#
#
echo x - putpict.h:
cat >putpict.h <<\STUNKYFLUFF
#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
STUNKYFLUFF
set `sum putpict.h`
if test 55308 != $1
then
echo putpict.h: Checksum error. Is: $1, should be: 55308.
fi
#
#
echo x - readpict.h:
cat >readpict.h <<\STUNKYFLUFF
#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<<MaxAmDepth*/ ];
   /* If you want to read any other property chunks, e.g. GRAB or CAMG, add
    * fields to this record to store them. */
   } ILBMFrame;

/** ReadPicture() ***********************************************************
 *
 * Read a picture from an IFF file, given a file handle open for reading.
 * Allocates BitMap RAM by calling (*Allocator)(size).
 *
 ****************************************************************************/

typedef UBYTE *UBytePtr;

#ifdef FDwAT

typedef UBytePtr Allocator(LONG);
   /* Allocator: a memory allocation procedure which only requires a size
    * argument. (No Amiga memory flags argument.) */

extern IFFP ReadPicture(LONG, struct BitMap *, ILBMFrame *, Allocator *);
              /*  file, bm,              iFrame,      allocator  */
   /* iFrame is the top level "client frame". */
   /* allocator is a ptr to your allocation procedure. It must always
    *   allocate in Chip memory (for bitmap data). */

   /* PS: Notice how we used two "typedef"s above to make allocator's type
    * meaningful to humans.
    * Consider the usual C style: UBYTE *(*)(), or is it (UBYTE *)(*()) ? */

#else /* not FDwAT */

typedef UBytePtr Allocator();
extern IFFP ReadPicture();

#endif

#endif READPICT_H
STUNKYFLUFF
set `sum readpict.h`
if test 28263 != $1
then
echo readpict.h: Checksum error. Is: $1, should be: 28263.
fi
#
#
echo x - remalloc.h:
cat >remalloc.h <<\STUNKYFLUFF
/** 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
STUNKYFLUFF
set `sum remalloc.h`
if test 47940 != $1
then
echo remalloc.h: Checksum error. Is: $1, should be: 47940.
fi
exit 0