/*
 *	read a degas pi1 or pi2 files. decode and stuff into raster array
 *	and color map. both ReadPI1 and ReadPI2 are here...
 */

static char *sccsid = "@(#) readpi.c 1.0 91/6/9 rosenkra\0\0                 ";

#include <stdio.h>
#include <osbind.h>
#include "mgif.h"


#ifdef LOCAL
#undef LOCAL
#endif
#ifdef GLOBAL
#undef GLOBAL
#endif
#define LOCAL		/*static*/
#define GLOBAL
#define reg_t		register

#define PI1		0		/* type of file (.pi1, etc) */
#define PI2		1		/* also res in file */
#define PI3		2


/*
 *	globals for GIF decode procedure (only needed in this file,
 *	should actually be static)
 */
LOCAL int	_Palette[16];	/* pi1/pi2 color palette */
LOCAL uchar_t	_Quant[8] = {0,36,72,108,144,180,216,255};
				/* for quantizing 8 levels (3 bits) to 256 */


/*
 *	local functions
 */
LOCAL void	_PI1toIndx ();
LOCAL void	_PI2toIndx ();


/*------------------------------*/
/*	ReadPI1			*/
/*------------------------------*/
GLOBAL int ReadPI1 (fname, raster, colormap, opt)
char	       *fname;		/* file name with .GIF */
uchar_t	       *raster;		/* place to put raster */
uchar_t		colormap[][3];	/* color map */
int		opt;		/* SILENT, INQUIRE, VERBOSE, NORMAL */
{

/*
 *	read a pi1 image from open file infile into raster array.
 *	the array will contain index into color table. caller supplies
 *	all needed space (raster array, color map, etc). colormap
 *	will contain either global or local color map, depending on image.
 *
 *	The following illustrates the general file layout of .PI1 files:
 *
 *		1	word	resolution
 *		16	word	palette
 *		16000	word	screen memory
 */

	static int	firsttime = 1;

	FILE	       *in;
	int		infile;
	reg_t long	ii;
	int		i;
	int		flag;
	int		nread;
	int		res;
	int		line[80];
	int		c;
	int		q;




	/*
	 *   open file...
	 */
	if (opt != SILENT)
	{
		printf ("   \n");
		printf ("\nEnter ReadPI1\n\n");
		printf ("Open file:                           %s\n", fname);
	}
	if ((in = fopenb (fname, "r")) == (FILE *) 0)
	{
		return (EGIFFILE);
	}



	/*
	 *   get ready for next image by clearing variables, tables
	 */
	if (firsttime)
		firsttime = 0;
	else
	{
		/* these take a while to do */
		if (opt != SILENT)
			printf ("\nResetting tables\n");

		for (ii = 0; ii < MAXIMG; ii++)
			raster[ii] = 0;
	}



	/*
	 *   make sure it is a pi1 file
	 */
	if (opt != SILENT)
		printf ("\nRead resolution\n");
	nread = fread (&res, 2, 1, in);
	if (nread != 1)
	{
		fclose (in);
		return (EGIFEOF);
	}
	if (res != PI1)
	{
		fclose (in);
		return (EGIFMAGIC);
	}
	if (opt != SILENT)
		printf ("     res = %d\n", res);



	/*
	 *   read palette...
	 */
	if (opt != SILENT)
		printf ("\nRead palette\n");
	nread = fread (_Palette, 2, 16, in);
	if (nread != 16)
	{
		fclose (in);
		return (EGIFEOF);
	}
	if (opt != SILENT)
	{
		printf ("     %04x %04x %04x %04x %04x %04x %04x %04x\n",
			_Palette[0], _Palette[1], _Palette[2], _Palette[3],
			_Palette[4], _Palette[5], _Palette[6], _Palette[7]);
		printf ("     %04x %04x %04x %04x %04x %04x %04x %04x\n",
			_Palette[8], _Palette[9], _Palette[10], _Palette[11],
			_Palette[12], _Palette[13], _Palette[14], _Palette[15]);
	}



	/*
	 *   set up colormap from palette...
	 */
	for (i = 0; i < 16; i++)
	{
		/*
		 *   the mask for the palette is 0x0777. we quantize based
		 *   on color table with 256 possible values.
		 */
		c              = _Palette[i];
		q              = (int) ((c & 0x0700) >> 8);
		colormap[i][0] = (uchar_t) _Quant[q];
		q              = (int) ((c & 0x0070) >> 4);
		colormap[i][1] = (uchar_t) _Quant[q];
		q              = (int)  (c & 0x0007);
		colormap[i][2] = (uchar_t) _Quant[q];
	}



	/*
	 *   read screen...
	 */
	if (opt != SILENT)
		printf ("\nRead screen\n");
	for (i = 0; i < 200; i++)
	{
		nread = fread (line, 2, 80, in);
		if (nread != 80)
		{
			fclose (in);
			return (EGIFEOF);
		}
		_PI1toIndx (line, raster);

		raster = (uchar_t *) ((long) raster + 320L);
	}
	fclose (in);

	/* at this point, Raster[] contains colormap indices at each pixel
	   and ColMap contains RGB colormap requantized to 256 levels. only
	   the first 16 elements of ColMap are used */

	return (EGIFOK);
}




/*------------------------------*/
/*	_PI1toIndx		*/
/*------------------------------*/
LOCAL void _PI1toIndx (pscrn, pras)
int	       *pscrn;
uchar_t	       *pras;
{

/*
 *	decompose gem bitmap row into colormap index. here we just get
 *	each pixel's color index and stuff it into the raster. the color
 *	map is done elsewhere.
 *
 *	it works like this:
 *
 *			   word, 16 bits
 *			|	.	 |
 *			|	.	 |
 *	plane 0		|0110010110001110|
 *	plane 1		|0100110111110000|
 *	plane 2		|0111110100000001|
 *	plane 3		|0000000110111000|
 *	plane 0		|     ^	.	 |
 *			|     |	.	 |    color index:
 *			      \-------------- 0 1 1 1 = 7
 *							|
 *							v  111111
 *					palette: 0123456789012345
 *							|
 *							v
 *							0 7 3 1
 *							  ^ ^ ^
 *							  | | |
 *						    red---/ | \---blue
 *							    |
 *							  green
 *
 *	the mask for the palette is 0x0777. low rez can use all 16 palette
 *	entries. we only need the color index. the example above shows
 *	further how to decompose that to rgb intensities.
 */

	register int	shift;
	register int	indx;
	register int	colindx;
	register int	ix;

	int		pl_0,		/* 4 planes in low rez... */
			pl_1,
			pl_2,
			pl_3;


	for (ix = 0; ix < 320; ix++)
	{
		/*
		 *   indx is byte, shift gets proper bit. pl_x are
		 *   each of the four planes of a gem image, and are
		 *   interleaved. given the pixel value for each plane,
		 *   the result maps to a color index which in turn
		 *   indexes into the palette for the color. the color
		 *   in the palette gives RGB values for the pixel.
		 */
/*		indx      = (ix / 16) * 4;*/
		indx      = (ix >> 4) << 2;
		shift     = 15 - (ix % 16);

		pl_0      = ((pscrn[indx  ] >> shift) & 1);
		pl_1      = ((pscrn[indx+1] >> shift) & 1);
		pl_2      = ((pscrn[indx+2] >> shift) & 1);
		pl_3      = ((pscrn[indx+3] >> shift) & 1);

		colindx   = (pl_3 << 3) | (pl_2 << 2) | (pl_1 << 1) | (pl_0);

		pras[ix] = (uchar_t) colindx;
	}
}




/*------------------------------*/
/*	ReadPI2			*/
/*------------------------------*/
GLOBAL int ReadPI2 (fname, raster, colormap, opt)
char	       *fname;		/* file name with .GIF */
uchar_t	       *raster;		/* place to put raster */
uchar_t		colormap[][3];	/* color map */
int		opt;		/* SILENT, INQUIRE, VERBOSE, NORMAL */
{

/*
 *	read a pi2 image from open file infile into raster array.
 *	the array will contain index into color table. caller supplies
 *	all needed space (raster array, color map, etc). colormap
 *	will contain either global or local color map, depending on image.
 *
 *	The following illustrates the general file layout of .PI2 files:
 *
 *		1	word	resolution
 *		16	word	palette
 *		16000	word	screen memory
 */

	static int	firsttime = 1;

	FILE	       *in;
	int		infile;
	reg_t long	ii;
	int		i;
	int		flag;
	int		nread;
	int		res;
	int		line[80];
	int		c;
	int		q;




	/*
	 *   open file...
	 */
	if (opt != SILENT)
	{
		printf ("   \n");
		printf ("\nEnter ReadPI2\n\n");
		printf ("Open file:                           %s\n", fname);
	}
	if ((in = fopenb (fname, "r")) == (FILE *) 0)
	{
		return (EGIFFILE);
	}



	/*
	 *   get ready for next image by clearing variables, tables
	 */
	if (firsttime)
		firsttime = 0;
	else
	{
		/* these take a while to do */
		if (opt != SILENT)
			printf ("\nResetting tables\n");

		for (ii = 0; ii < MAXIMG; ii++)
			raster[ii] = 0;
	}



	/*
	 *   make sure it is a pi1 file
	 */
	if (opt != SILENT)
		printf ("\nRead resolution\n");
	nread = fread (&res, 2, 1, in);
	if (nread != 1)
	{
		fclose (in);
		return (EGIFEOF);
	}
	if (res != PI2)
	{
		fclose (in);
		return (EGIFMAGIC);
	}
	if (opt != SILENT)
		printf ("     res = %d\n", res);



	/*
	 *   read palette...
	 */
	if (opt != SILENT)
		printf ("\nRead palette\n");
	nread = fread (_Palette, 2, 16, in);
	if (nread != 16)
	{
		fclose (in);
		return (EGIFEOF);
	}
	if (opt != SILENT)
	{
		printf ("     %04x %04x %04x %04x %04x %04x %04x %04x\n",
			_Palette[0], _Palette[1], _Palette[2], _Palette[3],
			_Palette[4], _Palette[5], _Palette[6], _Palette[7]);
		printf ("     %04x %04x %04x %04x %04x %04x %04x %04x\n",
			_Palette[8], _Palette[9], _Palette[10], _Palette[11],
			_Palette[12], _Palette[13], _Palette[14], _Palette[15]);
	}



	/*
	 *   set up colormap from palette...
	 */
	for (i = 0; i < 4; i++)
	{
		/*
		 *   the mask for the palette is 0x0777. we quantize based
		 *   on color table with 256 possible values.
		 */
		c              = _Palette[i];
		q              = (int) ((c & 0x0700) >> 8);
		colormap[i][0] = (uchar_t) _Quant[q];
		q              = (int) ((c & 0x0070) >> 4);
		colormap[i][1] = (uchar_t) _Quant[q];
		q              = (int)  (c & 0x0007);
		colormap[i][2] = (uchar_t) _Quant[q];
	}



	/*
	 *   read screen...
	 */
	if (opt != SILENT)
		printf ("\nRead screen\n");
	for (i = 0; i < 200; i++)
	{
		nread = fread (line, 2, 80, in);
		if (nread != 80)
		{
			fclose (in);
			return (EGIFEOF);
		}
		_PI2toIndx (line, raster);

		raster = (uchar_t *) ((long) raster + 640L);
	}
	fclose (in);

	/* at this point, Raster[] contains colormap indices at each pixel
	   and ColMap contains RGB colormap requantized to 256 levels. only
	   the first 16 elements of ColMap are used */

	return (EGIFOK);
}




/*------------------------------*/
/*	_PI2toIndx		*/
/*------------------------------*/
LOCAL void _PI2toIndx (pscrn, pras)
int	       *pscrn;
uchar_t	       *pras;
{

/*
 *	decompose gem bitmap row into colormap index. here we just get
 *	each pixel's color index and stuff it into the raster. the color
 *	map is done elsewhere.
 *
 *	it works like this:
 *
 *			   word, 16 bits
 *			|	.	 |
 *			|	.	 |
 *	plane 0		|0110000110001110|
 *	plane 1		|0100110111110000|
 *	plane 0		|     ^	.	 |
 *			|     |	.	 |    color index:
 *			      \-------------- 1 0 = 2
 *						    |
 *						    v       111111
 *					palette:  0123456789012345
 *						    |
 *						    v
 *						    0 7 3 1
 *						      ^ ^ ^
 *						      | | |
 *						red---/ | \---blue
 *						        |
 *
 *	the mask for the palette is 0x0777. med rez can use 4 palette
 *	entries. we only need the color index. the example above shows
 *	further how to decompose that to rgb intensities.
 */

	register int	shift;
	register int	indx;
	register int	colindx;
	register int	ix;

	int		pl_0,		/* 2 planes in med rez... */
			pl_1;


	for (ix = 0; ix < 640; ix++)
	{
		/*
		 *   indx is byte, shift gets proper bit. pl_x are
		 *   each of the four planes of a gem image, and are
		 *   interleaved. given the pixel value for each plane,
		 *   the result maps to a color index which in turn
		 *   indexes into the palette for the color. the color
		 *   in the palette gives RGB values for the pixel.
		 */
/*		indx      = (ix / 16) * 2;*/
		indx      = (ix >> 4) << 1;
		shift     = 15 - (ix % 16);

		pl_0      = ((pscrn[indx  ] >> shift) & 1);
		pl_1      = ((pscrn[indx+1] >> shift) & 1);

		colindx   = (pl_1 << 1) | (pl_0);

		pras[ix] = (uchar_t) colindx;
	}
}





