/****************************************************************/
/*    "zip2dsk" converts four Zip-Code files into               */
/*              C-64 disk image                                 */
/*                                                              */
/*    v1.0:   May 16, 1993                                      */
/*                                                              */
/*    Author: Paul David Doherty (h0142kdd@rz.hu-berlin.de)     */
/****************************************************************/

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

#define ZIPNAMELENGTH 16

FILE *infile;
FILE *outfile;
char zipname[ZIPNAMELENGTH];

int track, max_sect;
unsigned char act_track[21][256];

void open_file (int);
void read_track (void);
void read_sector (void);
void write_track (void);
void usage (void);

/*******************************************************************/
/*  MAIN function                                                  */
/*******************************************************************/

void
main (int argc, char **argv)
{
  char outname[ZIPNAMELENGTH + 4];

  if (--argc != 1)
    usage ();

  strcpy (zipname, argv[argc]);
  strcpy (outname, zipname);
  strcat (outname, ".dsk");

  if ((outfile = fopen (outname, "wb")) == NULL)
    {
      printf ("Error: Can't create \"%s\"\n", outname);
      exit (5);
    }

  for (track = 1; track <= 35; track++)
    {
      max_sect = 16 + ((track < 31) ? 1 : 0) + ((track < 25) ? 1 : 0) + ((track < 18) ? 2 : 0);

      switch (track)
        {
        case 1:
          open_file (1);
          break;
        case 9:
          open_file (2);
          break;
        case 17:
          open_file (3);
          break;
        case 26:
          open_file (4);
          break;
        }

      read_track ();
      write_track ();
    }
}


/*******************************************************************/
/*  Function: open_file                                            */
/*******************************************************************/

void
open_file (int number)
{
  char inputname[ZIPNAMELENGTH + 2];

  inputname[0] = number + 0x30;
  inputname[1] = '\0';
  strcat (inputname, "!");
  strcat (inputname, zipname);

  if (number > 1)
    fclose (infile);

  if ((infile = fopen (inputname, "rb")) == NULL)
    {
      printf ("Error: Can't find \"%s\"\n", inputname);
      exit (5);
    }

  fseek (infile, ((number == 1) ? 4 : 2), SEEK_SET);
}

/*******************************************************************/
/*  Function: read_track                                           */
/*******************************************************************/

void
read_track (void)
{
  int sect;

  for (sect = 0; sect <= max_sect; sect++)
    read_sector ();
}

/*******************************************************************/
/*  Function: read_sector                                          */
/*******************************************************************/

void
read_sector ()
{
  unsigned char trk, sec, len, rep, repnum, chra;
  int i, j, count;

  trk = getc (infile);
  sec = getc (infile);

  if ((trk & 0x80) != 0)
    {
      len = getc (infile);
      rep = getc (infile);
      count = 0;

      for (i = 0; i < len; i++)
        {
          chra = getc (infile);
          if (chra != rep)
            {
              act_track[sec][count] = chra;
              count++;
            }
          else
            {
              repnum = getc (infile);
              chra = getc (infile);
              i = i + 2;
              for (j = 0; j < repnum; j++)
                {
                  act_track[sec][count] = chra;
                  count++;
                }
            }
        }
    }

  else if ((trk & 0x40) != 0)
    {
      chra = getc (infile);
      for (i = 0; i < 256; i++)
        act_track[sec][i] = chra;
    }

  else
    {
      for (i = 0; i < 256; i++)
        act_track[sec][i] = getc (infile);
    }
}

/*******************************************************************/
/*  Function: write_track                                          */
/*******************************************************************/

void
write_track (void)
{
  int i, j;

  for (i = 0; i <= max_sect; i++)
    for (j = 0; j < 256; j++)
      putc (act_track[i][j], outfile);
}

/*******************************************************************/
/*  Function: usage                                                */
/*******************************************************************/

void
usage (void)
{
  printf ("\nZip To Dsk V1.0\n");
  printf ("\n");
  printf (" Usage: Zip2Dsk Zip_Image_Name\n\n");
  exit (0);
}
