#include<stdio.h>
#include<stdlib.h>
#include<strings.h>
#include<allinc.h>
#include<unistd.h>
#include<signal.h>
#include<vga.h>
#include<vgagl.h>
#include<vgakeyboard.h>
#include<sys/time.h>
#include<sys/types.h>
#include<fcntl.h>
#include"zsoftpcx.h"

typedef struct timeval t_tv;
typedef struct timezone t_tz;
	
unsigned long giverand(unsigned long range,int seedadd);

void viewpcx(int XBeg,int YBeg,char *libname,char *indexname,int cnum,int orientation);

void north_pixel(int *x,int *y,int xm,int ym,int xb,int yb,int pixel);

void east_pixel(int *x,int *y,int xm,int ym,int xb,int yb,int pixel);

void south_pixel(int *x,int *y,int xm,int ym,int xb,int yb,int pixel);

void west_pixel(int *x,int *y,int xm,int ym,int xb,int yb,int pixel);		

void main(int argc,char *argv[]) {
	char question[5000];
	char name[200];
	int hand[3][2] = {{0,0},{0,0},{0,0}};
	int done=0;
	int deckx[78] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
			 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
			 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };	
	int vgamode=G640x480x256;
	char posit[3][80] = {"Past","Present","Future"};

	int pos[3][2]={{85,160},{270,160},{455,160}};

	int seed,x,y;

	printf("\nVGATarot - Three Card V0.3\n");
	printf("\nPlease enter your name (first and last) > ");
	gets(name);
	printf("Please enter your question\n> ");
	gets(question);
	
	for(x=0,seed=0;x!=strlen(name);x++,seed+=name[x]);
	for(x=0;x!=strlen(question);x++,seed+=question[x]);

	y=0;
	done=0;
	
	while(!done) {
		x=(int)giverand(78,seed);
		if(deckx[x]==0) {
			deckx[x]=1;
			hand[y][0]=x; 
			if((int)giverand(100,seed)>50) hand[y][1]=1; else hand[y][1]=0;
			y++; } 
		if(y==3) done=1; }

	if(!vga_hasmode(vgamode)) {
		printf("mode is unsupported\n"); 
		exit(-1); }
		
	vga_setmode(vgamode);
	gl_setcontextvga(vgamode);
	gl_enableclipping();
	gl_setwritemode(WRITEMODE_OVERWRITE);
	
	printf("\n");

	for(x=0;x!=3;x++) {
		if(hand[x][1]==0) seed=1; else seed=3;
		printf("%-20s : %s %s\n",posit[x],deck[hand[x][0]],hand[x][1]==0?"":"Reversed");
		viewpcx(pos[x][0],pos[x][1],"tarotlib.lbr","tarotlib.index",hand[x][0],seed); }
		
	printf("\n");

	getchar();
	vga_setmode(TEXT);
	
	exit(1); }
	
unsigned long giverand(unsigned long range,int seedadd)
	{ 
	t_tv tv;
	t_tz tz;
		
	gettimeofday(&tv,&tz);
	srandom((unsigned int)tv.tv_usec+(unsigned int)seedadd);
	return (unsigned long)((random()%range)+1); }

void viewpcx(int XBeg,int YBeg,char *libname,char *indexname,int cnum,int orientation) { 
	int fi; /* index file */
	int fp; /* data file */
	unsigned char *data_pix;
	unsigned long foffset;
	unsigned long flength;
	int XPos,YPos,XMax,YMax;
	zhead pcx;
	Palette pal;
	unsigned long x;
	unsigned int y,z,inbyte;
	unsigned char inc;

	if((fi=open(indexname,O_RDONLY))==-1) {
		vga_setmode(TEXT);
		printf("cannot open index file\n");
		exit(-1); }
		
	lseek(fi,cnum*8,SEEK_SET); /* get the correct index */
	
	read(fi,&foffset,sizeof(foffset)); /* get the offset */
	read(fi,&flength,sizeof(flength)); /* get the length */
	
	close(fi); /* close index file */
	
	if((fp=open(libname,O_RDONLY))==-1) { /* open library file */
		vga_setmode(TEXT);
		printf("cannot open library file\n");
		exit(-1); }
	
	lseek(fp,foffset,SEEK_SET); /* go to correct offset in library */
			
	if(read(fp,&pcx,sizeof(pcx))!=sizeof(pcx)) { /* read PCX header information */
		vga_setmode(TEXT);
		printf("cannot read header information of picture %d\n",cnum);
		exit(-1); }
		
	XMax=(int)pcx.x2; YMax=(int)pcx.y2; /* set the x and y dimensions of the picture */
	
	lseek(fp,128-sizeof(pcx),SEEK_CUR);
	
	if((data_pix=(char *)malloc(flength-128))==NULL) { /* get picture memory */
		vga_setmode(TEXT);
		printf("couldn't allocate picture data memory\n");
		exit(-1); }	
		
	if(((unsigned long)read(fp,data_pix,(flength-128)))!=(flength-128)) { /* read picture data */
		vga_setmode(TEXT);
		printf("couldn't read in picture data\n");
		exit(-1); }
		
	close(fp); /* close library file */
	
	data_pix+=(flength-128-768); /* get to the palette data */
				
	for(x=0;x<255;x++) { /* set the palette data */
		inc=*data_pix++;
		pal.color[x].red=(inc/4);
		inc=*data_pix++;
		pal.color[x].green=(inc/4);
		inc=*data_pix++;
		pal.color[x].blue=(inc/4); }
		
	data_pix-=(flength-131); /* why 131?  I've no damn clue, but it works better than 128 */
		
	gl_setpalette(&pal); /* set the palette */
	
	switch(orientation) { /* set up correct orientation parameters */
		case 1 : /* north */ 
					XMax=(int)pcx.x2+1;
					YMax=(int)pcx.y2;
					XPos=XBeg; 
					YPos=YBeg; 
					break;
		case 2 : /* east */ 
					XMax=(int)pcx.x2+1;
					YMax=(int)pcx.y2;
					XPos=YBeg+YMax;
					YPos=XBeg;
					break;
		case 3 : /* south */ 
					XMax=(int)pcx.x2+1;
					YMax=(int)pcx.y2;
					XPos=XBeg+XMax; 
					YPos=YBeg+YMax; 
					break;
		case 4 : /* west */ 
					XMax=(int)pcx.x2+1;
					YMax=(int)pcx.y2;
					XPos=YBeg;
					YPos=XBeg+XMax;
					break; }
	
	for(x=0;x<(XMax*YMax);) { /* decode the picture */
		inbyte=(unsigned int)*data_pix++;
		if(inbyte>0xc0) { /* RLE compression */
			inbyte-=0xc0;
			y=(unsigned int)*data_pix++;
			for(z=0;z<inbyte;z++) {
				x++;
				switch(orientation) {
					case 1 : north_pixel(&XPos,&YPos,XMax,YMax,XBeg,YBeg,y); break;
					case 2 : east_pixel(&XPos,&YPos,XMax,YMax,XBeg,YBeg,y); break;					
					case 3 : south_pixel(&XPos,&YPos,XMax,YMax,XBeg,YBeg,y); break;
					case 4 : west_pixel(&XPos,&YPos,XMax,YMax,XBeg,YBeg,y); break; } } }
		else {
			x++;
			switch(orientation) {
				case 1 : north_pixel(&XPos,&YPos,XMax,YMax,XBeg,YBeg,inbyte); break;
				case 2 : east_pixel(&XPos,&YPos,XMax,YMax,XBeg,YBeg,inbyte); break;									
				case 3 : south_pixel(&XPos,&YPos,XMax,YMax,XBeg,YBeg,inbyte); break;
				case 4 : west_pixel(&XPos,&YPos,XMax,YMax,XBeg,YBeg,inbyte); break; } } }
				
		free(data_pix); } /* free the data, we are done */

void north_pixel(int *x,int *y,int xm,int ym,int xb,int yb,int pixel) {
	if(*y>(ym+yb)) return;
	gl_setpixel(*x,*y,pixel);
	*x=*x+1;
	if(*x==(xm+xb)) {
		*x=xb;
		*y=*y+1; } }
		
void south_pixel(int *x,int *y,int xm,int ym,int xb,int yb,int pixel) { 
	if(*y==yb) return;
	gl_setpixel(*x,*y,pixel);
	*x=*x-1;
	if(*x==xb) {
		*x=xm+xb;
		*y=*y-1; } }		
		
void west_pixel(int *x,int *y,int xm,int ym,int xb,int yb,int pixel) {
	if(*x>(ym+yb)) return;
	gl_setpixel(*x,*y,pixel);
	*y=*y-1;
	if(*y==xb) {
		*y=xb+xm;
		*x=*x+1; } }
		
void east_pixel(int *x,int *y,int xm,int ym,int xb,int yb,int pixel) {
	if((*x)<yb) return;
	gl_setpixel(*x,*y,pixel);
	*y=*y+1;
	if(*y==(xm+xb)) {
		*y=xb;
		*x=*x-1; } }
		