/*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 ) ; 
 
} 
