/* intel16.c - read an intel hex file */
/* Copyright (c) 1994 Ian King */

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

unsigned char checksum;

int getachar(FILE *file)
{
	int c;

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

	return c;
}

unsigned char getbyte(FILE *file)
{
	unsigned char byte;
	unsigned int  data;

	fscanf(file,"%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(FILE *file, int *memory, int *minaddr, int *maxaddr)
{
	int address;
	int linetype = 0;
	int wordsthisline;
	int i;
	int lineCount = 1;
	int csby;
	unsigned char hi, lo;

	*minaddr = MAXPICSIZE;
	*maxaddr = -1;

	while (1)
	{
		if (getachar(file) != ':' )
		{
			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(file)/2;
		hi = getbyte(file);
		lo = getbyte(file);
		address = (hi<<8 | lo) / 2;

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

		linetype = getbyte(file);	/* 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(file);
			hi = getbyte(file);
			memory[address] = (hi<<8) | lo;

			if (*minaddr > address)
				*minaddr = address;

			if (*maxaddr < address)
				*maxaddr = address;

			++address;
		}

		csby = getbyte(file);	/* 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(file);		/* lose <return> */

		lineCount++;
	}
}

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