home *** CD-ROM | disk | FTP | other *** search
- /**************************************************/
- /* PCPIP - CPM to PC-DOS FILE TRANSFER UTILITY */
- /* Written by Eric Leininger */
- /* 2647 Welsford Rd. */
- /* Columbus Ohio 43221 */
- /* */
- /* Do whatever you want with this program, */
- /* except please do not sell it or any parts */
- /* of it. */
- /* */
- /* This program does direct calls to BIOS */
- /* routines and as distributed will work only */
- /* with Osborne 1 machines. */
- /* */
- /* For those of you who know C well, sorry if */
- /* some of my techniques are crude. One of these */
- /* days I'll read my manual. */
- /* */
- /* Most of the technical information regarding */
- /* how this works (i.e. what is the fat I keep */
- /* talking about) can be found in the IBM DOS */
- /* manual Appendix C. */
- /* */
- /**************************************************/
- /* Compile instructions: */
- /* -Developed using the C/80 compiler 2.0 */
- /* and the M80 assembler */
- /* -Needs to be linked with: */
- /* CLIB.REL - C80 Library */
- /* DUMP.REL - debugging routines */
- /* BISOCALL.REL - BIOS call interface */
- /* PCLIB.REL - miscellaneous routines */
- /* (some specific to PCPIP) */
- /* PRINTF.REL - formatted print routines */
- /* END.REL - end marker */
- /**************************************************/
- /* Change History: */
- /* Rev 0 12/29/82 - Original Release */
- /* Rev 1 8/09/83 - Added double sided */
- /* Rev 1.1 2/3/84 - Forced drive a: on */
- /* IBM to CPM xfer because */
- /* of problem vith vector */
- /* version */
- /* Rev 2.0 3/10/84- Added support for DOS */
- /* 2.0 (9 sectors/track) */
- /**************************************************/
- /* Known Problems: */
- /* -Does not look at all directory entries on */
- /* a double sided disk (its on the flip side)*/
- /* -Will not correctly display the size of the*/
- /* PC-Dos file if over 64K. */
- /* -Can create duplicate directory entries on */
- /* the PC-DOS disk. */
- /* -BIOS errors are not trapped */
- /**************************************************/
- /* Note undocumented features: */
- /* -Entering 'y' before hiting return after */
- /* inserting disks invokes the DEBUG mode. */
- /* -Entering 's' at menu displays the FAT */
- /* chain */
- /**************************************************/
-
- #include PRINTF.H
- #define BDOS 5
- static char *copybuf; /* copy buffer */
- static char *dirbuf; /* point to pc dir */
- static char *fat; /* point to file */
- /* allocation table */
-
- static char debug; /* y for debug = yes */
- static int f1,ferror; /* file flags */
-
- static char disktyp; /* s=single; d=double */
- static int secclus; /* sectors/cluster */
- static int cluslen; /* cluster length */
- static int secoff; /* sector offset of */
- /* first cluster */
- static int dostyp; /* 1=1.1; 2=2.0 */
- static int sectrk; /* sectors/track */
- static int fatsec; /* first fat sector */
- static int dirsec; /* first dir sector */
- static int dirnum; /* number of directory*/
- /* entries */
- static int maxfat; /* highest cluster */
-
- static int side,track,sector;
- /* these always refer */
- /* to the osborne disk */
- /* (I think) */
-
- main(argc,argv)
- int argc; char *argv[];
- { static int f2,c,d;
- static int dev;
- /* static char *cpmver,cpmvec; */
-
- printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
- printf("Program PCPIP - Osborne Rev 2.0\n\n\n");
- printf("CPM / PC-DOS file transfer utility\n");
- printf(" Developed by Eric Leininger\n\n\n");
-
- printf("Insert CPM disk in drive A,\n");
- printf(" PC disk in drive B \n\n");
- printf("Hit return to continue...\n");
- c = getone();
- debug = c; /* if "y" then debug on */
-
- /* Get Buffer Space (total of 7K) */
- copybuf = alloc(2560); /* clusters in/out */
- dirbuf = alloc(3584); /* pc-dos directory */
- fat = alloc(1024); /* pc-dos fat */
-
- /* Read Directory on PC disk */
- pcdirin();
-
- /* Option Menu */
- while (c != 'e')
- {
- printf("\nSource for copy? (c=CPM, p=PC, r=reset, e=EXIT)\n");
- c = getone();
-
- /* Search and copy to CPM */
- if (c == 'p')
- srchdir();
-
- /* Copy to PC */
- if (c == 'c') {
- oztopc();
- c = 'c';
- }
-
- /* Reset for disk change */
- if (c == 'r')
- {
- printf("Change disks and hit return to continue...\n");
- c = getone();
- debug = c;
- pcdirin();
- }
-
- /* List cluster chain */
- if (c == 's')
- lstch();
- }
-
- printf("\n\n*** End of PCPIP ***\n\n\n");
- exit();
-
-
- }
-
-
- pcdirin()
- /* read fat, determine disk type, and then read */
- /* the directory. */
- { int dev,cluster;
- char *secadd;
-
- reset();
-
- /* Read File Allocation Table (first copy) */
- fo≥ (secto≥ ╜ 4╗ secto≥ <╜ 11╗ secto≥++)
- { dev = 1;
- seldev(dev);
- track = 0;
- settrk(track);
- secadd= fat+((sector-4)*128);
- setdma(secadd);
- setsec(sector);
- cpmread();
- }
-
- /* determine disk type */
- /* (single or double, 8 or 9 tracks) */
- disktyp = '?';
- cluster = getfat(0,fat);
- if (cluster == 0x0FFE)
- {
- printf("..Single sided diskette, 8 sectors/track..\n");
- disktyp = 's';
- dostyp = 1;
- cluslen = 512;
- dirsec = 12;
- dirnum = 64;
- maxfat = 314;
- sectrk = 8;
- secclus = 1;
- secoff = 7;
- }
- if (cluster == 0x0FFF)
- {
- printf("..Double sided diskette, 8 sectors/track..\n\n");
- printf(" Note that PC to CPM file transfers will\n");
- printf(" fail if any data is on side 2. Also only\n");
- printf(" 80 of the 112 directory entries are \n");
- printf(" available.\n");
- disktyp = 'd';
- dostyp = 1;
- cluslen = 1024;
- dirsec = 12;
- dirnum = 80;
- maxfat = 316;
- sectrk = 8;
- secclus = 2;
- secoff = 10;
- }
-
- if (cluster == 0x0FFC)
- {
- printf("..Single sided diskette, 9 sectors/track..\n");
- printf(" Note that only the root directory\n");
- printf(" is available.\n");
- disktyp = 's';
- dostyp = 2;
- cluslen = 512;
- dirsec = 20;
- dirnum = 64;
- maxfat = 352;
- sectrk = 9;
- secclus = 1;
- secoff = 9;
- }
- if (cluster == 0x0FFD)
- {
- printf("..Double sided diskette, 9 sectors/track..\n\n");
- printf(" Note that PC to CPM file transfers will\n");
- printf(" fail if any data is on side 2, only 64\n");
- printf(" of the 112 root directory entries are \n");
- printf(" available (sub-directories are not\n");
- printf(" supported).\n");
- disktyp = 'd';
- dostyp = 2;
- cluslen = 1024;
- dirsec = 20;
- dirnum = 64;
- maxfat = 355;
- sectrk = 9;
- secclus = 2;
- secoff = 12;
- }
- if (disktyp == '?')
- {
- printf("*** ERROR - UNRECOGNIZED DISK ***\n");
- printf(" First fat entry = %x\n",cluster);
- exit();
- }
-
- /* Read directory sectors */
- printf("\nPlease wait - reading IBM directory...");
- fo≥ (secto≥ ╜ dirsec; secto≥ <╜ dirsec - 1 + dirnum/4; secto≥++)
- { dev = 1;
- seldev(dev);
- track = 0;
- settrk(track);
- secadd= dirbuf+((sector-dirsec)*128);
- setdma(secadd);
- setsec(sector);
- cpmread();
- }
- printf(" Thank you.\n");
-
- return;
- }
-
- srchdir()
- /* Decode directory */
- { int entry;
- int found;
- char used,erased,dir,never,*entryadd;
-
- erased = 0xE5;
- dir = 0x2E;
- never = 0x00;
- for (entry = 0; entry <= dirnum -1; entry++)
- { entryadd = dirbuf+(entry*32);
- used = *entryadd;
- if (used != erased && used != dir && used != never)
- {found++;
- getdir(found,entryadd);
- }
- }
- return;
- }
-
- getdir(found,entryadd)
- int found;
- char *entryadd;
- {
- int bytes,size,cluster,*pint;
- char ans,fname[15],name[9],ext[4];
- bytes = 8;
- getstring(8,name,entryadd);
- entryadd = entryadd + 8;
- getstring(3,ext,entryadd);
- cname(fname,name,ext);
- pint = entryadd + 20;
- size = *pint;
- pint = entryadd + 18;
- cluster = *pint;
- /* need to decode 4 byte size fields */
- printf("\n\nFile = %s ; %d bytes ; %d = 1st cluster\n",fname,size,cluster);
- printf("Copy to disk A:?(y/n)\n");
- ans = getone();
- if (ans == 'y')
- { pctooz(fname,cluster);
- }
- return;
- }
-
-
- pctooz(name,cluster)
- int cluster;
- char name[];
- /**************************************************/
- /* PCOZ */
- /* Copies the file 'name' to the osborne disk. */
- /* Uses the cluster to begin, then chains through */
- /* the FAT for the remaining. */
- /**************************************************/
- {
- int fchan;
- char upline;
- upline = '\013';
- printf("\n\nCopying file %s PC => CPM\n",name);
- ferror = 0;
- fchan = file(name);
- if (ferror != 1)
- {
- printf(" First cluster=%d\n",cluster);
- while (ferror != 1 && cluster < maxfat)
- {
- pcread(cluster);
- if (side == 0)
- {
- ferror = write(fchan,copybuf,cluslen);
- if (ferror != cluslen)
- {
- printf("\n\n*** WRITE ERROR, COPY ABORTED ***\n\n");
- ferror = 1;
- }
- }
-
- cluster = getfat(cluster,fat);
- printf("%c Next cluster=%d \n",upline,cluster);
- }
- fclose(fchan);
- }
- return;
- }
-
- pcread(cluster)
- int cluster;
- /**************************************************/
- /* PCREAD */
- /* Reads the cluster requested into the copy */
- /* buffer. */
- /**************************************************/
- {
- int dev,secr,check,check1;
- char ans,c,*secadd;
-
- dev = 1;
-
- if (debug == 'y') printf("Reading cluster %d\n",cluster);
-
- /* decode cluster to osborne side, track, */
- /* and sector */
- osbsec(cluster);
-
- if (side == 1)
- {
- printf("***OOPS - attempt to read flip side***\n");
- printf(" ---Cluster skipped, copy continuing--\n");
- printf("Hit return to continue\n");
- c = getone();
- }
-
- if (side != 1)
- {
- for (secr = sector;secr < sector+cluslen/128;secr++)
- {
- if (debug == 'y') printf("Reading Osborne track %d sector %d\n",track,secr);
- seldev(dev);
- settrk(track);
- setsec(secr);
- secadd = copybuf+(secr-sector)*128;
- setdma(secadd);
- cpmread();
- }
- }
-
- return;
- }
-
- osbsec(cluster)
- /* decode cluster number to osborne side, track, */
- /* and sector */
- int(cluster);
- {
- int logsec,check;
-
- /* find pc-dos logical sector */
- logsec = cluster - 2;
- logsec = logsec * secclus;
- logsec = logsec + secoff;
- /* find pc-dos track and sector */
- track = logsec / sectrk;
- sector = logsec - track * sectrk;
- /* convert to osborne track and sector */
- sector = sector * 4;
- side = 0;
- if (disktyp == 'd')
- {
- check = track / 2;
- if (track != check * 2)
- side = 1;
- track = track /2;
- }
-
- /* return */
-
- return;
-
- }
-
-
- lstch()
- { int sect,nexts,empty;
- empty = 0;
- for (sect = 1;sect < maxfat;sect++)
- { nexts = getfat(sect,fat);
- printf("FAT of %d = %d \n",sect,nexts);
- if(nexts == 0)
- empty++;
- if(empty > 35)
- sect = maxfat;
- }
- return;
- }
-
- getnext(cluster)
- /* Get the next free cluster */
- int(cluster);
- {
- int i,j,next;
- if (debug == 'y') printf("Looking for free cluster at %d\n",cluster);
- next = cluster;
- while (next != 0 && cluster <= maxfat)
- {
- next = getfat(cluster,fat);
-
- /* Check for flip side */
- osbsec(cluster);
- if (debug == 'y') printf("Cluster %d, side %d \n",cluster,side);
- if (side == 1)
- next = 1;
-
- cluster++;
- }
-
- if (debug == 'y') printf("Found free cluster at %d\n",cluster-1);
-
- if(next != 0)
- {
- printf("***ERROR - PC disk full***\n");
- ferror = 1;
- }
-
- return(cluster-1);
- }
-
-
-
-
- file(fname)
- char fname[];
- /**************************************************/
- /* FILE */
- /* */
- /* This routine opens the file 'fname' and */
- /* the channel number. */
- /* */
- /**************************************************/
- { int i;
- char ans,dname[15];
- /* First, see if file exists */
- /* i = fopen(fname,"r");
- if (i > 0)
- {
- fclose(i);
- printf("File exists on drive A:\n");
- printf(" OK to overwrite? (Y/N)\n");
- ans = getone();
- if (ans != 'y')
- {
- ferror = 1;
- return;
- }
- } */
-
- /* Now open for output */
- /* Force to drive A: */
- for ( i = 0; i <= 13; i++)
- dname[i+2] = fname[i];
- dname[0] = 'A';
- dname[1] = ':';
- i = fopen(fname,"w");
- if (i > 0) return i;
- printf("Can't Open: %s\n",dname);
- ferror = 1;
- return;
- }
-
-
-
- oztopc()
- {
- char name[15];
- int i,max;
- max = 14;
- printf("\nOK, CPM to PC file transfer\n");
- printf("Enter file name:");
- istring(&name[0],max);
- ozpc(name);
- printf("...Copy complete\n");
- return;
- }
-
-
- pcdirout()
- /* Rewrite directory and FAT on PC disk */
- { int base,dev,fatsize;
- char *secadd;
-
- /* Write directory sectors */
- fo≥ (secto≥ ╜ dirsec╗ secto≥ <╜ dirsec-1+dirnum/4╗ secto≥++)
- { dev = 1;
- seldev(dev);
- track = 0;
- settrk(track);
- secadd= dirbuf+((sector-dirsec)*128);
- setdma(secadd);
- setsec(sector);
- cpmput();
- }
-
- /* Write File Allocation Table (two copies) */
- fatsize = dostyp * 4;
- for (base = 4; base <= 4 + fatsize;base = base + fatsize)
- {
- fo≥ (secto≥ ╜ base╗ secto≥ <╜ base-1+fatsize╗ secto≥++)
- { dev = 1;
- seldev(dev);
- track = 0;
- settrk(track);
- secadd= fat+((sector-base)*128);
- setdma(secadd);
- setsec(sector);
- cpmput();
- }
- }
-
- return;
- }
-
- ozpc(name)
- char name[];
- {
- int i,fchan,cread;
- int length,cluster,start,next;
- char upline,dname[17];
- upline = '\013';
- /* Force name to drive A: */
- for (i = 0; i <= 14; i++)
- dname[i] = name[i];
- if (dname[1] != ':') {
- for (i = 14; i >= 0; i--)
- dname[i+2] = dname[i];
- }
- dname[0] = 'A';
- dname[1] = ':';
- /* make sure drive is not specified on PC-DOS dir */
- for (i = 0; i <= 14; i++)
- name[i] = dname[i+2];
- printf("\n\nCopying file %s (CPM => PC)\n",dname);
-
- ferror = 0;
- fchan = fopen(dname,"rb");
- if (fchan == 0)
- {
- printf("*** Can't open file ***\n");
- return;
- }
-
- /* Find first empty cluster */
- start = getnext(2);
- /* And go to it */
- printf("\n");
- next = start;
- length = 0;
- cread = read(fchan,copybuf,cluslen);
- while (cread > 0 && ferror ==0) {
- printf("%c Have read %d, cluster = %d, next = %d\n",upline,cread,cluster,next);
- cluster = next;
- next = pcwrite(cluster);
- length = length + cread;
- cread = read(fchan,copybuf,cluslen);
- }
-
- printf("End of read, last read was %d, last write to %d\n",cread,cluster);
-
- if (ferror ==0);
- {
- pclose(cluster);
- makedir(name,start,length);
-
- /* rewrite fat and directory */
- pcdirout();
-
- printf("\nCopy complete\n");
- }
-
- fclose(fchan);
- return;
- }
-
- makedir(name,start,length)
- char name[];
- int start,length;
- {
- char c;
- int i,entry;
- char used,erased,never,*entryadd,*namadd;
-
- int found;
- int bytes,size,*pint;
- char ans,;
-
- printf("Make PC directory entry...\n");
- printf(" Name = %s\n",name);
- printf(" First Sector = %d\n",start);
- printf(" Length = %d\n",length);
-
- /* First get address of first available directory */
- /* entry */
-
-
- erased = 0xE5;
- never = 0x00;
- for (entry = 0; entry <= 63; entry++)
- { entryadd = dirbuf+(entry*32);
- used = *entryadd;
- if (used == erased || used == never)
- break;
- }
-
- /* Now format new entry */
-
- for (i = 0;i <= 31;i++)
- *(entryadd + i) = '\0';
- pint = entryadd + 26;
- *pint = start;
- pint = entryadd + 28;
- *pint = length;
-
- for (i = 0;i <= 10;i++)
- *(entryadd + i) = ' ';
-
- namadd = entryadd;
- for (i = 0;i <= 12; i++)
- {
- if (name[i] != '.' && name[i] != '\0')
- {
- *namadd = name[i];
- namadd = namadd +1;
- }
-
- if (name[i] == '.')
- namadd = entryadd + 8;
-
- if (name[i] == '\0')
- break;
-
- }
-
- if (debug == 'y') dump(32,entryadd,"New dir entry = ");
- return;
- }
-
-
- pclose(cluster)
- int cluster;
- {
- char c;
- printf("Close PC fat chain...\n");
- printf(" Last Sector = %d\n",cluster);
- pchain(cluster,0XFFF,fat);
- return;
- }
-
- pcwrite(cluster)
- int cluster;
- /**************************************************/
- /* PCWRITE */
- /* Writes the cluster requested from the copy */
- /* buffer */
- /**************************************************/
- {
- int next,dev,secr;
- char ans,*secadd;
- if (debug == 'y') printf("Writing cluster %d\n",cluster);
-
- dev = 1;
-
- osbsec(cluster);
-
- for (secr = sector;secr < sector+cluslen/128;secr++)
- {
- if (debug == 'y') printf("Writing Osborne track %d sector %d\n",track,secr);
- seldev(dev);
- settrk(track);
- setsec(secr);
- secadd = copybuf+(secr-sector)*128;
- setdma(secadd);
- cpmput();
- }
- next = getnext(cluster+1);
-
- pchain(cluster,next,fat);
-
- return(next);
- }
-
- /* ************* END OF PCPIP.C ************* */