/************************************************************************/
/*	Perlin Production Co. Ltd. July 2012				*/
/*	GAS, bi-directional Alpha Sprite image Generator, v.2.1		*/
/************************************************************************/

#include "stdio.h"
#include "fdlib.h"
#include "gas.h"

WrtMix(_fd, _alpha, _image,_invert)
FD		*_fd;
char		_alpha;
char		_image;
unsigned	_invert;
{
	char	seq[2];
	seq[0] = _invert ? ~_alpha : _alpha;
	seq[1] = _invert ? (~_image & _alpha) : _image;

	if (write(_fd->file,seq,2) != 2)
		trouble("failed to write to",_fd->name);
}


#define	INCCOL	0
#define	DECCOL	1

WrtCol(_fd, _alpha, _image, _height, _deccol,_invert)
FD		*_fd;
char		*_alpha;
char		*_image;
unsigned	_height;
unsigned	_deccol;
unsigned	_invert;
{
	unsigned	h;

	if (!_deccol)
	 for (h=0; h < _height; ++h)
		WrtMix(_fd,*_alpha++,*_image++,_invert);
	else
	 for (h=0; h < _height; ++h)
		WrtMix(_fd,*--_alpha,*--_image,_invert);
}



WrtDst(_fd, _depth, _width, _height,_invert)
FD		*_fd;
unsigned	_depth;
unsigned	_width;
unsigned	_height;
unsigned	_invert;
{
	FD		*dst;
	char		*alpha,*image;
	int		d,w,h;
	unsigned	plane;
	unsigned	dirrow;

	dst	= (&_fd[FD_DST]);
	alpha	= _fd[FD_ABM].buf;
	image	= _fd[FD_IBM].buf;
	plane	= _width * _height;
	dirrow	= 1;

	for (d=0; d < _depth; ++d)
	{
	  if (d & 1)
	  {	/* columns in the plane are right to left */
		alpha	+= plane;
		image	+= plane;

		for (w=0; w < _width; ++w)
		{
			if (++dirrow & 1)
			{	/* column rows are bottom to top */
				WrtCol(dst,alpha,image,_height,DECCOL,_invert);
				alpha -= _height;
				image -= _height;
			}
			else
			{	/* column rows are top to bottom */
			 	alpha -= _height;
			 	image -= _height;
			 	WrtCol(dst,alpha,image,_height,INCCOL,_invert);
			}
		}

		alpha	+= plane;
		image	+= plane;
	 }
	 else
	 {	/* columns in the plane are left to right */
		for (w=0; w < _width; ++w)
		{
			if (++dirrow & 1)
			{	/* column rows are top to bottom */
				alpha += _height;
				image += _height;
				WrtCol(dst,alpha,image,_height,DECCOL,_invert);
			}
			else
			{	/* column rows are bottom to top */
				WrtCol(dst,alpha,image,_height,INCCOL,_invert);
				alpha += _height;
				image += _height;
			}
		}
	 }
	}
}


int main(argc,argv)
int	argc;
char	**argv;
{
	FD	fd[FD_NUM];
	int	phases;
	int	depth;
	int	invert;
	int	width;
	int	height;
	unsigned sizSrc; /* size of the source image in bytes */
	unsigned sizBuf; /* size of image + extra column for shifted sprite */
	unsigned sizDst; /* size of a SINGLE destination image == sizBuf * 2 */
	int	i, step;
	int	incwdt; /* width increment when phases > 1*/
	char	fill;
	int	nbytes;
	
	if ( argc < NPARAM || argc > MPARAM )
		banner("invalid number of parameters");

	width	= ArgInt(argv, PI_WDT, 1, MAXSW, "sprite width");
	height	= ArgInt(argv, PI_HGT, 1, MAXSH, "sprite height");
	
	for (i=0; i<FD_NUM; ++i) InitFD(&fd[i]);

	fd[FD_ABM].name = argv[PS_ABM];
	fd[FD_IBM].name = argv[PS_IBM];
	fd[FD_DST].name = argv[PS_DST];

	/* Optional parameters */

	phases	= (argc > PI_PHS)
		? ArgInt(argv, PI_PHS, 1, MAXPHS,"image phases")
		: MAXPHS;

	incwdt	= phases > 1 ? 1 : 0;

	depth	= (argc > PI_DPT)
		? ArgInt(argv, PI_DPT, 1, MAXSD,"sprite depth")
		: DEFSD;

	invert	= (argc > PI_INV)
		? ArgInt(argv, PI_INV, 0, 1,"bitmap inversion mode")
		: DEFINV;

	if (!strcmp(fd[FD_ABM].name,fd[FD_IBM].name))
		usage("source file names must differ");

	if (  !strcmp(fd[FD_ABM].name,fd[FD_DST].name)
	   || !strcmp(fd[FD_IBM].name,fd[FD_DST].name)
	   ) usage("destination file name must be unique");

	OpenFD(&fd[FD_ABM],FCB_READ);
	OpenFD(&fd[FD_IBM],FCB_READ);

	sizSrc	= depth  * width * height;

	for (i=0; i < FD_DST; ++i)
	 if (fd[i].size < sizSrc) trouble("short file",fd[i].name);

	if (fd[FD_ABM].size != fd[FD_IBM].size)
		trouble("input file sizes differ",0);

	sizBuf = depth * height * (width + incwdt);
	sizDst = sizBuf * 2;

	if (invert)	printf("inverted colors, alpha-transparency mask\n");
	else		printf("normal colors  , image-transparency mask\n");

	printf("depth : %d, width : %d, height: %d\n", depth, width, height);
	printf("phases: %d, sizSrc: %d, sizDst: %d\n", phases, sizSrc, sizDst);


	fill = invert ? 0xFF : 0;

	ABufFD(&fd[FD_ABM], sizBuf, fill);
	ABufFD(&fd[FD_IBM], sizBuf, 0x00);

	ReadFD(&fd[FD_ABM], depth, width, height, incwdt);
	ReadFD(&fd[FD_IBM], depth, width, height, incwdt);

	width += incwdt;

	if (invert)	InvPln(&fd[FD_ABM], depth, width, height);
	if (!invert)	InvBuf(&fd[FD_ABM]);

	CreatFD(&fd[FD_DST],FCB_WRITE);

	step = 8 / phases;

	for (i = 0; i < phases; i+= step )
	{
		putchar('.');
		WrtDst(fd, depth, width, height,invert);
		RarBuf(&fd[FD_ABM], 0xFF, step, depth, width, height);
		RarBuf(&fd[FD_IBM], 0x00, step, depth, width, height);
	}

	CloseFD(&fd[FD_DST]);

	nbytes = phases * sizDst;

	DisInp(fd[FD_DST].name,nbytes);

	printf	("%x hex bytes successfully written to %s\n"
		, nbytes, fd[FD_DST].name);
	
	for (i=0; i < FD_DST; ++i)
	{
		free(fd[i].buf);
		CloseFD(&fd[i]);
	}
	return 0;
}
