/* intel16.c  - read/write intel get 16	*/
/* (c) I.King 1994			*/
/*					*/
/* Acnowledgement:			*/
/* the intricacies of INHX16 were	*/
/* extracted from the source of pp.c	*/
/* David Tait's 16C84 programmer	*/
/* (david.tait@man.ac.uk) and the MChip	*/
/* 93 databook (which lies!)		*/
/*					*/

#include "pu_defs.h"
#include <stdio.h>
#include <ctype.h>

unsigned char checksum;
FILE *inputfile;
FILE *outputfile;

int getachar()
{
	int c;

	do
		c = fgetc(inputfile);
	while (c == '\r');		/* strip LF out of MSDOS files */

	return c;
}

unsigned char getbyte()
{
	unsigned char byte;
	unsigned int  data;

	fscanf(inputfile,"%02x",&data);

	byte = data & 0xff;
	checksum += byte;	/* all the bytes are used in the checksum */
				/* so here is the best place to update it */
	return byte;
}

void readihex16(char *filename, PICDEFN *pic, int *top)
{
	unsigned int address;
	unsigned int maxAddress = 0;
	int linetype = 0;
	int wordsthisline;
	int i;
	int lineCount = 1;
	unsigned short *memory;
	int csby;
	unsigned char hi, lo;

	memory = pic->picmemmap;

	if ((inputfile = fopen(filename,"r")) == NULL)
	{
		printf("Could not open input file %s\n",filename);
		exit(1);
	}
      
	while (1)
	{
		if (getachar() != ':' )
		{
			printf("Need a colon as first character in each line\n");
			printf("Colon missing in line %d\n", lineCount);
			exit(1);
		}

		checksum = 0;

		wordsthisline = getbyte()/2;
		hi = getbyte();
		lo = getbyte();
		address = (hi<<8 | lo) / 2;

		/* wierdness of INHX16! address different */
		/* endian-ness and 2x too big */

		linetype = getbyte();	/* 0 for data, 1 for end  */

		if(linetype == 1)	/* lets get out of here hit the end */
			break;

		for(i=0; i<wordsthisline; i++)
		{
			if (address >= MAXPICSIZE)
			{
				printf("Address out of range\n");
				printf("Got 0x%04x maximum is 0x%04x at line %d\n",address,MAXPICSIZE, lineCount);
				exit(1);
			}

			lo = getbyte();
			hi = getbyte();
			memory[address] = (unsigned short)((hi<<8) | lo);
			++address;
			if (address > maxAddress)
				maxAddress = address;
		}

		csby = getbyte();	/* get the checksum byte */
					/* this should make the checksum zero */
					/* due to side effect of getbyte */

		if (checksum)
		{
			printf("Checksum error in input file.\n");
			printf("Got 0x%02x want 0x%02x at line %d\n",csby, (0-checksum) & 0xff, lineCount);
			exit(1);
		}

		(void)getachar();		/* lose <return> */

		lineCount++;
	}

	fclose(inputfile);

	*top = maxAddress;
}

void printhex(int val)
{
	int chop;

	chop = val & 0xff;
	fprintf(outputfile,"%02X",chop);
	checksum += chop;
}

void writeihex16(char *filename, PICDEFN *pic, int top)
{
	int current;
	int numinthisline;
	int i;
	int addr;
	int numberofwords;

	numberofwords = top + 1;

	if ((outputfile=fopen(filename,"w")) == NULL)
	{
		printf("Could not open output file %s\n",filename);
		exit(1);
	}

	current = 0;

	while(current < numberofwords)
	{
		checksum = 0;
		numinthisline = numberofwords - current;

		if (numinthisline > 8)
			numinthisline = 8;

		fputc(':',outputfile);

		printhex(numinthisline*2);

		addr = current*2;

		printhex(addr>>8);
		printhex(addr);

		printhex(0);

		for(i=0;i<numinthisline;i++)
		{
			printhex(pic->picmemmap[current+i]);
			printhex(pic->picmemmap[current+i]>>8);
		}

		printhex(0-checksum);		
		fputc('\n', outputfile);

		current += numinthisline;
	}

	fprintf(outputfile,":00000001FF\n");
	fclose(outputfile);
}

/* ... The End ... */
