#include #include #include #define READ_BUFFER_SIZE 4096 #define MAX_LINE_LENGTH 512 void processS19 (FILE * infile, FILE * outfile, FILE * errfile); unsigned char hex2bin (unsigned char *hexstring, unsigned char *returnbuf, unsigned long nChars); unsigned char checksum(unsigned char *data, unsigned long nLength); int showhelp = 0; int showmap = 0; int savemap = 0; int minsize = 0; int fullblock = 0; int gotinfile = 0; int gotoutfile = 0; int goterrfile = 0; int main(int argc, char *argv[]) { FILE * infile = stdin; FILE * outfile = stdout; FILE * errfile = stderr; unsigned long i = 0; for (i=1;i\tMinimum size of output file (pads with 0x01s if output is smaller)\n\n"); printf("-f\twrite ENTIRE memory block, even if empty (by default only data between\n\tfirst and last non-zero bytes are written)\n"); printf("\n"); printf("the memory block usage map appears as follows:\n"); printf("\t# or . - 16 byte block. # if any bytes are != 01, . if all bytes are 01\n"); printf("\tthere are 64 blocks per line, giving 1024 bytes per line.\n"); printf("\tthe byte range is specified on the right.\n"); printf("\tat the top, each 256 byte boundary is marked.\n"); printf("\n"); printf("EXAMPLE OF MEMORY BLOCK MAP:\n"); printf(" | 0x100 | 0x200 | 0x300 | 0x400\n"); printf("################................................................ 0000-03FF\n"); printf("................................####............................ 0400-07FF\n"); printf("................................................................ 0800-0BFF\n"); printf("... etc up to FC00-FFFF line.\n"); printf("this map indicates that the first 255 bytes from 0-0xFF are used, along with a\n\t64 byte chunk from 0x600 to 0x63F\n"); } else { processS19(infile, outfile, errfile); } close(infile); close(outfile); close(errfile); return 0; } void processS19(FILE * infile, FILE * outfile, FILE * errfile) { #ifdef DEBUG printf("Building binary data...\n"); #endif unsigned char buf[READ_BUFFER_SIZE]; unsigned char cline[MAX_LINE_LENGTH]; unsigned char finalImage[65536]; char hexArr[16] = "0123456789ABCDEF"; unsigned long clinePos = 0; unsigned long bufPos = 0; unsigned long i,j,r; for (r=0;r < 65536;finalImage[r++] = 0x01); while (r = fread(buf,1,READ_BUFFER_SIZE,infile)) { buf[r] = 0; bufPos = 0; while (bufPos < r) { if (buf[bufPos] == 13 || buf[bufPos] == 10) { while (buf[bufPos] == 13 || buf[bufPos] == 10) bufPos++; cline[clinePos] = 0; if (cline[0] == 'S') { char lData[514]; unsigned char len = 0; unsigned char checkSum_calc; unsigned char checkSum_save; hex2bin(cline + 2, (char*) &len, 2); checkSum_calc = hex2bin(cline + 2, lData, len * 2); hex2bin(cline + (len * 2) + 2, &checkSum_save,2); char checksumHex[3] = "aa\0"; checksumHex[0] = hexArr[(checkSum_calc & 0xF0) >> 4]; checksumHex[1] = hexArr[checkSum_calc & 0x0F]; if (checkSum_save != checkSum_calc) fprintf(errfile,"CHECKSUMS DONT MATCH (saved %x, calced %x) FOR LINE %s\n",checkSum_save,checkSum_calc,cline); switch (cline[1]) { case '0': /* S0 record. address field is zeroed. data as follows: char[20] module name, char[2] version, char[2] revision, char* description probably safe to ignore */ case '1': /* S1 record. standard data record. only 2 bytes of address field used */ if (1) { unsigned int addr = 0; addr = ((((unsigned int) lData[1]) << 8) & 0xFF00) | ((unsigned int) lData[2] & 0xFF); memcpy(finalImage + addr, lData + 3, len - 3); } case '2': /* S2 record. standard data record. only 3 bytes of address field used. */ case '3': /* S3 record. standard data record. all 4 bytes of address field used. */ case '5': /* S5 record. address field contains count of S1,2,3 records so far. no data. */ case '7': /* S7 record. address contains start of execution address. no data. */ case '8': /* S8 record. address contains 3 byte start of execution address. no data. */ case '9': /* S9 record. address contains 2 byte start of execution address. no data. */ break; } } clinePos = 0; } cline[clinePos++] = buf[bufPos++]; } } if (showmap) printf("\n | 0x100 | 0x200 | 0x300 | 0x400\n"); if (savemap) fprintf(outfile,"\n | 0x100 | 0x200 | 0x300 | 0x400\n"); if (1) { unsigned int firstData = 0xFFFF,lastData = 0; i = j = 0; for (r=0;r < 65536; r++) { if ((r & 0x3FF) == 0 && r > 0) if (showmap) printf(" %04X-%04X\n",r - 0x400,r-1); if (savemap) fprintf(outfile," %04X-%04X\n",r - 0x400,r-1); if (finalImage[r] != 0x01) { i = j = 1; if (r < firstData) firstData = r; if (r > lastData) lastData = r; } if ((r & 0xF) == 0xF) { if (showmap) printf(i?"#":"."); if (savemap) fprintf(outfile,i?"#":"."); i=0; } } if (showmap) printf(" %04X-%04X\n",r - 0x400,r-1); if (savemap) fprintf(outfile, " %04X-%04X\n",r - 0x400,r-1); if (firstData <= lastData) { int eFirstData = 0, eLastData = 65535; if (fullblock == 0) { eFirstData = firstData; eLastData = lastData; } if ((i = fwrite((void*) ((unsigned long) &finalImage + eFirstData),1, eLastData - eFirstData + 1,outfile)) != (eLastData - eFirstData + 1)) { fprintf(errfile,"write error: %d\n",i); } else { while (i < minsize) i += fwrite("\0",1,1,outfile); } } #ifdef DEBUG printf("\nfirst data at %x, last at %x (%d)\n",firstData,lastData,i); #endif } } unsigned char hex2bin (unsigned char *hexstring, unsigned char *returnbuf, unsigned long nChars) { unsigned char byte; unsigned long i; unsigned long j; for (i=0;i < nChars;i++) { j = i >> 1; if ((i & 1) == 0) returnbuf[j] = 0; if ((hexstring[i] >= '0') && (hexstring[i] <= '9')) { returnbuf[j] |= (hexstring[i] - '0') << ((i & 1)?0:4); } else if ((hexstring[i] >= 'A') && (hexstring[i] <= 'F')) { returnbuf[j] |= (hexstring[i] - 'A' + 10) << ((i & 1)?0:4); } } return(checksum(returnbuf, nChars >> 1)); } unsigned char checksum(unsigned char *data, unsigned long nLength) { unsigned long i; unsigned char q = 0; for (i=0;i < nLength;i++) { q = (q + (data[i])); } return ~q; }