M68000BFP.txt

(7 KB) Pobierz
/* This file contains source code to read a Motorola S-record file into
** a memory image.  The size of the file cannot exceed BUFSIZE of data.
** The image is then written to disk either as binary data starting at
** address 0 with no data gaps, or as a C array of unsigned longs.
** Input lines must be no longer than MAXLINE.  No check is made!
**
**      Author:         Eric McRae, Electro-Logic Machines, Inc.
**      Date:           Copyright 1994
**
** This source code is made available to the public "as is".  No
** warranty is given or implied for it's proper operation.  This source
** code may be used in whole or in part as long as this copyright is
** included.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* Comment the following line for non PC applications */
#define PCDOS

/* Uncomment the following line if you want a binary output instead of
** a structure
*/
/* #define BINARY  */

#ifdef PCDOS                    /* Intel x86 architecture */
#define BUFSIZE 49152           /* 48K to avoid segment hopping */
#else                           /* Any reasonable (non-segmented) arch... */
#define BUFSIZE 65536           /* As big as you want */
#endif

#define MAXLINE 256             /* Length of longest input line + 1 */
/* Globals */
FILE *infilePH, *outfilePH;     /* Handles for input and output files */
unsigned char *bufAC,           /* Allocated image buffer */
    *highestPC = NULL;          /* Highest buffer address written */

/* Change this string to reflect the name of the output array */
char headerAC[] = "unsigned long sRec[] =\n{\n";

/* Predeclarations */
int parsebufN( char * );                /* Does the actual parsing */

void main(int argc, const char * argv[])
{
    int c,                              /* Temp char storage */
        resN;                           /* result status */
    char *lbufPC, lbufAC[MAXLINE];
   int linectrN = 0;            /* Used to correlate parse fail to input line */

#ifndef BINARY
        int i;
    unsigned long *codePL; 
    unsigned char *codePC;
#endif
 
    /* Check the argument count */
    if( argc != 3 )             /* If didn't specify input and output files */
    {
        printf("Usage: %s: infile outfile\n", argv[0] );
        exit(1);
    }

    /* OK, let's open some files */
    if( ( infilePH = fopen( argv[1], "r" )  )== NULL )
    {
        printf("%s: Couldn't open input file %s\n", argv[0], argv[1] );
        exit(2);
    }

    if( ( outfilePH = fopen( argv[2], "w" ) ) == NULL )
    {
        printf("%s: Couldn't open output file %s\n", argv[0], argv[3] );
        exit(3);
    }

    /* OK, get a buffer and clear it. */
    if( (bufAC = calloc( (size_t)BUFSIZE, (size_t)1 )) == NULL )
    {
        printf("%s: Couldn't malloc memory for buffer\n", argv[0] );
        exit(4);
    }

    lbufPC = lbufAC;                    /* Point at beginning of line buffer */
    while( c = fgetc( infilePH )) 
    {
        if( (c == '\n') || (c == EOF) ) /* If found end of line or file */
        {                               /* Parse the Line */
            if( ( c == EOF ) && (  ferror( infilePH ) ) )
            {
                printf("%s: Error reading input file\n", argv[0] );
                exit(5);
            }
            else
            {           /* OK, have a complete line in buffer */
                linectrN++;             /* Increment line counter */
                if( lbufPC == lbufAC )
                        break;          /* ignore blank lines */
                *lbufPC = 0;            /* Terminate the line string */
                if( resN = parsebufN( lbufAC ) ) /* Parse data record to mem */
                {
                    printf("%s: Error reading input file at line %d, return code = %d\n",
                        argv[0], linectrN, resN );
                    exit( resN );
                }
                lbufPC = lbufAC;        /* Repoint line buffer pointer */
            }           /* End of have a complete line */
        }
        else
        *lbufPC++ = c;                  /* Place char into line buffer */
    }

    /* At this point, the input file has been emptied.  Now dispose of the
    ** output data according to compilation mode.
    */

#ifdef BINARY

    /* Write the buffer back to disk as a binary image */
    resN = fwrite( bufAC, 1, (size_t)((highestPC - bufAC) + 1), outfilePH );
    if( resN != (int)( (highestPC - bufAC) + 1) )
    {
        printf("%s: Error writing output file\n", argv[0] );
        exit( 6 );
    }

#else
    /* Produce a file that can be included in a C program.  Data is read
    ** from buffer as bytes to avoid portability/endian problems with
    ** this program.
    */
    /* Output header first, then 1 long per line */
    fwrite( (void *)headerAC, 1, (size_t)(sizeof( headerAC )-1), outfilePH );

    codePL = (unsigned long *)bufAC;
    for( i = (highestPC - bufAC + 1) / 4; i; i-- )      /* for each long */
    {
        codePC = (unsigned char *)codePL++;
        sprintf(lbufAC, "0x%02x%02x%02x%02x%s",
            *codePC, *(codePC + 1), *(codePC + 2), *(codePC + 3),
            i == 1 ? "\n" : ",\n" );            /* No comma after final long */
        fwrite( lbufAC, 1, (size_t)(strlen( lbufAC )), outfilePH );
    }
    /* OK, data has been written out, close end of array */
    fwrite( "};\n", 1, (size_t)3, outfilePH );
#endif
}                                             

/* Function: parsebufV
**      Parses an S-record in the buffer and writes it into the buffer
**      if it is has a valid checksum.
**
** Args:        pointer to character buffer for null terminated line
** Returns:     int result code: 0 = success, else failure
*/
int parsebufN(  char *lbufPC )
{
    unsigned long addrL;
    unsigned char cksmB,        /* checksum of addr, count, & data length */
        *bufPC;                 /* Pointer into memory array */
    int i, countN,              /* Number of bytes represented in record */
        oheadN,                 /* Number of overhead (addr + chksum) bytes */
        tvalN;                  /* Temp for check checksum */

    switch( *(lbufPC+1) )       /* examine 2nd character on the line */
    {
    case '1':                   /* 16 bit address field */
        if( sscanf(lbufPC, "S1%2x%4lx", &countN, &addrL ) != 2 )
            return( 10 );       /* Flag error in S1 record */
        oheadN = 3;             /* 2 address + 1 checksum */
        break;

    case '2':                   /* 24 bit address field */
        if( sscanf(lbufPC, "S2%2x%6lx", &countN, &addrL ) != 2 )
            return( 11 );       /* Flag error in S2 record */
        oheadN = 4;             /* 3 address + 1 checksum */
        break;

    case '3':                   /* 32 bit address field */
        if( sscanf(lbufPC, "S3%2x%8lx", &countN, &addrL ) != 2 )
            return( 12 );       /* Flag error in S3 record */
        oheadN = 5;             /* 4 address + 1 checksum */
        break;

    default:                    /* ignore all but S1,2,3 records. */
        return( 0 );
    }

    if( addrL > BUFSIZE ) return( 13 ); /* if address exceeds buffer size */
    bufPC = bufAC + addrL;      /* otherwise, point to right spot in buffer */

    /* OK now see if checksum is OK, while reading data to buffer */
    cksmB = 0;
    countN++;                   /* Bump counter to read final checksum too */
    for( i = 1; i <= countN; i++ )
    {
        sscanf( lbufPC + i*2, "%2x", &tvalN );  /* Scan a 2 hex digit byte  */
        cksmB += (unsigned char)tvalN;
        if( ( i > oheadN ) && ( i < countN ) )  /* If scanned a data byte */
            *bufPC++ = (unsigned char) tvalN;   /* write it to the buffer */
    }
    if( cksmB += 1 ) return( 14 );      /* flag checksum error */

    if( (bufPC - 1) > highestPC )
        highestPC = bufPC - 1;          /* track highest address loaded */

    return( 0 );                        /* Successful return */
}
Zgłoś jeśli naruszono regulamin