home *** CD-ROM | disk | FTP | other *** search
- /* ilbmr.c --- ILBM loading routines for use with iffparse */
-
- /*----------------------------------------------------------------------*
- * ILBMR.C Support routines for reading ILBM files.
- * (IFF is Interchange Format File.)
- *
- * Based on code by Jerry Morrison and Steve Shaw, Electronic Arts.
- * This software is in the public domain.
- * Modified for iffparse.library 05/90
- * This version for the Commodore-Amiga computer.
- *----------------------------------------------------------------------*/
-
- #include "iffp/ilbm.h"
- #include "iffp/packer.h"
- #include "iffp/ilbmapp.h"
-
- #define movmem CopyMem
-
- #define MaxSrcPlanes (25)
-
- extern struct Library *GfxBase;
-
- /*---------- loadbody ---------------------------------------------------*/
-
- LONG loadbody(iff, bitmap, bmhd)
- struct IFFHandle *iff;
- struct BitMap *bitmap;
- BitMapHeader *bmhd;
- {
- BYTE *buffer;
- ULONG bufsize;
- LONG error = 1;
-
- D(bug("In loadbody\n"));
-
- if(!(currentchunkis(iff,ID_ILBM,ID_BODY)))
- {
- message("ILBM has no BODY\n"); /* Maybe it's a palette */
- return(IFF_OKAY);
- }
-
- if((bitmap)&&(bmhd))
- {
- D(bug("Have bitmap and bmhd\n"));
-
- bufsize = MaxPackedSize(RowBytes(bmhd->w)) << 4;
- if(!(buffer = AllocMem(bufsize,0L)))
- {
- D(bug("Buffer alloc of %ld failed\n",bufsize));
- return(IFFERR_NOMEM);
- }
- error = loadbody2(iff, bitmap, NULL, bmhd, buffer, bufsize);
- D(bug("Returned from getbody, error = %ld\n",error));
- }
- FreeMem(buffer,bufsize);
- return(error);
- }
-
-
- /* like the old GetBODY */
- LONG loadbody2(iff, bitmap, mask, bmhd, buffer, bufsize)
- struct IFFHandle *iff;
- struct BitMap *bitmap;
- BYTE *mask;
- BitMapHeader *bmhd;
- BYTE *buffer;
- ULONG bufsize;
- {
- UBYTE srcPlaneCnt = bmhd->nPlanes; /* Haven't counted for mask plane yet*/
- WORD srcRowBytes = RowBytes(bmhd->w);
- WORD destRowBytes = bitmap->BytesPerRow;
- LONG bufRowBytes = MaxPackedSize(srcRowBytes);
- int nRows = bmhd->h;
- WORD compression = bmhd->compression;
- register int iPlane, iRow, nEmpty;
- register WORD nFilled;
- BYTE *buf, *nullDest, *nullBuf, **pDest;
- BYTE *planes[MaxSrcPlanes]; /* array of ptrs to planes & mask */
- struct ContextNode *cn;
-
- D(bug("srcRowBytes = %ld\n",srcRowBytes));
-
- cn = CurrentChunk(iff);
-
- if (compression > cmpByteRun1)
- return(CLIENT_ERROR);
-
- D(bug("loadbody2: compression=%ld srcBytes=%ld bitmapBytes=%ld\n",
- compression, srcRowBytes, bitmap->BytesPerRow));
- D(bug("loadbody2: bufsize=%ld bufRowBytes=%ld, srcPlaneCnt=%ld\n",
- bufsize, bufRowBytes, srcPlaneCnt));
-
- /* Complain if client asked for a conversion GetBODY doesn't handle.*/
- if ( srcRowBytes > bitmap->BytesPerRow ||
- bufsize < bufRowBytes * 2 ||
- srcPlaneCnt > MaxSrcPlanes )
- return(CLIENT_ERROR);
-
- D(bug("loadbody2: past conversion checks\n"));
-
- if (nRows > bitmap->Rows) nRows = bitmap->Rows;
-
- D(bug("loadbody2: srcRowBytes=%ld, srcRows=%ld, srcDepth=%ld, destDepth=%ld\n",
- srcRowBytes, nRows, bmhd->nPlanes, bitmap->Depth));
-
- /* Initialize array "planes" with bitmap ptrs; NULL in empty slots.*/
- for (iPlane = 0; iPlane < bitmap->Depth; iPlane++)
- planes[iPlane] = (BYTE *)bitmap->Planes[iPlane];
- for ( ; iPlane < MaxSrcPlanes; iPlane++)
- planes[iPlane] = NULL;
-
- /* Copy any mask plane ptr into corresponding "planes" slot.*/
- if (bmhd->masking == mskHasMask)
- {
- if (mask != NULL)
- planes[srcPlaneCnt] = mask; /* If there are more srcPlanes than
- * dstPlanes, there will be NULL plane-pointers before this.*/
- else
- planes[srcPlaneCnt] = NULL; /* In case more dstPlanes than src.*/
- srcPlaneCnt += 1; /* Include mask plane in count.*/
- }
-
- /* Setup a sink for dummy destination of rows from unwanted planes.*/
- nullDest = buffer;
- buffer += srcRowBytes;
- bufsize -= srcRowBytes;
-
- /* Read the BODY contents into client's bitmap.
- * De-interleave planes and decompress rows.
- * MODIFIES: Last iteration modifies bufsize.*/
-
- buf = buffer + bufsize; /* Buffer is currently empty.*/
- for (iRow = nRows; iRow > 0; iRow--)
- {
- for (iPlane = 0; iPlane < srcPlaneCnt; iPlane++)
- {
- pDest = &planes[iPlane];
-
- /* Establish a sink for any unwanted plane.*/
- if (*pDest == NULL)
- {
- nullBuf = nullDest;
- pDest = &nullBuf;
- }
-
- /* Read in at least enough bytes to uncompress next row.*/
- nEmpty = buf - buffer; /* size of empty part of buffer.*/
- nFilled = bufsize - nEmpty; /* this part has data.*/
- if (nFilled < bufRowBytes)
- {
- /* Need to read more.*/
-
- /* Move the existing data to the front of the buffer.*/
- /* Now covers range buffer[0]..buffer[nFilled-1].*/
- movmem(buf, buffer, nFilled); /* Could be moving 0 bytes.*/
-
- if(nEmpty > ChunkMoreBytes(cn))
- {
- /* There aren't enough bytes left to fill the buffer.*/
- nEmpty = ChunkMoreBytes(cn);
- bufsize = nFilled + nEmpty; /* heh-heh */
- }
-
- /* Append new data to the existing data.*/
- if(ReadChunkBytes(iff, &buffer[nFilled], nEmpty) < nEmpty)
- return(CLIENT_ERROR);
-
- buf = buffer;
- nFilled = bufsize;
- nEmpty = 0;
- }
-
- /* Copy uncompressed row to destination plane.*/
- if(compression == cmpNone)
- {
- if(nFilled < srcRowBytes) return(IFFERR_MANGLED);
- movmem(buf, *pDest, srcRowBytes);
- buf += srcRowBytes;
- *pDest += destRowBytes;
- }
- else
- {
- /* Decompress row to destination plane.*/
- if ( unpackrow(&buf, pDest, nFilled, srcRowBytes) )
- /* pSource, pDest, srcBytes, dstBytes */
- return(IFFERR_MANGLED);
- else *pDest += (destRowBytes - srcRowBytes);
- }
- }
- }
- return(IFF_OKAY);
- }
-
-
- /* ----------- getcolors ------------- */
-
- /* getcolors - allocates a ilbm->colortable for at least MAXAMCOLORREG
- * and loads CMAP colors into it, setting ilbm->ncolors to number
- * of colors actually loaded.
- */
- LONG getcolors(struct ILBMInfo *ilbm)
- {
- struct IFFHandle *iff;
- int error = 1;
-
- if(!(iff=ilbm->ParseInfo.iff)) return(CLIENT_ERROR);
-
- if(!(error = alloccolortable(ilbm)))
- error = loadcmap(iff, ilbm->colortable, &ilbm->ncolors);
- if(error) freecolors(ilbm);
- D(bug("getcolors: error = %ld\n",error));
- return(error);
- }
-
-
- /* alloccolortable - allocates ilbm->colortable and sets ilbm->ncolors
- * to the number of colors we have room for in the table.
- */
-
- LONG alloccolortable(struct ILBMInfo *ilbm)
- {
- struct IFFHandle *iff;
- struct StoredProperty *sp;
-
- LONG error = CLIENT_ERROR;
- ULONG ctabsize;
- USHORT ncolors;
-
- if(!(iff=ilbm->ParseInfo.iff)) return(CLIENT_ERROR);
-
- if(sp = FindProp (iff, ID_ILBM, ID_CMAP))
- {
- /*
- * Compute the size table we need
- */
- ncolors = sp->sp_Size / 3; /* how many in CMAP */
- ncolors = MAX(ncolors, MAXAMCOLORREG);
-
- ctabsize = ncolors * sizeof(Color4);
- if(ilbm->colortable =
- (Color4 *)AllocMem(ctabsize,MEMF_CLEAR|MEMF_PUBLIC))
- {
- ilbm->ncolors = ncolors;
- ilbm->ctabsize = ctabsize;
- error = 0L;
- }
- else error = IFFERR_NOMEM;
- }
- D(bug("alloccolortable for %ld colors: error = %ld\n",ncolors,error));
- return(error);
- }
-
-
- void freecolors(struct ILBMInfo *ilbm)
- {
- if(ilbm->colortable)
- {
- FreeMem(ilbm->colortable, ilbm->ctabsize);
- }
- ilbm->colortable = NULL;
- ilbm->ctabsize = 0;
- }
-
-
-
- /* Passed IFFHandle, pointer to colortable array, and pointer to
- * a USHORT containing number of colors caller has space to hold,
- * loads the colors and sets pNcolors to the number actually read.
- *
- * NOTE !!! - Old GetCMAP passed a pointer to a UBYTE for pNcolors
- * This one is passed a pointer to a USHORT
- */
- LONG loadcmap(struct IFFHandle *iff, WORD *colortable,USHORT *pNcolors)
- {
- register struct StoredProperty *sp;
- register LONG idx;
- register ULONG ncolors;
- register UBYTE *rgb;
- LONG r, g, b;
-
- if(!(colortable))
- {
- message("No colortable allocated\n");
- return(1);
- }
-
- if(!(sp = FindProp (iff, ID_ILBM, ID_CMAP))) return(1);
-
- rgb = sp->sp_Data;
- ncolors = sp->sp_Size / sizeofColorRegister;
- if(*pNcolors < ncolors) ncolors = *pNcolors;
- *pNcolors = ncolors;
-
- idx = 0;
- while (ncolors--)
- {
- r = (*rgb++ & 0xF0) << 4;
- g = *rgb++ & 0xF0;
- b = *rgb++ >> 4;
- colortable[idx] = r | g | b;
- idx++;
- }
- return(0);
- }
-
- /*
- * Returns CAMG or computed mode for storage in ilbm->camg
- *
- * ilbm->Bmhd structure must be initialized prior to this call.
- */
- ULONG getcamg(struct ILBMInfo *ilbm)
- {
- struct IFFHandle *iff;
- struct StoredProperty *sp;
- UWORD wide,high,deep;
- ULONG modeid = 0L;
-
- if(!(iff=ilbm->ParseInfo.iff)) return(0L);
-
- wide = ilbm->Bmhd.pageWidth;
- high = ilbm->Bmhd.pageHeight;
- deep = ilbm->Bmhd.nPlanes;
-
- D(bug("Getting CAMG for w=%ld h=%ld d=%ld ILBM\n",wide,high,deep));
-
- /*
- * Grab CAMG's idea of the viewmodes.
- */
- if (sp = FindProp (iff, ID_ILBM, ID_CAMG))
- {
- modeid = (* (ULONG *) sp->sp_Data);
-
- /* knock bad bits out of old-style 16-bit viewmode CAMGs
- */
- if((!(modeid & MONITOR_ID_MASK))||
- ((modeid & EXTENDED_MODE)&&(!(modeid & 0xFFFF0000))))
- modeid &=
- (~(EXTENDED_MODE|SPRITES|GENLOCK_AUDIO|GENLOCK_VIDEO|VP_HIDE));
-
- /* check for bogus CAMG like DPaintII brushes
- * with junk in upper word and extended bit
- * not set in lower word.
- */
- if((modeid & 0xFFFF0000)&&(!(modeid & 0x00001000))) sp=NULL;
- }
-
- if(!sp) {
- /*
- * No CAMG (or bad CAMG) present; use computed modes.
- */
- if (wide >= 640) modeid = HIRES;
- if (high >= 400) modeid |= LACE;
- if (deep == 6)
- {
- modeid |= ilbm->EHB ? EXTRA_HALFBRITE : HAM;
- }
- D(bug("No CAMG found - using mode $%08lx\n",modeid));
- }
-
- D(bug("getcamg: modeid = $%08lx\n",modeid));
- return(modeid);
- }
-