// Sample IFF File Reader
//
// This function will return a pointer to a buffer that holds the raw image.
// just free the pointer to delete this buffer. After returning, the array
// colordat will hold the adjusted palette of this pic.
//
// Also, this has been modified to only read in form PBM brushes. form ILBM's
// (the "old" type) are not supported. use the "new" deluxe paint .lbm type
// and do not choose "old".

#include <stdio.h>
#include <conio.h>
#include <process.h>
#include <bios.h>
#include <fcntl.h>
#include <malloc.h>
#include <mem.h>
#include "iff.h"
#include "ack3d.h"

	extern	    int	    ErrorCode;

unsigned char far  colordat[768];  /* maximum it can be...256 colors	*/

unsigned char far  cplanes[8][80]; /* setting max at 640 pixels width	*/
				   /* thats 8 pixels per byte per plane */
unsigned char far  *pplanes= (char far *) &cplanes[0][0];  /* for a form pbm	    */

unsigned char far * Readiff(char *picname)
   {
   FILE *pic;
   form_chunk   fchunk;
   ChunkHeader  chunk;
   BitMapHeader bmhd;
   long length;
   char value;	   // must remain signed, no matter what. ignore any warnings.
   int sofar;
   int width,height,planes;
   int pixw;
   unsigned char far *destx, *savedestx;

   if ((pic = fopen(picname,"r+b"))== NULL)
	{
	ErrorCode = ERR_BADFILE;
	return(0L);
	}

   fread(&fchunk,1,sizeof(form_chunk),pic); /* read in the first 12 bytes*/

   if (fchunk.type != FORM)
      {
      fclose(pic);
      return(0L);
      }

   if (fchunk.subtype != ID_PBM)
      {
      printf("Error: Not form PBM!");
      fclose(pic);
      return(0L);
      }
   // now lets loop...Because the Chunks can be in any order!
   while(1)
      {
      fread(&chunk,1,sizeof(ChunkHeader),pic);
      ByteFlipLong(&(long)(chunk.ckSize));
      if (chunk.ckSize & 1) chunk.ckSize ++;	// must be word aligned
      if(chunk.ckID == ID_BMHD)
          {
	  fread(&bmhd,1,sizeof(BitMapHeader),pic);
          bmhd.w=swab(bmhd.w);                  // the only things we need.
          bmhd.h=swab(bmhd.h);
          destx = (unsigned char far *)farmalloc((bmhd.w * bmhd.h)+4);
          if ( !destx ) return(0L);
          savedestx = destx;

          destx[0] = bmhd.w%256;
          destx[1] = bmhd.w/256;
          destx[2] = bmhd.h%256;
          destx[3] = bmhd.h/256;
          destx += 4;
          continue;
          }
      if(chunk.ckID == ID_CMAP)
          {
          int i;
          unsigned char r,g;

          fread(colordat,1,chunk.ckSize,pic);
          for (i=0;i<768;i++)
              {
               r = colordat[i];   // r,g do not stand for red and green
              g = r >> 2;
	      colordat[i] = g;
              }
          continue;
          }
      if(chunk.ckID == ID_BODY)
          {
          for(height = 0; height<bmhd.h; height ++)
             {
             unsigned char *dest;
	     dest = (unsigned char *)&(pplanes[0]); /* point at first char  */
             sofar = bmhd.w;                        /* number of bytes = 8  */
             if (sofar&1) sofar++;
             while (sofar)
                {
                if (bmhd.compression)
                   {
                   value=fgetc(pic);      /* get the next byte    */
                   // if (value == 128) continue; /* NOP..just get another*/
                   if (value > 0)
                      {
                      int len;
                      len = value +1;
                      sofar -= len;
                      if(!(fread(dest,len,1,pic)))
			  {
                          fclose(pic);
                          return(0L);
                          }
                      dest +=len;
                      }
                   else
                      {
                      int count;
                      count = -value; /* get amount to dup */
                      count ++;
                      sofar -= count;
                      value=fgetc(pic);
                      while (--count >= 0) *dest++ = value;
                      }
                   }
                else
                   {
                   fread(dest,sofar,1,pic); /* just throw on plane */
                   sofar = 0;
                   }
                }
             if (sofar < 0)
                {
		fclose(pic);
		}
	     _fmemcpy(destx,pplanes,bmhd.w);
	     destx += bmhd.w;
	     }
	  break; /* leave if we've unpacked the BODY*/
	  }
      fseek(pic,chunk.ckSize,SEEK_CUR);
      }

   fclose(pic);
   return((char far *)savedestx);
   }

void ByteFlipLong(long *NUMBER)
   {
   // Hey, I didn;t write this function!!!
   long int Y, T;
   int I;

   T = *NUMBER;
   Y=0;for (I=0;I<4;I++){Y = Y | (T & 0xFF);if (I<3) {Y = Y << 8;T = T >> 8;}}
   *NUMBER = Y;
   }

int swab(unsigned short number)
   {
   unsigned int xx1,xx2;
   unsigned int result;

   xx1 = number <<8; xx2 = number >>8; result = xx1|xx2;
   return(result);
   }
