/* * ihxtobin, converts Intel hex format to binary * Copyright 2002, 2004 Chris Williams * * This program 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 of the License, or * (at your option) any later version. * * This program 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 this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* I wrote this a couple years ago, so there are probably * some beginner's mistakes in here. :-/ Just FYI. */ /* FIXME: This programs takes no arguments like for infile, outfile, or * even to display help or program version. Add them, please. */ #include #define STRINGIZE(n) STRINGIZE2(n) #define STRINGIZE2(n) #n char PROGRAMNAME[] = "ihxtobin"; int main(int argc, char *argv[]) { int c; int minaddr = 0xFFFF, maxaddr = 0x0000; unsigned char checksum = 0; int len, addr = 0, type; unsigned char fillbyte = 0x00; enum { STATE_COLON, STATE_LEN, STATE_ADDR, STATE_TYPE, STATE_DATA, STATE_CHECKSUM, STATE_DONE } state = STATE_COLON; unsigned char mem[0x10000]; memset(mem, fillbyte, 0x10000); while ((c = getchar()) != EOF && state != STATE_DONE) { switch (state) { case STATE_COLON: if (c == ':') ++state; break; case STATE_LEN: { char lenstr[3]; ungetc(c, stdin); if (fgets(lenstr, 3, stdin) == NULL) break; /* fprintf(stderr,"len = '%s' ", lenstr); */ if (sscanf(lenstr, "%X", &len) == EOF) break; /* fprintf(stderr,"(%02X) ", len); */ ++state; break; } case STATE_ADDR: { char addrstr[5]; ungetc(c, stdin); if (fgets(addrstr, 5, stdin) == NULL) break; /* fprintf(stderr,"addr = '%s' ", addrstr); */ if (sscanf(addrstr, "%X", &addr) == EOF) break; /* fprintf(stderr,"(%04X) ", addr); */ ++state; break; } case STATE_TYPE: { char typestr[3]; ungetc(c, stdin); if (fgets(typestr, 3, stdin) == NULL) break; /* fprintf(stderr,"type = '%s' ", typestr); */ if (sscanf(typestr, "%X", &type) == EOF) break; /* fprintf(stderr,"(%02X) ", type); */ switch (type) { case 0x00: if (addr < minaddr) minaddr = addr; if (addr + len > maxaddr) maxaddr = addr + len; ++state; break; case 0x01: state = STATE_DONE; break; case 0x02: case 0x04: fprintf(stderr, "%s: record type %02X not supported yet. Sorry.\n", PROGRAMNAME, type); return -1; default: fprintf(stderr, "%s: invalid record type %02X\n", PROGRAMNAME, type); return -1; } break; } case STATE_DATA: { unsigned char *m = 0; char datastr[3]; int n; checksum = 0; ungetc(c, stdin); for (m = mem + addr; m < mem + addr + len; ++m) { if (fgets(datastr, 3, stdin) == NULL) break; if (sscanf(datastr, "%X", &n) == EOF) break; *m = n; checksum += n; } ++state; break; } case STATE_CHECKSUM: { char csstr[3]; int cs; ungetc(c, stdin); if (fgets(csstr, 3, stdin) == NULL) break; if (sscanf(csstr, "%X", &cs) == EOF) break; /* fprintf(stderr, "cs = '%s' (%02X) ", csstr, cs); */ checksum += cs+len+addr+(addr>>8)+type; if (checksum) { fprintf(stderr, "%s: checksum error (%02X)", PROGRAMNAME, checksum); /*else fputs("checksum ok ", stderr);*/ fprintf(stderr, " at %04X\n", addr); } state = STATE_COLON; break; } default: fprintf(stderr, "%s: coding error: illegal state ("__FILE__", "STRINGIZE(__LINE__)")\n", PROGRAMNAME); } } /* fprintf(stderr, "minaddr = %04X, maxaddr = %04X\n", minaddr, maxaddr); */ for (addr = minaddr; addr < maxaddr; ++addr) putchar(mem[addr]); /*printf("%02X", mem[addr]);*/ return 0; }