[mod.computers.laser-printers] ROMs for QMS800

grim@HUEY.UDEL.EDU (Dan Grim) (03/23/87)

Here are three programs that should help with QMS roms.  The
first one decodes a rom-format font and should pretty well
document the rom-format as I understand it.  The last two
convert fonts in down-load format to rom-format.  There is a
separate program for portrait and landscape fonts.  I am
copying this message to laser-lovers because I responded to
one other request for these programs with the wrong program!
I apologize to the person that got that program since I don't
remember who it was!

------------------------------ bits.c ----------------------------
#include <stdio.h>

int checksum;

main(argc,argv)
	int argc;
	char *argv[];
{
	FILE *f;
	unsigned char font_head[16];
	unsigned short char_head[12];
	char *filename;
	int code1,code2,curloc,i,j,h,hh,height,width,x,z;
	short scan_flag,verbose,hex;
	int characters,first,number;

	if (argc < 2)
	{
		printf("Usage: %s {-vhs} <file> {start loc}\n",argv[0]);
		printf("    This program lists the contents of a QMS");
		printf(" Lasergrafix 1200 rom-based font.\n");
		printf("    -v makes a very verbose listing with every");
		printf(" byte of data decoded.\n");
		printf("    -h makes a hex format file that can be reencoded");
		printf(" with the 'rom' program.\n");
		printf("    -s makes a scan for all of the fonts in a file.\n");
		exit(1);
	}

	/*
	 *	Here are the defaults:
	 */

	verbose = 0;
	hex = 0;
	scan_flag = 0;
	curloc = 0;

	filename = (char *)0;
	for (i = 1; i < argc; i++)
	{
		if (argv[i][0] == '-')
			switch(argv[i][1])
			{
			case 'v':
				verbose = 1;
				break;
			case 'h':
				hex = 1;
				break;
			case 's':
				scan_flag = 1;
				break;
			default:
				printf("%s: bad switch: %s\n",argv[0],argv[i]);
				exit(1);
			}
		else
		if (filename == (char *)0)
			filename = argv[i];
		else
			(void)sscanf(argv[i],"%o",&curloc);
	}

	if (verbose + hex + scan_flag > 1)
	{
		printf("%s: only one switch at a time please!\n");
		exit(1);
	}

	if (filename == (char *)0)
	{
		printf("%s: no filename specified\n",argv[0]);
		exit(1);
	}

	if ((f = fopen(filename,"r")) == NULL)
	{
		printf("%s: can't read '%s'\n",argv[0],filename);
		exit(1);
	}

	if (curloc)
		(void)fseek(f,(long)curloc,0);

	/*
	 *	The first part of the font is a header of the form:
	 *
	 *		struct font_header
	 *		{
	 *			char flag1;			/* always hex f0					*/
	/*			char flag2;			/* always hex 0f					*/
	/*			char characters;	/* number of characters in the font	*/
	/*			char format;		/* font format, 0 = X, 1 = Y		*/
	/*			char number2;		/* low order font number			*/
	/*			char name[4];		/* i.e. CORB, SRPD, CORI, etc.		*/
	/*			char version;		/* version number in ASCII			*/
	/*			char zero[2];		/* two bytes of zero				*/
	/*			char basline;		/* offset to the baseline			*/
	/*			char zero1;			/* another byte of zero				*/
	/*			char number1;		/* high order font number			*/
	/*			char checksum;		/* sum of other 15 bytes of header	*/
	/*		};
	 */

	first = 1;
again:
	for (i = 0; i < 16; i++)
		font_head[i] = fgetc(f);

	if (font_head[0] != 0xf0 || font_head[1] != 0x0f)
	{
		if (!first)
		{
			printf("End of File!\n");
			exit(0);
		}
		printf("%s: Bad marker at start of font: %02x %02x\n",
			argv[0],font_head[0],font_head[1]);
		exit(1);
	}

	if (font_head[3] != 0 && font_head[3] != 1)
	{
		printf("%s: This font is in the wrong format!\n",argv[0]);
		exit(1);
	}

	characters = font_head[2];
	number = font_head[14] * 256 + font_head[4];

	if (!hex)
		printf("%06o/ ",curloc);
	for (i = 0; i < 16; i++)
		printf("%02x ",font_head[i]);
	curloc += 16;

	if (!hex)
	{
		if (font_head[10] != 0 || font_head[11] != 0 || font_head[13] != 0)
			printf("\n%s: Warning: some zero bytes are non zero ",argv[0]);
		checksum = 0;
		for (i = 0; i < 15; i++)
			checksum += font_head[i];
		checksum &= 0xff;
		printf("Checksum: %02x %s\n",checksum,
			font_head[15] == checksum ? "[ok]" : "[mismatch]");
	}

	if (verbose || scan_flag)
	{
		printf("\nFont Header Contents:\n\n");
		printf("    Number of characters: %d\n",characters);
		printf("    Font format: %d: ",font_head[3]);
		if (font_head[3] == 0)
			printf("X orientation, P for 800, L for 1200\n");
		else
		if (font_head[3] == 1)
			printf("Y orientation, P for 1200, L for 800\n");
		else
			printf("Unknown orientation\n");
		printf("    Font number: %d\n",number);
		printf("    Font name: %.4s\n",font_head+5);
		printf("    Font version: %c\n",font_head[9]);
		printf("    Font baseline offset: %d\n\n",font_head[12]);
	}

	if (hex)
		printf("\n");
	checksum = 0;
	while (feof(f) == 0 && characters-- > 0)
	{
		/*
		 *	There is a header for each character which has the form:
		 *
		 *		struct char_header
		 *		{
		 *			short zero;		/* always zero						*/
		/*			short width1;	/* char width in pixels				*/
		/*			short width2;	/* same, may be different if a char	*/
		/*							/* had multiple bit maps but this	*/
		/*							/* never happens in ROM because a	*/
		/*							/* bit map can be arbitrarily large	*/
		/*			short height;	/* char height in pixels			*/
		/*			short area1;	/* high order char area, see below	*/
		/*			short area2;	/* low order char area, see below	*/
		/*			short ascii;	/* characters ASCII code			*/
		/*			short below;	/* empty rows below bit map + 8000	*/
		/*			short left;		/* empty columns at left of bit map	*/
		/*			short bheight;	/* bit map height in pixels			*/
		/*			short cols1;	/* high order columns in bit map	*/
		/*			short cols2;	/* low order columns in bit map		*/
		/*		};
		 *
		 *	The area information is encoded using a scheme which is
		 *	explained by looking at the code below.  The reason for
		 *	the encoding escapes me but seems consistent in all of
		 *	the ROMs I've examined.
		 *
		 *	The column width encoding is demonstrated by the 'cols'
		 *	subroutine below.  The encoding depends also on the height
		 *	of the character in 16-bit words.
		 */

		if (!hex && !scan_flag)
			printf("%06o/ ",curloc);
		for (i = 0; i < 12; i++)
		{
			char_head[i] = nexti(f);
			if (!scan_flag)
				printf("%04x ",char_head[i]);
		}
		curloc += 24;

		width = char_head[2];
		height = char_head[9];
		h = (height + 15) / 16;
		hh = (char_head[3] + 15) / 16;
		code1 = char_head[10];
		code2 = char_head[11];

		x = 0;
		if (hh & 1 && width & 1)
		{
			z = 0x299 - hh * width;
			while (z < 0x25a)
			{
				x++;
				z += 0x40;
			}
		}
		else
		{
			z = 0x1d0 - hh * width;
			while (z < 0x191)
			{
				x++;
				z += 0x40;
			}
		}
		if (!hex && (x != char_head[4] || z != char_head[5]))
			printf(" *** %x %3x",x,z);
		z = cols(h,code1,code2);

		if (verbose)
		{
			printf("\n\nCharacter Header Contents:\n\n");
			printf("    ASCII character code: %d (%o)\n",
				char_head[6],char_head[6]);
			if (font_head[3] == 0)
			{
				printf("    Character width: %d\n",char_head[0]);
				printf("    Character height: %d\n",width);
				printf("    Horizontal offset: %d\n",char_head[7]&0x7fff);
				printf("    Vertical offset: %d\n",char_head[8]);
			}
			else
			{
				printf("    Character width: %d\n",width);
				printf("    Character height: %d\n",char_head[3]);
				printf("    Vertical offset: %d\n",char_head[7]&0x7fff);
				printf("    Horizontal offset: %d\n",char_head[8]);
			}
			printf("    Bit map columns: %d\n",height);
			printf("    Bit map rows: %d\n",z);
		}
		while (feof(f) == 0)
		{
			if (z-- == 0)
				break;
			if (hex)
				printf("\n");
			else
			if (verbose)
				printf("\n%06o/ ",curloc);
			for (i = 0; i < h; i++)
			{
				curloc += 2;
				j = nexti(f);
				if (hex)
					printf("%04x",j);
				else
				if (verbose)
					print_bin(j);
			}
		}
		j = nexti(f);
		if (!hex && j)
			printf("\n%06o/ %04x is not zero",curloc,j);
		curloc += 2;
		if (hex)
			printf("\n0000");
		if (scan_flag)
			;
		else
		if (hex || !verbose)
			printf("\n");
		else
			printf("\n\n");
	}
	j = nexti(f);
	checksum -= ((j >> 8) & 0xff) + (j & 0xff);
	checksum &= 0xffff;
	if (hex)
		printf("%04x\n",j);
	else
		printf("%06o/ %04x Checksum: %04x %s\n",curloc,j,
			checksum,j == checksum ? "[ok]" : "[mismatch]");
	curloc += 2;
	if (scan_flag)
	{
		printf("\n");
		first = 0;
		goto again;
	}
}

nexti(f)
	FILE *f;
{
	int t;

	t = fgetc(f);
	t = (t << 8) + fgetc(f);
	checksum += (t & 0xff) + ((t >>8) & 0xff);
	return t;
}

print_bin(i)
	int i;
{
	int j;

	for (j = 15; j >= 0; j--)
		(void)fputc(((i >> j) & 1) ? '*' : ' ',stdout);
}

cols(w,x,c)
	int w,x,c;
{
	if (c > 0x40)
	{
		c -= x * 0x40;
		return (0x109 - c) / w;
	}
	else
	{
		c -= x * 0x40;
		return (0x40 - c) / w;
	}
}
------------------------------ roml.c ----------------------------
#include <stdio.h>
#include <ctype.h>

#define	FONT_DIR	"/usr/local/fonts/canon"

/*
 *	This program reads a Lasergrafix 1200 font definition
 *	in download format and writes a file suitable for
 *	storing in a ROM.
 */

int checksum;			/* For accumulating ROM checksum		*/
int space;				/* Flag which determines where spaces	*/
						/* go in the hex encoded output file	*/

main(argc,argv)
	int argc;
	char *argv[];
{
	FILE *fi,*fo;
	char filename[50];
	char name[4],version;
	register int i,j,char_count;
	int c,h1,h2,k;
	int aa,bbb,ddd,eee,hhh,www,xxx,yyy;
	int eight_bit,number;

	if (argc != 4)
	{
		printf("Usage: %s <number> <font file> <rom file>\n",
			argv[0]);
		exit(1);
	}

	number = atoi(argv[1]);
	if (number < 1 || number > 32767)
	{
		printf("%s: font number (%d) out of range!\n",
			argv[0],number);
		exit(1);
	}

	if ((fi = fopen(argv[2],"r")) == NULL)
	{
		(void)sprintf(filename,"%s/%s",FONT_DIR,argv[2]);
		if ((fi = fopen(filename,"r")) == NULL)
		{
			printf("%s: can't read '%s'\n",argv[0],argv[2]);
			exit(1);
		}
	}

	if ((fo = fopen(argv[3],"w")) == NULL)
	{
		printf("%s: can't write '%s'\n",argv[0],argv[3]);
		exit(1);
	}

	eight_bit = 0;
	c = getc(fi);
	while (c == 'E' || c == 'S' || c == 'X' || c == 'Y')
	{
		if (c == 'E')
			eight_bit = getc(fi) - '0';
		while ((c = getc(fi)) != '\n' && c != EOF)
			;
		c = getc(fi);
	}
	if (c != 'L')
	{
		printf("%s: this only works for landscape fonts!\n",argv[0]);
		exit(1);
	}

	version = getc(fi);
	for (i = 0; i < 4; i++)
		name[i] = getc(fi);
	hhh = intin(fi,3);
	bbb = 0;
	if (isdigit(i = getc(fi)))
	{	
		(void)ungetc(i,fi);
		bbb = intin(fi,3);
		i = getc(fi);
	}
	if (i != ',')
	{
		if (i == 'T')
			printf("%s: can't handle version 2 fonts!\n",
				argv[0]);
		else
			printf("%s: comma missing after glyph height - '%c'!\n",
				argv[0],i);
		exit(1);
	}
	if (!eight_bit && (i = getc(fi)) != '\n')
	{
		printf("%s: newline missing after glyph height - '%c'!\n",
			argv[0],i);
		exit(1);
	}

	char_count = 0;
	checksum = 0;
	(void)fseek(fo,48L,0);
	aa = 0;
	while (1)
	{
		h1 = hexin(fi);
		h2 = hexin(fi);
		if (h1 == -1 || h2 == -1)
		{
			printf("%s: non hex digit in char code, last good char %x\n",
				argv[0],aa);
			exit(1);
		}
		aa = (h1 << 4) + h2;
		www = intin(fi,3);
		yyy = intin(fi,3);
		xxx = intin(fi,3);
		ddd = intin(fi,3);
		eee = intin(fi,3);
		char_count++;
		space = 0;
		put_int(www,fo);
		put_int(0,fo);
		put_int(hhh,fo);
		put_int(www,fo);
		j = area(www,hhh,&k);
		put_int(k,fo);
		put_int(j,fo);
		put_int(aa,fo);
		put_int(0x8000+eee,fo);
		put_int(ddd,fo);
		put_int(xxx,fo);
		j = codeword(xxx,yyy,&k);
		put_int(k,fo);
		put_int(j,fo);
		(void)fputc('\n',fo);
		j = 2 * ((xxx + 15) / 16);
		while (yyy--)
		{
			for (i = 0; i < j; i++)
			{
				space = 0;
				if (eight_bit)
					put_byte(fgetc(fi),fo);
				else
				{
					h1 = hexin(fi);
					h2 = hexin(fi);
					if (h1 == -1 || h2 == -1)
					{
						printf("%s: bad hex code in character %2x!\n",
							argv[0],aa);
						exit(1);
					}
					put_byte((h1 << 4) + h2,fo);
				}
			}
			(void)fputc('\n',fo);
		}
		space = 0;
		put_int(0,fo);
		(void)fputc('\n',fo);
		i = getc(fi);
		if ((!eight_bit && i == '\n') || (eight_bit && i == '^'))
			break;
		if (i != ',')
		{
			printf("%s: comma missing after char %2x bitmap!\n",
				argv[0],aa);
			exit(1);
		}
		if (!eight_bit && getc(fi) != '\n')
		{
			printf("%s: newline missing after char %2x bitmap!\n",
				argv[0],aa);
			exit(1);
		}
	}
	space = 0;
	put_int(checksum,fo);
	(void)fputc('\n',fo);
	(void)fseek(fo,0L,0);
	checksum = 0;
	space = 0;
	put_byte(0xf0,fo);			/* Beginning of font markers	*/
	put_byte(0x0f,fo);			/* ...more of the same			*/
	put_byte(char_count,fo);	/* Number of chars in the font	*/
	put_byte(0,fo);				/* Format version number = 0	*/
	put_byte(number,fo);		/* Low order font number		*/
	for (i = 0; i < 4; i++)
		put_byte(name[i],fo);	/* Font name					*/
	put_byte(version,fo);		/* Font version					*/
	put_byte(0,fo);				/* Must be zero					*/
	put_byte(0,fo);				/* Must be zero					*/
	put_byte(bbb,fo);		/* Baseline offset				*/
	put_byte(0,fo);				/* Must be zero					*/
	put_byte(number >> 8,fo);	/* High order font number		*/
	put_byte(checksum,fo);		/* Header checksum				*/
	(void)fputc('\n',fo);
	(void)fclose(fi);
	(void)fclose(fo);
	exit(0);
}

char hex[] = {"0123456789ABCDEF"};

put_byte(b,f)
	int b;
	FILE *f;
{
	b &= 0xff;
	checksum += b;
	if (space == 0)
		space = 1;
	else
		(void)fputc(' ',f);
	(void)fputc(hex[(b >> 4) & 0xf],f);
	(void)fputc(hex[b & 0xf],f);
}

put_int(i,f)
	int i;
	FILE *f;
{
	put_byte(i >> 8,f);
	space = 0;
	put_byte(i,f);
}

intin(f,k)
	FILE *f;
	register int k;
{
	register int c,i;

	i = 0;
	while (k--)
	{
		c = getc(f);
		if (c < '0' || c > '9')
		{
			printf("bad number in 'intin'\n");
			exit(1);
		}
		i = i * 10 + c - '0';
	}
	return i;
}

hexin(f)
	FILE *f;
{
	register int c;

	c = getc(f);
	while (c == '\n')
		c = getc(f);
	if ('0' <= c && c <= '9')
		c -= '0';
	else
	if ('A' <= c && c <= 'F')
		c -= 'A' - 10;
	else
	if ('a' <= c && c <= 'f')
		c -= 'a' - 10;
	else
		c = -1;
	return c;
}

codeword(w,o,x)
	register int w,o;
	register int *x;
{
	register int c;

	w = (w + 15) / 16;
	*x = 0;
	if (w & 1 && o & 1)
	{
		c = 0x109 - w * o;
		while (c <= 0xc6)
		{
			c += 0x40;
			(*x)++;
		}
	}
	else
	{
		c = 0x40 - w * o;
		while (c < 1)
		{
			c += 0x40;
			(*x)++;
		}
	}
	return c;
}

area(i,j,k)
	register int i,j;
	register int *k;
{
	register int l;

	i = (i + 15) / 16;
	*k = 0;
	if (i & 1 && j & 1)
	{
		l = 0x299 - i * j;
		while (l < 0x25a)
		{
			l += 0x40;
			(*k)++;
		}
	}
	else
	{
		l = 0x1d0 - i * j;
		while (l < 0x191)
		{
			l += 0x40;
			(*k)++;
		}
	}
	return l;
}
------------------------------ romp.c ----------------------------
#include <stdio.h>
#include <ctype.h>

#define	FONT_DIR	"/usr/local/fonts/raven"

/*
 *	This program reads a Lasergrafix 1200 font definition
 *	in download format and writes a file suitable for
 *	storing in a ROM.
 */

int checksum;			/* For accumulating ROM checksum		*/
int space;				/* Flag which determines where spaces	*/
						/* go in the hex encoded output file	*/

main(argc,argv)
	int argc;
	char *argv[];
{
	FILE *fi,*fo;
	char filename[50];
	char name[4],version;
	register int i,j,char_count;
	int c,h1,h2,k;
	int baseline,char_cd,eight_bit,glyph_ht,glyph_wd,number;
	int map_ht,map_wd,off_ht,off_wd;

	if (argc != 4)
	{
		printf("Usage: %s <number> <font file> <rom file>\n",
			argv[0]);
		exit(1);
	}

	number = atoi(argv[1]);
	if (number < 1 || number > 32767)
	{
		printf("%s: font number (%d) out of range!\n",
			argv[0],number);
		exit(1);
	}

	if ((fi = fopen(argv[2],"r")) == NULL)
	{
		(void)sprintf(filename,"%s/%s",FONT_DIR,argv[2]);
		if ((fi = fopen(filename,"r")) == NULL)
		{
			printf("%s: can't read '%s'\n",argv[0],argv[2]);
			exit(1);
		}
	}

	if ((fo = fopen(argv[3],"w")) == NULL)
	{
		printf("%s: can't write '%s'\n",argv[0],argv[3]);
		exit(1);
	}

	eight_bit = 0;
	c = getc(fi);
	while (c == 'E' || c == 'S' || c == 'X' || c == 'Y')
	{
		if (c == 'E')
			eight_bit = getc(fi) - '0';
		while ((c = getc(fi)) != '\n' && c != EOF)
			;
		c = getc(fi);
	}
	if (c != 'P')
	{
		printf("%s: this only works for portrait fonts!\n",
			argv[0]);
		exit(1);
	}

	version = getc(fi);
	for (i = 0; i < 4; i++)
		name[i] = getc(fi);
	glyph_ht = intin(fi,3);
	baseline = 0;
	if (isdigit(i = getc(fi)))
	{	
		(void)ungetc(i,fi);
		baseline = intin(fi,3);
		i = getc(fi);
	}
	if (i != ',')
	{
		if (i == 'T')
			printf("%s: can't handle version 2 fonts!\n",
				argv[0]);
		else
			printf("%s: comma missing after glyph height - '%c'!\n",
				argv[0],i);
		exit(1);
	}
	if (!eight_bit && (i = getc(fi)) != '\n')
	{
		printf("%s: newline missing after glyph height - '%c'!\n",
			argv[0],i);
		exit(1);
	}

	char_count = 0;
	checksum = 0;
	(void)fseek(fo,48L,0);
	while (1)
	{
		h1 = hexin(fi);
		h2 = hexin(fi);
		if (h1 == -1 || h2 == -1)
		{
			printf("%s: non hex digit in char code\n",argv[0]);
			exit(1);
		}
		char_cd = (h1 << 4) + h2;
		glyph_wd = intin(fi,3);
		map_wd = intin(fi,3);
		map_ht = intin(fi,3);
		off_wd = intin(fi,3);
		off_ht = intin(fi,3);
		char_count++;
		space = 0;
		put_int(0,fo);
		put_int(glyph_wd,fo);
		put_int(glyph_wd,fo);
		put_int(glyph_ht,fo);
		j = area(glyph_ht,glyph_wd,&k);
		put_int(k,fo);
		put_int(j,fo);
		put_int(char_cd,fo);
		put_int(0x8000+off_ht,fo);
		put_int(off_wd,fo);
		put_int(map_ht,fo);
		j = codeword(map_ht,map_wd,&k);
		put_int(k,fo);
		put_int(j,fo);
		(void)fputc('\n',fo);
		j = 2 * ((map_ht + 15) / 16);
		while (map_wd--)
		{
			for (i = 0; i < j; i++)
			{
				space = 0;
				if (eight_bit)
					put_byte(fgetc(fi),fo);
				else
				{
					h1 = hexin(fi);
					h2 = hexin(fi);
					if (h1 == -1 || h2 == -1)
					{
						printf("%s: bad hex code in character %2x!\n",
							argv[0],char_cd);
						exit(1);
					}
					put_byte((h1 << 4) + h2,fo);
				}
			}
			(void)fputc('\n',fo);
		}
		space = 0;
		put_int(0,fo);
		(void)fputc('\n',fo);
		i = getc(fi);
		if ((!eight_bit && i == '\n') || (eight_bit && i == '^'))
			break;
		if (i != ',')
		{
			printf("%s: comma missing after char %2x bitmap!\n",
				argv[0],char_cd);
			exit(1);
		}
		if (!eight_bit && getc(fi) != '\n')
		{
			printf("%s: newline missing after char %2x bitmap!\n",
				argv[0],char_cd);
			exit(1);
		}
	}
	space = 0;
	put_int(checksum,fo);
	(void)fputc('\n',fo);
	(void)fseek(fo,0L,0);
	checksum = 0;
	space = 0;
	put_byte(0xf0,fo);			/* Beginning of font markers	*/
	put_byte(0x0f,fo);			/* ...more of the same			*/
	put_byte(char_count,fo);	/* Number of chars in the font	*/
	put_byte(1,fo);				/* Format version number = 1	*/
	put_byte(number,fo);		/* Low order font number		*/
	for (i = 0; i < 4; i++)
		put_byte(name[i],fo);	/* Font name					*/
	put_byte(version,fo);		/* Font version					*/
	put_byte(0,fo);				/* Must be zero					*/
	put_byte(0,fo);				/* Must be zero					*/
	put_byte(baseline,fo);		/* Baseline offset				*/
	put_byte(0,fo);				/* Must be zero					*/
	put_byte(number >> 8,fo);	/* High order font number		*/
	put_byte(checksum,fo);		/* Header checksum				*/
	(void)fputc('\n',fo);
	(void)fclose(fi);
	(void)fclose(fo);
	exit(0);
}

char hex[] = {"0123456789ABCDEF"};

put_byte(b,f)
	int b;
	FILE *f;
{
	b &= 0xff;
	checksum += b;
	if (space == 0)
		space = 1;
	else
		(void)fputc(' ',f);
	(void)fputc(hex[(b >> 4) & 0xf],f);
	(void)fputc(hex[b & 0xf],f);
}

put_int(i,f)
	int i;
	FILE *f;
{
	put_byte(i >> 8,f);
	space = 0;
	put_byte(i,f);
}

intin(f,k)
	FILE *f;
	register int k;
{
	register int c,i;

	i = 0;
	while (k--)
	{
		c = getc(f);
		if (c < '0' || c > '9')
		{
			printf("bad number in 'intin'\n");
			exit(1);
		}
		i = i * 10 + c - '0';
	}
	return i;
}

hexin(f)
	FILE *f;
{
	register int c;

	c = getc(f);
	while (c == '\n')
		c = getc(f);
	if ('0' <= c && c <= '9')
		c -= '0';
	else
	if ('A' <= c && c <= 'F')
		c -= 'A' - 10;
	else
	if ('a' <= c && c <= 'f')
		c -= 'a' - 10;
	else
		c = -1;
	return c;
}

codeword(w,o,x)
	register int w,o;
	register int *x;
{
	register int c;

	w = (w + 15) / 16;
	*x = 0;
	if (w & 1 && o & 1)
	{
		c = 0x109 - w * o;
		while (c <= 0xc4)
		{
			c += 0x40;
			(*x)++;
		}
	}
	else
	{
		c = 0x40 - w * o;
		while (c < 1)
		{
			c += 0x40;
			(*x)++;
		}
	}
	return c;
}

area(i,j,k)
	register int i,j;
	register int *k;
{
	register int l;

	i = (i + 15) / 16;
	*k = 0;
	if (i & 1 && j & 1)
	{
		l = 0x299 - i * j;
		while (l < 0x25a)
		{
			l += 0x40;
			(*k)++;
		}
	}
	else
	{
		l = 0x1d0 - i * j;
		while (l < 0x191)
		{
			l += 0x40;
			(*k)++;
		}
	}
	return l;
}