
/* Program to convert disk into disk image file */
/* To run, give the source drive as a parameter */
/* The output file will be called drivea (which will have to renamed to
	DriveA when transferred to Unix */
/* By P. McGavin 20/8/98, using dumpdisk.c by D. Hedley 18/6/94 */

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

#include <exec/exec.h>
#include <dos/dos.h>
#include <devices/trackdisk.h>
#include <utility/tagitem.h>

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

static int unit, type;

static struct
{
	int tracks, sectors, heads;
	char *descr;
} *dt, drivetypes[] =
{
	{ 40,  9, 2, "360k 5¬\"" },
	{ 80, 15, 2, "1.2MB 5¬\"" },
	{ 80,  9, 2, "720k 3«\"" },
	{ 80, 18, 2, "1.44MB 3«\"" },
};

static char buf[18 * 512];
static struct MsgPort *track_mp = NULL;
static struct IOExtTD *track_io = NULL;
static BOOL track_is_open = FALSE;

void _STDcleanup (void)
{
  if (track_is_open) {
    track_io->iotd_Req.io_Length = 0;
    track_io->iotd_Req.io_Command = TD_MOTOR;
    DoIO ((struct IORequest *)track_io);
    CloseDevice ((struct IORequest *)track_io);
  }
  if (track_io != NULL)
    DeleteExtIO ((struct IORequest *)track_io);
  if (track_mp != NULL)
    DeletePort (track_mp);
}

int main (int argc, char *argv[])
{
  FILE *f;
  int i;
  char *programname;

  if (argc == 0)
    programname = "amidumpdisk";
  else
    programname = argv[0];

  if (argc != 4) {
    fprintf (stderr, "Usage: %s <unit> <type> <outputfile>\n", programname);
    fprintf (stderr, "       where <unit> is 0, 1, 2 or 3\n");
    fprintf (stderr, "       and <type> is 360, 720, 1200 or 1440\n");
    return 10;
  }

  unit = atoi(argv[1]);
  if (unit < 0 || unit >= 4) {
    fprintf (stderr, "%s: unit must be 0, 1, 2 or 3\n", programname);
    return 10;
  }

  type = atoi(argv[2]);
  switch (type) {
    case 360:
      dt = &drivetypes[0];
      break;
    case 1200:
      dt = &drivetypes[1];
      break;
    case 720:
      dt = &drivetypes[2];
      break;
    case 1440:
      dt = &drivetypes[3];
      break;
    default:
      fprintf (stderr, "%s: type must be 360, 720, 1200 or 1440\n",
               programname);
      return 10;
  }

  if ((track_mp = CreatePort (0, 0)) != NULL &&
      (track_io = (struct IOExtTD *)CreateExtIO (track_mp, sizeof(struct IOExtTD))) != NULL &&
      OpenDevice ("mfm.device", unit, (struct IORequest *)track_io,
                  TDF_ALLOW_NON_3_5) == 0) {
    track_is_open = TRUE;

    if ((f = fopen (argv[3], "wb")) != NULL) {

      for (i = 0; i < dt->heads * dt->tracks; i++) {
        track_io->iotd_Req.io_Length = (dt->sectors * 512);
        track_io->iotd_Req.io_Data = buf;
        track_io->iotd_Req.io_Offset = i * (dt->sectors * 512);
        track_io->iotd_Req.io_Command = CMD_READ;
        if (DoIO ((struct IORequest *)track_io) != 0)
          fprintf (stderr, "Error %d reading track %d from diskette\n",
                   track_io->iotd_Req.io_Error, i);
        if (fwrite (buf, 1, dt->sectors * 512, f) != dt->sectors * 512)
          fprintf (stderr, "Error writing track %d to %s\n", i, argv[1]);
      }

      fclose (f);
    }
  }

  return 0;
}
