/*

------------------------------------------------------------------

Black Nebula

File :				loadpic.c
Programmer:		Colin Adams/Someone else
Date:				28/4/91
Last Modified :	10/6/91

Description:

Loads an IFF picture file into both bitmaps of the buffered
display.  Based on something so old I can't remember where I got
this code.  I've modified it a few times though...

------------------------------------------------------------------

*/

/*	------------------------------------------------------------------
		Defines and Includes
		------------------------------------------------------------------
*/

#define AMIGA_INCLUDES
#include "3d.h"

#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

/*	------------------------------------------------------------------
		Macros
		------------------------------------------------------------------
*/

#define ROUNDODDUP(a) (((a)+1)&(~1L))
#define MakeID(a,b,c,d) ((a)<<24L | (b)<<16L | (c)<<8 | (d))
#define SafeRead(a,b,c) if (Read((BPTR)a,(APTR)b,c)==-1L) { Close((BPTR)a); return(NULL); }

/*	------------------------------------------------------------------
		Typedefs
		------------------------------------------------------------------
*/

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;


/*	------------------------------------------------------------------
		Data Structures
		------------------------------------------------------------------
*/

struct FileHandle *f79_outfp;
BitMapHeader f79_bmhd;
char *f79_bufstart;
Chunk f79_header;

/*	------------------------------------------------------------------
		External Structures
		------------------------------------------------------------------
*/

extern struct BitMap my_bit_map, back_bit_map;
extern struct IntuitionBase *IntuitionBase;
extern struct GfxBase *GfxBase;

/*	------------------------------------------------------------------
		Code
		------------------------------------------------------------------
*/


void F79_CleanUpandExit(void)
{
   if(f79_bufstart)
      FreeMem(f79_bufstart,(long)f79_header.ckSize); 
   if(f79_outfp)
      Close((BPTR)f79_outfp); 
}

char F79_ReadILBM(char *fspec)
{
  struct FileHandle *fp;
  char colormap[32][3], *sourcebuf;
  short colorcount;
  long id, ViewModes = 0;

  fp=(struct FileHandle *)Open(fspec,MODE_OLDFILE);	
  if (fp==0)
  {
		F79_CleanUpandExit();
		return 1;
  }
  
	SafeRead(fp,&f79_header,(long)sizeof(f79_header));
  
	if (f79_header.ckID!=ID_FORM) 
  { 
		Close((BPTR)fp); 
		F79_CleanUpandExit(); 
		return 1;
  }

  SafeRead(fp,&id,(long)sizeof(id));
  if (id!=ID_ILBM) 
  { 
		Close((BPTR)fp); 
		F79_CleanUpandExit(); 
		return 1;
  }

  for (;;)
	{
    SafeRead(fp,&f79_header,(long)sizeof(f79_header));

    if (f79_header.ckID==ID_BODY) break;

    switch(f79_header.ckID)
	  {
      case ID_BMHD: SafeRead(fp,&f79_bmhd,(long)sizeof(f79_bmhd));
                    break;

      case ID_CMAP: SafeRead(fp,&colormap[0][0],(long)f79_header.ckSize);
                    colorcount=f79_header.ckSize/3;
                    break;

      case ID_CAMG: SafeRead(fp,&ViewModes,(long)f79_header.ckSize);
                    break;

      default:      Seek((BPTR)fp,ROUNDODDUP(f79_header.ckSize),OFFSET_CURRENT);
    }
  }

  /* Read planes into RAM for ease if decompression */
     
  sourcebuf=f79_bufstart=(char *)AllocMem((long)f79_header.ckSize,MEMF_PUBLIC|MEMF_FAST);
  if (sourcebuf==0L)
  {
     sourcebuf=f79_bufstart=(char *)AllocMem((long)f79_header.ckSize,MEMF_PUBLIC|MEMF_CHIP);
     if (!sourcebuf)
     {
        F79_CleanUpandExit();
     	return 1;
     }
  }

  SafeRead(fp,sourcebuf,(long)f79_header.ckSize);
  Close((BPTR)fp);
	return 0;
}      

void F79_Expand(BitMapHeader *bmhd, char *sourcebuf)
{
  char n,*destbuf, *tempbuf;
  short plane,linelen, rowbytes, i;

  linelen = bmhd->w/8;

  for (i=0;i<bmhd->h;i++)
    for (plane=0;plane<bmhd->nPlanes;plane++)
	  {
		 int j;
		 
		 for(j=0; j<2; j++)
		 {
			if(!j)
			{
	      	destbuf = (char *)(my_bit_map.Planes[plane])+linelen*i;
				tempbuf = sourcebuf;
			}
			else
			{
				destbuf = (char *)(back_bit_map.Planes[plane])+linelen*i;
				sourcebuf = tempbuf;
			}

      	if (bmhd->compression==cmpByteRun1)
			{
        	rowbytes = linelen;

        	while (rowbytes)
				{
        		n = *sourcebuf++; /* fetch block run marker */

   	       	if (n>=0)
					{
     	      	movmem(sourcebuf,destbuf,(unsigned int)++n);
						rowbytes -= n;
     	      	destbuf += n; sourcebuf += n;
     	   	}
     	   	else
					{
						n = -n+1;
						rowbytes -= n;
						setmem(destbuf,(unsigned int)n,(unsigned int)*sourcebuf++);
						destbuf+=n;
        	  	}
				}
      	}
      	else
		 	{
				movmem(sourcebuf,destbuf,(unsigned int)linelen);
				sourcebuf += linelen;
      	}
		}
	}
}

void loadpic(char *argv)
{
	char error;

	if(error = F79_ReadILBM(argv))
		return;

	F79_Expand(&f79_bmhd,f79_bufstart);
}

/* end of module loadpic.c */