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

FILE *infile;
FILE *outfile;
unsigned char track_data[8193];
unsigned char sector_flag[21];
char filename[1024];
unsigned sector, max_sector;

void fileerror()

{
    printf("File is corrupted.\n\r");
    exit(1);
}

void error()

{
    fclose(infile);
    fclose(outfile);
    exit(1);
}

void error2()

{
    fclose(outfile);
    exit(1);
}

void fillmemory(unsigned char *buffer, unsigned int bytes, unsigned char filler)

{
    int x;
    for (x=0; x<bytes; x++)
        buffer[x]=filler;
}

unsigned short int read_sector(FILE *f, unsigned char track)

{
    unsigned char trk, sec, len, rep, repnum, chra;
    unsigned short int i,j,count;
    fread(&trk,1,1,f);
    fread(&sec,1,1,f);
    if (((trk&63)!=track)||(sector_flag[sec]!=0)||(sec>max_sector)) 
        fileerror();
    sector_flag[sec]=1;
    if ((trk&128)==128) {
        printf("1");
        fread(&len,1,1,f);
        fread(&rep,1,1,f);
        count=0;
        for (i=0; i<len; i++) {
            if (feof(f)) 
                error();
            fread(&chra,1,1,f);
            if (chra!=rep) {
                track_data[(sec<<8)+count]=chra;
                count++;
            } 
            else {
                fread(&repnum,1,1,f);
                if (feof(f)) 
                    fileerror();
                fread(&chra,1,1,f);
                i=i+2;
                for (j=0; j<repnum; j++) {
                    track_data[(sec<<8)+count]=chra;
                    count++;
                }
            }
        }
    }
    else if ((trk&64)==64) {
        printf("2");
        if (feof(f)) 
            fileerror();
        fread(&chra,1,1,f);
        fillmemory((unsigned char *)&track_data[sec<<8],256,chra);
    } 
    else {
        printf("3");
        i=fread(&track_data[sec<<8],256,1,f);
        if (i!=1)
            fileerror();
    }
    return 0;
}

unsigned short int openfile(unsigned char p, char *name)

{
    if (p>1)  
        fclose(infile);
    filename[0]=p+48;
    filename[1]='!';
    strcpy(&filename[2],name);
    infile=fopen(filename,"rb");
    if (infile==NULL) {
        printf("Error opening file\n\r");
        return 1;
    }
    if (p==1)
        fseek(infile,4,SEEK_SET);
    else
        fseek(infile,2,SEEK_SET);
    return 0;
}

//label Error, Error2;

int main(int argc, char *argv[])

{
    unsigned short int block_count;
    unsigned char track;
    printf("\n\rZipCode 2 D64 - Extract Zipcode disks to .D64 images.\n\rModified by duet <duet@sci.fi>.\n\r");
    if (argc!=3) {
        printf("Usage: zip2d64 <zipcode file> <d64 image>\n\r");
        exit(1);
    }  
    outfile=fopen(argv[2],"wb");
    if (outfile==NULL)
        fileerror();    
    block_count=0;
    for (track=1; track<36; track++) {
        fillmemory((unsigned char *)&track_data,sizeof(track_data),0);
        if ((track>=1) && (track<=17)) 
            max_sector=20;
        if ((track>=18) && (track<=24)) 
            max_sector=18;
        if ((track>=25) && (track<=30)) 
            max_sector=17;
        if ((track>=31) && (track<=35)) 
            max_sector=16;
      switch(track) {
          case 1: 
              if (openfile(1,argv[1])!=0) 
                  error2();
              break;
          case 9: 
              if (openfile(2,argv[1])!=0) 
                  error2();
              break;
          case 17: 
              if (openfile(3,argv[1])!=0)
                  error2();
              break;
          case 26: 
              if (openfile(4,argv[1])!=0) 
                  error2();
              break;
          default:
              break;
      }
      fillmemory((unsigned char *)&sector_flag,sizeof(sector_flag),0);
      printf("Track %i ",track);
      for (sector=0; sector<max_sector+1; sector++) {
          block_count++;
          if (read_sector(infile,track)!=0) 
              error();
      }
      fwrite(&track_data,max_sector*256+256,1,outfile);
      printf("\n\r");
    }
    fclose(infile);
    fclose(outfile);
    return 0;
}
