/***************************************************************************/
/**                                                                       **/
/**                Written by JF FABRE (fabre@supaero.fr)                 **/
/**                                                                       **/
/**                This program may be freely distibuted                  **/
/**                                                                       **/
/**             as long as this header is included unmodified             **/
/**                                                                       **/
/***************************************************************************/

#include <stdio.h>
#include <stdlib.h>

#include <dos/dos.h>
#include <proto/dos.h>
#include <proto/exec.h>
#include <pragmas/dos_pragmas.h>
#include <pragmas/exec_pragmas.h>

#include <string.h>

#define Erreur(s) {printf("** %s\n",s);CloseAll();exit(0);}

#define CloseAll() {if (fr) fclose(fr);if (fw) fclose(fw);if (buff_src) free(buff_src);}

extern struct ExecBase *SysBase;
extern struct DosLibrary *DOSBase;

#define NO_SYNC -2
#define ONE_SYNC -1
#define THR_SYNC 0

extern ULONG GetWord680x0(UBYTE *bu);

long SeekSync(char *,long *);
long SeekZero(char *,long);

/*** Chercher le zero ***/

long SeekZero(char *buff,long len)

{
  long i=0;

  while ( buff[i]!='\0' )
  {
   i++;
   if (i==len) return -1;
  }

return i;
}

/*** Chercher la synchro ***/

long SeekSync(char *buff,long *len)

{
  int i=0;
  
  do
  {
   i++;
   if (i==(*len)) return NO_SYNC;
  }

  while ( (*(buff++)) !=0x16);

  switch ( *(buff++) )
    {
     case 0x16 : break;
     case 0x24 : *len-=i+1;return ONE_SYNC;
     default : return NO_SYNC;
    }

  switch ( *(buff++) )
    {
     case 0x16 : break;
     case 0x24 : *len-=i+2;return ONE_SYNC;
     default : return NO_SYNC;
    }

  *len-=i+3;
  return THR_SYNC;
}

/*** prog principal ***/

main(argc,argv)

unsigned int argc;
char **argv;

{
FILE *fr,*fw;
long tape_size,bytes_read,length,end_adr,begin_adr,i=0,var;
char *buff_origin,*buff_src;
int correct=0,do_correct,err_found=0;
char ch[200];

fr=fw=NULL;
buff_src=NULL;

printf("\n-- Amoric TapeInfo -- Written by JF FABRE --\n\n");
if (argc<2) Erreur("Usage : TapeInfo <tapefile>");

if ( (argc==3)&&(!strncmp(argv[1],"-c",2)) )
  {
   correct=1;
   printf("** Correcting mode activated...\n\n");
  }

if (!(fr=fopen(argv[1],"rb")))
  {
    if (argc==2) Erreur("Can't open source file !");
    if (!(fr=fopen(argv[2],"rb"))) Erreur("Can't open source file !");
  }
    
fseek(fr,0,SEEK_END);
tape_size=ftell(fr);
rewind(fr);

buff_src=(char *)malloc(tape_size);

if (buff_src==NULL) Erreur("Not enough memory !");

if (correct)
  {
   if ( (fw=fopen("T:OricTMP.DAT","wb")) ==NULL ) Erreur("Unable to open TMP file !! Correction aborted...\n");
  }

printf("Loading source file : %s...\n",argv[1+correct]);
bytes_read=fread(buff_src,1,tape_size,fr);
fclose(fr);
printf("File size : %d bytes.\nAnalysing tape...\n",bytes_read);

length=bytes_read;

do
{
buff_origin=buff_src;

printf("\nProgram %d : Offset $%x\n",i+1,tape_size-length);

switch (SeekSync(buff_src,&length))
  {
    case NO_SYNC:  if (!i) Erreur("No sync found...\n");
                   i=-2;length=tape_size;break;
    case ONE_SYNC: printf("Weak Sync found at offset $%x.\n",tape_size-length-2);buff_src+=2;do_correct=1;err_found=1;break;
    case THR_SYNC: printf("Good Sync found at offset $%x.\n",tape_size-length-4);buff_src+=4;do_correct=0;break;
  }

i++;

buff_src+=4;

end_adr=GetWord680x0(buff_src);
begin_adr=GetWord680x0(buff_src+2);

buff_src+=5;

printf("Program name : %s\n",buff_src);
printf("Start : $%x\011End : $%x\011Length : $%x\n", begin_adr,end_adr,end_adr-begin_adr-1);

if (begin_adr>=end_adr) Erreur("Incoherent start/end addresses");

if ((var=SeekZero(buff_src,length))==-1) Erreur("Name not terminated.");

buff_src+=var+end_adr-begin_adr+2;
length-=11+var+end_adr-begin_adr;

if ((correct)&&(tape_size-length>0))
  {
  printf("Correcting part %d...\n",i);
  if (do_correct)
    {
    fputc(0x16,fw);
    fputc(0x16,fw);
    }
  if (length<=0) var--;
  fwrite(buff_origin,1,13+var+end_adr-begin_adr,fw);
  }
if (length<=0) break;

}


while (i!=-1);

CloseAll();

if (correct)
  {
  sprintf(ch,"c:copy T:OricTMP.DAT %s",argv[2]);

  DOSBase=(struct DosLibrary *)OpenLibrary("dos.library",0);
  if (err_found) Execute(ch,NULL,NULL);
  DeleteFile("T:OricTMP.dat");
  CloseLibrary((struct Library *)DOSBase);
  }

}


