#include "iff.h" extern void *IntuitionBase,*GfxBase,*DiskfontBase; /* READILBM.C : NewZAP support routines - (c) 1986 John Hodgson */ #define DISK_ERR 1 /* error processing */ #define IFF_ERR 2 #define OUT_OF_MEM 3 #define EXPAND_ERR 4 #define BAD_MODE 5 #define MakeID(a,b,c,d) ((a)<<24L | (b)<<16L | (c)<<8 | (d)) #define ID_FORM MakeID('F','O','R','M') #define ID_ILBM MakeID('I','L','B','M') #define ID_BMHD MakeID('B','M','H','D') #define ID_CAMG MakeID('C','A','M','G') #define ID_CMAP MakeID('C','M','A','P') #define ID_BODY MakeID('B','O','D','Y') #define cmpByteRun1 1 #define ROUNDODDUP(a) (((a)+1)&(~1L)) typedef struct { long ckID,ckSize; } Chunk; typedef struct { short w,h,x,y; char nPlanes,masking,compression,pad1; short transparentColor; char xAspect, yAspect; short pageWidth,pageHeight; } BitMapHeader; short Mode; unsigned char *pdiskptr; #define SafeRead(a,b,c) if (ReadNEW(a,b,c)==-1L) \ { CloseNEW(a); return(DISK_ERR); } void *AllocMem(),*AllocRaster(); /************************************************************************ * * * Routine name(s) : ReadILBM() * * Author : D. John Hodgson * * Environment : Aztec "C", default * * * * ReadILBM attempts to read an IFF file into an user-supplied * * bitmap. Returns TRUE if successful. Brushes supported. * * * * OPTIONS : Filespec reflects user-supplied pointer to IFF file in * * RAM if mode argument is non-zero. Otherwise, disk. * * * * LIMITATIONS : Bare-bones ILBM; no masking, CATS/LISTS/PROPS. * * All other graphics (compressed or not) supported. * ************************************************************************/ void *OpenNEW(name,accessMode) unsigned char *name; long accessMode; { struct FileHandle *Open(); if (!Mode) return(Open(name,accessMode)); pdiskptr=name; /* initialize pseudo-disk RAM ptr */ return(pdiskptr); } long ReadNEW(file,buffer,length) struct FileHandle *file; char *buffer; long length; { long Read(); if (!Mode) return(Read(file,buffer,length)); movmem(pdiskptr,buffer,(unsigned int)length); pdiskptr+=length; return(length); } long SeekNEW(file,position,tmode) struct FileHandle *file; long position,tmode; { long Seek(); if (!Mode) return(Seek(file,position,tmode)); /* Note : RAM seek only supports one mode : OFFSET_CURRENT! */ if (tmode!=OFFSET_CURRENT) return(BAD_MODE); pdiskptr+=position; return((long)pdiskptr-position); /* Seek() returns previous position! */ } void CloseNEW(file) struct FileHandle *file; { if (!Mode) Close(file); } /* tag : core routines live here! */ ReadILBM(fspec,mode,picmap) char *fspec; /* AmigaDOS filename */ short mode; struct PicMap *picmap; { struct FileHandle *fp; Chunk header; BitMapHeader bmhd; unsigned char colormap[MAXCOLORS][3],*bufstart,*sourcebuf; short i; long id; Mode=mode; setmem(picmap,sizeof(*picmap),0L); if (!(fp=OpenNEW(fspec,MODE_OLDFILE))) return(DISK_ERR); SafeRead(fp,&header,(long)sizeof(header)); if (header.ckID!=ID_FORM) { CloseNEW(fp); return(IFF_ERR); } SafeRead(fp,&id,(long)sizeof(id)); if (id!=ID_ILBM) { CloseNEW(fp); return(IFF_ERR); } for (;;) { SafeRead(fp,&header,(long)sizeof(header)); if (header.ckID==ID_BODY) break; switch(header.ckID) { case ID_BMHD: SafeRead(fp,&bmhd,(long)sizeof(bmhd)); /* force WORD boundary for all pics */ bmhd.w=(bmhd.w + 0xf) & 0xfff0; break; case ID_CMAP: SafeRead(fp,&colormap[0][0],(long)header.ckSize); for (i=0;icolormap[i]=colormap[i][2]>>4 | colormap[i][1] & 0xf0 | (colormap[i][0] & 0xf0)<<4; break; case ID_CAMG: SafeRead(fp,&picmap->ViewModes,(long)header.ckSize); break; default: SeekNEW(fp,ROUNDODDUP(header.ckSize),OFFSET_CURRENT); } } /* make some forced assumptions if CAMG chunk unavailable */ if (!picmap->ViewModes) { if (bmhd.w>LOWIDTH) picmap->ViewModes=HIRES; if (bmhd.h>LOHEIGHT) picmap->ViewModes|=LACE; } /* Read planes into RAM for ease if decompression */ if (Mode) sourcebuf=bufstart=pdiskptr; /* memory-resident IFF? */ else { /* disk-resident IFF? */ if (!(sourcebuf=bufstart=AllocMem((long)header.ckSize,MEMF_PUBLIC))) return(OUT_OF_MEM); SafeRead(fp,sourcebuf,(long)header.ckSize); CloseNEW(fp); } InitBitMap(&picmap->BitMap,(long)bmhd.nPlanes,(long)bmhd.w,(long)bmhd.h); /* if we -REALLY- need a blank page, zero after allocating! */ for (i=0;iBitMap.Planes[i]=AllocRaster((long)bmhd.w,(long)bmhd.h))) { FreeBitMap(&picmap->BitMap); return(OUT_OF_MEM); } i=Expand(&bmhd,bufstart,&picmap->BitMap); if (!Mode) FreeMem(bufstart,(long)header.ckSize); return(i); /* error if unpacking prob */ } FreeBitMap(bitmap) struct BitMap *bitmap; { short i; /* take into acct partially allocated maps (due to error) */ for (i=0;iDepth;i++) { if (bitmap->Planes[i]) FreeRaster( bitmap->Planes[i],(long)bitmap->BytesPerRow*8,(long)bitmap->Rows); } setmem(bitmap,sizeof(bitmap),0L); /* prevent dbl-dealloc errs */ } Expand(bmhd,sourcebuf,bitmap) /* Fast line decompress/deinterleave */ BitMapHeader *bmhd; register char *sourcebuf; struct BitMap *bitmap; { register char n,*destbuf; /* in order of preferred allocation */ register short plane,rowlen,rowbytes,i; rowlen=(bmhd->w)>>3; for (i=0;ih;i++) /* process n lines/screen */ for (plane=0;planenPlanes;plane++) { /* process n planes/line */ destbuf=(char *)(bitmap->Planes[plane])+rowlen*i; if (bmhd->compression==cmpByteRun1) { /* compressed screen? */ rowbytes=rowlen; while (rowbytes>0) { /* unpack until 1 scan-line complete */ n=*sourcebuf++; /* fetch block run marker */ /* uncompressed block? copy n bytes verbatim */ if (n>=0) { ++n; movmem(sourcebuf,destbuf,(unsigned int)n); rowbytes-=n; destbuf+=n; sourcebuf+=n; } else { /* compressed block? expand n duplicate bytes */ n=-n+1; setmem(destbuf,(unsigned int)n,(unsigned int)*sourcebuf); rowbytes -=n; sourcebuf++; destbuf+=n; } } /* finish unpacking line */ if (rowbytes) return(EXPAND_ERR); /* shouldn't be any left over! */ } else { /* uncompressed? just copy */ movmem(sourcebuf,destbuf,(unsigned int)rowlen); sourcebuf+=rowlen; destbuf+=rowlen; } } /* finish interleaved planes, lines */ return(0); /* good result! */ }