home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
BEEHIVE
/
UTILITYS
/
PCSWP05.ARC
/
PCSWP05.C
< prev
next >
Wrap
Text File
|
1991-03-10
|
28KB
|
1,053 lines
/*************************************************
PCSWP
Eugene Nolan
2/10/89
c/o DHN* RCPM 215-623-4040
This utility allows you access to IBM PC 320/360k floppies
if:
1 - Your systems has a means of accessing DS/DD 5.25
with 512 byte sectors and 8 or 9 physical sectors/track.
This means that your system must support 4k or 4.5k bytes
per track on your floppy. It must also alternate heads
when it overflows the current track.
It:
1 - Allows you to spec the drive the DOS disk is on
2 - Get a directory listing of the DOS disk
3 - Copy a single file at a time to the DOS disk (no wildcards) from
a specified CPM drive/user
4 - Sweep the DOS disk
A - Foreward or backwards
B - View a file ( if file is not ASCII, sorry )
C - Delete a DOS file
D - Tag a DOS file for later mass copy
E - Untag a previously tagged file
F - Copy all tagged files to a designated CPM drive/user
5 - During file copies from/to the DOS disk, you will be asked
whether to proceed on not if the destination file exists
Limitations:
1 - Only 320k and 360k format supported.
2 - File names with 05 in dos directory as first character
of name may display funny, as no conversion to the true
E5h will be made.
3 - For file copys from/to the DOS disk, no data verification is done
4 - No autologin of DOS disk, if you change the disk, tell the
program by re-specifying the drive the DOS disk is on
5 - Checks are made to verify the DOS disk is a DOS disk of the supported
formats, but given the right circumstances, it is possible to trick
the program (possible but unlikely).
Many commercial systems have a utility that will allow you to
define this format. For those of you who wish to roll your own
DPB, the values are:
DPBF: ;DISK PARAMETER BLOCK for IBM 360k
DW 36 ;SECTORS PER TRACK ( 32 if 320k disk)
DB 3 ;BLOCK SHIFT FACTOR
DB 7 ;BLOCK MASK
DB 0 ;EXTENT MASK
DW 359 ;DISK SIZE-1 (319 if 320k disk)
DW 63 ;DIRECTORY MAX (Not applicable)
DB 128+64 ;ALLOC 0 ditto
DB 0 ;ALLOC 1 ditto
DW 8 ;CKS ditto
DW 0 ;TRACK OFFSET ditto
General Notes:
This program is written in Small C 2.11. In doing so it makes use
of some of Small C's internal data bases (namely _fcbptr) and it's
method of allocating storage for global variables. In doing so, it
will probably not compile correctly with ANY commercial compiler.
Also note again, if you change the 'DOS' disk, TELL THE PROGRAM by
using the SELECT DOS DISK function from the main menu.
And please do not get in the habit of Control-C'ing out of it,
Small C lets you do it, but there may be side effects, use the
exit from the main menu. ( Only applies if you have been able to
succesfully select a DOS disk).
The program in it's current version is somewhat slow in it's write's
to the DOS floppy. This is because, for the time being, the BIOS
calls to 'write sector' are initiated with a 'write to directory' code,
which flushes each 128 byte CPM sector individually, regardless of
any allocation management code in the BIOS.
***************************************************************/
#define VER 0 /* current version of this code */
#define REV 5 /* current revision level */
/* Psuedo 'c' structure for dos directory entry, DO NOT change order */
char dfilen[11], /* dos file name from directory */
dattri, /* dos attribute */
dresrv[10], /* dos reserved */
dhms[2], /* dos hour/min/sec */
dmdy[2]; /* dos month/day/year */
int ddclus, /* dos root cluster */
dfllsb, /* dos file length LSB */
dflmsb; /* dos file length MSB */
char cfilen[15], /* cpm file name for build fcb */
cldat[1024], /* cluster data stored here */
taghld[224], /* Holds tags of files on DOS write functions */
cpmdsk, /* CPM drive to copy to */
*dirent; /* pointer to current dir entry in dir[] on DOS disk */
int cclust, /* current cluster being processed */
newclu, /* next cluster to allocate on write */
clupnt, /* address for newclu */
user, /* CPM user to copy to */
empdsk, /* ==112 if no usable files on dos disk */
swppnt; /* pointer into dir[] for sweep function */
#define SETUSR 32 /* CPM BDOS call for set user # */
#define SETDRV 14 /* ditto for set default drive */
#define GETDRV 25 /* ditto for get default drive */
char *pfat0, /* pointer to DOS fat0 */
*pfat1, /* pointer to dos fat1 */
fat0[1024], /* hold MS-DOS FAT 0 (if 360k) */
fat[1024], /* Holds MS-DOS FAT 1 (if 320k,else fat0&1 if 320) */
dir[3584]; /* Holds MS-DOS Directory */
char filenam[16]; /* Filename we are copying to CPM */
int seldsk, /* Disk MS-DOS is on, A=0,B=1 */
biodpb, /* ==0 if BIOS said bad disk selected */
track, /* CPM track on MS-DOS disk */
sector, /* CPM sector on MS-DOS disk */
fsize, /* DOS file size in K */
swpsiz, /* size of all files tagged in K */
dirsiz, /* total k of all files on disk */
fillsb, /* current count of bytes to write LSB */
filmsb, /* current count of files to write MSB */
dsmax, /* max sector to read based upon 320/360k */
fatsiz; /* size of fat based upon 320/360k */
int disp; /* ==1 if display directory */
char *fatpnt, /* pointer to fat[] */
*dirpnt, /* pointer to dir[] */
*dma, /* pointer to set dma address to */
*jnkpnt; /* used in file size calc and FAT verification */
int maxsec, /* =32 for 320k, =36 for 360k */
maxclu, /* =315 for 320k, = 355 for 360k */
cpmspt, /* Seldsk returns the DPB's CPMSPT here */
sptcpm; /* used for verifying DOS format matches CPM */
extern _fcbptr[10]; /* Small C pointers to FCB's it builds */
#define STDIN 0 /* Small C's channel number for console input */
/**************
Start here
***************/
main()
{
int i,flag;
char d;
#asm
lhld 1 ; get address of warm boot in BIOS
mvi l,1bh
shld dtosel+1 ; store address of BIOS SELDSK jump
mvi l,1eh
shld ttosel+1 ; store address of BIOS SETTRK
mvi l,21h
shld stosel+1 ; store address of BIOS SETSEC
mvi l,24h
shld dmasel+1 ; store address of BIOS SETDMA
mvi l,27h
shld readsc+1 ; store address of BIOS READSC
mvi l,2ah
shld writsc+1 ; store address of BIOS WRITSC
#endasm
seldsk=255; /* flag no disk selected yet */
printf("\n\n **** PCSWP %d.%d ****\n\n",VER,REV);
printf(" Gene Nolan\n\n");
flag=1;
while(flag) {
i=menu(); /* display menu and get selection */
switch (i)
{
case 1: /* select disk for DOS files */
printf("\nEnter drive DOS disk is on (A,B,,,) : ");
d=getchar(); d=toupper(d);
if ((d>='A')&&(d<='P'))
{ seldsk=d-65; rdwrdr(0); /* convert to 0-15 and read
FAT's and directory */
if(!biodpb) { seldsk=255;
printf("\n\n ** BIOS rejected drive");
force();
}
if(!((sptcpm==32)||(sptcpm==36))) { /* BIOS DPB CPMSPT */
seldsk=255;
printf("\n\n *** Disk DPB definition not correct,");
printf(" Need SPT=32 or 36, ABORTED ***\n");
force();
}
if(seldsk!=255) {
if(sptcpm!=maxsec) { /* check disk DPB is correct */
seldsk=255;
printf("\n\n ** DPB CPMSPT(%d) != DOS SPT(%d), aborted\n",
sptcpm,maxsec); force(); }
else {
printf(" *** 3");
if(maxsec==32) putchar('2'); else putchar('6');
printf("0 K disk found ***\n");
}
}
}
else { printf("\n\n ** A->P only!"); force(); }
break;
case 2: disdir(); break; /* DOS disk directory */
case 3: dosswp(); break; /* sweep function */
case 4: cpmdos(); break; /* Copy CPM file to DOS disk */
case 5: flag=0; break; /* done */
default:
}
}
}
/* ********** */
menu() /* display menu */
{
printf("\n\n");
printf(" 1 = Select drive with DOS files on (A,B,C,,,)\n");
printf(" 2 = DOS disk directory\n");
printf(" 3 = Sweep DOS disk\n");
printf(" 4 = Copy to DOS\n");
printf(" 5 = Quit\n");
printf("\nChoice = ");
return((getchar()-48)&255);
}
/* ************* */
rdwrdr(rdwr) int rdwr; /* read/write FAT's/DIR from dos disk */
{
int i,defdrv,tdsk;
defdrv=_bdos(GETDRV,0); /* get CPM BDOS default drive */
seldk(); /* select disk given by seldsk */
sptcpm=cpmspt; /* save what seldsk returned from DPB */
if(!biodpb) return(1); /* BIOS returned a 0, bad drive selected */
if(rdwr) { printf("\n\n Writing"); suwrdr(); /* set up for FAT/DIR write */
}
else {
printf("\n\n Reading"); if(surdwr()) return; /* set up for FAT/DIR read */
}
printf(" DOS FAT's and directory\n");
dma=pfat0; /* start dma to/from memory here */
for(i=4;i<dsmax;i++) /* read 'CPM' sectors from disk */
{
track=i/maxsec; sector=i%maxsec;/* track=int(cpmsec/X) sector=mod(cpmsec,X) */
setdma(); settrk(); setsec(); /* BIOS calls */
if(rdwr) wsectr(); /* read or write? */
else rsectr();
dma+=128;
}
tdsk=seldsk; /* restore CPM BDOS default drive */
seldsk=defdrv;
seldk();
seldsk=tdsk;
if(rdwr) { dma=dir+12; /* restore our tags if was a write */
for(i=0;i<112;i++) {
*dma=taghld[i*2]; *(dma+1)=taghld[i*2+1];
dma+=32;
}
}
if(!rdwr) { /* if reading, verify the 2 FAT's we just read
match */
dma=pfat0; jnkpnt=pfat1;
for(i=0;i<fatsiz;i++) {
if(!(((*dma++)&&255)==((*jnkpnt++)&&255))) {
printf("\n\n FAT's do not match!!! Select aborted\n"); force(); seldsk=255;
i=fatsiz;
}
}
}
disp=0; disdir(); disp=1; /* recalc file numbers */
return(0); /* no errors */
}
/* ************** */
surdwr() { /* set up for read of directory
read first 128 bytes of FAT0 to determine
disk size working with */
int i;
dma=fat0; /* start dma to memory here */
track=0; sector=4;
setdma(); settrk(); setsec(); rsectr(); /* BIOS calls */
maxsec=0; i=*dma&255;
if(i==255) { /* 320k disk */
maxsec=32; maxclu=315; pfat0=fat; pfat1=fat+512; dsmax=40;
fatsiz=512; }
if(i==253) { /* 360k disk */
maxsec=36; maxclu=355; pfat0=fat0; pfat1=fat; dsmax=48;
fatsiz=1024; }
if(maxsec==0) {
printf("\n\n *** Not 320k or 360k DOS disk, aborted ***\n");
force(); seldsk=255; return(1); }
return(0);
}
/* *************** */
suwrdr() { /* set up for write directory */
int i;
dma=dir+12;
for(i=0;i<112;i++) {
taghld[i*2]=*dma; taghld[i*2+1]=*(dma+1); /* keep old tags */
*dma=0; *(dma+1)=0; dma+=32; } /* clear all file */
/* numbers from reserved */
/* bytes (used by SWP)*/
#asm
lhld fatsiz ; get size of FAT table
push h
pop b
lhld pfat1 ; get pointer to working copy
xchg
lhld pfat0 ; get pointer to FAT0
fatcpy: ldax d ; copy FAT1 to FAT0
mov m,a
inx h
inx d
dcx b
mov a,b
ora c
jnz fatcpy
#endasm
}
/* **************** */
disdir() { /* display directory at dir[] */
int i,j,k;
char *dmap;
if(seldsk==255) { nodos(); return; } /* no DOS disk selected, abort */
k=0; printf("\n\n");
dirsiz=0; /* total file sizes */
for(i=0;i<112;i++) { /* possible 112 files */
dma=dir+i*32; /* dma=dos directory entry */
jnkpnt=dma+28; /* point to file size area */
switch(*dma&255) {
case 0:
case 46:
case 229: *(dma+13)=255; break; /* not used ,sub dir, or erased */
default: if ((*(dma+11)&24)==0) { /* not sub dir or vol label */
*(dma+13)=k+1; /* store file number in reserv*/
fsizek(); dirsiz=dirsiz+fsize; /* total size of tagged */
if(disp) {
for(j=0;j<8;j++) putchar(*dma++); putchar('.');
for(j=0;j<3;j++) putchar(*dma++);
printf(" %4dk ",fsize);
}
k=k+1; if(disp) {
if(!(k%4)) putchar('\n');
if(!(k%88)) { printf("* MORE *"); getchar();
putchar("\n"); }
}
}
else *(dma+13)=255;
}
}
if(disp) printf("\n\n Total %d files, %dk\n",k,dirsiz);
}
/* ************* */
seldk() { /* use bios to select disk given by seldsk */
#asm
lhld seldsk
push h
pop b
dtosel: call 0 ; filled in above with bios entry
shld biodpb ; save DPB pointer so can check for errors */
mov a,l
ora h
jz dselng
lxi d,0ah
dad d
mov e,m
inx h
mov d,m
xchg
mov e,m
mvi d,0
xchg
shld cpmspt
dselng:
#endasm
}
/* ************ */
settrk() { /* use bios to set disk track given by track */
#asm
lhld track
push h
pop b
ttosel: call 0 ; filled in above
#endasm
}
/* ************ */
setsec() { /* use bios to set sector given by sector */
#asm
lhld sector
push h
pop b
stosel: call 0 ; filled in above
#endasm
}
/* ************ */
setdma() { /* use bios to set dma address */
#asm
lhld dma
push h
pop b
dmasel: call 0 ; filled in above */
#endasm
}
/* ************ */
rsectr() { /* use bios call to read track/sector to dma */
#asm
readsc: call 0 ; filled in above */
#endasm
}
/* ********** */
wsectr() { /* use BIOS call to write trk/sec to dma */
#asm
mvi c,1
writsc: call 0
#endasm
}
/* ****************** */
dosswp() { /* sweep the dos directory */
int i,inc,lim,lim1;
char b;
if(seldsk==255) { nodos(); return; } /* no DOS disk selected,abort */
swpmnu(); /* display sweep menu */
dma=dir+12; /* use a reserved for tags */
for(i=0;i<112;i++) { *dma=0; dma=dma+32; } /* clear all tags */
b=0;
swpsiz=0; /* current K of tagged files */
swppnt=0; /* directory entry being
processed */
inc=1; lim=112; lim1=0; dma=dir; /* move foreward in directory
if hit file #112, wrap to
file 0 */
jnkpnt=dma+28; /* point to file size in dos dir */
while(b!='X') {
dma=dir+swppnt*32; /* point to current entry */
shofil(inc,lim,lim1); /* show file and tag */
b=getchar(); /* get function */
b=toupper(b);
inc=1; lim=113; lim1=0; /* default to move foreward */
jnkpnt=dma+28; /* point to file size in dos dir */
fsizek(); /* get this files size */
switch(b) {
case 'T': /* tag file, up size of tagged files */
if(*(dma+12)!=1) { *(dma+12)=1; swpsiz=swpsiz+fsize; }
break;
case 'U': /* untag, if was tagged, subtract
size from size of tagged */
if(*(dma+12)) { swpsiz=swpsiz-fsize; }
*(dma+12)=0; break;
case 'B': inc=-1; lim=-1; lim1=111; break; /* move backward in directory
if hit file #=-1, wrap to
file # 112 */
/* back up */
case 'M': mascop(); swpsiz=0; break; /* copy tagged files to CPM */
case 'V': viewfl(); break; /* View the file */
case 'D': printf(" ARE YOU SURE? "); b=getchar(0); b=toupper(b);
if((b&255)=='Y') {
if(*(dma+12)) swpsiz=swpsiz-fsize;
deldos();
}
break;
case '?': swpmnu(); break; /* display menu */
}
if(b!=13) putchar('\n'); /* if not just CR, put out a CR */
if(!((b=='?')||(b=='M')||(b=='V'))) /* if not help or mass copy, to next fil */
{ swppnt=swppnt+inc; if(swppnt==lim) swppnt=lim1; }
}
}
/* ************** */
swpmnu() { /* display sweep menu */
printf("\n\n T - Tag file U - Untag file\n");
printf (" M - Mass copy B - Backwards\n");
printf (" V - View file X - Exit sweep\n");
printf (" ? - This D - Delete file\n");
printf (" CR or other advances\n\n");
}
/* *************** */
deldos() { /* erase the file pointed to by dma */
int d;
movdir();
cclust=ddclus;
*dma=229;
while(cclust!=-1) {
ddclus=cclust; nextcl(); d=cclust; cclust=ddclus; newclu=0;
tagclu(); cclust=d;
}
rdwrdr(1);
}
/* *************** */
shofil(inc,lim,lim1) int inc,lim,lim1; { /* display next filename for/back */
int i,k;
char b,*cpnt;
i=1;
empdsk=0; /* assume disk not empty */
while(i) {
if(((*(dma+11))&24)==0) { /* ==10h = volume label,==8 = subdir */
b=*dma; /* get first byte directory entry */
switch (b&255) {
case 0: /* empty, subdir, or erased = skip file */
case 46:
case 229: swppnt=swppnt+inc; if (swppnt==lim) swppnt=lim1;
empdsk=empdsk+1; break;
default: i=0; /* good file, display name and tag */
}
}
else { swppnt=swppnt+inc; if (swppnt==lim) swppnt=lim1; empdsk=empdsk+1; }
dma=dir+swppnt*32;
if(empdsk==113) i=0; /* if no files, done */
}
if(empdsk==113) printf(" NO FILES\n ");
else {
cpnt=dma; printf(" %2d. %c: ",(*(dma+13)&255),seldsk+65);
for(i=0;i<8;i++) putchar(*cpnt++); putchar('.');
for(i=0;i<3;i++) putchar(*cpnt++);
jnkpnt=dma+28; /* point to file size in dos dir */
printf(" %4dk :",fsizek());
cpnt++; if(*cpnt==1) putchar('*'); else putchar(' '); /* check for tagged */
if(swpsiz) printf(" > %dk ",swpsiz); /* if any tagged, show size */
}
}
/* ***************** */
mascop() { /* copy all tagged files */
int i;
i=0;
if(empdsk==113) { printf(" no files! \n"); return; }
printf(" Dest Drv(A,B,,) = "); /* ask for destination drive */
cpmdsk=getchar(); cpmdsk=toupper(cpmdsk);
i=cpmdsk&255;
if((i<65)||(i>81)) { printf("\n\n ** drive A-P only"); force(); return; }
if(askusr()) return; /* get destination user */
for(i=0;i<112;i++) { /* check tags for all files in directory */
dma=dir+i*32;
if (*(dma+12)==1) { /* ==1= tagged */
*(dma+12)=0; /* untag it */
cfdos(); /* copy this file to CPM */
}
}
}
/* ***************** */
cfdos() { /* copy from dos to cpm */
int *cfd;
char b;
movdir(); /* build psuedo structure */
cfilen[0]=cpmdsk; /* put in destination disk */
cfilen[1]=':';
strncpy(&cfilen[2],dfilen,8); cfilen[10]='.'; /* move filename over */
strncpy(&cfilen[11],&dfilen[8],3);
printf(" Copying to %c%d:%s",cfilen[0],user,&cfilen[2]);
fillsb=dfllsb; filmsb=dflmsb; /* copy filesize to working */
cfd=fopen(cfilen,"r");
if(cfd) {
fclose(cfd);
printf(" exists, delete(Y/N) "); b=getchar(); b=toupper(b);
if((b&255)!='Y') { printf(" aborted\n"); return; }
}
cfd=fopen(cfilen,"w"); /* open file for writing */
if(!cfd) { printf("\n\n ** could not open, no copy"); force(); return; }
cclust=ddclus; /* get root cluster */
while(cclust!=-1) { /* while not last cluster */
rdwrcl(0); /* read cluster */
#asm
lxi h,fillsb ; filmsb::lsb=filmsb:lsb-400h
mvi c,0
mov a,m
ora a
sbb c
mov m,a
inx h
mov a,m
sbi 4
mov m,a
inx h
mov a,m
sbb c
mov m,a
inx h
mov a,m
sbb c
mov m,a
#endasm
if(filmsb<0) { /* less than 1024 left */
fillsb+=1024; jnkpnt=cldat+fillsb; *(jnkpnt+1)=26; /* put in EOF(1Ah) */
fwrite(cldat,1,fillsb,cfd); /* write to CPM */
}
else fwrite(cldat,1,1024,cfd); /* read cluster,write to cpm */
nextcl(); /* get next cluster number */
}
if(ferror(cfd)) { printf("\n\n ** Error writing file "); force(); }
fclose(cfd); putchar('\n');
}
/* ******* */
viewfl() { /* view DOS file */
int i,j,vsize,lcnt;
movdir(); /* build psuedo structure */
lcnt=1;
fillsb=dfllsb; filmsb=dflmsb; /* copy filesize to working */
cclust=ddclus; /* get root cluster */
printf("\n\n *** Ctrl-C aborts\n");
while(cclust!=-1) { /* while not last cluster */
rdwrcl(0); /* read cluster */
#asm
lxi h,fillsb ; filmsb:lsb=filmsb:lsb-400h
mvi c,0
mov a,m
ora a
sbb c
mov m,a
inx h
mov a,m
sbi 4
mov m,a
inx h
mov a,m
sbb c
mov m,a
inx h
mov a,m
sbb c
mov m,a
#endasm
if(filmsb<0) vsize=fillsb+1024; /* less than 1024 */
else vsize=1024;
jnkpnt=cldat;
for(i=0;i<vsize;i++) { /* display data from buffer */
switch(*jnkpnt&255) {
case 10: lcnt+=1; /* LF */
default : _bdos(2,(*jnkpnt)&255); /* display character */
}
jnkpnt++;
if(!(lcnt%23)) { /* pause if mod(lcnt,23)=0 */
printf(" * MORE *"); while(!(j=_bdos(6,255))); lcnt=1; _bdos(2,13);
printf(" "); _bdos(2,13);
}
if(j==3) { cclust=-1; i=vsize; } /* Ctrl-C, abort */
}
if(j!=3) nextcl(); /* not aborted, get next cluster */
}
putchar('\n');
}
/* ********************* */
movdir() { /* move from mem @dma to dfilen */
dirent=dfilen; /* point to psuedo structure */
#asm
lhld dma ;source pointer
xchg
lhld dirent ;destination pointer
mvi c,20h ;32 bytes
md1: ldax d ;move em'
mov m,a
inx h
inx d
dcr c
jnz md1
#endasm
}
/* **************** */
nextcl() { /* get next cluster from fat given current cluster */
int i;
i=cclust%2; /* get odd/even cluster number */
cclust=(cclust*24)/16; /* cluster*1.5=next cluster */
#asm
lhld pfat1
; lxi h,fat ;get pointer to start of fat[]
xchg
lhld cclust ;get current cluster number
dad d ;index fat
xchg
ldax d ;get data from fat to cclust
mov l,a
inx d
ldax d
mov h,a
shld cclust
#endasm
if (i) { /* last cluster # odd? */
#asm
lhld cclust ;yes, take upper 12 bits from fat
mvi e,4
shclus: ora a
mov a,h
rar
mov h,a
mov a,l
rar
mov l,a
dcr e
jnz shclus
shld cclust
#endasm
}
else cclust=cclust&4095; /* no, take lower 12 bits */
if (cclust>4087) cclust=-1; /* if last cluster, set=-1 */
}
/* ************** */
rdwrcl(rdwr) int rdwr; { /* rd/wr whole cluster given by cclust to cldat[] */
int i,cpmsec,defdrv,d;
defdrv=_bdos(GETDRV,0);
cpmsec=(((cclust-2)*2)+(dsmax/4))*4; /* calc absolute 128 byte sector */
dma=cldat; /* put data here */
seldk(); /* select dos disk */
for(i=0;i<8;i++) { /* read 8 128 byte sectors=1 cluster */
/* printf(" dma=%x, cpmsec=%d\n",dma,cpmsec); */
track=cpmsec/maxsec; sector=cpmsec%maxsec;
setdma(); settrk(); setsec();
if(rdwr) wsectr();
else rsectr();
cpmsec+=1;
dma+=128;
}
d=seldsk; /* restore BDOS defualt disk */
seldsk=defdrv;
seldk();
seldsk=d;
}
/* ********** */
fsizek() { /* calc file size in K */
#asm
lhld jnkpnt ;get address of 2 word file size
inx h
mov e,m ; point to second byte
inx h
mov d,m
inx h
mov l,m ; l/d/e has high 3 bytes of file size
mvi c,2
fsizshf:
ora a ; shift l/d/e 2 bits right
mov a,l
rar
mov l,a
mov a,d
rar
mov d,a
mov a,e
rar
mov e,a
dcr c
jnz fsizshf
xchg ; hl now has byte count/400h
inx h
shld fsize
#endasm
}
/* *********** */
cpmdos() { /* copy CPM file to DOS disk */
int *cfd,i;
char b;
if(seldsk==255) { nodos(); return; }
if((fredir()==112)||(gnewcl()>maxclu)) { printf("\n\n ** No Room on DOS");
force(); return; }
putchar('\n');
if(askusr()) return; /* if bad dest user, abort */
printf("File name <D:>NAME.EXT = "); /* ask for file to copy */
_gets(cfilen,15,STDIN,0); /* read response, 0 terminated */
cfd=fopen(cfilen,"r"); /* try to open */
if(!cfd) { printf("\n\n ** Not found"); force(); return; }
dma=_fcbptr[3]+1; /* point to SMC's FCB */
for(i=0;i<11;i++) *dma=(*dma++)&127; /* strip high bit */
for(i=0;i<112;i++) { dma=dir+i*32; /* see if file exists on DOS disk */
if(!(*(dma+13)==255)) { /* look at our 'file number' field
to see if we found valid name here */
if(!(strncmp(dma,_fcbptr[3]+1,11))) { i=112;
printf(" exists, overwrite(Y/N) "); b=getchar(); b=toupper(b);
if((b&255)=='Y') { deldos(); fredir(); gnewcl(); }
else { fclose(cfd); printf(" aborted\n"); return; }
}
}
}
strncpy(dfilen,_fcbptr[3]+1,11); /* copy from Small C's internal FCB
to psuedo structure file name */
dfllsb=dflmsb=0; /* filesize=0 */
ddclus=cclust=newclu; /* base cluster=current cluster=
unused cluster */
while(newclu!=4095) { /* ==4095= CPM EOF found */
fsize=fread(cldat,1,1024,cfd); /* read from CPM */
sumsiz(); rdwrcl(1); /* sum amount read */
if(fsize==1024) { /* if 1k read */
if(gnewcl()>maxclu) { /* get a new cluster */
printf(" \n\n *** DOS DISK FULL, Copied file BAD **\n\n"); force();
newclu=4095;
}
else { tagclu(); cclust=newclu; } /* current cluster=new one */
}
else {
newclu=4095; /* CPM EOF, tag last cluster with FFF */
tagclu();
}
}
i=ferror(cfd);
fclose(cfd);
if(i) {
printf("\n\n ** Error reading file, Copied file BAD, disk select aborted");
force();
seldsk=255;
}
else { /* good file copy */
dattri=32; /* Mark archive (not changed) */
#asm
lhld dirpnt ; copy psuedo structure to dir[] area */
lxi d,dfilen
mvi c,20h ; 32 bytes
ctodir: ldax d
mov m,a
inx h
inx d
dcr c
jnz ctodir
lhld dirpnt ; Take away CPM's attribute bits
mvi c,0bh
nfattr: mov a,m
ani 7fh
mov m,a
inx h
dcr c
jnz nfattr
#endasm
rdwrdr(1); /* write FATS & DIR */
}
}
/* ****** */
askusr() {
printf(" User = "); scanf("%d",&user);
if((user<0)||(user>15)) { printf("\n\n ** User 0-15 only"); force() ;
return(1);
}
_bdos(SETUSR,user);
return(0);
}
/* ********* */
sumsiz() { /* sum up file size in double precision */
int j;
#asm
lhld fsize ; current amount read (0-1024)
xchg
lhld dfllsb ; sum with previous total
dad d
shld dfllsb
lda dflmsb
aci 0
sta dflmsb
#endasm
}
/* *********** */
writcl() {
printf("writ cclust= %d",cclust);
}
/* ******** */
tagclu() { /* point cclust at newclu */
jnkpnt=(cclust*24)/16; /* offset from fat[0] =cluster # * 1.5 */
#asm
; lxi d,fat
lhld pfat1
xchg
lhld jnkpnt
dad d
lda cclust
ani 1
jnz clhigh
lda newclu
mov m,a
inx h
mov a,m
ani 0f0h
mov c,a
lda newclu+1
ora c
mov m,a
jmp dsclu
clhigh:
xchg
lhld newclu
xchg
mvi c,4
shclu: ora a
mov a,e
ral
mov e,a
mov a,d
ral
mov d,a
dcr c
jnz shclu
mov a,m
ani 0fh
ora e
mov m,a
inx h
mov m,d
dsclu:
#endasm
}
/* ****** */
fredir() { /* find a free directory entry */
int i;
char b;
dirpnt=dir; /* start looking at first entry */
i=0; b=1;
while((b&255)&&(i<112)) { /* while this entry used */
b=*dirpnt; /* get status */
switch (b&255) {
case 0: /* not used */
case 229: b=0; break; /* erased */
default : dirpnt=dirpnt+32; b=*dirpnt; i+=1; /* look at next entry */
}
}
return(i);
}
/* ****** */
gnewcl() { /* get an unallocated cluster */
newclu=2; jnkpnt=1; /* start looking at cluster 2 */
while((jnkpnt==1)&&(newclu<=maxclu)) {
clupnt=(newclu*24)/16; /* offset from fat[0]=cluster*1.5 */
#asm
; lxi d,fat
lhld pfat1
xchg
lhld clupnt
lda newclu
dad d
ani 1
jnz newhgh
mov a,m
ora a
jnz notfre
inx h
mov a,m
ora a
jnz notfre
dcx h
mvi m,0ffh
inx h
mov a,m
ani 0f0h
ori 0fh
mov m,a
jmp isfre
newhgh: mov a,m
ani 0f0h
jnz notfre
inx h
mov a,m
ora a
jnz notfre
dcx h
mov a,m
ani 0fh
ori 0f0h
mov m,a
inx h
mvi m,0ffh
isfre: lxi h,0
shld jnkpnt
notfre:
#endasm
if(jnkpnt) newclu+=1; /* last one used, check next one */
}
return(newclu);
}
/* ******** */
force() { /* error occured, make operator hit a key */
int i;
printf(" *** hit any key *** \n");
i=getchar();
}
/* ******* */
nodos() { /* say no DOS disk selected */
printf("\n\n ** NO DOS DISK SELECTED"); force();
}