/* P2TXT by R. J. Marks 1993
 * (for XTender)
 * Public domain
 */


#include <stdio.h>

typedef unsigned char byte;
#define NAK "#\0"

byte linebuf[32768]; /* BBBBIIIIIIGGGGGG buffer for those lovely m/c REMs */

/**************** the zx81 char set as transposed for PC ******************/

/* nak = 'not a kharacter', of course! */
/* spacing may not end up being *exactly* the same, but is very close */

char charset[256][10]=
{
/* 000-009 */ " \0",NAK,NAK,NAK,NAK,NAK,NAK,NAK,NAK,NAK,
/* 010-019 */ NAK,"\"\0","Ý\0","$\0",":\0","?\0","(\0",")\0",">\0","<\0",
/* 020-029 */ "=\0","+\0","-\0","*\0","/\0",";\0",",\0",".\0","0\0","1\0",
/* 030-039 */ "2\0","3\0","4\0","5\0","6\0","7\0","8\0","9\0","A\0","B\0",
/* 040-049 */ "C\0","D\0","E\0","F\0","G\0","H\0","I\0","J\0","K\0","L\0",
/* 050-059 */ "M\0","N\0","O\0","P\0","Q\0","R\0","S\0","T\0","U\0","V\0",
/* 060-069 */ "W\0","X\0","Y\0","Z\0","RND\0","INKEY$ \0","PI\0",NAK,NAK,NAK,
/* 070-079 */ NAK,NAK,NAK,NAK,NAK, NAK,NAK,NAK,NAK,NAK,
/* 080-089 */ NAK,NAK,NAK,NAK,NAK, NAK,NAK,NAK,NAK,NAK,
/* 090-099 */ NAK,NAK,NAK,NAK,NAK, NAK,NAK,NAK,NAK,NAK,
/* 100-109 */ NAK,NAK,NAK,NAK,NAK, NAK,NAK,NAK,NAK,NAK,
/* 110-119 */ NAK,NAK,NAK,NAK,NAK, NAK,NAK,NAK,NAK,NAK,
/* 120-129 */ NAK,NAK,NAK,NAK,NAK, NAK,NAK,NAK,NAK,NAK,
/* 130-139 */ NAK,NAK,NAK,NAK,NAK, NAK,NAK,NAK,NAK,"\"\0",
/* 140-149 */ "Ý\0","$\0",":\0","?\0","(\0",")\0",">\0","<\0","=\0","+\0",
/* 150-159 */ "-\0","*\0","/\0",";\0",",\0",".\0","0\0","1\0","2\0","3\0",
/* 160-169 */ "4\0","5\0","6\0","7\0","8\0","9\0","a\0","b\0","c\0","d\0",
/* 170-179 */ "e\0","f\0","g\0","h\0","i\0","j\0","k\0","l\0","m\0","n\0",
/* 180-189 */ "o\0","p\0","q\0","r\0","s\0","t\0","u\0","v\0","w\0","x\0",
/* 190-199 */ "y\0","z\0","\"\"\0","AT \0","TAB \0",NAK,"CODE \0","VAL \0",
			"LEN \0","SIN \0",
/* 200-209 */ "COS \0","TAN \0","ASN \0","ACS \0","ATN \0","LN \0","EXP \0",
			"INT \0","SQR \0","SGN \0",
/* 210-219 */ "ABS \0","PEEK \0","USR \0","STR$ \0","CHR$ \0","NOT \0",
			"**\0"," OR \0"," AND \0","<=\0",
/* 220-229 */ ">=\0","<>\0"," THEN\0"," TO \0"," STEP \0"," LPRINT \0",
      " LLIST \0"," STOP\0"," SLOW\0"," FAST\0",
/* 230-239 */ " NEW\0"," SCROLL\0"," CONT \0"," DIM \0"," REM \0",
			" FOR \0"," GOTO \0"," GOSUB \0"," INPUT \0",
			" LOAD \0",
/* 240-249 */ " LIST \0"," LET \0"," PAUSE \0"," NEXT \0"," POKE \0",
			" PRINT \0"," PLOT \0"," RUN \0"," SAVE \0",
			" RAND \0",
/* 250-255 */ " IF \0"," CLS\0"," UNPLOT \0"," CLEAR\0"," RETURN\0",
      " COPY\0"
};

/************************* program starts here ****************************/


/* main program */
main(argc,argv)
int argc;
char **argv;
{
FILE *in;

if(argc!=2)
	{
	printf("P2TXT (for XTender) by R. J. Marks (1993) for improbabledesigns\n\n");
	printf("Public domain - must be distributed in an unmodified form.\n\n");
	printf("Lists ZX81 .P files to stdout. Uses lowercase for inverse video.\n");
	printf("Graphics and unused characters give a hash (#) character.\n\n");

	printf("Usage:  p2txt infile.p >outfile.txt   to save to outfile.txt,\n");
	printf("  or    p2txt infile.p >prn           to send to printer.\n");
	}
else
	{
	if((in=fopen(argv[1],"rb"))==NULL)
		printf("Error: couldn't open file '%s'\n",argv[1]);
	else
		{
		thrashfile(in);      /* process it */
		fclose(in);
		}
	}
}

/* process (opened) .P file to stdout */
thrashfile(in)
FILE *in;
{
int inbyte,b1,b2;
int f,linelen,linenum,d_file,total;

for(f=1;f<=3;f++) inbyte=fgetc(in);   /* ignore sys vars */
b1=fgetc(in); b2=fgetc(in);           /* except d_file */
d_file=b1+256*b2;
for(f=1;f<=111;f++) inbyte=fgetc(in); /* ignore more sys vars */

total=d_file-16509; /* if d_file is after, prog is 16509 to d_file-1 right? */

/* run through 'total' bytes, interpreting them as ZX81 program lines */
getline(in,&linenum,&linelen,&total);
while(total>=0)
	{
	printf("%4d",linenum);
	xlatline(linelen);
	getline(in,&linenum,&linelen,&total);
	}
}

/* get a single ZX81 program line & line number & length */
getline(in,linenum,linelen,t)
FILE *in;
int *linenum,*linelen,*t;
{
int b1,b2,f;

b1=fgetc(in);
b2=fgetc(in);
*linenum=b1*256+b2;
(*t)-=2;

b1=fgetc(in);
b2=fgetc(in);
*linelen=b1+256*b2;
(*t)-=2;

for(f=0;f<*linelen;f++)
	{
	linebuf[f]=fgetc(in);
	(*t)--;
	}
}

/* translate line into keywords using the charset array */
xlatline(linelen)
int linelen;
{
int f;

for(f=0;f<linelen-1;f++)
	{
	if((linebuf[0]!=234)&&(linebuf[f]==126))
		f+=5;  /* avoid inline FP numbers - but ok for REMs */
	else
		printf("%s",charset[linebuf[f]]);
	}
printf("\n");
}
