/*SCCS header - %W% %G% */ /************************************************************************ * * * File : x2x_2.c * * Version: 0.0 * * Author : Gary Duncan * * 24 Inkster St * * Kambah ACT 2902 * * Australia * * * *-----------------------------------------------------------------------* * * Modification record * ------------------- * * Date By whom Change * ---- ------- ------ * * 12 Apr 89 GMD AMIGA'd * 01 Jul 89 " Changed K64 to K64K * *------------------------------------------------------------------------ * *------------------------------------------------------------------------------ * Contents * ------- *+ *+ rite_rec writes DLL record to disc *+ get_rtype validates input file as INTEL/MOTOROLA/TEK.. *+ f_reset resets file pointer to start *+ dll_Irec builds an INTEL record *+ dll_Mrec builds a MOTOROLA record *+ dll_Trec builds a TEKTRONIX record *+ dll_Txrec builds a TEKTRONIX-extended record *+ dll_Qrec builds a QTAM record *+ sum_get gets a checksum on a string *+ xgetc gets a DLL byte *+ xputc puts a DLL addr/byte pair in buffer *+ fill_ipbuf replenish i/p buffer *+ get_len determine # of contiguous bytes in record *+ * ******************************************************************************/ #include "x2x_amiga.h" #include "x2x_data.c" /*************************************************************************** Function : rite_rec Purpose : Puts DLL record into buffer and writes to disc when full , or when forced Entry : Returns : ****************************************************************************/ int rite_rec ( fptr , fmadr , len ) int fptr ; char *fmadr ; int len ; { while ( len-- ) { dlldbuf [odccon++] = *fmadr++ ; /* copy to buffer */ if ( odccon == OPBUFLEN ) /* if full write */ { if ( write( fptr , dlldbuf , OPBUFLEN) != OPBUFLEN ) { fprintf (stderr,"(rite_rec) - write error" ); perror("Disc write error: "); exit(3); } odccon = 0 ; } } } /*************************************************************************** Function : get_rtype Purpose : Determines type of DLL file Entry : Returns : with file type ****************************************************************************/ int get_rtype ( ) { int ch ; int retval = 1 ; ch = Ichar () ; /* 1st chara assumed to define file type !*/ switch ( ch ) { case ':' : /* INTEL */ break ; case 'S' : /* MOTOROLA */ ch = Ichar() -'0' ; /* get type 1,2,3 */ switch (ch) { case 3 : ++retval ; case 2 : ++retval ; case 1 : ++retval ; xiMaddr = retval + 1 ; break ; default : retval = 0 ; } break ; case '/' : /* TEKTRONIX */ retval = 5 ; break ; case '%' : /* TEKTRONIX - extended */ retval = 6 ; break ; case 'Q' : /* QTAM */ retval = 7 ; break ; default : retval = 0 ; break ; /* ????????? */ } f_reset () ; /* reset file ptrs */ return ( retval -1 ) ; } /*************************************************************************** Function : f_reset Purpose : resets pointers to DLL file- ensures read starts at beginning Entry : Returns : TRUE - FALSE- ****************************************************************************/ int f_reset () { boffs = 0 ; disclen = 0 ; if ( lseek ( iffp , 0L , L_SET ) == -1 ) /* reset file ptr */ { fprintf (stderr, "lseek fail\n" ) ; exit(1) ; } } /*************************************************************************** Function : dll_Irec Purpose : builds an INTEL DLL record Entry : Returns : # of charas in record ****************************************************************************/ int dll_Irec ( tipe , addr , len ) int tipe , len ; long addr ; { int count , j ; uchar ch ; int t2data ; t2data = addr << 12 ; /* convert to seg offset */ if ( tipe == 2 ) addr = 0 ; /*----------- calc checksum --------------------------------*/ Icsum = 0 ; Icsum += sum_get ( 'I' , &addr , 2 ) ; /* addr */ Icsum += sum_get ( 'I' , &tipe , 1 ) ; /* type */ Icsum += sum_get ( 'I' , &len , 1 ) ; /* len */ /* -----------now build buffer ------------------------*/ opbuf [0] = ':' ; chcon = convc2 ( len ) ; opbuf [IRLEN] = chcon >> 8 ; opbuf [IRLEN+1] = chcon & 0xFF ; chcon = convc2 ( tipe ) ; /* rec type - data= 0 */ opbuf [IRTYPE] = chcon >> 8 ; opbuf [IRTYPE+1] = chcon & 0xFF ; chcon = convc2 ( (int)(addr >> 8) ) ; /* load addr - hi */ opbuf [IRADDR] = chcon >> 8 ; opbuf [IRADDR+1] = chcon & 0xFF ; chcon = convc2 ( (int)addr ) ; /* load addr - lo */ opbuf [IRADDR+2] = chcon >> 8 ; opbuf [IRADDR+3] = chcon & 0xFF ; for ( count = 0 , j = 0; count < len ; ++ count, j += 2 ) /* now the data */ { if ( tipe == 2 ) /* fudge for USBA record */ { ch = t2data >> 8 ; t2data <<= 8 ; } else ch = xgetc ( ) ; /* get data chara */ Icsum += sum_get ( 'I' , &ch , 1 ) ; /* accum c/sum */ chcon = convc2 ( ch ) ; opbuf [IRDATA + j ] = chcon >> 8 ; opbuf [IRDATA+1 + j ] = chcon & 0xFF ; } Icsum = - Icsum ; chcon = convc2 ( Icsum ) ; /* checksum */ opbuf [IRDATA + j ] = chcon >> 8 ; opbuf [IRDATA + 1 +j ] = chcon & 0xFF ; return ( IRDATA + 2 + j ) ; /* return length */ } /*************************************************************************** Function : dll_Mrec Purpose : builds a MOTOROLA 68000 DLL record Entry : Returns : TRUE - FALSE- ****************************************************************************/ int dll_Mrec ( tipe , addr , len ) int tipe , len ; long addr ; { int count , j ; uchar ch ; static int size ; int offs ; /*------------- abort if S1 and addr > K64K ----------------------------*/ if ( (xoMaddr == 2) && ( (addr+len) > K64K ) ) { fprintf ( stderr , "\007\nAbort: address overflow! ( %ld )\n" ,addr+len ); exit (1) ; } offs = 2 * ( xoMaddr - 2) ; /* addr offset start */ size = len + 1 + offs/2 + 2 ; /*----------- calc checksum --------------------------------*/ Icsum = 0 ; Icsum += sum_get ( 'I' , &addr , 4 ) ; /* addr */ Icsum += sum_get ( 'I' , &size , 1 ) ; /* len */ /* -----------now build buffer ------------------------*/ opbuf [0] = 'S' ; opbuf [1] = tipe ; chcon = convc2 ( size ) ; opbuf [MRLEN] = chcon >> 8 ; opbuf [MRLEN+1] = chcon & 0xFF ; /*----------------- now the variable address length ------------------*/ for ( count=0 , j = 2*xoMaddr-2 ; count < (xoMaddr) ; ++count , j -= 2 ) { ch = addr ; addr >>= 8 ; chcon = convc2 ( ch ) ; /* byte -> 2 ASCII hex */ opbuf [MRADDR+ j + 0] = chcon >> 8 ; opbuf [MRADDR+ j + 1] = chcon & 0xFF ; } /*---------------------- now the data ----------------------------------*/ for ( count = 0 , j = 0; count < len ; ++ count, j += 2 ) /* now the data */ { ch = xgetc ( ) ; Icsum += sum_get ( 'I' , &ch , 1 ) ; /* accum c/sum */ chcon = convc2 ( ch ) ; opbuf [MRDATA + offs + j ] = chcon >> 8 ; opbuf [MRDATA+1 + offs +j ] = chcon & 0xFF ; } Icsum = ~Icsum ; /* 1s complement */ chcon = convc2 ( Icsum ) ; /* checksum */ opbuf [MRDATA + offs + j ] = chcon >> 8 ; opbuf [MRDATA + offs + 1 +j ] = chcon & 0xFF ; return ( MRDATA + offs + 2 + j ) ; /* return length */ } /*************************************************************************** Function : dll_Trec Purpose : builds a TEKTRONIX DLL record Entry : Returns : TRUE - FALSE- ****************************************************************************/ int dll_Trec ( tipe , addr , len ) int tipe , len ; long addr ; { int count , j ; uchar ch ; /*------------- abort if addr > K64K ----------------------------*/ if ( (addr+len) > K64K ) { fprintf ( stderr , "\007\nAbort: address overflow! ( %ld )\n" ,addr+len ); exit (1) ; } /*----------- calc load checksum --------------------------------*/ Tcsum = 0 ; Tcsum += sum_get ( 'T' , &addr , 2 ) ; /* addr */ Tcsum += sum_get ( 'T' , &len , 1 ) ; /* len */ chcon = convc2 ( Tcsum ) ; /* put checksum in record */ opbuf [ TRSUM ] = chcon >> 8 ; opbuf [ TRSUM + 1 ] = chcon & 0xFF ; /* -----------now build buffer ------------------------*/ opbuf [0] = '/' ; chcon = convc2 ( len ) ; opbuf [TRLEN] = chcon >> 8 ; opbuf [TRLEN+1] = chcon & 0xFF ; chcon = convc2 ( (int)(addr >> 8) ) ; /* load addr - hi */ opbuf [TRADDR] = chcon >> 8 ; opbuf [TRADDR+1] = chcon & 0xFF ; chcon = convc2 ( (int) addr ) ; /* load addr - lo */ opbuf [TRADDR+2] = chcon >> 8 ; opbuf [TRADDR+3] = chcon & 0xFF ; /* -----------now build buffer ------------------------*/ Tcsum = 0 ; for ( count = 0 , j = 0; count < len ; ++ count, j += 2 ) /* now the data */ { ch = xgetc ( ) ; Tcsum += sum_get ( 'T' , &ch , 1 ) ; /* accum c/sum */ chcon = convc2 ( ch ) ; opbuf [TRDATA + j ] = chcon >> 8 ; opbuf [TRDATA+1 + j ] = chcon & 0xFF ; } if ( len ) /* last record , skip (small fudge)*/ { chcon = convc2 ( Tcsum ) ; /* checksum */ opbuf [TRDATA + j ] = chcon >> 8 ; opbuf [TRDATA + 1 +j ] = chcon & 0xFF ; } else j -= 2 ; return ( TRDATA + 2 + j ) ; /* return length */ } /*************************************************************************** Function : dll_Txrec Purpose : builds a TEKTRONIX - extended DLL record Entry : Returns : TRUE - FALSE- ****************************************************************************/ int dll_Txrec ( tipe , addr , len ) int tipe , len ; long addr ; { int count , j , k; uchar ch ; int nochars = 2*len +14 ; /* chara count in record */ opbuf [0] = '%' ; /* record header chara */ opbuf [ nochars + 2 ] = 0 ; /*----------- record length (#of charas) -------------------------------*/ /* ( make addr field max of 8 charas ( 32 bit address ) */ chcon = convc2 ( nochars ) ; /* put checksum in record */ opbuf [ TRXLEN + 0 ] = chcon >> 8 ; opbuf [ TRXLEN + 1 ] = chcon & 0xFF ; /*-------------- now the record type ------------------------------------*/ opbuf [ TRXTYPE ] = tipe ; /*--------------- now a fake csum ---------------------------------------*/ opbuf [ TRXSUM ] = '0' ; opbuf [ TRXSUM +1 ] = '0' ; /*-------------- now the addr length ( 8 for now ) ----------------------*/ opbuf [ TRXADDR ] = '8' ; /* # of charas */ count = addr >> 24 ; /* top 8 bits */ chcon = convc2 ( count ) ; opbuf [TRXADDR + 1 ] = chcon >> 8 ; opbuf [TRXADDR + 2 ] = chcon & 0xFF ; count = addr >> 16 ; /* next 8 bits */ chcon = convc2 ( count ) ; opbuf [TRXADDR + 3 ] = chcon >> 8 ; opbuf [TRXADDR + 4 ] = chcon & 0xFF ; count = addr >> 8 ; /* next 8 bits */ chcon = convc2 ( count ) ; opbuf [TRXADDR + 5 ] = chcon >> 8 ; opbuf [TRXADDR + 6 ] = chcon & 0xFF ; count = addr ; /* low 8 bits */ chcon = convc2 ( count ) ; opbuf [TRXADDR + 7 ] = chcon >> 8 ; opbuf [TRXADDR + 8 ] = chcon & 0xFF ; /*-------------- now put data in buffer -----------------------------*/ for ( count = 0 , j = 0; count < len ; ++ count, j += 2 ) /* now the data */ { ch = xgetc ( ) ; chcon = convc2 ( ch ) ; opbuf [TRXDATA + j ] = chcon >> 8 ; opbuf [TRXDATA+1 + j ] = chcon & 0xFF ; } /*----------------- now build and store checksum -----------------------*/ for ( count = 0 , k = 0 ; count < nochars ; ++count ) { if ( (j = get_hex (opbuf [count + 1])) == -1) { fprintf ( stderr , "dll_TXrec bad hex chara\n" ) ; fprintf ( stderr , opbuf ) ; exit ( 1 ) ; } k += j ; /* accum checksum */ } chcon = convc2 ( k ) ; /* put in buffer */ opbuf [TRXSUM ] = chcon >> 8 ; opbuf [TRXSUM + 1 ] = chcon & 0xFF ; return ( nochars + 1 ) ; /* return length */ } /*************************************************************************** Function : dll_Qrec Purpose : gen a QTAM record Entry : Returns : TRUE - FALSE- ****************************************************************************/ int dll_Qrec ( tipe , addr , len ) int tipe , len ; long addr ; { int count , j ; uchar ch ; /* -----------now build buffer ------------------------*/ opbuf [0] = 'Q' ; opbuf [1] = len ; opbuf [2] = addr >> 16 ; opbuf [3] = addr >> 8 ; opbuf [4] = addr ; for ( count = 0 ; count < len ; ++ count) /* put data in buffer */ { ch = xgetc ( ) ; opbuf [ 5 + count ] = ch ; } for ( count = 0 , j = 0 ; count < (len + 4) ; ++ count ) /* calc c/sum */ j += opbuf [ 1 + count] ; opbuf [ 1 + count ] = - j ; /* put c/sum in buffer */ return ( len + 6 ) ; /* return length */ } /*************************************************************************** Function : sum_get Purpose : Accumulates a checksum on a string Entry : "I" / "T" ptr to char string length Returns : uchar : checksum ****************************************************************************/ int sum_get ( type , ptr , len ) char *ptr ; int type , len ; { int csum ; int count ; switch ( type ) { case 'I' : for ( count = 0 , csum = 0 ; count < len ; ++count , ++ptr ) csum += *ptr & 0xFF ; break ; case 'T' : for ( count = 0 , csum = 0 ; count < len ; ++count , ++ptr) csum += (*ptr & 0xF) + ((*ptr >> 4) & 0xF ) ; break ; } return ( csum & 0xFF ) ; } /*************************************************************************** Function : xgetc Purpose : gets next chara from input buffer Entry : Returns : chara , or -1 ( empty ) *ptr = addr ***************************************************************************/ int xgetc ( ) { int ch , temp ; char *ptr = mallocptr ; if ( !xccnt ) return -1 ; /* empty */ ch = xipbuf [xnrp].bite ; /* get chara */ /* if mode 3 ( checksum gen ) , put byte in array */ if ( xmode == 3 ) { if ( (temp = xipbuf[xnrp].addr) > 0xFFFF ) { fprintf ( stderr , "(xgetc) : addr > K64K !\n" ) ; exit (1) ; } ptr += temp ; *ptr = ch ; /* plant byte in array */ } --xccnt ; if ( ++xnrp == IPLEN ) xnrp = 0 ; return ( ch & 0xFF ) ; } /*************************************************************************** Function : xputc Purpose : loads an addr/ data chara pair from DLL record to xipbuf Entry : Returns : TRUE - buffer not full FALSE- buffer full ***************************************************************************/ int xputc ( addr , bite ) long addr ; uchar bite ; { if ( csum > 255 ) csum = (++csum) & 0xFF ; /* wrap prev carry */ csum += bite ; /* accum checksum */ xipbuf [xnwp].addr = addr ; xipbuf [xnwp++].bite = bite ; if ( xnwp == IPLEN ) xnwp = 0 ; if ( ++xccnt == IPLEN ) /* full check */ return ( FALSE ) ; else return ( TRUE ) ; } /*************************************************************************** Function : fill_ipbuf Purpose : fills up xipbuf with addr/data pairs made from DLL file records Entry : Returns : TRUE - ip file not empty FALSE- ip fill now empty ***************************************************************************/ int fill_ipbuf () { while ( (xccnt < (IPLEN-300)) && xeof ) /* read DLL records until EOF or enough for o/p */ { switch ( ipftype ) { case 0 : xeof = get_Irec () ; /* get INTEL record -- deASCIIed */ break ; case 1 : /* MOTOROLA */ case 2 : case 3 : xeof = get_Mrec() ; break ; case 4 : /* TEKTRONIX */ xeof = get_Trec () ; break ; case 5 : /* TEKTRONIX - extended */ xeof = get_trec () ; break ; case 6 : /* QTAM */ xeof = get_Qrec () ; break ; } ; } } /*************************************************************************** Function : get_len Purpose : scans i/p data buffer to see how many contiguous bytes there are ( up to reclen ) - does not allow overflow past K64K boundary if dest. file is INTEL ( to allow type 2 tec gen. ) Entry : Returns : # of bytes *ptr = addr field of start byte ***************************************************************************/ int get_len ( aptr ) long *aptr ; { int count = 0 ; long addr ; int ptr ; ptr = xnrp ; /* scan from read ptr */ addr = xipbuf [ptr].addr ; *aptr = addr ; /* hold start addr for external use */ ousban= addr >> 16 ; /* for INTEL , hold K64 seg # */ if ( !xccnt ) /* check odd conditions */ { *aptr = 0 ; return ( xccnt ) ; } else if ( xccnt == 1 ) return ( xccnt ) ; while ( count++ != xccnt ) /* read up to what's in buffer */ { if ( ptr == IPLEN ) ptr = 0 ; /* wrap buffer ptr */ if ( xipbuf [++ptr].addr != ++addr ) /* contiguous ? */ break ; if ( count == reclen ) /* ( up to selected data length ) */ break ; if ( !opftype ) { if (ousban != (addr >> 16) ) /* if INTEL check for K64 overflow */ break ; } } return ( count ) ; }