/* Unsqueezes Infocom data files
 * Brian Parker 5/10/85
 * Moved to Amiga 21/6/87
 */

#include "stdio.h"

/*extern	Enable_Abort;*/

void main()
{
	FILE *fopen(),*fp;
	char	a[3];		/* temporary storage array */
	char	file[128];	/* file name */
	char	sector[20];	/* sector to start at */
	char	buf[2048];	/* file buffer */
	char	words[1000];	/* contains key words */
	int	place[100];	/* points to words in array 'words' */
	char	x,uppercase,punct,wordnum,wdflag,last;
	int	i,point,arraypos,e;
	long	isector;

	uppercase = 0;
	punct = 0;
	last = 0;
	wordnum = 0;
	wdflag = 0;
	point = 0x40;	/* key words start at 40 hex */
	arraypos = 0;
	place[0]=0;	/* first word always starts at 0 */

/*	Enable_Abort=1;*/	/* Turn on CNTRL C checking */

	printf("\n        Infocom File Unsqueezer");
	printf("\n        ------- ---- ----------");
	printf("\n\n          Brian Parker 21/6/87");

	printf("\n\n\nWhat is the name of the file to print? ");
	gets(file);
	if((fp = fopen(file,"r")) == NULL){
		printf("Couldn't open file.\n");
		exit(1);
	}
	printf("\nWhat position to start at? ");
	gets(sector);
	isector=atoi(sector);


/* First scan table of common words at file location 40 hex and store these
   words (96 of them) sequentially in array "words".
   A pointer to each word in this array is atored in array "place". */

	fread(buf,640,1,fp);
	while(wordnum<96){
		words[arraypos]=((*(buf+point) & 124)>>2) + 91;
		words[arraypos + 1]=(((*(buf + point) & 3)<<3)
			| ((*(buf + point + 1)&224)>>5))+91;
		words[arraypos+2]=(*(buf+point+1)&31)+91;
		arraypos+=3;
		point+=2;
		if(*(buf+point-2)&128)
			place[++wordnum]=arraypos;
	}

/* Now work backwards through the words and remove space-filling characters
   at the end of words i.e. char 96 */
	
	for(wordnum=96;wordnum>0;--wordnum){
		for(i=place[wordnum]-1;words[i]==96;--i)
			words[i]=0;
	}

/* Now search through words and add punctuation and upper case as needed */

	for(wordnum=0;wordnum<96;++wordnum){
		for(i=place[wordnum];i<place[wordnum+1];++i){
			if(uppercase){
				uppercase=0;
				words[i]=upcase(words[i]);
			}
			else if(punct){
				punct=0;
				words[i]=punc(words[i]);
			}
			else{
				switch (words[i]){
				case	91:
					words[i]=' ';
					break;
				case	95:
					uppercase=1;
					words[i]=0;	/* 0 = null */
					break;
				case	96:
					punct=1;
					words[i]=0;
					break;
				}
			}
		}
	}

/* Main routine starts here */
/* Now that the 96 key words are stored, the file can be unsqueezed */

	if(fseek(fp,isector,0)==-1){	/* set R/W pointer as required */
		printf("Too large a value.\n");
		exit(1);
	}
	i=0;
	while((fread(buf,1,2048,fp) != 0)){	/* read in 2K at a time */
		for(;i<2048;i+=2){
/* set 'last' if flag bit set, indicating that this is the end of a word */
			last=*(buf+i)&128;
/* Extract three characters from every 2 bytes */
/* Also add 91 to each value so that most letters correspond to their ASCII
   values */
			*(a)=((*(buf+i) & 124)>>2)+91;
			*(a+1)=(((*(buf+i) & 3)<<3)|((*(buf+i+1)&224)>>5))+91;
			*(a+2)=(*(buf+i+1) & 31)+91;
/* If this is the end of a word, wipe off space-filling characters (char 5) */
			if (last){
				for (x=2;a[x]==96;--x)
					a[x]=91;
			}
/* Go through these characters and look for prefix characters etc. */
			for (x=0;x<3;x++){
/* If flag set for key word replacement then type relevant word */
				if(wdflag){
	for(e=place[32*(wdflag-1)+a[x]-91];e<place[32*(wdflag-1)+a[x]-90];++e)
						printf("%c",words[e]);
					wdflag=0;
				}
/* If uppercase flag set then print in upper case */
				else if(uppercase){
					uppercase=0;
					printf("%c",upcase(a[x]));
				}
/* punctuation flag set then print corresponding punctuation symbol */
				else if(punct){
					punct=0;
					printf("%c",punc(a[x]));
				}
				else 	switch (a[x]){
/* If prefix character 1,2 or 3 found then set word flag */
					case 92:
						wdflag=1;
						break;
					case 93:
						wdflag=2;
						break;
					case 94:
						wdflag=3;
						break;
/* If prefix character 5 found then set punctuation flag */
					case 96:
						punct=1;
						break;
/* If prefix character 4 found then set upper case flag */
					case 95:
						uppercase=1;
						break;
/* If space character (char 0) found then print space */
					case 91:
						printf(" ");
						break;
/* Otherwise, just print the character as is */
					default:
						printf("%c",a[x]);
						break;
					}
			}
		}
		i-=2048;
	}
	printf("\n\n                  <END OF FILE>\n");
	printf("              Press RETURN to exit.\n");
	gets(sector);		/* wait so that window doesn't disappear */
	exit(0);
}

punc(c)		/* returns puncuation symbol or digit corresponding to c */
int c;
{
	switch(c){
	case 'a':
		c='<';
		break;
	case 'b':
		c='\n';
		break;
	case 'c':
		c='0';
		break;
	case 'd':
		c='1';
		break;
	case 'e':
		c='2';
		break;
	case 'f':
		c='3';
		break;
	case 'g':
		c='4';
		break;
	case 'h':
		c='5';
		break;
	case 'i':
		c='6';
		break;
	case 'j':
		c='7';
		break;
	case 'k':
		c='8';
		break;
	case 'l':
		c='9';
		break;
	case 'm':
		c='.';
		break;
	case 'n':
		c=',';
		break;
	case 'o':
		c='!';
		break;
	case 'p':
		c='?';
		break;
	case 'q':
		c='_';
		break;
	case 'r':
		c='#';
		break;
	case 's':
		c=96;
		break;
	case 't':
		c=34;
		break;
	case 'u':
		c='/';
		break;
	case 'v':
		c=92;
		break;
	case 'w':
		c='-';
		break;
	case 'x':
		c=':';
		break;
	case 'y':
		c='(';
		break;
	case 'z':
		c=')';
		break;
	}
	return (c);
}

upcase(c)		/* converts c to uppercase */
int c;
{
	c-=32;
	return(c);
}

/* end of zorklook.c */
