/* === PC side of DISKLINK (Borland C) ================================ */

#include <conio.h>
#include <stdio.h>

#define TRUE  1
#define FALSE 0
typedef int boolean;

typedef unsigned char byte;

/* ORIC to PC basic routines ------------------------------------ */

void ack(void)
{  asm mov dx, 0x378
   asm mov al, 0x10
   asm out dx, al
   asm mov al, 0xef
   asm out dx, al
}

byte read_port(int port)
{  byte b;

   asm mov dx, port
   asm in  al, dx
   asm mov b, al

   return b;
}

byte get_nibble(void)
{  static byte strobe;
   static boolean started = FALSE;

   byte b,r;

   if (started)
      do b = read_port(0x379);
      while ((strobe == (b & 0x80)) && !kbhit());

   started = TRUE;
   b = read_port(0x379);
   r = (b & 0x78) >> 3;
   strobe = b & 0x80;

   ack();

   return r;
}

byte get_byte(void)
{  byte n1,n2;

   n1 = get_nibble();
   n2 = get_nibble();

   return (n2 << 4) + n1;
}

int get_int(void)
{  byte b1,b2;

   b1 = get_byte();
   b2 = get_byte();

   return (b2 << 8) + b1;
}

/* Write a positive int as 4 bytes to a file (big endian) ------- */

void fputi(int i, FILE *f)
{  byte b[3];
   int j;

   for (j = 0; j <= 3; j++) b[j] = 0;

   for (j = 0; i > 0; j++)
   {  b[j] = i % 256;
      i = i >> 8;
   }

   for (j = 0; j <= 3; j++) fputc(b[j],f);
}

/* Main --------------------------------------------------------- */

void main(int argc, char **argv)
{
/* Diskette parameters */

   int sector_size;
   int sector_min;
   int sector_max;
   int track_min;
   int track_max;

/* Output file */

   FILE *f;    /* file per se */
   char *fn;   /* file name */

/* Byte from ORIC and counters */

   byte b;
   int i,s,t;

/* Get rid of 1st nibble : ORIC not sending anything now */
   b = get_nibble();

/* Get diskette parameters - sent by ORIC in a sector */

   printf("Expecting diskette parameters ... ");

   sector_size = get_int();
   sector_min  = get_int();
   sector_max  = get_int();
   track_min   = get_int();
   track_max   = get_int();

   /* 10 bytes received so far */

   for (i = 11; i <= sector_size; i++)
      b = get_byte();

   printf("\n");

   printf("Sector size %d\n", sector_size);
   printf("Sector min  %2d  max  %2d\n", sector_min, sector_max);
   printf("Track  min  %2d  max  %2d\n", track_min,  track_max);

/* Open output file */

   if (argc == 1)
      fn = "oricdisk.img";
   else
      fn = *++argv;

   f = fopen(fn, "wb");
   if (f == NULL)
   {  printf("Can't open %s\n", fn);
      exit(1);
   }

/* Write a 256 byte header for oric2mfm */

   for (i = 0; i < 8; i++) fputc("ORICDISK"[i], f);
   fputi(1, f);                            /* number of sides   */
   fputi(track_max - track_min + 1, f);    /* number of tracks  */
   fputi(sector_max - sector_min + 1, f);  /* number of sectors */
   /* 20 bytes written so far ... */
   for (i = 21; i <= 256; i++) fputc('\0', f); /* filling */

/* Transfer Oric diskette */

   printf("\n");

   for (t = track_min; t <= track_max; t++)
   {  for (s = sector_min; s <= sector_max; s++)
      {  for (i = 1; i <= sector_size; i++)
         {  if (kbhit())
            {  fclose(f);
               printf("\n*** Transfer interrupted\n");
               exit(2);
            }
            else
            {  b = get_byte();
               /* printf("%2d %2d %3d : %X\n", t, s, i , b); */
               fputc(b, f);
            }
         }
         printf("\rTrack %2d Sector %2d transferred ...", t, s);
      }
   }
   fclose(f);
   printf("\n*** Transfer complete\n");
   exit(0);
}
