home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / lambda / soundpot / p / pcpip2.lbr / PCPIP.CZ / PCPIP.C
Encoding:
C/C++ Source or Header  |  1993-10-25  |  18.9 KB  |  735 lines

  1. /**************************************************/                    
  2. /* PCPIP - CPM to PC-DOS FILE TRANSFER UTILITY    */
  3. /*  Written by Eric Leininger                     */
  4. /*             2647 Welsford Rd.                  */
  5. /*             Columbus Ohio 43221                */
  6. /*                                                */
  7. /* Do whatever you want with this program,        */
  8. /*  except please do not sell it or any parts     */
  9. /*  of it.                                        */
  10. /*                                                */
  11. /* This program does direct calls to BIOS         */
  12. /*  routines and as distributed will work only    */
  13. /*  with Osborne 1 machines.                      */
  14. /*                                                */
  15. /* For those of you who know C well, sorry if     */
  16. /*  some of my techniques are crude. One of these */
  17. /*  days I'll read my manual.                     */
  18. /*                                                */
  19. /* Most of the technical information regarding    */
  20. /*  how this works (i.e. what is the fat I keep   */
  21. /*  talking about) can be found in the IBM DOS    */
  22. /*  manual Appendix C.                            */
  23. /*                                                */
  24. /**************************************************/                    
  25. /* Compile instructions:              */
  26. /*    -Developed using the C/80 compiler 2.0       */
  27. /*     and the M80 assembler              */
  28. /*    -Needs to be linked with:          */
  29. /*     CLIB.REL - C80 Library              */
  30. /*     DUMP.REL - debugging routines          */
  31. /*     BISOCALL.REL - BIOS call interface      */
  32. /*     PCLIB.REL - miscellaneous routines      */
  33. /*               (some specific to PCPIP)      */
  34. /*     PRINTF.REL - formatted print routines      */
  35. /*     END.REL - end marker              */
  36. /**************************************************/
  37. /* Change History:                  */
  38. /*     Rev 0 12/29/82 - Original Release      */
  39. /*     Rev 1  8/09/83 - Added double sided      */
  40. /*     Rev 1.1 2/3/84 - Forced drive a: on      */
  41. /*                      IBM to CPM xfer because   */
  42. /*            of problem vith vector    */
  43. /*              version           */
  44. /*     Rev 2.0 3/10/84- Added support for DOS       */
  45. /*                      2.0 (9 sectors/track)      */
  46. /**************************************************/
  47. /* Known Problems:                  */
  48. /*     -Does not look at all directory entries on */
  49. /*      a double sided disk (its on the flip side)*/ 
  50. /*     -Will not correctly display the size of the*/
  51. /*    PC-Dos file if over 64K.          */
  52. /*     -Can create duplicate directory entries on */
  53. /*    the PC-DOS disk.              */
  54. /*     -BIOS errors are not trapped          */
  55. /**************************************************/         
  56. /* Note undocumented features:              */
  57. /*    -Entering 'y' before hiting return after  */ 
  58. /*       inserting disks invokes the DEBUG mode.  */
  59. /*    -Entering 's' at menu displays the FAT    */
  60. /*       chain                         */
  61. /**************************************************/ 
  62.  
  63. #include PRINTF.H
  64. #define BDOS 5
  65. static char *copybuf;    /*  copy buffer        */ 
  66. static char *dirbuf;    /*  point to pc dir    */
  67. static char *fat;    /*  point to file      */
  68.                      /*   allocation table  */
  69.  
  70. static char debug;    /*  y for debug = yes  */
  71. static int  f1,ferror;    /*  file flags         */
  72.  
  73. static char disktyp;       /*  s=single; d=double */
  74. static int  secclus;    /*  sectors/cluster    */
  75. static int  cluslen;    /*  cluster length     */
  76. static int  secoff;     /*  sector offset of   */
  77.                         /*   first cluster           */
  78. static int  dostyp;        /*  1=1.1; 2=2.0       */
  79. static int  sectrk;     /*  sectors/track      */
  80. static int  fatsec;        /*  first fat sector   */
  81. static int  dirsec;        /*  first dir sector   */
  82. static int  dirnum;        /*  number of directory*/
  83.                            /*   entries           */
  84. static int  maxfat;        /*  highest cluster    */
  85.  
  86. static int  side,track,sector;
  87.                         /* these always refer  */
  88.                         /* to the osborne disk */
  89.                         /* (I think)           */
  90.  
  91. main(argc,argv)
  92. int argc; char *argv[];
  93. {    static int f2,c,d;
  94.         static int dev;
  95. /*    static char *cpmver,cpmvec; */
  96.  
  97.     printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); 
  98.     printf("Program PCPIP  - Osborne Rev 2.0\n\n\n"); 
  99.     printf("CPM / PC-DOS file transfer utility\n");
  100.     printf("   Developed by Eric Leininger\n\n\n");
  101.  
  102.     printf("Insert CPM disk in drive A,\n");
  103.     printf("       PC disk in drive B \n\n");
  104.     printf("Hit return to continue...\n");
  105.     c = getone();
  106.     debug = c;       /* if "y" then debug on */
  107.  
  108. /*      Get Buffer Space (total of 7K)             */
  109.     copybuf = alloc(2560); /* clusters in/out  */
  110.         dirbuf = alloc(3584);  /* pc-dos directory */
  111.         fat = alloc(1024);     /* pc-dos fat       */
  112.  
  113. /*    Read Directory on PC disk   */
  114.     pcdirin();
  115.  
  116. /*      Option Menu                 */
  117.     while (c != 'e')
  118.        {
  119.            printf("\nSource for copy? (c=CPM, p=PC, r=reset, e=EXIT)\n");    
  120.        c = getone();
  121.     
  122. /*         Search and copy to CPM            */
  123.        if (c == 'p')
  124.           srchdir();
  125.  
  126. /*         Copy to PC                       */
  127.        if (c == 'c') {
  128.           oztopc();
  129.           c = 'c';
  130.        }    
  131.  
  132. /*         Reset for disk change            */
  133.        if (c == 'r')
  134.           {
  135.                  printf("Change disks and hit return to continue...\n");
  136.           c = getone();
  137.           debug = c;    
  138.           pcdirin();
  139.           }
  140.  
  141. /*         List cluster chain                */
  142.            if (c == 's')
  143.           lstch();
  144.        }
  145.  
  146.     printf("\n\n*** End of PCPIP ***\n\n\n");
  147.     exit();
  148.  
  149.  
  150. }
  151.  
  152.  
  153. pcdirin()
  154. /* read fat, determine disk type, and then read   */
  155. /* the directory.                                 */  
  156. {    int dev,cluster;
  157.     char *secadd;    
  158.  
  159.     reset();
  160.  
  161. /*    Read File Allocation Table (first copy)   */
  162.         fo≥ (secto≥ ╜ 4╗ secto≥ <╜ 11╗ secto≥++)
  163.         { dev = 1;
  164.         seldev(dev);    
  165.         track = 0;
  166.         settrk(track);
  167.         secadd= fat+((sector-4)*128);
  168.         setdma(secadd);
  169.         setsec(sector);
  170.         cpmread();
  171.         }
  172.  
  173. /*     determine disk type                      */
  174. /*       (single or double, 8 or 9 tracks)      */
  175.     disktyp = '?';
  176.     cluster = getfat(0,fat);
  177.     if (cluster == 0x0FFE)
  178.       {
  179.           printf("..Single sided diskette, 8 sectors/track..\n");
  180.       disktyp = 's';
  181.           dostyp = 1;
  182.       cluslen = 512;
  183.           dirsec = 12;
  184.           dirnum = 64;
  185.           maxfat = 314;
  186.           sectrk = 8;
  187.           secclus = 1;
  188.           secoff = 7;
  189.           }
  190.     if (cluster == 0x0FFF)
  191.       {
  192.           printf("..Double sided diskette, 8 sectors/track..\n\n");
  193.       printf("  Note that PC to CPM file transfers will\n");
  194.       printf("  fail if any data is on side 2. Also only\n");
  195.       printf("  80 of the 112 directory entries are \n");
  196.       printf("  available.\n");
  197.       disktyp = 'd';
  198.           dostyp = 1;
  199.       cluslen = 1024;
  200.           dirsec = 12;
  201.           dirnum = 80;
  202.           maxfat = 316;
  203.           sectrk = 8;
  204.           secclus = 2;
  205.           secoff = 10;
  206.       }
  207.  
  208.     if (cluster == 0x0FFC)
  209.       {
  210.           printf("..Single sided diskette, 9 sectors/track..\n");
  211.       printf("  Note that only the root directory\n");
  212.       printf("  is available.\n");
  213.       disktyp = 's';
  214.           dostyp = 2;
  215.       cluslen = 512;
  216.           dirsec = 20;
  217.           dirnum = 64;
  218.           maxfat = 352;
  219.           sectrk = 9;
  220.           secclus = 1;
  221.           secoff = 9;
  222.       }
  223.     if (cluster == 0x0FFD)
  224.       {
  225.           printf("..Double sided diskette, 9 sectors/track..\n\n");
  226.       printf("  Note that PC to CPM file transfers will\n");
  227.       printf("  fail if any data is on side 2, only 64\n");
  228.       printf("  of the 112 root directory entries are \n");
  229.       printf("  available (sub-directories are not\n");
  230.           printf("  supported).\n");
  231.       disktyp = 'd';
  232.           dostyp = 2;
  233.       cluslen = 1024;
  234.           dirsec = 20;
  235.           dirnum = 64;
  236.           maxfat = 355;
  237.           sectrk = 9;
  238.           secclus = 2;
  239.           secoff = 12;
  240.       }
  241.     if (disktyp == '?')
  242.       {
  243.       printf("*** ERROR - UNRECOGNIZED DISK ***\n");
  244.       printf("  First fat entry = %x\n",cluster);
  245.       exit();
  246.       }
  247.  
  248. /*    Read directory sectors                     */
  249.     printf("\nPlease wait - reading IBM directory...");
  250.         fo≥ (secto≥ ╜ dirsec; secto≥ <╜ dirsec - 1 + dirnum/4; secto≥++)
  251.         { dev = 1;
  252.         seldev(dev);    
  253.         track = 0;
  254.         settrk(track);
  255.         secadd= dirbuf+((sector-dirsec)*128);
  256.         setdma(secadd);
  257.         setsec(sector);
  258.         cpmread();
  259.         }
  260.     printf("  Thank you.\n");
  261.     
  262.     return;
  263. }
  264.  
  265. srchdir()
  266. /*    Decode directory                          */
  267. {    int entry;
  268.     int found;
  269.     char used,erased,dir,never,*entryadd;    
  270.  
  271.     erased = 0xE5;
  272.     dir = 0x2E;
  273.     never = 0x00;
  274.     for (entry = 0; entry <= dirnum -1; entry++)
  275.         { entryadd = dirbuf+(entry*32);
  276.         used = *entryadd;
  277.         if (used != erased && used != dir && used != never)
  278.             {found++;
  279.             getdir(found,entryadd);
  280.             }
  281.         }
  282.     return;
  283. }
  284.  
  285. getdir(found,entryadd)
  286. int found;
  287. char *entryadd;
  288. {
  289.     int bytes,size,cluster,*pint;
  290.     char ans,fname[15],name[9],ext[4];
  291.     bytes = 8;
  292.     getstring(8,name,entryadd);
  293.     entryadd = entryadd + 8;
  294.     getstring(3,ext,entryadd);
  295.      cname(fname,name,ext);
  296.     pint = entryadd + 20;
  297.     size = *pint;
  298.     pint = entryadd + 18;
  299.     cluster = *pint;
  300. /* need to decode 4 byte size fields */
  301.     printf("\n\nFile = %s ; %d bytes ; %d = 1st cluster\n",fname,size,cluster);
  302.     printf("Copy to disk A:?(y/n)\n");
  303.     ans = getone();
  304.     if (ans == 'y')
  305.         { pctooz(fname,cluster);
  306.                 }
  307.     return;
  308. }
  309.  
  310.  
  311. pctooz(name,cluster)
  312. int cluster;
  313. char name[];
  314. /**************************************************/                    
  315. /* PCOZ                                           */
  316. /* Copies the file 'name' to the osborne disk.    */
  317. /* Uses the cluster to begin, then chains through */
  318. /* the FAT for the remaining.                     */
  319. /**************************************************/
  320. {
  321.     int fchan;
  322.     char upline;
  323.     upline = '\013';
  324.     printf("\n\nCopying file %s PC => CPM\n",name);
  325.     ferror = 0;
  326.     fchan = file(name);
  327.     if (ferror != 1)
  328.        {    
  329.        printf("  First cluster=%d\n",cluster);
  330.        while (ferror != 1 && cluster < maxfat)
  331.             {
  332.         pcread(cluster);
  333.         if (side == 0)
  334.            {    
  335.            ferror = write(fchan,copybuf,cluslen);
  336.            if (ferror != cluslen)
  337.              {
  338.              printf("\n\n*** WRITE ERROR, COPY ABORTED ***\n\n");
  339.              ferror = 1;
  340.              }
  341.             }
  342.  
  343.         cluster = getfat(cluster,fat);
  344.         printf("%c  Next cluster=%d     \n",upline,cluster);
  345.         }
  346.            fclose(fchan);
  347.        }
  348.     return;
  349. }
  350.  
  351. pcread(cluster)
  352. int cluster;
  353. /**************************************************/                    
  354. /* PCREAD                                         */
  355. /* Reads the cluster requested into the copy      */
  356. /*  buffer.                      */
  357. /**************************************************/
  358. {
  359.     int dev,secr,check,check1;
  360.     char ans,c,*secadd;
  361.  
  362.     dev = 1;
  363.  
  364. if (debug == 'y') printf("Reading cluster %d\n",cluster);
  365.  
  366. /* decode cluster to osborne side, track,         */
  367. /* and sector                                     */
  368.         osbsec(cluster);
  369.  
  370.         if (side == 1)
  371.          {
  372.      printf("***OOPS - attempt to read flip side***\n");
  373.      printf(" ---Cluster skipped, copy continuing--\n"); 
  374.      printf("Hit return to continue\n");
  375.      c = getone();
  376.      }
  377.  
  378.     if (side != 1)
  379.      {
  380.          for (secr = sector;secr < sector+cluslen/128;secr++)
  381.            {
  382. if (debug == 'y') printf("Reading Osborne track %d sector %d\n",track,secr);
  383.            seldev(dev);    
  384.        settrk(track);
  385.        setsec(secr);
  386.        secadd = copybuf+(secr-sector)*128;
  387.        setdma(secadd);
  388.        cpmread();
  389.        }
  390.          }
  391.  
  392.     return;
  393. }
  394.  
  395. osbsec(cluster)
  396. /* decode cluster number to osborne side, track,  */
  397. /* and sector                                     */
  398. int(cluster);
  399. {
  400.     int logsec,check;
  401.  
  402. /* find pc-dos logical sector                     */ 
  403.         logsec = cluster - 2;
  404.         logsec = logsec * secclus;
  405.         logsec = logsec + secoff;
  406. /* find pc-dos track and sector                   */
  407.         track = logsec / sectrk;
  408.         sector = logsec - track * sectrk;
  409. /* convert to osborne track and sector            */         
  410.      sector = sector * 4;
  411.     side = 0;
  412.     if (disktyp == 'd')
  413.           {
  414.       check = track / 2;
  415.       if (track != check * 2)
  416.         side = 1;
  417.       track = track /2;
  418.       }
  419.  
  420. /* return                                        */
  421.  
  422.     return;
  423.  
  424. }
  425.  
  426.  
  427. lstch()
  428. {          int sect,nexts,empty;
  429.     empty = 0;
  430.     for (sect = 1;sect < maxfat;sect++)
  431.       { nexts = getfat(sect,fat);
  432.         printf("FAT of %d = %d \n",sect,nexts);
  433.         if(nexts == 0)
  434.           empty++;
  435.         if(empty > 35)
  436.           sect = maxfat;     
  437.       }
  438.     return;
  439. }
  440.  
  441. getnext(cluster)
  442. /* Get the next free cluster  */
  443. int(cluster);
  444.     {
  445.     int i,j,next;
  446. if (debug == 'y') printf("Looking for free cluster at %d\n",cluster);
  447.     next = cluster;
  448.     while (next != 0 && cluster <= maxfat)
  449.        {
  450.        next = getfat(cluster,fat);
  451.  
  452. /*     Check for flip side       */
  453.            osbsec(cluster);
  454. if (debug == 'y') printf("Cluster %d, side %d \n",cluster,side);
  455.            if (side == 1)
  456.               next = 1;
  457.  
  458.        cluster++;
  459.        }
  460.  
  461. if (debug == 'y') printf("Found free cluster at %d\n",cluster-1);
  462.  
  463.     if(next != 0)
  464.        {
  465.        printf("***ERROR - PC disk full***\n");
  466.        ferror = 1;
  467.        }
  468.  
  469.     return(cluster-1);
  470.     }
  471.  
  472.  
  473.  
  474.  
  475. file(fname)
  476. char fname[];
  477. /**************************************************/                    
  478. /* FILE                                           */
  479. /*                                                */
  480. /* This routine opens the file 'fname' and        */
  481. /* the channel number.                            */
  482. /*                                                */
  483. /**************************************************/
  484. {    int i;
  485.     char ans,dname[15];
  486. /*  First, see if file exists                     */
  487. /*    i = fopen(fname,"r");
  488.     if (i > 0)
  489.        {
  490.        fclose(i);
  491.        printf("File exists on drive A:\n");
  492.        printf("  OK to overwrite? (Y/N)\n");
  493.         ans = getone();
  494.        if (ans != 'y')
  495.           {
  496.           ferror = 1;
  497.           return;            
  498.               }
  499.            } */
  500.  
  501. /*   Now open for output                          */
  502. /* Force to drive A:                              */
  503.     for ( i = 0; i <= 13; i++)
  504.       dname[i+2] = fname[i];
  505.     dname[0] = 'A';
  506.     dname[1] = ':';
  507.     i = fopen(fname,"w");
  508.     if (i > 0) return i;
  509.     printf("Can't Open: %s\n",dname);
  510.     ferror = 1;
  511.     return;
  512.  
  513.  
  514.  
  515. oztopc()
  516.     {
  517.     char name[15];
  518.     int i,max;
  519.     max = 14;
  520.     printf("\nOK, CPM to PC file transfer\n");
  521.     printf("Enter file name:");
  522.     istring(&name[0],max);
  523.     ozpc(name);
  524.     printf("...Copy complete\n");
  525.     return;
  526.     }
  527.  
  528.  
  529. pcdirout()
  530. /*  Rewrite directory and FAT on PC disk          */
  531. {    int base,dev,fatsize;
  532.     char *secadd;    
  533.  
  534. /*    Write directory sectors                     */
  535.         fo≥ (secto≥ ╜ dirsec╗ secto≥ <╜ dirsec-1+dirnum/4╗ secto≥++)
  536.         { dev = 1;
  537.         seldev(dev);    
  538.         track = 0;
  539.         settrk(track);
  540.         secadd= dirbuf+((sector-dirsec)*128);
  541.         setdma(secadd);
  542.         setsec(sector);
  543.         cpmput();
  544.         }
  545.  
  546. /*    Write File Allocation Table  (two copies)  */
  547.     fatsize = dostyp * 4;
  548.     for (base = 4; base <= 4 + fatsize;base = base + fatsize)
  549.        {
  550.            fo≥ (secto≥ ╜ base╗ secto≥ <╜ base-1+fatsize╗ secto≥++)
  551.           { dev = 1;
  552.           seldev(dev);    
  553.           track = 0;
  554.           settrk(track);
  555.           secadd= fat+((sector-base)*128);
  556.           setdma(secadd);
  557.           setsec(sector);
  558.           cpmput();
  559.           }
  560.        }
  561.  
  562.     return;
  563. }
  564.  
  565. ozpc(name)
  566. char name[];
  567. {    
  568.     int i,fchan,cread;
  569.     int length,cluster,start,next;
  570.     char upline,dname[17];
  571.     upline = '\013';
  572. /* Force name to drive A:                        */
  573.     for (i = 0; i <= 14; i++)
  574.      dname[i] = name[i];
  575.         if (dname[1] != ':') {
  576.       for (i = 14; i >= 0; i--)
  577.         dname[i+2] = dname[i];
  578.     }
  579.     dname[0] = 'A';
  580.     dname[1] = ':';
  581. /* make sure drive is not specified on PC-DOS dir */
  582.     for (i = 0; i <= 14; i++)
  583.      name[i] = dname[i+2];
  584.     printf("\n\nCopying file %s   (CPM => PC)\n",dname);
  585.  
  586.     ferror = 0;
  587.     fchan = fopen(dname,"rb");
  588.     if (fchan == 0)
  589.        {
  590.        printf("*** Can't open file ***\n");
  591.        return;
  592.        }
  593.  
  594. /* Find first empty cluster                    */
  595.     start = getnext(2);
  596. /* And go to it                               */
  597.     printf("\n");
  598.     next = start;
  599.     length = 0;
  600.     cread = read(fchan,copybuf,cluslen);
  601.     while (cread > 0 && ferror ==0) {
  602. printf("%c Have read %d, cluster = %d, next = %d\n",upline,cread,cluster,next);
  603.         cluster = next;
  604.         next = pcwrite(cluster);
  605.         length = length + cread;    
  606.         cread = read(fchan,copybuf,cluslen);
  607.         }
  608.          
  609. printf("End of read, last read was %d, last write to %d\n",cread,cluster);
  610.  
  611.     if (ferror ==0);
  612.          {
  613.            pclose(cluster);
  614.        makedir(name,start,length);
  615.  
  616. /* rewrite fat and directory */
  617.        pcdirout();
  618.  
  619.        printf("\nCopy complete\n");
  620.        }
  621.  
  622.     fclose(fchan);
  623.     return;
  624.  
  625. makedir(name,start,length)
  626. char name[];
  627. int  start,length;    
  628.     {
  629.     char c;
  630.     int i,entry;
  631.     char used,erased,never,*entryadd,*namadd;    
  632.  
  633.     int found;
  634.     int bytes,size,*pint;
  635.     char ans,;
  636.  
  637.     printf("Make PC directory entry...\n");
  638.     printf("   Name = %s\n",name);
  639.     printf("   First Sector = %d\n",start);
  640.     printf("   Length = %d\n",length);
  641.  
  642. /* First get address of first available directory */
  643. /*  entry                                         */
  644.  
  645.  
  646.     erased = 0xE5;
  647.     never = 0x00;
  648.     for (entry = 0; entry <= 63; entry++)
  649.         { entryadd = dirbuf+(entry*32);
  650.         used = *entryadd;
  651.         if (used == erased || used == never)
  652.             break;
  653.         }
  654.  
  655. /* Now format new entry                          */
  656.  
  657.     for (i = 0;i <= 31;i++)
  658.       *(entryadd + i) = '\0';
  659.     pint = entryadd + 26;
  660.     *pint = start;
  661.     pint = entryadd + 28; 
  662.     *pint = length;
  663.  
  664.     for (i = 0;i <= 10;i++)
  665.       *(entryadd + i) = ' ';
  666.  
  667.     namadd = entryadd;
  668.     for (i = 0;i <= 12; i++)
  669.        {
  670.        if (name[i] != '.' && name[i] != '\0')
  671.           {
  672.           *namadd = name[i];
  673.           namadd = namadd +1;
  674.           }
  675.  
  676.        if (name[i] == '.')
  677.           namadd = entryadd + 8;
  678.  
  679.        if (name[i] == '\0')
  680.           break;
  681.  
  682.        }
  683.         
  684. if (debug == 'y') dump(32,entryadd,"New dir entry = ");
  685.     return;
  686.     }
  687.  
  688.  
  689. pclose(cluster)
  690. int cluster;
  691.     {
  692.     char c;
  693.     printf("Close PC fat chain...\n");
  694.     printf("   Last Sector = %d\n",cluster);
  695.     pchain(cluster,0XFFF,fat);
  696.     return;
  697.     }
  698.  
  699. pcwrite(cluster)
  700. int cluster;
  701. /**************************************************/                    
  702. /* PCWRITE                                        */
  703. /* Writes the cluster requested from the copy     */
  704. /*  buffer                                        */
  705. /**************************************************/
  706. {
  707.     int next,dev,secr;
  708.     char ans,*secadd;
  709. if (debug == 'y') printf("Writing cluster %d\n",cluster);
  710.  
  711.     dev = 1;
  712.  
  713.     osbsec(cluster);
  714.  
  715.     for (secr = sector;secr < sector+cluslen/128;secr++)
  716.            {
  717. if (debug == 'y') printf("Writing Osborne track %d sector %d\n",track,secr);
  718.            seldev(dev);    
  719.        settrk(track);
  720.        setsec(secr);
  721.        secadd = copybuf+(secr-sector)*128;
  722.        setdma(secadd);
  723.        cpmput();
  724.        }
  725.     next = getnext(cluster+1);
  726.  
  727.     pchain(cluster,next,fat);
  728.  
  729.     return(next);
  730. }
  731.  
  732. /*  ************* END OF PCPIP.C *************  */
  733.