/******************* ( Animation Construction Kit 3D ) ***********************/
/*			Deluxe Paint file reader			     */
/* CopyRight (c) 1993  Authors: Jaimi McEntire, Lary Myers		     */
/*****************************************************************************/
//
// 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 "ack3d.h"
#include "ackeng.h"
#include "ackext.h"
#include "iff.h"


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 * AckReadiff(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_BADPICNAME;
	return(0L);
	}

   fread(&fchunk,1,sizeof(form_chunk),pic); /* read in the first 12 bytes*/

   if (fchunk.type != FORM)
      {
      fclose(pic);
      ErrorCode = ERR_INVALIDFORM;
      return(0L);
      }

   if (fchunk.subtype != ID_PBM)
      {
      printf("Error: Not form PBM!");
      fclose(pic);
      ErrorCode = ERR_NOPBM;
      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 *)malloc((bmhd.w * bmhd.h)+4);
	  if ( !destx )
	    {
	    fclose(pic);
	    ErrorCode = ERR_NOMEMORY;
	    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);
			  ErrorCode = ERR_BADPICFILE;
			  free(savedestx);
			  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);
   }
