;==================================================================== ; SWAPCOPY v 2.3 | ; | ; A single drive file copy program Kaypro NEW 2 & 10 models | ;==================================================================== ; ; Modified for the video of the Kaypro models only. ; Automatically sets logged drive for all copy operations. ; ; Added auto-input prompting and cursor addressing for console ; messages. ; ; This is the program Kaypro --> SHOULD HAVE GIVEN EVERY PURCHASER ; of a NEW 2 model. ; ; Steve Sanders Tampa, FL 01/06/84 (813) 937-7249 voice ; (813) 937-3608 (813) 937-6829 data 300/1200 24 hrs ;.................................................................... ; ; Allows files to be transfered from one diskette to ; another in a system with only a single drive. ; ; Allows ambiguous file specifications. ; Allows transfer of files larger than available memory, ; and transfer of multiple files in a single pass. ; ; Allows use of dissimiliar media (i.e., to copy ; programs from a single density master diskette ; to a double density working diskette). ; ; Disk to disk file transfer program. ; ; At the command level, the command: ; ; A>SWAPCOPY FILENAME.EXT ; ; will copy the file FILENAME.EXT from diskette ; to diskette, prompting as necessary to allow the ; diskette in drive A to be swapped. ; ; or... ; ; A>SWAPCOPY *.* ; ; will prompt for each filename found on disk ; with (y/n) and copy as many as possible into ; memory and so on ... ; ; =================================================== ; === PROGRAM ABORTS IF NO FILE SPEC IS ENTERED === ; =================================================== ; ;/////////////////////////////// ; ; equates ; boot equ 0 ;system reboot bdos equ 5 ;bdos entry point memtop equ 6 ;pointer to start of fbase fcb1 equ 5ch ;first file name & source fcb fcb2 equ 6ch ;second file name tpa equ 100h ;beginning of tpa ; false equ 0 true equ 255 ; esc equ 27 bell equ 7 clrscr equ 26 ;clear screen/home cursor eos equ 23 ;clear to end of screen eol equ 24 ;clear to end of line cntrlc equ 3 tab equ 9 lf equ 10 cr equ 13 secsiz equ 128 ;bytes per sector ; org tpa ;where else? ; swapcopy: lxi sp,stack;set up local stack space ; mvi a,false sta done ;we're not done yet sta one2go ;nor do we have a file to go ; mvi c,isdrv ;get the current drive call bdos sta drive ;store it ; mvi a,true sta rflag ;report operations - yes sta qflag ;query before copy - yes ; lxi h,buf+eofo mvi m,true ;set initial eof to true ; lhld memtop lxi d,-(secsiz+freeo+8) dad d ;highest availiable dma buffer shld buftop ; lxi h,buf shld fpbpnt ;free space starts at buf ; mvi a,1 sta names ;initial next-names count ; lxi d,banner call print ; lda fcb1+1 ;check for filename or *.* cpi ' ' ;if none entered jnz sdisk lxi d,nospec jmp abort ;abort with error msg ; sdisk: lxi d,sourmx ;or... call prompt ;ask for the source disk call ffname ;get the first matching file name call adjpnt call filfpb ;set rdma & wdma pointers, fill in file name call query ;is the first file to be copied? jnc nxtnam ;if not, try the next file mvi a,true sta one2go ;if so, set 'one to go' to true, then copy it ; rdloop: lda fileof ana a jm wr ;start writing when the last file has been read lhld rdma call fulbuf jc wr ; or when the buffer space has been exhausted ; lhld eof mov a,m ana a jz samfil ;if not end-of-file, we're on the same file. ; call adjpnt ;Else, this is the start of a new file... call filfpb ;adjust pointers & fill new fpb xra a lhld sfext mov m,a ;source file extent := 0 lhld sfcr mov m,a ;source file current record := 0 lhld dfext mov m,a ;dest file extent := 0 lhld dfcr mov m,a ;dest file current record := 0 lhld eof mov m,a ;eof := false lhld made mov m,a ;made := false lhld opened mov m,a ;opened := false lhld last mov m,a ;last := false mvi a,true sta fpbusd ;mark current fpb as used lhld sfcb call open ; samfil: call read lhld eof mov a,m ana a jz samnam ;read sectors until eof or buffer full ; nxtnam: call ffname ;on eof, find the next name to be considered lxi h,names mov a,m sta namcnt nnloop: call fnname ;find next name... lxi h,namcnt dcr m jnz nnloop ;as many times as necessary. lxi h,names inr m ;then bump the count for the next pass ; lda fileof ana a ;if all matching file names have been copied jm wr ;(or passed over), start writing. call query ;is the first file to be copied? jnc nxtnam ;if not, try the next file mvi a,true sta one2go ;if so, set 'one to go' to true, then copy it lda fpbusd ana a ;if the current fpb is unused, use it jz samnam lhld rdma ;else set up the next fpb, and use it mov a,m inx h mov h,m mov l,a shld fpbpnt ;next block starts just past rdma jmp rdloop ; samnam: lhld rdma call bump ;rdma := rdma + secsiz jmp rdloop ; wr: lda one2go ;anything for the destination disk? ana a jz fini ;if not, we're done. lxi h,buf shld fpbpnt ;fpbpnt := buf call adjpnt lxi d,destmx call prompt ;prompt(destmx) ; wrnext: lhld made mov a,m ana a jnz a$m ;if already made, don't make it again ; mvi m,true ;if not made, set made := true lhld opened mvi m,true ;then set opened := true, call make ;then make the file. ; a$m: lhld opened mov a,m ana a jnz a$op ;if already opened, don't open it again mvi m,true lhld dfcb call open ;if not open, open it & set opened := true ; a$op: lhld rdma mov e,m inx h mov d,m ;de gets rdma lhld wdma mov a,e cmp m ;compare least signifigant bytes jnz nequal inx h mov a,d cmp m jz equal ;is wdma equal to rdma? ; nequal: call write ;if not, write a sector lhld wdma call bump ;wdma := wdma + secsiz jmp a$op ; equal: call close ;when wdma = rdma, close the file lhld eof mov a,m ana a ;done with file? jz skprpt ;if not, don't report the transfer yet. lda rflag ana a ;is the 'Report' option set? jz skprpt ;if not, don't report the file transfer. ; lxi d,cpydmx call print ;print 'Copied ' lhld dfcb call pfname ;print the file name call crlf ;start a new line ; skprpt: lhld wdma call fulbuf ;if the whole buffer has been written, jc wrexit ;try to read another some more in ; lhld rdma ;else, set up to write the next file mov e,m inx h mov d,m xchg ;hl points to next fpb shld fpbpnt ;set up the file param. block pointer lhld last mov a,m sta done ana a jnz fini ;if the last file has been written, we're done call adjpnt jmp wrnext ;else adjust pointers, then write the next file ; wrexit: lda done ana a ;shall we exit or read more files? jnz fini ;we're done, so exit ; lxi b,freeo lxi d,buf lhld fpbpnt call ldir ;move the last fpb to the start of the buffer ; lxi h,buf shld fpbpnt call adjpnt call filfpb ;set up the pointers at the start of the buffer ; lxi d,sourmx call prompt ;ask for the source disk jmp rdloop ; fini: lxi d,systmx call prompt ;prompt for system disk lxi d,normal abort: call print rst boot ; namsiz equ 12 ;size of a disk file name (1+8+3) fcbsiz equ 36 ;size of a file control block sfcbo equ 0 ;offset to source fcb sfexto equ 12 ;offset to source file extent scro equ 32 ;offset to source file current record dfcbo equ 36 ;offset to destination file control block dfexto equ 48 ;offset to destination file extent dcro equ 68 ;offset to destination file current record rdmao equ 72 ;offset to read zone pointer wdmao equ 74 ;offset to write zone pointer madeo equ 76 ;offset to file-made flag openo equ 77 ;offset to file-open flag eofo equ 78 ;offset to end-of-file flag lasto equ 79 ;offset to last-file flag freeo equ 80 ;offset to start of freespace ; adjpnt: lhld fpbpnt ;compute and save the... lxi d,sfexto dad d shld sfext ; pointer to source file extent lxi d,scro-sfexto dad d shld sfcr ; pointer to source file current record, lxi d,dfcbo-scro dad d shld dfcb ; pointer to dest fcb, lxi d,dfexto-dfcbo dad d shld dfext ; pointer to dest file extent, lxi d,dcro-dfexto dad d shld dfcr ; pointer to dest file current record, lxi d,rdmao-dcro dad d shld rdma ; pointer to read dma zone, inx h inx h shld wdma ; pointer to write dma zone, inx h inx h shld made ; pointer to file made flag, inx h shld opened ; pointer to file-open flag inx h shld eof ; pointer to end-of-file flag, inx h shld last ; pointer to the 'last-file' flag, inx h shld fspace ;and the pointer to the start of free space. ret ; filfpb: lhld fpbpnt xchg lhld fileof ;get offset into directory bufffer mvi h,0 dad h dad h dad h dad h dad h ;multiply by 32 lxi b,dirbuf dad b ;hl points to file name lxi b,namsiz push h push b call ldir ;move file name to source fcb pop b lhld dfcb xchg pop h call ldir ;move file name to destination fcb lhld fspace xchg lhld rdma mov m,e inx h mov m,d ;point rdma to start of free space inx h mov m,e inx h mov m,d ;point wdma to start of free space ret ; bump: mvi a,secsiz add m mov m,a ;add sector size to l.s. byte of address rnc inx h inr m ;if carry, increment m.s. byte of address ret ; fulbuf: mov e,m inx h mov d,m ;de gets address to be compared lhld buftop mov a,l sub e mov a,h sbb d ret ;return with carry set if @(de) > buftop ; query: lda qflag ana a stc rz ;copy all files if not querying lxi d,copymx call print ;print 'Copy ' lda fileof ani 3 add a add a add a add a add a ;get 32 * file offset lxi h,dirbuf add l mov l,a adc h sub l mov h,a ;point hl to filename call pfname ;print the filename lxi d,qmark call print ;print '?' getit: mvi c,cstsf ;check console for chr call bdos ora a jz getit ;if none - loop until chr waiting mvi c,cif call bdos ;get the chr cpi ' ' ;if a blank jz getit ;loop and wait for next chr ani (not 20h) and 255 sui 'Y' ;if y or Y stc rz ;copy the file cmc ret ; pfname: mvi a,8 call pathl ;print 8 characters in the name, mvi e,'.' call co ;print a period, mvi a,3 ;print the 3 characters in the extension. ; pathl: inx h mov e,m call co ;print the character @+(hl) dcr a jnz pathl ;repeat (a) times ret ; ; system interface routines ; cif equ 1 ;console input function # cof equ 2 printf equ 9 ;print buffer function # linef equ 10 ;line input function # cstsf equ 11 ;get console status function # resetf equ 13 ;select & write enable drive A seldsk equ 14 ;select disk drive openf equ 15 ;open file function # closef equ 16 ;close file function # sfff equ 17 ;search for first function # sfnf equ 18 ;search for next function # deletef equ 19 ;delete file function # readf equ 20 ;sequential file read writef equ 21 ;sequential file write makef equ 22 ;create & open a new file isdrv equ 25 ;interogate selected drive dmaf equ 26 ;set dma address function # ; open: mvi c,openf xchg call bdos inr a jz openng ret openng: lxi d,cantop jmp abort ; close: mvi c,closef lhld dfcb xchg call bdos lhld opened mvi m,false ret ; read: lhld rdma mov e,m inx h mov d,m call setdma mvi c,readf lhld fpbpnt xchg call bdos lhld eof mov m,a ana a rnz ret ; write: lhld wdma mov e,m inx h mov d,m call setdma mvi c,writef lhld dfcb xchg call bdos ana a jnz cantwr ret cantwr: lxi d,space jmp abort ; make: mvi c,deletef lhld dfcb xchg call bdos mvi c,makef lhld dfcb xchg call bdos inr a jz makeng ret makeng: lxi d,wrprot call print lxi d,nodir jmp abort ; setdma: mvi c,dmaf jmp bdos ; reset: mvi c,resetf call bdos ; april 1982 - select desired disk drive mvi c,seldsk lda drive mov e,a jmp bdos ; ; crlf: mvi e,cr call co mvi e,lf co: push h push psw mvi c,cof call bdos pop psw pop h ret ; print: mvi c,printf jmp bdos ; ffname: lxi d,dirbuf call setdma mvi c,sfff lxi d,fcb1 call bdos sta fileof inr a jnz fixf lxi d,nofile jmp abort ; fnname: lxi d,dirbuf call setdma mvi c,sfnf lxi d,fcb1 call bdos sta fileof add a sbb a ;a:=255 if fileof=255, else 0 lhld last mov m,a ; ; april 1982 fix for cpm1.4 where numbers >3 were detected ; but not desired...hence and with 3 ; fixf: lda fileof cpi 255 rz ani 3 sta fileof ret ; prompt: call print clear: mvi c,cstsf call bdos ana a jz wait mvi c,cif call bdos ;if there's a char waiting, get it & ignore it. jmp clear wait: mvi c,cif call bdos ;get the next char cpi cntrlc jz boot cpi cr jnz badch ;explain the procedure call reset ret ; badch: lxi d,explan jmp prompt ; ldir: mov a,m stax d inx h inx d dcx b mov a,c ora b jnz ldir ret ; ; console messages ; ; note: all these messages contain cursor addressing and video ; attribute calls useable only on a Kaypro. ; [steve] ; banner: db clrscr,esc,'B0' db ' ' db cr,lf,' ',esc,'B1' db ' KAYPRO SWAPCOPY v2.3 SINGLE FLOPPY FILE COPYING PROGRAM ' db esc,'C1',' ',cr,lf,' ',esc,'B1' db ' by Steve Sanders 06-Jan-85 ' db esc,'C1',' ',cr,lf db ' ' db cr,lf,lf,esc,'C0','$' sourmx: db esc,61,38,32,eos,esc,'B0',esc,'B1' db ' Insert SOURCE disk, press : ' db esc,'C1',esc,'C0',bell,'$' destmx: db esc,61,38,32,eos,esc,'B0',esc,'B1' db ' Insert DESTINATION disk, press : ' db esc,'C1',esc,'C0',bell, '$' systmx: db esc,61,38,32,eos,esc,'B0' db ' Insert SYSTEM disk, press to finish: ' db esc,'C0',bell, '$' copymx: db esc,61,39,32,eos,esc,'B0',' Copy --> $' cpydmx: db esc,61,39,32,eos,bell,esc,'B0',' Copied --> $' qmark: db ' (y/n)? ',esc,'C0',bell,'$' explan: db esc,'B6',esc,61,45,32,esc,'B0' db ' ' db cr,lf,' ',esc,'B1',esc,'B2' db ' To continue, hit the key ' db esc,'C1',' ',cr,lf,' ',esc,'B1' db ' To abort, hit CTRL-C ' db esc,'C2',esc,'C1',' ',cr,lf db ' ' db esc,'C1',esc,'C0',esc,'C6','$' normal: db esc,61,37,49,eos,lf,lf db '== SwapCopy is finished ==',cr,lf,bell,'$' nospec: db bell,esc,61,37,32,eos db ' No file specification was entered - ABORTING.' db cr,lf,lf,' Use *.* for all or specify filename desired.' db cr,lf,lf,lf,esc,'B3' db 'Note: Currently logged drive will be used for copying.' db esc,'C3',cr,lf,bell,'$' nofile: db esc,61,45,64, 'No source files',bell, cr, lf, '$' nodir: db esc,61,45,59,'Directory space exhausted',bell, cr, lf, '$' cantop: db esc,61,45,63, 'Can''t reopen file.',bell, cr, lf, '$' space: db esc,61,45,62, 'Disk space exhausted.',bell, cr, lf, '$' wrprot: db esc,61,45,60, 'Diskette Write protected?', bell,cr, lf, '$' ; ; data areas ; sfcb: ds 0 fpbpnt: ds 2 ;pointer to start of the file param. block sfext: ds 2 ;pointer to source file extent byte sfcr: ds 2 ;pointer to source file current record byte dfcb: ds 2 ;pointer to destination file control block dfext: ds 2 ;pointer to dest file extent byte dfcr: ds 2 ;pointer to dest file current record byte buftop: ds 2 ;pointer to top of free memory rdma: ds 2 ;pointer to next read dma zone wdma: ds 2 ;pointer to next write dma zone made: ds 2 ;pointer to file made flag opened: ds 2 ;pointer to file open flag eof: ds 2 ;pointer to end of file flag last: ds 2 ;pointer to last file flag fspace: ds 2 ;pointer to start of free buffer space fileof: ds 1 ;file offset. index into dirbuf done: ds 1 ;all files copied flag names: ds 1 ;number of the next file to be copied namcnt: ds 1 ;copy of 'names'. used as a counter drive ds 1 ;drive number 0-3 for a-d and so on qflag: ds 1 ;'Query' option flag rflag: ds 1 ;'Report' option flag fpbusd: ds 1 ;current fpb has been used flag one2go: ds 1 ;there is a file to be transfered flag ; ds 64 ;32 level stack stack: ds 0 ; dirbuf: ds secsiz ;buffer for searching the directory ; buf: ds 0 ;buffer starts here and extends to fbase ; end swapcopy