/*SCCS header -          %W%   %G%                                     */
/************************************************************************ 
*                                                                       * 
*                      Filename:        x2x_3.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
* 
*------------------------------------------------------------------------ 
 
 
* 
*------------------------------------------------------------------------------ 
* Contents 
* ------- 
*+ 
*+              dos_fname       gens output file name if under DOS 
*+              func1           exitsif Func 1 key hit ( DOS only ) 
*+              get_rstart      looks for DLL record start 
*+              sol_params      solicits for input params 
*+              com_params      processes command line parameters              
*+              open_ifile      opens input file 
*+              open_ofile      opens output file  
*+              gen_csum        builds and writes checksum record 
*+              date            reformats SCCS vers / date  
*+              usage           error message - 
*+  
* 
******************************************************************************/ 
 
#include "x2x_amiga.h"
#include "x2x_data.c"

 
/*************************************************************************** 
 
 
  Function :            dos_fname     
 
 
  Purpose  :           cater for limited file name length etc in MS_DOS 
                       ( PC application ) 
 
  Entry    : 
 
 
  Returns  :     TRUE -  
 
                 FALSE-  
 
***************************************************************************/ 
 
 
 
int dos_fname () 
 
 
 
{ 
#ifdef AMIGA 
 
 
int j = 0 ; 
int k = 0 ; 
uchar ch ; 
 
while ( ch = ofile[j]) 
  { 
     if ( ch == '.' ) 
        break ; 
 
     ++j ; 
  } 
 
 ofile [j] = '\0' ; 
 strcat ( ofile , sfx[opftype] ) ;   /* append suffix */ 
 
 if ( strcmp ( ofile , ifile ) )      /* ensure difference */ 
     return ;                       /* some , exit */ 
 
 /*-- in file name ...XYZ.EXT , start replacing from X <- with & until 
  *      uniqueness , or exhaustion 
  */ 
 
 while ( --j ) 
     { 
        ofile [j] = '&' ;     /* god , this is tedious.... */        
 
        if ( strcmp ( ofile , ifile ) )      /* ensure difference */ 
          return ;                       /* some , exit */ 
 
     } 
 
  fprintf ( stderr , "Too many &s in input file name !\n" ) ; 
  exit( 1 ) ; 
 
 
#endif  
} 

#if 0
 
/*************************************************************************** 
 
 
  Function :      func1 
 
  Purpose  :      looks for Func1 from  keyboard 
 
  Entry    : 
 
  Returns  :     TRUE -  found it 
 
                 FALSE- 
 
 
 
****************************************************************************/ 
 
 
int  func1 () 
 
 
 
{ 
#ifdef AMIGA 
 
uchar ch ; 
 
   if ( scr_poll () != -1 ) 
     { 
      ch = scr_getc () ; 
       
      if ( ch == (0x3B | 0x80 ) ) 
         return ( TRUE ) ;           /* found it */ 
     } 
 
#endif 
 
   return (FALSE ) ; 
} 
#endif
 
/*************************************************************************** 
 
 
  Function :       get_rstart     
 
 
  Purpose  :       search for DLL record start given header char 
 
  Entry    :       header chara ( : / % S Q ) 
 
 
  Returns  :      if found , exits from program otherwise 
 
                 
 
***************************************************************************/ 
 
 
int get_rstart ( ich ) 
 
uchar ich ; 
 
{ 
 int j = 0 ; 
 int cch = 0 ; 
 
      while ( ich != cch )               /* search for record start  */ 
	{ 
          if (  ( cch=Ichar() ) == -1 )  /* get chara from input file */ 
            { 
                fprintf ( stderr , "Unexpected EOF on input file" ) ; 
                exit (1) ; 
	    } 
           if ( j++ > 100 )   /* nominal length of  search */ 
            { 
                fprintf ( stderr ,  
            "Can't find a record header chara ( %c ) in 100 chara search!\n" , 
                   ich  ) ; 
                exit (1) ; 
	    } 
 
	} 
} 
 
/*************************************************************************** 
 
 
  Function :       sol_params 
 
 
  Purpose  :       solicits user for parameters 
 
  Entry    :        
 
 
  Returns  :       
 
                 
 
***************************************************************************/ 
 
 
 
int  sol_params ()  
 
 
{ 
int  kk ; 
 
 
 /*------------------ get input DLL file ---------------------------*/ 
 
   printf("Input file name ? " ); 
   gets ( ifile ) ; 
 
   open_ifile ( ifile )  ;            /* open file - determine type */ 
 
 /*------------------ get output DLL file type ---------------------------*/ 
 
 kk = 0 ; 
 while ( !kk ) 
   { 
     printf ( 
       "\nOutput file type ( I, M1, M2, M3, T, Tx  ) ?  " )  ; 
     gets ( kbuf ) ; 
      
     switch ( kk = kbuf[0] )           /* announce input file type */ 
       { 
        case 'i' :                 /* INTEL */ 
        case 'I' :                 /* INTEL */ 
                 opftype = 0 ; 
                 break ; 
        case 'm' :                 /* MOTOROLAs */ 
        case 'M' :                 /* MOTOROLAs */ 
                 opftype = 0 ; 
                 switch ( kbuf[1] - '0' ) 
		  { 
		  case 3 :  ++opftype ; 
                  case 2 :  ++opftype ; 
                  case 1 :  ++opftype ; 
                     xoMaddr = opftype +1 ;  /* addr len */  
                     break ; 
		  default : 
                      kk = 0 ;              /* force error */                  
		  } 
                 break ; 
 
	case 't' : 
        case 'T' :                 /* TEKTRONIX */ 
                  
                 ( kbuf[1] == 'x' ) ? (opftype = 5) : (opftype = 4 ) ; 
 
                 break ; 
 
        default : 
                     kk = 0 ;      /* error - loop */ 
 
        }  
   } 
 
 /*----------------- create o/p file -------------------------*/ 
 
  open_ofile ( ifile ) ; 
 
/*------------ now solicit record data length --------------------------*/ 
 
 while (1) 
   {   
      reclen = 0 ; 
      printf (   
       "\nRecord data length ( Max = 255 , default = 16 bytes) ?  " ) ; 
      gets ( opbuf ) ; 
      if ( !strlen (opbuf) )      /* RET means default  */ 
	  { 
             reclen = 16 ; 
             break ; 
	  } 
      kk = sscanf ( opbuf , "%d" , &reclen  ) ; 
       
      if ( (reclen > 0)  && (reclen < 256 ) ) 
        break ; 
    } 
 
   /*----- adjust reclen if MOTOROLA and overflow ---------------------------*/ 
 
   if ( (xoMaddr + reclen) > 255 )    /* 1 byte length only ! */ 
     { 
       reclen = 255 - xoMaddr ;      /* adjust */ 
       fprintf ( stderr , 
        "Rec length overflow , data length adjusted to %d \n" , reclen ) ; 
     } 
 
} 
 
/*************************************************************************** 
 
 
  Function :       open_ifile 
 
 
  Purpose  :       opens input file , announces type 
 
  Entry    :        
 
 
  Returns  :      file ptr 
 
                 
 
***************************************************************************/ 
 
int open_ifile ( ptr ) 
 
char *ptr ; 
 
 
{ 
 
   if(( iffp = open( ptr , O_RDONLY)) < 0)    /* source file */ 
    { 
        fprintf(stderr,"Error: unable to open '%s'\n",  ifile); 
        exit(1); 
    } 
 
 /*---------------- validate file type -------------------------------*/ 
 
 ipftype = get_rtype (  ) ;    /* get DLL file type */ 
 
 switch ( ipftype )           /* announce input file type */ 
   { 
   case 0 :                 /* INTEL */ 
   case 1 :                 /* MOTOROLAs  */ 
   case 2 : 
   case 3 : 
   case 4 :                 /* TEKTRONIX */ 
   case 5 :                 /* TEKTRONIX - extended  */ 
       break ; 
 
   default : 
              fprintf ( stderr , "Unknown input file type\n" ); 
              exit (1) ; 
   }  
 
  printf (  "\nInput file type is :  %s" , iipftype[ ipftype ] ) ; 
 
 } 
 
/*************************************************************************** 
 
 
  Function :           com_params        
 
 
  Purpose  :           scans command line for invocation parameters 
                       - does things with them 
 
  Entry    :        
 
 
  Returns  :           mode type ( 2 or 3 )       
 
                 
 
***************************************************************************/ 
 
int com_params ( count , ptr ) 
int count ; 
char **ptr ; 
 
 
{ 
char *argptr ; 
char *iptr ; 
int ch ; 
int mode = 2 ; 
 
while ( --count )                   /* scan the input params , if any */ 
  { 
   argptr = *++ptr ; 
   if ( *argptr++ == '-' ) 
     { 
      switch ( *argptr++ )           /* look for the param */ 
       { 
       case 'I' : 
       case 'i' :                  /*  Input file name */ 
 
            open_ifile ( iptr = argptr ) ;   /* open it */ 
            break ; 
 
       case 'D' :                  /* dots ?? */ 
       case 'd' :     
 
            pdots = 1;             /* no */ 
            break ; 
 
       case 'O' : 
       case 'o' :                 /* Output file type */ 
       
           switch ( *argptr++ ) 
	     { 
             case 'i' : 
	     case 'I' :           /* INTEL  */ 
                opftype = 0 ;               
                break ; 
 
	     case 'm' : 
	     case 'M' :           /* MOTOROLA */ 
                ch = *argptr - '0' ; 
                opftype = 0 ; 
                switch (ch) 
                  { 
		  case 3 :   ++opftype ; 
		  case 2 :   ++opftype ; 
		  case 1 :   ++opftype ; 
                       xoMaddr = opftype + 1; 
                       break ; 
	          default : 
                       usage () ; 
                       exit (1) ; 
 
		  } 
                break ; 
                 
	     case 'T' :           /* TEKTRONIX  */ 
                opftype = 4 ;               
                break ; 
 
	     case 't' :           /* TEKTRONIX - extended  */ 
                opftype = 5 ;               
                break ; 
               
             } 
           break ; 
 
       case 'S' : 
       case 's' :                 /*  record length */ 
         reclen = atoi ( argptr ) ;     
         if ( !reclen || (reclen > 255) ) 
	   { 
              usage () ; 
              exit (1) ; 
	   } 
         break ;  
 
       case 'C' :             /* Checksum generation */ 
       case 'c' : 
 
         opftype = 0 ;        /* set o/p file type = INTEL */ 
         if ( xmode == 3 )        
                  /* ensure INTEL file if mode 3 ( checksum gen ) */ 
           { 
             if ( ipftype != 0 ) 
               { 
                 fprintf ( stderr , "File must be INTEL format!\n" ) ; 
                 exit (1) ; 
	       } 
           } 
         if ( !(mallocptr = malloc ( (long)(64*1024) ))  )    /* get a K64 byte array */ 
            { 
              fprintf ( stderr , "Malloc fail!\n" ) ; 
              exit (1) ; 
            } 
         for ( aa=0 ; aa < 64*1024L ; ++aa )    /* init with FFs */ 
            { 
              *(mallocptr+aa) = 0xFF ; 
            } 
         mode = 3 ;                /* set mode type */ 
         break ; 
	   
      case 'R' :                    /* checksum mode - optional ROM size */ 
      case 'r' : 
         romsize = atoi ( argptr ) ; 
         switch ( romsize )    /* yes , validate ROM size */ 
	  { 
           case 2 : 
	   case 4 : 
 	   case 8 : 
	   case 16 : 
	   case 32: 
	   case 64: 
              break ;               /* valid sizes s*/ 
	  default : 
              fprintf ( stderr , "Invalid ROM size !\n" ) ; 
              exit (1) ; 
	  } 
        break ; 
 
      case 'P' :                    
      case 'p' : 
                                 /* checksum mode - dump printable charas 
                                    to "temp.x2x" ; used for getting EMU 
                                    screen dumps in manual preparation */ 
        xpflag = TRUE ; 
        if(( tffp= open( "temp.x2x" ,  
                  O_RDWR | O_CREAT | O_TRUNC , 0666)) < 0 )     
           { 
             fprintf(stderr,"Error: unable to open temp.x2x\n" ); 
             exit(1); 
           } 
        break ; 
 
      default :               /* Invalid para */ 
          { 
           usage () ; 
           exit (1) ; 
          }   
    } 
    } 
  else                    /* no "-" sign , error */ 
   { 
     usage (); 
     exit (1) ; 
   } 
 } 
 
 
 /*--------  verify params ---------------------*/ 
 
 if ( (!iffp) || (opftype == -1 ) )   /* ensure enough params */ 
   { 
     usage () ; 
     exit (1) ; 
   } 
 open_ofile ( iptr ) ;              /* open output file */ 
 
 if ( mode == 3 )       /* checksum mode ? */ 
    { 
      return ( mode ) ; 
    } 
 
   /*----- adjust reclen if MOTOROLA and overflow ---------------------------*/ 
 
   if ( (xoMaddr + reclen) > 255 )    /* 1 byte length only ! */ 
       reclen = 255 - xoMaddr ;      /* adjust */ 
 
 
  return ( mode ) ;   
} 
 
/*************************************************************************** 
 
 
  Function :            open_ofile        
 
 
  Purpose  :            gens o/p file name and opens same 
 
  Entry    :        
 
 
  Returns  :       
 
                 
 
***************************************************************************/ 
 
int open_ofile ( iptr ) 
 
char *iptr ; 
 
{ 
 
  strcpy ( ofile , iptr ) ;        /* create a o/p file */  
 
/*---------------- muck around if using stone-age MS_DOS on PC ------*/ 
 
#ifdef AMIGA 
    dos_fname () ; /* MS_DOS :chara file-names, only one '.' allowed , yuk ..*/ 
#else 
  strcat ( ofile , sfx[opftype] ) ;   /* append suffix */ 
#endif    
 
  if(( offp= open( ofile , O_RDWR | O_CREAT | O_TRUNC , 0666)) < 0 )     
    { 
        fprintf(stderr,"Error: unable to open '%s'\n" , ofile ); 
        exit(1); 
    } 
 
  printf (  "\nOutput file is :  %s  ( %s )\n" ,  
                               ofile ,iipftype[opftype] ) ;  
 
} 
 
/*************************************************************************** 
 
 
  Function :           gen_csum 
 
 
  Purpose  :           builds and writes checksum record to disc 
                 
 
  Entry    :           
 
 
  Returns  :           
                               
 
 
****************************************************************************/ 
 
 
int gen_csum ()  
 
 
{ 
int j , k  ; 
int addr = (long)romsize*1024 -2 ; 
	        
 
  /*------------ now calc ROM checksum ----------------------------*/ 
 
  for ( j=0 , csum=0 ; j < addr  ; j +=2 ) 
    { 
       csum += *(uchar *)(mallocptr + j) ; 
       csum += ((int)*(uchar *)(mallocptr + j + 1)) << 8 ; 
    } 
 
  /* ----------- now calc record checksum -----------------------*/ 
 
  k = 2 + (addr&0xFF) + (addr>>8) + (csum&0xFF) + (csum>>8) ; 
  k = -k ; 
 
  /*------------- now build record ------------------------------*/ 
 
    opbuf[0] = ':' ; 
    opbuf[1] = '0' ; 
    opbuf[2] = '2' ;    /* length */ 
     
 
   j = convc2 ( addr >> 8 ) ;           /* load addr - hi */ 
   opbuf [IRADDR] = j >> 8 ; 
   opbuf [IRADDR+1] = j & 0xFF ; 
 
   j = convc2 ( addr ) ;                /* load addr - lo */ 
   opbuf [IRADDR+2] = j >> 8 ; 
   opbuf [IRADDR+3] = j & 0xFF ; 
 
   j = convc2 ( csum  ) ;               /* ROM checksum  - lo */ 
   opbuf [IRDATA] = j >> 8 ; 
   opbuf [IRDATA+1] = j & 0xFF ; 
 
   j = convc2 ( csum >> 8 ) ;           /* ROM checksum -  hi */ 
   opbuf [IRDATA+2] = j >> 8 ; 
   opbuf [IRDATA+3] = j & 0xFF ; 
 
   j = convc2 ( k ) ;                /* record checksum  */ 
   opbuf [IRDATA+4] = j >> 8 ; 
   opbuf [IRDATA+5] = j & 0xFF ; 
 
   opbuf [xdllen=IRDATA+6] = '\n' ;        /* append RETURN  to  record */ 
 
  /*--------------now write record to disc ----------------------------------*/ 
 
    ++datarecs ; 
    ++oprecs ; 
    totchars += 2 ;                  /* update total data chara count */ 
 
    rite_rec ( offp , opbuf , ++xdllen ) ;   /* write it */ 
 
 
} 
 
/*************************************************************************** 
 
  Function :       date  
 
  Purpose  :       plants SCCS Vers #/build date in banner 
 
  Entry    :       ptr to start of vers/date in banner 
 
  Exit conditions:  ptr to rehacked string  
 
 
 
****************************************************************************/ 
 
char *date ( optr ) 
 
char *optr ;                   /* ptr to date line */ 
 
{ 
 
static char month[] = "JanFebMarAprMayJunJulAugSepOctNovDec" ; 
 
/*                     0123456789012345678901234                       */ 
static char copy[]  = "[ V x.x   -   dd mmm yy ]" ;      /* build, copy out*/ 
 
int j , k  ; 
char ch ; 
char *iptr ; 
 
 
/*---------------------------------------------------------------------------*/ 
 
   iptr = &sccs_id[0] ; 
   while ( *iptr++ == ' ' ) ;    /* look for start of SCCS vers. # */ 
   --iptr   ; 
      
   /*----------- copy Vers # to build buffer---------------------------*/ 
 
   j = 4 ;                           /* start of Vers in build buffer */ 
   while ( (ch = *iptr++) != ' ' )    
        copy[j++] = ch ; 
 
   /*---------------- get Months, convert and put in buffer-------------*/ 
 
   while ( (ch = *iptr++) == ' ' ) ;  /* look for start of months */ 
   --iptr ; 
 
   j = 0 ; 
   while ( (ch = *iptr++) != '/' )    /* 1 or 2 charas   */ 
     { 
         j = 10*j + (ch - '0') ;          /* yes */ 
     } 
 
   j = 3 * (j-1) ;                     /* index to start of "mmm" charas */ 
 
   for ( k=0 ; k < 3 ; ++k , ++j ) 
      copy [17+k] = month[j] ;         /* copy 3 charas to buffer */ 
 
   /*---------------- get days, and put in buffer-----------------------*/ 
 
   copy[15] = *iptr++ ;                    /* days - 1 */ 
   if ( (ch = *iptr++) != '/' ) 
      { 
         copy[14] = copy[15] ;         /* shuffle up */ 
         copy[15] = ch ;                /* days 2 - if there */ 
       } 
    ++iptr; 
 
   /*---------------- get years,  and put in buffer-----------------------*/ 
 
   copy[21] = *iptr++ ;                    
   copy[22] = *iptr++ ;                    
 
   return ( copy ) ;    /* return with ptr to string */ 
    
} 
 
/*************************************************************************** 
 
 
  Function :           usage 
 
 
  Purpose  :          prints calling params for "emu" 
                 
 
  Entry    :           
 
 
  Returns  :           
                               
 
 
****************************************************************************/ 
 
 
int usage () 
 
{ 
static char *rats[] = { 
"\n", 
"Usage 1 & 2 :\n", 
"-----------\n", 
" Converts a given ASCII-hex file in Down-Line Load (DLL) format to another\n", 
" or the same  DLL format . \n", 
" ( Note that record checksums are not verified in the source file - this\n", 
"   means that a record  can be altered and the file regenerated without the\n", 
"   tedium of having to recalculate the checksum ).\n", 
"\n", 
"usage <1> : x2x   ( parameters are solicited )", 
"\n", 
"usage <2> : x2x -Ifilename -Otype [-Sxxx] \n",
"\n", 
"     (O)utput file types  : \n" , 
"                       I  = Intel\n", 
"                       M1 = Motorola S1\n", 
"                       M2 = Motorola S2\n", 
"                       M3 = Motorola S3\n", 
"                       T  = Tektronix\n", 
"                       t  = Tektronix-extended\n", 
"     xxx = record data length ( 1-255 , def=16 )\n" ,  
"\n", 
"" 
} ; 
 
int j = 0 ; 
char *ptr ; 
 
 
  while ( *(ptr = rats[j++])  ) 
    printf ( "%s", ptr ) ; 
 
} 
