/* Read ".HEX" files and store it in memory
Copyright (C) 2001, 2002, 2003, 2004, 2005
Craig Franklin
This file is part of gputils.
gputils is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
gputils is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with gputils; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "stdhdr.h"
#include "libgputils.h"
#define LINESIZ 520
char linebuf[LINESIZ];
char *linept;
int checksum;
FILE *infile;
/* Converts a single ASCII character into a number */
unsigned int a2n(char character)
{
unsigned int number;
if(character < 0x3A) {
number = character-0x30;
} else {
/* convert lower case to upper */
character &= 0xDF;
number = character-0x37;
}
return number;
}
unsigned int readbyte()
{
unsigned int number;
linept++;
number = a2n(*linept) << 4;
linept++;
number |= a2n(*linept);
checksum += number;
return number;
}
unsigned int readword()
{
unsigned int number;
number = readbyte();
number = (readbyte() << 8) | number;
return number;
}
unsigned int swapword(unsigned int input)
{
unsigned int number;
number = ((input & 0xFF) << 8) | ((input & 0xFF00) >> 8);
return number;
}
struct hex_data *
readhex(char *filename, MemBlock *m)
{
struct hex_data *info = malloc(sizeof(*info));
int length, address, type, data;
int i;
int page = 0;
info->hex_format = inhx8m;
info->size = 0;
info->error = 0;
/* Open the input file */
if ( (infile = fopen(filename,"rt")) == NULL ){
perror(filename);
exit(1);
}
/* go to the beginning of the file */
fseek(infile, 0L, 0);
/* set the line pointer to the beginning of the line buffer */
linept = linebuf;
/* read a line of data from the file, if NULL stop */
while(fgets(linept, LINESIZ, infile))
{
/* set the line pointer to the beginning of the line buffer */
linept = linebuf;
checksum = 0;
/* fetch the number of bytes */
length = readbyte();
if (length == 0) {
fclose(infile);
return info;
}
if (info->hex_format != inhx16) {
length = length / 2;
}
/* fetch the address */
address = readword();
address = swapword(address);
if (info->hex_format == inhx16) {
address = address * 2;
}
/* read the type of record */
type = readbyte();
if (type == 4) {
if (info->hex_format == inhx16) {
printf("\nhex format error\n");
fclose(infile);
info->error = 1;
return info;
}
/* inhx32 segment line*/
page = readword();
info->hex_format = inhx32;
} else {
/* read the data */
for (i = 0; i < length; i += 1) {
data = readword();
if (info->hex_format == inhx16) {
data = swapword(data);
}
i_memory_put(m,
((page << 16) | (address + (i << 1))>>1),
data | MEM_USED_MASK);
}
info->size += (length * 2);
}
/* read the checksum, data is thrown away*/
data = readbyte();
if ((checksum & 0xFF) != 0) {
if (info->hex_format == inhx8m) {
/* first attempt at inhx8m failed, try inhx16 */
fseek(infile, 0L, 0);
info->hex_format = inhx16;
info->size = 0;
/* data in i_memory is trash */
i_memory_free(m);
m = i_memory_create();
} else {
printf("\nChecksum Error\n");
fclose(infile);
info->error = 1;
return info;
}
}
/* set the line pointer to the beginning of the line buffer */
linept = linebuf;
}
fclose(infile);
return info;
}
syntax highlighted by Code2HTML, v. 0.9.1