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

#include "prtrans.h"

#if !defined(__MAIN_C__)
#define main	main_prsave
#endif

unsigned char buffer[65536];

int main (int argc, char **argv);

int main (int argc, char **argv) {
  unsigned long start, end, length;
  unsigned driveraddr, basicaddr;
  FILE *file = stdout;
  unsigned bank = 0;
  char **parameters = argv;
  baseaddr = portaddr[DEFAULT_PORT];

  while (*++parameters && **parameters == '-') { /* check for options */
    if (parameters[0][1] == '-') { /* "--" ends options */
      parameters++;
      break;
    }

    switch (parameters[0][1]) {
    case 'b':
      bank = strtoul (*++parameters, NULL, 16);

      if (bank > 255) {
	fprintf (stderr, "%s: Illegal memory bank specified.\n", *argv);
	return 1;
      }

      break;

    case 'p':
      baseaddr = strtoul (*++parameters, NULL, 16);

      if (baseaddr > 3) {
	fprintf (stderr, "%s: The printer port number must be between 0 and 3.\n",
			 *argv);
	return 1;
      }

      baseaddr = portaddr[baseaddr];

      break;

    case '?':
    case 'h':
    Usage:
      fprintf (stderr, "%s: Dumps a memory area on a remote "
		       "computer to a file or standard output.\n\n", *argv);
      fprintf (stderr, "Usage: %s [options] startaddress endaddress [filename]\n",
		       *argv);
      fprintf (stderr, "Options:\n\t"
			 "-b bank\t"
			     "Specify the memory bank (in hex)\n\t"
			 "-p port\t"
			     "Specify the printer port (0 to 3)\n");
      return 1;

    default:
      fprintf (stderr, "%s: Illegal option `%s'.\n", *argv, *parameters);
      goto Usage;
    }
  }

  if (!*parameters) goto Usage;

  start = strtoul (*parameters++, NULL, 16);

  if (!*parameters) goto Usage;

  end = strtoul (*parameters++, NULL, 16);

#ifdef WRAP_AROUND
  if (start & ~65535 || end & ~65535)
    goto Usage;
#else
  if (start & ~65535 || end & ~65535 || (start >= end && end))
    goto Usage;
#endif /* WRAP_AROUND */

  if (prinit()) {
    fprintf (stderr, "%s: Could not get the I/O permissions.\n", *argv);
    return 4;
  }

  if (*parameters) { /* a file name was specified */
    if (parameters[1])
      goto Usage; /* more than one filename specified */

    if (!(file = fopen(*parameters, "wb"))) {
      fprintf (stderr, "%s: Could not open the file `%s'.\n", *argv,
		       *parameters);
      return 5;
    }
  }

  output (REQ_INFO); /* request machine info */

  fprintf (stderr, "%s: machine type %u.\n", *argv, wait_input ());

  driveraddr = wait_input();
  driveraddr |= wait_input() << 8;
  basicaddr = wait_input();
  basicaddr |= wait_input() << 8;

  fprintf (stderr, "%s: Driver address %04X, BASIC start address %04X.\n",
		   *argv, driveraddr, basicaddr);

  output (REQ_SAVE); /* op code for download */
  output (bank); /* bank address */

  if (wait_input ()) {
    fprintf (stderr, "%s: not ready to transfer\n", *argv);
    return 6;
  }
  else
    fprintf (stderr, "%s: ok to transfer\n", *argv);

  output (start);
  output (start >> 8);
  output (end);
  output (end >> 8);

  fputc (start, file);
  fputc (start >> 8, file);

  length = (end - start) & 65535;

  if (!length) length = 65536;

  receive (buffer, length);
  fwrite (buffer, 1, length, file);

  prclose ();

  return 0;
}
