
/* Filter to convert Terak hex files to disk files */
/* Copyright 1990 by John Foust */
/* July 12, 1990 */

#include <stdio.h>
#include <string.h>

#include "teradecl.h"
#define PRIMARY
#include "teravars.h"


/* */

char hexLine[ 1500 ];


/* */

unsigned char lineBytes[ 520 ];


/* */

unsigned char blockData[ 520 ];


/* Given a string, remove a given char at the end of it */

void zap_char( char *buffer )
{
int len;


    len = strlen( buffer );
    if (len > 0) {

        len --;
        if (buffer[ len ] == 10 || buffer[ len ] == 13) {
            buffer[ len ] = 0;
        }

        if (len > 0) {
            len --;
            if (buffer[ len ] == 10 || buffer[ len ] == 13) {
                buffer[ len ] = 0;
            }
        }
    }
}


/* Given a character 0..9, A..F; return 0..16 */

unsigned char inhex( short ch )
{
    if (ch >= (short) 'A') {
        return (unsigned char) (ch - 55);
    }
    else {
        return (unsigned char) (ch - 48);
    }
}


int main( int argc, char **argv )
{
char *ptr;
unsigned char *out;
unsigned char *blkPtr;
short blk;
short each;
short incheck;
short mycheck;
int linecount;
short maxblk;

char inname[128];
char outname[128];
FILE *infp;
FILE *outfp;


    infp = NULL;
    outfp = NULL;

    if (argc == 2) {
        strcpy( inname, argv[1] );
    }
    else {
        puts("Converts Terak hex files to disk files");
        puts("Usage: cv filename.hex");
        goto out;
    }

    /* Open input file from command line */
    printf( "Input file '%s'\n", inname );
    infp = fopen( inname, "r" );
    if (infp == NULL) {
        puts("Couldn't open file.");
        goto out;
    }

    /* Get 'F filename' or 'V volumename' */
    fgets( hexLine, 1400, infp );
    zap_char( hexLine );

    outname[0] = 0;
    strcpy( outname, &hexLine[2] );
    if (outname[0] == 0) {
        strcpy( outname, "unk" );
    }

    /* Does this file describe a volume or a file? */
    if (hexLine[0] == 'V') {
        puts("Volume");
        strcat( outname, ".vol" );
    }
    else if (hexLine[0] == 'F') {
        puts("File");
    }

    /* Open output file using the file name or volume name in the first line of file */
    outfp = fopen( outname, "wb" );
    printf( "Output file '%s'\n", outname );
    if (outfp == NULL) {
        puts("Couldn't open file.");
        goto out;
    }

    maxblk = 0;
    linecount = 0;

    /* While can get lines */
    while (fgets( hexLine, sizeof(hexLine), infp ) != NULL) {

        linecount ++;

        /* Check for special error messages */
        if (hexLine[0] == 'E' && hexLine[1] == 'R' && hexLine[2] == 'R') {
            puts(hexLine);
            continue;
        }

        /* Can show block numbers while we convert if necessary */
#ifdef SHOWHEX
{
char foo[5];

        foo[0] = hexLine[0];
        foo[1] = hexLine[1];
        foo[2] = hexLine[2];
        foo[3] = hexLine[3];
        foo[4] = 0;
        puts(foo);
}
#endif

        /* Convert each pair of hex chars to a single byte value */
        ptr = hexLine;
        out = lineBytes;
        for (each=0; each<(512+2+1)*2; each++) {
            *out = (unsigned char) (16 * inhex( *ptr++ ));
            *out += inhex( *ptr++ );
            out ++;
        }

        /* Block number, two bytes, from 0000 to 04AB */
        blk = lineBytes[0] * 256 + lineBytes[1];
        maxblk = blk;

        /* Checksum: one byte at end */
        incheck = lineBytes[ 512+2 ];

        /* Calc the checksum of what we have here */
        mycheck = 0;
        blkPtr = &lineBytes[2];
        for (each=0; each<512; each++) {
            mycheck += *blkPtr ++;
            mycheck = (mycheck % 255);
        }

        if (incheck != mycheck) {
            printf( "Checksum error block %hd, file had %02hx, we got %02hx\n", blk, incheck, mycheck );
        }

        /* Write the data block to the output file */
        fwrite( &lineBytes[2], (size_t) 512, (size_t) 1, outfp );
    }

    puts("Done.");

    if (linecount != (maxblk+1)) {
        printf( "Lines %d, max block %hd\n", linecount, maxblk );
    }

out:
    if (infp != NULL) {
        fclose( infp );
    }
    if (outfp != NULL) {
        fclose( outfp );
    }

    return 0;
}


