/* ---------------------------------------------------------------------- */
/*                   Copyright (C) 1992 by Natrlich!                     */
/*                      This file is copyrighted!                         */
/*                Refer to the documentation for details.                 */
/* ---------------------------------------------------------------------- */
#include "defines.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define __BIG_GENERATOR__
#include OSBIND
#if OS == MSDOS
# undef peek
# undef poke
#endif
#include "code.h"

/* ---------------------------------------------------------- */
/* rev. history   1.1 --                                      */
/*      Fill up holes option included & C64/AppleII Support   */
/*                1.2 -- no real changes                      */
/* Ref: Bill and Teds bogus Journey Soundtrack.               */
/* ---------------------------------------------------------- */
#if __NSTDC__
void           nferror( char huge *),
               fixheader( void);
#endif

struct ffffhead
{
   word  ffff,
         start,
         end;
} header, oldhead;



word   __x;

void fixheader()
{
   header.start = dpeek( &header.start);
   header.end   = dpeek( &header.end);
}

#if OS == TOS
int     tossable;
#endif
int   fillholes,
   applify,
   cbmify;


void nferror( s)
char huge *s;
{
   fprintf( stderr, "xtrctbin: Error \"%s\"\n", s);
#if OS == TOS
   keypress();
#endif
   exit(1);
}

static char    infile[128], outfile[128];
lword          pos;

main( argc, argv)
int   argc;
char  **argv;
{
   int            i = 0,
   fp, fq,
   excellent = 0;
   char huge      *room;
   unsigned long  space,
                  mspace = 0;
   long           bread;
                  
   while( ++i < argc)
   {
      if( *argv[i] == '-')
         switch( argv[i][1])
         {
#if OS == TOS
            case 'T' :
               case 't' :
                  tossable = 1;
                  break;
#endif
#ifdef __DATE__
                  case ':' :
                     fputs( __DATE__, stderr);
# ifdef __TIME__
                  fprintf( stderr, " %s", __TIME__);
# endif                              
                  putc( '\n', stderr);
                  break;
#endif               
                  case 'a' :   
                     case 'A' :
                        if( applify = ! applify)
                           fillholes = 1;
                  break;
                  
                  case 'c' :   
                     case 'C' :
                        if( cbmify = ! cbmify)
                           fillholes = 1;
                  break;

                  case 'F' :
                     case 'f' :
                        fillholes = ! fillholes;
                  break;
                  
                  case 'V' :
                     case 'v' :
                        fprintf( stderr, "xtrctbin v1.2 1991 by Natuerlich! -- extracts pure binary data from com files\n");
                  break;
               }
      else
         if( ! infile[0])
            strcpy( infile, argv[i]);
         else
            if( ! outfile[0])
               strcpy( outfile, argv[i]);
            else
               goto usage;
   }
   if( ! (infile[0] && outfile[0]))
      goto usage;
   
   if( (fp = (int) Fopen( infile, 0)) < 0)
      nferror("File open failed");
   if( (fq = (int) Fkreate( outfile, 0x664)) < 0)
      nferror("File creation failed");
   
   if( (bread = Fread( fp, 6L, &header)) < 6)
      nferror("File trunctated");
   if( header.ffff != 0xFFFF)
      nferror("Not a $FF $FF binary file");
   if( applify || cbmify)
   {   
      Fwrite( fq, 2L, &header.start);
      if( applify)
      {
         pos = 2;
         Fwrite( fq, 2L, &header.start);
      }
   }
   
   
   for(;;)
   {
      fixheader();
      space = (unsigned long) (1 + header.end - header.start);
      if( space > mspace)
      {
         if( mspace)
            Mfree( room);
         if( ! (room = (char *) Malloc( (lword) (mspace = space))))
            nferror("out of memory");
      }
      if( excellent && fillholes)
      {
         lword  amount = (lword) header.start - oldhead.end - 1;
         word   i;

         memset( room, 0, space);

         for( i = amount / space; i--;)
            Fwrite( fq, space, room);
         if( amount %= space)
            Fwrite( fq, amount, room);
      }

      if( Fread( fp, space, room) != space)
         nferror("read failed (file truncated ?)");
      if( Fwrite( fq, space, room) != space)
         nferror("write failed (disk full ?)");
      memcpy( &oldhead, &header, (long) sizeof( struct ffffhead));  /*Bogus*/
      excellent = 1;
      if( (bread = Fread( fp, 4L, (char huge *) &header + 2)) <= 0)
         break;
      if( bread < 4)
         nferror("Garbage at end of segment");
      if( header.start == 0xFFFF)
      {
         header.ffff  = header.start;
         header.start = header.end;
         if( (bread = Fread( fp, 2L, (char huge *) &header + 4)) <= 0 ||
             bread < 2)
            nferror("This is a trashed binary");
      }
   }

   if( applify)
   {
      lword curr;
      word  bar;

      curr = Fseek( 0L, fq, SEEK_CUR);
      Fseek( pos, fq, SEEK_SET);
      pos = curr - pos - 2;
      dpoke( &bar, (word) pos);
      if( Fwrite( fq, 2L, &bar) != 2)
         nferror("out of precious diskspace");
   }


#if OS == TOS
   keypress();
#endif
   return(0);

usage:
#if OS == TOS
   fputs( "usage: xtrctbin [-fact] infile outfile\n", stderr);
#else
   fputs( "usage: xtrctbin [-fac] infile outfile\n", stderr);
#endif
   fputs( "\
\t-a\t: 'Applify' binary, prefaces a ADR,LEN header (& -f option)\n\
\t-c\t: 'C64ify'  binary, prefaces a ADR header (& -f option)\n\
\t-f\t: fill up holes in extracted binary\n\
\t-v\t: version\n", stderr);
#if OS == TOS
   fputs( "\t-t : wait for keypress before exiting\n", stderr);
   keypress();
#endif
   return( 1);
}

keypress()
{
#if OS == TOS
   if( tossable)
   {
      while( Bconstat( 2))
         Bconin( 2);
      Bconin( 2);
   }
#endif
}
