home *** CD-ROM | disk | FTP | other *** search
/ ftp.elysium.pl / ftp.elysium.pl.tar / ftp.elysium.pl / games / C64_CDROM_96 / fcopypc.cpp < prev    next >
C/C++ Source or Header  |  2008-03-13  |  19KB  |  937 lines

  1. //
  2. // (C) 1993-1996  The Whiz-zards Association
  3. //
  4. // Fcopy C64<->PC
  5. //
  6. // Written by M. Edzes
  7. //
  8.  
  9. #include <stdio.h>
  10. #include <conio.h>
  11. #include <bios.h>
  12. #include <dos.h>
  13. #include <stdlib.h>
  14. #include <ctype.h>
  15. #include <string.h>
  16.  
  17. /* Technical data for C64 Fcopy program.
  18.  
  19.     Cable:
  20.  
  21.    11 wires. 1 GND, 2*5 data lines.
  22.  
  23.    The PC printer port interface has four adresses, of which the  lowest
  24.     two I know the usage.
  25.  
  26.    The base port adress of the LPT1..N port can be found in the BIOS  data
  27.    space at adress 0x0400:0x0080 .. 0x0400:0x0087.
  28.    Every 2 byte word is a port base adress. Usually, LPT1 resides at  0x378.
  29.  
  30.    The 0x378 port is the 8 bit printer output, of which the lower 5  bits
  31.    are connected to the lower 5 input bits of port $dc01 on the C64.
  32.  
  33.     The lower 5 bits of the C64 $dc00 output port have been connected  to the
  34.    printer error input lines, which are the upper 5 bits of 0x379,  where the
  35.     HIGHEST BIT (bit 7) IS INVERTED!!!
  36.  
  37.    This is all.
  38.  
  39.     Now for the c64diskfile structure:
  40.  
  41.    A file consists of 683 (number of sector) * 261 (sizeof sector) +  5
  42.      (file header size) = .... bytes.
  43.  
  44.     You may use the class c64diskfile definition for your own use,  it's
  45.    very easy.
  46.  
  47.      In your program you can open a new file by:
  48.  
  49.  
  50.    c64diskfile filevariable(accesstype mode)
  51.  
  52.     , where mode is either READ or WRITE. Now, use
  53.  
  54.    filevariable.setname(char *filename) // ONLY sets the filename. No  other
  55.                         action. Do this BEFORE open.
  56.  
  57.    filevariable.open()    // obvious. Will only open files in READ  mode if
  58.                  the SIZE and FORMATHEADER are correct. Returns
  59.                   true if successful. Sets the filepos at track=1,
  60.                   sector=0.
  61.  
  62.  
  63.    filevariable.close(int error)   // if error is true the file will  be
  64.                         deleted (if it was opened WRITE),
  65.                       otherwise not.
  66.  
  67.    filevariable.exists()  // obvious. Returns true on success, does  NOT check
  68.                  the fileheader.
  69.  
  70.    filevariable.positiontr(int trk) // Sets the current filepos to  track trk
  71.                          , sector 0. Only neccesary if not
  72.                        reading succesive tracks (dir)
  73.  
  74.    filevariable.getid(unsigned char id1,unsigned char id2)
  75.                  // Gets id out of formatheader.
  76.    filevariable.putid(unsigned char id1,unsigned char id2)
  77.                  // Writes an id into the file, and
  78.                      changes filepos to track=1,sector=0.
  79.     filevariable.gettrack(int trk,unsigned char *buffer)
  80.     filevariable.puttrack(int trk,unsigned char *buffer)
  81.                 // Read or write a C64 track from/to the file
  82.                    trk is ONLY used to calculate the number of
  83.                     sectors to read/write. Filepos will be up-
  84.                     dated accordingly. NO PREPOSITIONING!
  85.  
  86.    accesstype filevariable.getmode()
  87.                   // returns READ or WRITE.
  88.  
  89.  
  90. */
  91.  
  92. class Joyconnection
  93. {
  94.  
  95.     int lptportout;
  96.    int lptportin;
  97.     enum dirs {FROM64,TO64};
  98.    dirs direction;
  99.  
  100. public:
  101.    Joyconnection(int prt) {lptportout=prt;lptportin=prt+1;};
  102.    ~Joyconnection() {outportb(lptportout,0xff);};
  103.     void abort() {outportb(lptportout,0xff);};
  104.     int putblock(unsigned char *,int);
  105.    int getblock(unsigned char *,int);
  106.    int init();
  107. private:
  108.    int putbyte(unsigned char);
  109.     int getbyte(unsigned char&);
  110. };
  111.  
  112. #define C64FHEADER "TWA!"
  113.  
  114. struct c64fheader {
  115. //   char hdr[sizeof(C64FHEADER)];
  116.     unsigned char id1;
  117.     unsigned char id2;
  118.     };
  119.  
  120.  
  121. struct c64sector {
  122.     unsigned char track;       // actual track   (redundant)
  123.     unsigned char sector;      // actual sector  (redundant)
  124.     unsigned char scrncode;    // one of "+-CHI?FL" etc.
  125.     unsigned char header;      // mostly 0x07
  126.     unsigned char data[256];
  127.     unsigned char chksum;      // header exored with all databytes.
  128.     };
  129.  
  130. enum accesstype {READ,WRITE};
  131.  
  132. class c64diskfile
  133. {
  134.  
  135.     FILE *fpd64, *fpf64;
  136.     char fnamed64[80],fnamef64[80];
  137.     c64fheader fhdr;
  138.     accesstype mode;
  139.  
  140. public:
  141.     c64diskfile(accesstype m) {mode=m;fpd64=NULL;fpf64=NULL;};
  142.     ~c64diskfile() {
  143.      if(fpd64!=NULL) fclose(fpd64);
  144.      if(fpf64!=NULL) fclose(fpf64);
  145.     };
  146.     void setname(char *s) {
  147.      strncpy(fnamed64,s,sizeof(fnamed64)-4);
  148.      strncpy(fnamef64,s,sizeof(fnamef64)-4);
  149.      strcat(fnamed64,".D64");
  150.      strcat(fnamef64,".F64");
  151.      };
  152.     accesstype getmode() {return mode;};
  153.     int exists();
  154.     int open();
  155.     void close(int);
  156.     void positiontr(int);
  157.     void gettrack(int,unsigned char *);
  158.     void puttrack(int,unsigned char *);
  159.     void getid(unsigned char&,unsigned char&);
  160.     void putid(unsigned char&,unsigned char&);
  161. };
  162.  
  163.  
  164.  
  165. int calcsectors(int tr)
  166. {
  167.  int se=21;
  168.  if(tr>17) se-=2;
  169.  if(tr>24) se--;
  170.  if(tr>30) se--;
  171.  return se;
  172. }
  173.  
  174.  
  175. int Joyconnection::putblock(unsigned char *s,int n)
  176. {
  177.  int i;
  178.  unsigned char chk;
  179.  unsigned char *p;
  180.  int err;
  181.  
  182.  do {
  183.   i=0;
  184.   chk='\0';
  185.   err=0;
  186.   p=s;
  187.   while(i<n && !err) {
  188.     i++;
  189.     chk+=*p;
  190.     err=putbyte(*(p++));
  191.   }
  192.   if(!err) err=putbyte(chk);
  193.   if(!err) err=getbyte(chk);
  194.   delay(1);
  195.   if(!err) err=chk;
  196.   if(err) {
  197.     err=init();
  198.     if(!err) err=-1;
  199.   }
  200.  } while((err!=0) && (err!=-2));
  201.  return err;
  202. }
  203.  
  204. int Joyconnection::getblock(unsigned char *s,int n)
  205. {
  206.  int i=0;
  207.  unsigned char *p;
  208.  unsigned char chk,ctmp;
  209.  int err;
  210.  
  211.  do {
  212.   i=0;
  213.   chk='\0';
  214.   err=0;
  215.   p=s;
  216.   while(i<n && !err) {
  217.     i++;
  218.     err=getbyte(ctmp);
  219.     *(p++)=ctmp;
  220.     chk+=ctmp;
  221.   }
  222.   if(!err) err=getbyte(ctmp);
  223.   if(!err) {
  224.     if(chk-ctmp) {
  225.      err=putbyte(0xff);
  226.      if(!err) err=-1;
  227.     } else {
  228.      err=putbyte(0);
  229.     }
  230.   }
  231.   if(err) {
  232.     err=init();
  233.     if(!err) err=-1;
  234.   }
  235.  } while((err!=0) && (err!=-2));
  236.  return err;
  237. }
  238.  
  239. int Joyconnection::putbyte(unsigned char c)
  240. {
  241.  unsigned char a,b;
  242.  
  243.  if(direction==FROM64) {
  244.   while(!(inportb(lptportin)&0x80));   // Wait for starting 0 1 0 0 0
  245.   outportb(lptportout,0x1f);
  246.   while(inportb(lptportin)&0x40);      // Wait for 0 0 0 0 0
  247.   direction=TO64;
  248.  }
  249.  
  250.  a=inportb(lptportin);
  251.  b=(c>>4);
  252.  outportb(lptportout,b);               //     o  0   d7 d6 d5 d4
  253.  while(inportb(lptportin)==a);         //     i  0 ~(d7 d6 d5 d4)
  254.  if((((a=inportb(lptportin))>>3)^b)==0xf) {
  255.   b=(c&((char)0xf))|0x10;
  256.   outportb(lptportout,b);
  257.   while(inportb(lptportin)==a);
  258.   if(((inportb(lptportin)>>'\3')^b)=='\17') return 0;
  259.  }
  260.  return -1;
  261. }
  262.  
  263. int Joyconnection::getbyte(unsigned char& c)
  264. {
  265.  unsigned char a,b;
  266.  
  267.  if(direction==TO64) {
  268.   outportb(lptportout,0x8);     // send starting 0 1 0 0 0
  269.   while(inportb(lptportin)&0x80);
  270.   outportb(lptportout,0);       // send 0 0 0 0 0
  271.   direction=FROM64;
  272.  }
  273.  while(!(inportb(lptportin)&0x80));   // C64 sending?
  274.  a=inportb(lptportin);
  275.  outportb(lptportout,(a>>3)^0xf);    // ackhi, 1 x x x x
  276.  while(inportb(lptportin)==a);
  277.  if(!((b=inportb(lptportin))&0x80)) {
  278.   outportb(lptportout,(b>>3)^0xf);   // acklo, 0 x x x x
  279.   c=((a<<1)&0xf0)|((b>>3)&0xf);
  280.   return 0;
  281.  }
  282.  return -1;
  283. }
  284.  
  285.  
  286. int Joyconnection::init()
  287. {
  288.  unsigned char cycle;
  289.  int chk;
  290.  int err=0;
  291.  
  292.  do {
  293.   if(kbhit()) {
  294.     switch(getch()) {
  295.      case 'Q':
  296.     case 'q': err=-2;
  297.             outportb(lptportout,0xff);
  298.           exit(err);
  299.     }
  300.   }
  301.   chk=0;
  302.   for(cycle=0;cycle<32;cycle++) {
  303.     outportb(lptportout,cycle);
  304.     gotoxy(1,1);
  305.     cprintf("!%02x!",cycle);
  306.     delay(1);
  307.    if(((inportb(lptportin)>>3)^0xf)!=cycle) chk=1;
  308.   }
  309.   if(!chk) {
  310.     outportb(lptportout,0x1a);
  311.    delay(1);
  312.     if((inportb(lptportin)>>3)!=0x1f) chk=1;
  313.   }
  314.  } while(chk && !err);
  315.  gotoxy(1,1);
  316.  cprintf("    ");
  317.  direction=TO64;
  318.  return err;
  319. }
  320.  
  321. int c64diskfile::exists()
  322. {
  323.  int exists=1;
  324.  
  325.  if((fpd64==NULL)&&(fpf64==NULL)) {
  326.   exists=0;
  327.   fpd64=fopen(fnamed64,"rb");
  328.   if(fpd64 != NULL) {
  329.     fclose(fpd64);
  330.     fpd64=NULL;
  331.     exists=1;
  332.   } else {
  333.     fpf64=fopen(fnamef64,"rb");
  334.     if(fpf64 != NULL) {
  335.      fclose(fpf64);
  336.      fpf64=NULL;
  337.      exists=2;
  338.     }
  339.   }
  340.  }
  341.  return exists;
  342. }
  343.  
  344. int c64diskfile::open()
  345. {
  346.  int success=0;
  347.  if(fpd64==NULL) {
  348.   if(mode==READ) {
  349.     fpd64=fopen(fnamed64,"rb");
  350.     if(fpd64!=NULL) {
  351.      fseek(fpd64,0L,SEEK_END);
  352.      if(ftell(fpd64)==(683L*256L)) {
  353.       fseek(fpd64,0L,SEEK_SET);
  354.       if(fpf64==NULL) {
  355.         fhdr.id1='M';
  356.         fhdr.id2='G';
  357.         fpf64=fopen(fnamef64,"rb");
  358.         if(fpf64!=NULL) {
  359.          fseek(fpf64,0L,SEEK_END);
  360.          if(ftell(fpf64)==((long)sizeof(c64fheader)+683L*3L)) {
  361.           fseek(fpf64,0L,SEEK_SET);
  362.           fread(&fhdr,sizeof(fhdr),1,fpf64);
  363.          } else {
  364.           fclose(fpf64);
  365.           fpf64=NULL;
  366.          }
  367.         }
  368.       }
  369. //   Get Disk ID from F64 file.
  370. //      if(strncmp(fhdr.hdr,C64FHEADER,sizeof(C64FHEADER))==0)  success=1;
  371.       success=1;
  372.      }
  373.     }
  374.     if(!success) {
  375.      fclose(fpd64);
  376.      fclose(fpf64);
  377.      fpd64=NULL;
  378.      fpf64=NULL;
  379.     }
  380.   } else {
  381.     fpd64=fopen(fnamed64,"wb");
  382.     if(fpd64!=NULL) {
  383.      fpf64=fopen(fnamef64,"wb");
  384.      if(fpf64!=NULL) {
  385.       success=1;
  386. //     strncpy(fhdr.hdr,C64FHEADER,sizeof(C64FHEADER));
  387.      fwrite(&fhdr,sizeof(fhdr),1,fpf64);
  388.      } else {
  389.       fclose(fpd64);
  390.       fpd64=NULL;
  391.      }
  392.     }
  393.   }
  394.  }
  395.  return (success);
  396. }
  397.  
  398. void c64diskfile::close(int error)
  399. {
  400.  if(fpd64!=NULL) {
  401.   fclose(fpd64);
  402.   if(error&&(mode==WRITE)) { remove(fnamed64); }
  403.   fpd64=NULL;
  404.   }
  405.  if(fpf64!=NULL) {
  406.   fclose(fpf64);
  407.   if(error&&(mode==WRITE)) { remove(fnamef64); }
  408.   fpf64=NULL;
  409.   }
  410. }
  411.  
  412. void c64diskfile::positiontr(int track)
  413. {
  414.  int i=1,se=0;
  415.  while(i<track) {
  416.   se+=calcsectors(i++);
  417.  }
  418.  fseek(fpd64,256L*(long)se,SEEK_SET);
  419.  fseek(fpf64,(long)sizeof(c64fheader)+3L*(long)se,SEEK_SET);
  420. }
  421.  
  422. void c64diskfile::gettrack(int track,unsigned char *buf)
  423. {
  424.  int se;
  425.  unsigned char chk;
  426.  int i;
  427.  
  428.  for (se=0;se<calcsectors(track);se++) {
  429.   *(buf++)=track;
  430.   *(buf++)=se;
  431.   if (fpf64 != NULL) {
  432.     fread(buf,3,1,fpf64);
  433.     buf+=2;
  434.     *(buf+256)=*buf;
  435.     }
  436.   else {
  437.     *(buf++)=0x2b;
  438.     *(buf++)=0x07;
  439.   }
  440.   fread(buf,256,1,fpd64);
  441.   if (fpf64 != NULL)
  442.     buf+=257;
  443.   else {
  444.     chk = '\0';
  445.     for(i=0;i<256;i++)
  446.       chk ^= *(buf++);
  447.     *(buf++) = chk;
  448.   }
  449.  }
  450. }
  451.  
  452. void c64diskfile::puttrack(int track,unsigned char *buf)
  453. {
  454.  int se;
  455.  
  456.  for (se=0;se<calcsectors(track);se++) {
  457.   buf+=2;
  458.   fwrite(buf,2,1,fpf64);
  459.   buf+=2;
  460.   fwrite(buf,256,1,fpd64);
  461.   buf+=256;
  462.   fwrite(buf,1,1,fpf64);
  463.   buf++;
  464.  }
  465. }
  466.  
  467. void c64diskfile::getid(unsigned char& id1,unsigned char& id2)
  468. {
  469.  id1=fhdr.id1;
  470.  id2=fhdr.id2;
  471. }
  472.  
  473. void c64diskfile::putid(unsigned char& id1,unsigned char& id2)
  474. {
  475.  fhdr.id1=id1;
  476.  fhdr.id2=id2;
  477.  fseek(fpf64,0L,SEEK_SET);
  478.  fseek(fpd64,0L,SEEK_SET);
  479.  fwrite(&fhdr,sizeof(fhdr),1,fpf64);
  480. }
  481.  
  482. void setupscreen()
  483. {
  484. int i;
  485.  clrscr();
  486.  cputs("The C64 <-> PC Fcopy program !");
  487.  for(i=1;i<36;i++) {
  488.   gotoxy(i+3,2);
  489.   cprintf("%c",i/10+'0');
  490.   gotoxy(i+3,3);
  491.   cprintf("%c",i-(i/10)*10+'0');
  492.  }
  493.  for(i=0;i<21;i++) {
  494.   gotoxy(1,i+4);
  495.   cprintf("%2d",i);
  496.  }
  497. }
  498.  
  499. int setupfile(c64diskfile& cf)
  500. {
  501.  int abort=0,success=0;
  502.  char fname[80];
  503.  int i;
  504.  
  505.  while(!abort && !success) {
  506.  
  507.   gotoxy(5,10);
  508.   cputs("Enter PC filename : ");
  509.   _setcursortype(_NORMALCURSOR);
  510.   i=0;
  511.   while((fname[i++]=getchar())!='\n');
  512.   fname[--i]='\0';
  513.   if(i==0) {
  514.     abort=1;
  515.   } else {
  516.     cf.setname(fname);
  517.     if(cf.getmode()==WRITE) {
  518.      i=1;
  519.      if(cf.exists()) {
  520.       gotoxy(5,11);
  521.       cputs("Filename exists. Overwrite y/n ? ");
  522.       i=0;
  523.       while(i==0) {
  524.         switch(tolower(getche())) {
  525.          case 'y' : cf.close(-1);
  526.           i=1;
  527.           break;
  528.          case 'n' : i=2;
  529.           break;
  530.         }
  531.       }
  532.      }
  533.      if(i==1) {
  534.       if(!cf.open()) {
  535.         gotoxy(5,12);
  536.         cprintf("Could not open file %s.D64 or %s.F64 for writing",fname,fname);
  537.         while(!kbhit()); getch();
  538.       } else {
  539.         success=1;
  540.       }
  541.      }
  542.     } else {
  543.      if(!cf.open()) {
  544.       gotoxy(5,11);
  545.       cprintf("Could not open file or illegal format in %s",fname);
  546.       while(!kbhit()); getch();
  547.      } else {
  548.       success=1;
  549.      }
  550.     }
  551.   }
  552.   _setcursortype(_NOCURSOR);
  553.   gotoxy(5,12); clreol();
  554.   gotoxy(5,11); clreol();
  555.   gotoxy(5,10); clreol();
  556.  }
  557.  if(abort) cf.close(-1);
  558.  return abort;
  559. }
  560.  
  561. int getdisk(Joyconnection joy)
  562. {
  563.  int abort=0;
  564.  unsigned char track,sector,scrncode,oldtrack,oldsector,id1,id2;
  565.  int tr,se;
  566.  unsigned char dbuffer[22*sizeof(c64sector)];
  567.  unsigned char *pdb;
  568.  
  569.  c64diskfile cf(WRITE);
  570.  
  571.  setupscreen();
  572.  abort=setupfile(cf);
  573.  if(!abort) {
  574.   track='S';        // scan has been modified
  575.   joy.putblock(&track,1);
  576.  
  577.   oldtrack=0;
  578.   oldsector=0;
  579.  
  580.   tr=1;
  581.   while(tr<36 && !abort) {
  582.  
  583.     if(kbhit()) if(tolower(getch())=='q') abort=0xff;
  584.     joy.putblock(&(unsigned char)abort,1);
  585.     if(!abort) {
  586.      se=calcsectors(tr);
  587.      pdb=dbuffer;
  588.      sector='\0';
  589.      while(sector<se-1) {
  590.       joy.getblock(pdb,sizeof(c64sector));
  591.       track=*pdb;
  592.       sector=*(pdb+1);
  593.       gotoxy(track+3,sector+4);
  594.       scrncode=*(pdb+2);
  595.       cprintf("%c",scrncode);
  596.       if((track==oldtrack)&&(sector==oldsector)) {
  597.         memmove(pdb-sizeof(c64sector),pdb,sizeof(c64sector));
  598.       } else {
  599.         pdb+=sizeof(c64sector);
  600.         oldtrack=track;
  601.         oldsector=sector;
  602.       }
  603.      }
  604.      cf.puttrack(tr,dbuffer);
  605.      tr++;
  606.     }
  607.   }
  608.   if(!abort) {
  609.  
  610.     joy.getblock(&id1,1);
  611.     joy.getblock(&id2,1);
  612.     cf.putid(id1,id2);
  613.   }
  614.  }
  615.  cf.close(abort);
  616.  return(abort);
  617. }
  618.  
  619. int putdisk(Joyconnection joy)
  620. {
  621.  int abort=0;
  622.  unsigned char track,sector,scrncode,retry,id1,id2;
  623.  int tr,se;
  624.  unsigned char dbuffer[sizeof(c64sector)*21];
  625.  unsigned char *pdb;
  626.  c64diskfile cf(READ);
  627.  
  628.  setupscreen();
  629.  abort=setupfile(cf);
  630.  
  631.  if(!abort) {
  632.  
  633.   gotoxy(5,10);
  634.   cputs("Insert Destination disk in the C64 drive (Space)");
  635.   do {
  636.     switch(tolower(getch())) {
  637.      case ' ':abort=0;
  638.           break;
  639.      case 'q':abort=-1;
  640.           break;
  641.      default :abort=1;
  642.     }
  643.   } while(abort==1);
  644.   gotoxy(5,10); clreol();
  645.  }
  646.  if(!abort) {
  647.  
  648.   track='M';   // multi has been modified
  649.   joy.putblock(&track,1);
  650.  
  651.   cf.getid(id1,id2);       // get the two id bytes
  652.   joy.putblock(&id1,1);
  653.   joy.putblock(&id2,1);
  654.   tr=1;
  655.   while(tr<36 && !abort) {
  656.  
  657.     if(kbhit()) {
  658.      if(tolower(getch())=='q') abort=0xff;
  659.     }
  660.     joy.putblock(&(unsigned char)abort,1);
  661.     if(!abort) {
  662.      pdb=dbuffer;
  663.      se=calcsectors(tr);
  664.      cf.gettrack(tr,dbuffer);
  665.      highvideo();
  666.      while(se-- >0) {
  667.  
  668.       joy.putblock(pdb,sizeof(c64sector));
  669.       track=*pdb;
  670.       sector=*(pdb+1);
  671.       gotoxy(track+3,sector+4);
  672.       scrncode=*(pdb+2);
  673.       cprintf("%c",scrncode);
  674.       pdb+=sizeof(c64sector);
  675.      }
  676.      normvideo();
  677.      do {
  678.       joy.getblock(&retry,1);
  679.       if(retry) {
  680.         gotoxy(1,1);
  681.         _setcursortype(_NORMALCURSOR);
  682.         cprintf("Error writing track %d. Retry,Ignore or Quit ? ",tr);
  683.         do {
  684.          switch(tolower(getch())) {
  685.     case 'q': retry='Q';
  686.           abort=1;
  687.           break;
  688.     case 'r': retry='R';
  689.           break;
  690.     case 'i': retry='I';
  691.           break;
  692.     default : retry=0;
  693.          }
  694.         } while(retry==0);
  695.         gotoxy(1,1);
  696.         clreol();
  697.         _setcursortype(_NOCURSOR);
  698.         joy.putblock(&retry,1);
  699.       }
  700.      } while(retry);
  701.     }
  702.     tr++;
  703.   }
  704.  }
  705.  cf.close(abort);
  706.  return(abort);
  707. }
  708.  
  709. void c64puts(unsigned char *s,int n)
  710. {
  711.  unsigned char c;
  712.  while(n--) {
  713.   c=*(s++);
  714.   if(c==0xa0) c=0x20;
  715.   if(c<0x20) c|=0x80;
  716.   putch(c);
  717.  }
  718. }
  719.  
  720. void printdir(unsigned char *dbuffer)
  721. {
  722.  unsigned char blocks[5],*pdb,track,sector;
  723.  int tr,se,row,i,blfree;
  724.  
  725.  static char c64filetype[][4] = {
  726.   "DEL",
  727.   "SEQ",
  728.   "PRG",
  729.   "USR",
  730.   "REL",
  731.   "EL?",
  732.   "EQ?",
  733.   "RG?",
  734.   "SR?",
  735.   "EL?",
  736.   "L??",
  737.   "Q??",
  738.   "G?B",
  739.   "R?L",
  740.   "L?O",
  741.   "H?C"
  742.   };
  743.  
  744.  gotoxy(45,1);
  745.  highvideo();
  746.  cputs("      ");
  747.  c64puts(dbuffer+0x90+4,23);
  748.  normvideo();
  749.  
  750. // parse sectors.
  751.  
  752.  track=18;
  753.  sector=1;
  754.  se=21;
  755.  row=2;
  756.  while(track==18) {
  757.   pdb=dbuffer+sizeof(c64sector)*sector+4;
  758.   track=*(pdb++);
  759.   sector=*(pdb++);
  760.   for(i=0;i<8;i++) {
  761.     if(row==25) {
  762.      while(!kbhit());
  763.      getch();
  764.      while(--row>2) {
  765.       gotoxy(45,row);
  766.       clreol();
  767.       }
  768.      }
  769.     if(*pdb!='\0') {
  770.      gotoxy(45,row++);
  771.      cprintf("%5d ",(int) (*(unsigned int *)(pdb+0x1c)));
  772.      c64puts(pdb+3,16);
  773.      cprintf("   %s%c",c64filetype[*pdb&0xf],((*pdb&0x40)?'<':' '));
  774.     }
  775.     pdb+=32;
  776.   }
  777.   if(--se<0) track=0; // cyclic directories never stop.
  778.  }
  779.  blfree=0;
  780.  for(tr=1;tr<36;tr++) {
  781.   blfree+=(int)(*(dbuffer+4+tr*4));
  782.   if(tr==17) tr++;
  783.   }
  784.  gotoxy(45,row);
  785.  cprintf("%5d BLOCKS FREE.",blfree);
  786.  while(!kbhit());
  787.  getch();
  788. }
  789.  
  790. void showc64dir(Joyconnection joy)
  791. {
  792.  unsigned char track,sector,oldtrack,oldsector;
  793.  int se,i,row;
  794.  unsigned char dbuffer[sizeof(c64sector)*22];
  795.  unsigned char *pdb;
  796.  track='D';
  797.  joy.putblock(&track,1);
  798.  se=calcsectors(18);
  799.  track='\0';
  800.  joy.putblock(&track,1);    // No abort
  801.  oldtrack=0;
  802.  oldsector=0;
  803.  pdb=dbuffer;
  804.  sector='\0';
  805.  while(sector<se-1) {
  806.   joy.getblock(pdb,sizeof(c64sector));
  807.   track=*pdb;
  808.   sector=*(pdb+1);
  809.   if((track==oldtrack)&&(sector==oldsector)) {
  810.     memmove(pdb-sizeof(c64sector),pdb,sizeof(c64sector));
  811.   } else {
  812.     pdb+=sizeof(c64sector);
  813.     oldtrack=track;
  814.     oldsector=sector;
  815.   }
  816.  }
  817.  printdir(dbuffer);
  818. }
  819.  
  820. void showc64filedir()
  821. {
  822.  unsigned char dbuffer[sizeof(c64sector)*21];
  823.  int abort,se;
  824.  
  825.  c64diskfile cf(READ);
  826.  
  827.  setupscreen();
  828.  abort=setupfile(cf);
  829.  if(!abort) {
  830.   cf.positiontr(18);
  831.   cf.gettrack(18,dbuffer);
  832.   printdir(dbuffer);
  833.  }
  834. }
  835.  
  836. void toggleretries(int& r,Joyconnection j)
  837. {
  838.  unsigned char tmp='T';
  839.  
  840.  j.putblock(&tmp,1);
  841.  
  842.  if(r==1) {
  843.   r=5;
  844.  } else {
  845.   r=1;
  846.  }
  847. }
  848.  
  849. #define BIOSLPT1ADR 0x408L
  850.  
  851. int main(int argc,char *argv[])
  852. {
  853.  int lpt=1;
  854.  int port=0;
  855.  char c;
  856.  int quit;
  857.  int retries=1;
  858.  
  859.  normvideo();
  860.  while(argc--) {
  861.   if(strnicmp(argv[0],"lpt",3)==0) {
  862.     lpt=(*argv[3]-'0');
  863.   }
  864.  }
  865.  if((lpt<5) && (lpt>0)) {
  866.   port=*(long far*)(BIOSLPT1ADR+(lpt-1)*2);
  867.   }
  868.  if(!port) {
  869.   printf("No LPT%c port found!\n",lpt+'0');
  870.  } else {
  871.  
  872.   Joyconnection j(port);
  873.  
  874.   _setcursortype(_NOCURSOR);
  875.   clrscr();
  876.  
  877.   gotoxy(1,3);
  878.  
  879.   cprintf("Waiting for connection...\r\n");
  880.   cprintf("Press 'q' to quit\r\n");
  881.  
  882.   if(j.init()) {
  883.     cprintf("abandoning program.");
  884.   } else {
  885.     quit=0;
  886.     while(!quit) {
  887.      setupscreen();
  888.      gotoxy(5,5);
  889.      cprintf("(c) 1993 The Whiz-zards Association");
  890.      gotoxy(5,7);
  891.      cprintf("  1 - Backup C64 disk to PC\r\n");
  892.      gotoxy(5,8);
  893.      cprintf("  2 - Restore C64 disk from PC\r\n");
  894.      gotoxy(5,9);
  895.      cprintf("  3 - Show C64 directory\r\n");
  896.      gotoxy(5,10);
  897.      cprintf("  4 - Show PC directory\r\n");
  898.      gotoxy(5,11);
  899.      cprintf("  5 - Show C64 directory from PC file");
  900.      gotoxy(5,12);
  901.      cprintf("  6 - Read retries on C64 (now %d)",retries);
  902.      gotoxy(5,14);
  903.      cprintf("  Q - Quit\r\n");
  904.      gotoxy(5,15);
  905.      cprintf("Pressing 'Q' during an option aborts.");
  906.      gotoxy(5,16);
  907.      cprintf("Please enter your choice : ");
  908.      _setcursortype(_NORMALCURSOR);
  909.      c=tolower(getche());
  910.      _setcursortype(_NOCURSOR);
  911.      switch(tolower(c)) {
  912.       case '1': getdisk(j);
  913.              break;
  914.       case '2': putdisk(j);
  915.              break;
  916.       case '3': showc64dir(j);
  917.              break;
  918.       case '4': clrscr();
  919.              system("dir");
  920.              getch();
  921.              break;
  922.       case '5': showc64filedir();
  923.              break;
  924.       case '6': toggleretries(retries,j);
  925.              break;
  926.       case 'q': quit=1;
  927.              break;
  928.      }
  929.     }
  930.   }
  931.   j.abort();
  932.  }
  933.  return(0);
  934. }
  935.  
  936.  
  937.