#include <functions.h>
#include <intuition/intuition.h> /* Nice because it includes everything else */
#include <libraries/dos.h>
#include "smalliff.h"

/* Ali T. Ozer, Oct, Nov 1987 */

/* This code to read IFF pictures originally from D. John Hodgson's "view" 
** program. LIMITATIONS : no masking, CATS/LISTS/PROPS. CAMG chunks 
** are supported.
*/

/* Original Copyright: 
** VIEW.C - tiny ILBM viewer; (c) 1986 DJH
*/

#define CRead(f,src,sz) if (Read (f, src, sz) == -1L) return (0);

int ReadILBM (fp, pic)
struct FileHandle *fp;    /* An already "Open"ed AmigaDOS file handle */
PicInfoStruct     *pic;
{
  unsigned char  cmap[MAXCOLORS][3];
  ChunkHeader    header;
  ID             id;
  int            cnt;

  CRead(fp, &header, (long)sizeof(ChunkHeader));
  if (header.ckID != ID_FORM) return (0);  /* Not IFF */

  CRead(fp, &id, (long)sizeof(id));
  if (id != ID_ILBM) return (0);           /* Not ILBM */

  while (1) {

    CRead(fp, &header, (long)sizeof(header));

    if (header.ckID == ID_BODY) break;

    switch(header.ckID) {
      case ID_BMHD: CRead(fp, &(pic->bmhd), (long) sizeof(BitMapHeader)); break;
      case ID_CMAP: CRead(fp, &(cmap[0][0]), header.ckSize);
                    pic->colorcount = (UBYTE)(header.ckSize/3); break;
      case ID_CAMG: CRead(fp, &(pic->viewmodes), header.ckSize); break;
      default:      Seek(fp, WordAlign(header.ckSize), OFFSET_CURRENT); break;
    }
  }

  pic->rawsourcesize  = header.ckSize;
  if ((pic->rawsource = AllocMem (header.ckSize, NULL)) == NULL)
     return (0);   /* Not enough memory */
 
  CRead(fp, pic->rawsource, header.ckSize);

  /* make some forced assumptions if CAMG chunk unavailable */

  if (pic->viewmodes == NULL) {
    if (pic->bmhd.w > MAXWIDTH)  pic->viewmodes |= HIRES;
    if (pic->bmhd.h > MAXHEIGHT) pic->viewmodes |= LACE;
  }

  for (cnt = 0; cnt < pic->colorcount; cnt++) {
    pic->colortable[cnt] = 
       (((UWORD)cmap[cnt][0]) << 4L) | 
       (((UWORD)cmap[cnt][1]))       |
       (((UWORD)cmap[cnt][2]) >> 4L);
  };
      
  return (1);
}      



Expand(bm, bmhd, sourcebuf) /* Fast line decompress/deinterleave */
struct BitMap *bm;
BitMapHeader  *bmhd;
register char *sourcebuf;
{
  
  register char n,*destbuf; /* in order of preferred allocation */
  register short plane,rowbytes;
  short    linelen,i,curloc;

  linelen=bmhd->w/8;
  curloc = 0;

  for (i=0;i<bmhd->h;i++) { /* process n lines/screen */
    for (plane=0;plane<bmhd->nPlanes;plane++) { /* process n planes/line */
      destbuf=(char *)(bm->Planes[plane])+curloc;

      if (bmhd->compression == cmpByteRun1) { /* compressed screen? */
        rowbytes=linelen;

        while (rowbytes) { /* unpack until 1 scan-line complete */
          n=*sourcebuf++; /* fetch block run marker */

          /* uncompressed block? copy n bytes verbatim */
          if (n>=0) {
            movmem(sourcebuf,destbuf,(unsigned int)++n); rowbytes-=n;
            destbuf+=n; sourcebuf+=n;
          }
          else { /* compressed block? expand n duplicate bytes */
            n=-n+1; rowbytes-=n;
            setmem(destbuf,(unsigned int)n,(unsigned int)*sourcebuf++);
            destbuf+=n;
          }

        } /* finish unpacking line */
      }
      else { /* uncompressed? just copy */
        movmem(sourcebuf,destbuf,(unsigned int)linelen);
        sourcebuf+=linelen; destbuf+=linelen;
      }
    } /* finish interleaved planes, lines */
    curloc += linelen;
  }
}
