/*************************************************************************
*                                unpTrack                                *
*                                                                        *
*               This program can unpack track packed files.              *
*                                                                        *
*************************************************************************/

// First we include a lot of things

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

#include <exec/types.h>
#include <exec/memory.h>
#include <dos/rdargs.h>
#include <dos/dosextens.h>
#include <devices/trackdisk.h>
#include <libraries/unpack.h>

#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/unpack.h>

// Global Variables
struct  Library *UnpackBase;
struct  UnpackInfo *cinfo=NULL;
struct  DriveStruct *dinfo=NULL;
struct  RDArgs *rda=NULL;
LONG    arguments[4] = {0,0,0,0};

#ifdef LATTICE
void __regargs _CXBRK(void)               // Catch CTRL-C Handling
{
  fprintf(stderr,"*** User breaked\n");   // Print out break message
  upUnuseDrive(dinfo);                    // and clean up after us
  upFreeCInfo(cinfo);
  CloseLibrary(UnpackBase);
  FreeArgs(rda);
  exit(0);                                // then we exit our program.
}
#endif


// Prototypes
__asm WORD Saver(register __a1 ULONG userdata, register __a2 struct UnpackInfo *ui);
__asm WORD SaverError(register __a1 ULONG userdata, register __a2 struct UnpackInfo *ui);

// Main program
void main (void)
{
extern  struct ExecBase *SysBase;
BOOL    error=0;


  if( ((struct Library*) DOSBase)->lib_Version < 37 )
  {
      fprintf(stderr,"unpTrack requires at least Kickstart 2.04!\n");
      exit(0);
  }

  if (rda = ReadArgs("FILE/A,DRIVE/A,VERIFY/S,NOBANNER/S",arguments,NULL))
  {
    if (UnpackBase = OpenLibrary("unpack.library",42L))
    {
      if (cinfo = upAllocCInfo())
      {
        printf("unpTrack 1.0 (5/10-1995) by Thomas Neumann\n\n");

        cinfo->ui_TrackJump = (void (*)(void *, void *))Saver;
        cinfo->ui_TrkErrJump = (void (*)(void *, void *))SaverError;
        cinfo->ui_Flag = UFN_NoA4;
        if (arguments[3] == 0)
          cinfo->ui_Flag |= UFN_Banner;

        if ((upDetermineFile(cinfo,(char *)arguments[0])) == NULL)
          error=1;
        else
          if ((cinfo->ui_CrunchType & 0x7f) != CRU_Track)
            fprintf(stderr,"File not a track crunched file\n");
          else
            if ((dinfo = upUseDrive(cinfo,(char *)arguments[1])) == NULL)
              error=1;
            else
            {
              printf("Insert a disk in drive %s and press return.",arguments[1]);
              while ((getchar() != 10)){}
              printf("\nUnpacking track:  0\n");
              if (upUnpack(cinfo) == 0)
                error=1;

              upUnuseDrive(dinfo);
            }

        if (error != 0)
          fprintf(stderr,"Unpack Error: %s\n",cinfo->ui_ErrorMsg);

        upFreeCInfo(cinfo);
      }
      CloseLibrary(UnpackBase);
    }
    else
      fprintf(stderr,"You need the unpack.library version 42 or higher\n");

  FreeArgs(rda);
  }
  else
    PrintFault(IoErr(),NULL);
}


__asm WORD Saver(register __a1 ULONG userdata, register __a2 struct UnpackInfo *ui)
{
UWORD track;
UBYTE err;
ULONG length;
UBYTE *vermem;
UBYTE *unpmem;
int   i;

  track=ui->ui_Track;
  length=ui->ui_DecrunchLen;
  if (ui->ui_Offset == -1)          // Test to see if it's a banner
  {
    printf("%c%c%c\n",0x0b,0x9b,0x4b);
    Write(Output(),ui->ui_DecrunchAdr,length);
    printf("\n\n");
  }
  else
  {
    printf("%cWriting   track: %2d\n",0x0b,track);
    err=upSendCmd(dinfo,ui->ui_DecrunchAdr,ui->ui_Offset,length,TD_FORMAT);

    if (err == 0)
      if (arguments[2] != 0)
      {
        printf("%cVerifying track: %2d\n",0x0b,track);
        if ((vermem=AllocMem(length,MEMF_CHIP)) != NULL)
        {
          err=upSendCmd(dinfo,vermem,ui->ui_Offset,length,CMD_READ);
          unpmem=ui->ui_DecrunchAdr;

          if (err == 0)
            for (i=0;i<length;i++)
              if (unpmem[i] != vermem[i])   // Compare the two memory blocks
                err=255;

          FreeMem(vermem,length);
          if (err == 255)
          {
            fprintf(stderr,"Verify error on track %d\n",track);
            return(-1);
          }
        }
      }

    if (err == 0)
      if (track != 79)
        printf("%cUnpacking track: %2d\n",0x0b,track+1);
      else
        printf("%c%c%c",0x0b,0x9b,0x4b);
    else
    {
      fprintf(stderr,"We got error number %d from the device\n",err);
      return(-1);
    }
  }
  return(0);      // Note that you has to be sure your compile will return
}                 // this value in register d0.


__asm WORD SaverError(register __a1 ULONG userdata, register __a2 struct UnpackInfo *ui)
{
  return(-1);
}
