8--READ 1STrPMFT COMt MFT48 ASMMFT48 DOC< The files with the extension .?Y? are LZH Encoded - like SQueezed or Crunched. The program UNCRLZH v1.1 or LT29 (or later version of these programs) are required to decode them. 1!͘2t2u2v2x2y2z }V02}02} V0>S2yV2x:x!y2z!͘!:yܘ!͘:] ‡!E ͘*}o{}o|g)l>g+"!]͘*!l͘!x͘' ¸;3:t!F#~#!"!p " " !{"*":t?!\!͈2t<2u* " !]͢!͘* s* ~6#] ͈" !]͢!͘2\2h2|`* *|}" !"*oʰ ¢3`Æ!͘*"*#"*+"|†!\!͈>2t~*!͘** r#s#" :t?:v!͘>2v!͘' ;3:u`!2\!͈`* " !]͢!͘ñ* ~//#] ͈" :z҇!e~w!]͢!͘2\2h2|͍͜±!)͘6* V#^#"V#^#"" " *|*ͫ!<͘6*"*+"|!\2!͈~ !Q͘* !c͘`:t¸!v:vC͘!͘' Y6;:vv!p " !{"2u!͘6!+ ͘~#ˆ~ #ÑS > ¨ ~ # .* ñ>?~. #\~ # *  >?73!p " 6*~͑"1!͘2_SO!T͢!͘o&))))):r ~Š*  ͈!` ͈" 6SO~#Øʹ>.ʹ~#´> > 'd }o|g yx> y0_:zE2w :z\:w_\\\\\:|*͈\MFT V4.8 for CP/M Plus, V1.4 Multi-File-Transfer for single disk drive, with multiple copy option. Buffer size = sectors Mount SOURCE disk, type RETURN (or ^C to reboot)Syntax error in filename - not found read error - sectors read Mount DESTINATION disk, type RETURN (or ^C to reboot)unable to create error writing file unable to close sectors written Completed. Type RETURN for another copy, OR... type ^C to reboot. ++ Memory buffer exceeded, cannot make duplicate copies this time...last output file is incomplete ++ ++ PROGRAM ABORTED ++ No file name specified ;;; MFT - multiple file transfer (for single drive systems) ; ; **Based on article in Dr. Dobbs Journal of Computer** ; **Calisthenics & Orthodontia #49, Box E, Menlo Park, Ca. 94025** ; by L.E. Hughes 9/79 ; Mycroft Labs ; Atlanta, Ga ; ------------------------- ;Version 4.8...Added counter to loop that prints ; out file names so that no more than 11 characters ; are printed and added "." to delineate file name ; from file type. Added "disk reset" call when the ; BDOS read function returns a value of 10 since that ; indicates a media change under cp/m plus (v3.x). ; Made slight modifications to messages that are ; printed to console. Also added disk reset call ; before each read pass. MFT now checks version of ; cpm at run time so no conditional assemble ; is necessary. ; (mabry...19 August 1983) ; ;Version 4.7B...Added symbol num$fls that must be ; equated to the maximum number of files that your ; system has on one logical drive. Till now it was ; fixed at 64 (ie "standard" CP/M). A drive with ; more than that would cause the file name table ; to blow up into the stack. (mabry) ; ;Version 4.7A...Added some code into disk reset ; subroutine so that if logged-in disk is not A: ; then files would be read from and written to ; that logged-in disk and not automatically from ; and to A: (dave mabry...23 Dec 82) ; ;Ver 4.7 - fixed some bugs relating to disk i/o and added ; switch for cp/m 2.2. ; ;Version 4.6A - gfn3 routine restored to version 4.5 - ; 4.6 revision did not handle eight char. filenames. ; I could not reproduce the error reported by cml when ; copying ufn.. (CHS) 4/30/81 ; ; Modified to VER. 4.6 to strip off $R/O attribute ; in output filename. If source was R/O then cp/m ; gave a "Bdos error on $R/O file" when an attempt was ; made to write to the newly created file. ; ; Changed 'jz gfn4' in rtn. gfn3 ; to 'jz gfn3' in order to ignore spaces ; in the file type. Before, whenever an extension ; was '.' multiple copies of the file ; name were built in the ifnt. ; ; Added equate 'nosys' and associated rtn. in section ; 'cfnt3:' in order to ignore all files with a 'sys' ; attribute. This will allow the user to mask-off ; any file(s) he doesn't want to copy. ; cml 4/10/81 ; ;Version 4.5 - 10/29/80 - Deleted system disk request of V4.0 ; to shorten messages, minor changes in abort options and ; other messages. Moved disk reset of V4.1 to point ; before directory search. (CHS) ; ;Version 4.4 - 10/28/80 - Modified to bail out with message ; if no FCB is specified. Updates rearranged with most ; recent first for reader convenience. (Charles H. Strom) ; ;VERSION 4.3 BY LEWIS MOSELEY, JR. 3/22/80 ; FIXED BUG WHICH SHOWED UP WHEN MULTIPLE COPIES WERE ; MADE OF A MULTIPLE EXTENT FILE, IN THAT CP/M OPEN ; THE NEXT EXTENT USING THE DATA AREA TO SEARCH THE ; DIRECTORY, SCREWING UP THE DATA BLOCK THAT IS THERE. ; ;VERSION 4.2 BY LEWIS MOSELEY, JR. 2/23/80 ; FIXED BUG THAT OCCURRED WHEN ONLY A SINGLE FILE ; WAS SPECIFIED AND THAT FILE WAS NOT FOUND: ; PROGRAM HUNG IN A LOOP ; ;VERSION 4.1 BY LES FREED AND LEWIS MOSELEY 2/11/80 ; ADDED DISK RESET ON DISK CHANGE TO ALLOW ; CHANGING DENSITY BETWEEN DISKS ; ADDED CTL-C ABORT ; ;VERSION 4.0 BY LEWIS MOSELEY, JR. 12/79 ; ADDED OPTION FOR MULTIPLE OUTPUT COPIES ; ADDED REQUEST FOR SYSTEM DISK BEFORE REBOOT ; ;MODIFIED FOR SOL & COMPATABLE COMPUTERS BY ;LEWIS MOSELEY, JR. - ATLANTA,GA. ; VERSION EQU 4 MODLEV EQU 8 ; ENTRY EQU 0005H ;bdos entry point TFCB EQU 005CH ;system file control block DBUF EQU 0080H ;system disk buffer ; TRUE EQU (NOT 0) AND 0FFH ;proper true value FALSE EQU 0H ; NOSYS EQU TRUE ;true to ignore all $SYS files ; The next symbol (NUM$FLS) must be set for the maximum number ; number of files you can possibly have on one disk. NUM$FLS EQU 128 ; <=== Be sure to set this for your system ; Every file takes away 16 bytes of ; buffer space for transfer so don't make ; it larger than it has to be. ; CR EQU 0DH LF EQU 0AH ; RCFC EQU 01 ;read console WCFC EQU 02 ;write console VNFC EQU 12 ;return version number RDFC EQU 13 ;reset disk SDFC EQU 14 ;select disk OFFC EQU 15 ;open file CFFC EQU 16 ;close file SFFC EQU 17 ;search first SNFC EQU 18 ;search next DFFC EQU 19 ;delete file RRFC EQU 20 ;read record WRFC EQU 21 ;write record MFFC EQU 22 ;make file CDFC EQU 25 ;get current disk SAFC EQU 26 ;set address ; FN EQU 01 ;file name offset FT EQU 09 ;file type offset EX EQU 12 ;extent number offset NR EQU 32 ;next record offset ; MEDCH EQU 10 ; error value for media changed (cpm plus) ; ORG 100H ; JMP MFT ; Jump over switches ; IGN$SYS: DB NOSYS ; True to ignore "system" files DB 0 ; Reserved for future enhancements DB 0 ; " " " " DB 0 ; " " " " ; MFT: LXI SP,STACK+64 LXI H,MSG1 ;print 'MFT VX.X (date)' CALL WASC XRA A ;clear break flags STA IBFLG STA OBFLG STA NDFLG ;clear no dup flag STA CPM2 ; Clear CP/M 2.x flag STA CPM3 ; Clear CP/M Plus flag (3.x) STA CPM2O3 ; Clear "CP/M 2 or 3" flag ; ; Now check for version of CP/M and set flags appropriately ; MVI C,VNFC ; Version number function CALL ENTRY MOV A,L ; Get return code ORA A ; Is it CP/M V1.4 ? JZ VER14 ; Yes, branch around this junk ANI 0FH ; Mask off high nybble ORI '0' ; Make if ascii STA CPMVN+2 ; Store version number of release MOV A,L ; Get return code again RLC ; Get high nybble RLC RLC RLC ANI 0FH ; Mask off low nybble ORI '0' ; Make it ascii STA CPMVN ; Store release number MOV A,L ; Get full number again CPI 20H ; Find version number for flags JC VER14 ; Jump if CP/M V1.4 CPI 30H ; Is it 2.x ? MVI A,TRUE ; Get ready to set flags JC VER2X ; Jump if CP/M V2.x STA CPM3 ; Set CP/M Plus flag only JMP VER14 ; VER2X: STA CPM2 ; Set flag for CP/M V2.x ; VER14: LDA CPM2 ; Set flag for cpm 2 or cpm 3 LXI H,CPM3 ORA M STA CPM2O3 ; ; Tell user version of cpm under which we are running ; LXI H,CPMV1 CALL WASC LXI H,CPMV2 LDA CPM3 ; Is it CP/M Plus or CP/M ? RRC CC WASC ; If yes, write "Plus" LXI H,CPMV3 CALL WASC ; Write version number ; LDA TFCB+1 ;If no FCB specified CPI ' ' ;then say so JNZ OK LXI H,MSGK ;and bail out CALL WASC ;here JMP 0000H ;via warm boot ; ;Calculate buffer size = fwa(BDOS) - fwa(MBUF) ; OK: LHLD ENTRY+1 ;hl = (entry+1) - 6 LXI D,-6 DAD D MOV A,L ANI 80H ;hl = hl mod 128 MOV L,A LXI D,MBUF ;hl = hl - fwa(MBUF) MOV A,L SUB E MOV L,A MOV A,H SBB D MOV H,A DAD H ;hl = hl / 128 MOV L,H MVI A,0 ACI 0 MOV H,A DCX H ;subtract one SHLD SPACE ;save as buffer size LXI H,MSG2 ;write 'Buffer size = ' CALL WASC LHLD SPACE ;write size of buffer CALL WDWC LXI H,MSG3 ;write ' sectors' CALL WASC ; ;Ask user to mount source disk ; MFT1: LXI H,MSG4 ;write 'Mount source disk, type CR' CALL WASC CALL RACC ;read response CPI 03 ;CTL-C ? JZ MFTL ;abort with message CPI CR ;loop if anything but CR JNZ MFT1 CALL WEOLC ;echo CR,LF CALL RESET ;reset disk system since disk has changed LDA IBFLG ;jump if ibflg set ORA A JNZ MFT2A ; ;Copy command line into cbuf ; LXI H,DBUF ;fwa of command line image LXI D,CBUF ;fwa of command buffer MOV B,M ;fetch command line image length INX H ; MFT2: MOV A,M ;fetch next byte from cli INX H STAX D ;store in dbuf INX D DCR B ;decrement count JNZ MFT2 ;loop until zero XRA A ;store zero byte at end STAX D LXI H,CBUF ;reset cbufp SHLD CBUFP CALL CFNT ;create file name table LXI H,FNT ;reset fnt pointers SHLD IFNTP SHLD OFNTP ; MFT2A: LXI H,MBUF ;reset mbuf pointer SHLD MBUFP LHLD SPACE ;reset msize SHLD MSIZE LDA IBFLG ;jump if ibflg not set ORA A JZ MFT3 LXI H,IFCB ;copy IFCB into TFCB LXI D,TFCB MVI B,33 CALL MOVE XRA A ;clear ibflg STA IBFLG INR A ;set obflg STA OBFLG LHLD IFNTP ;back ifntp up 4 bytes LXI D,-4 DAD D SHLD IFNTP LXI H,TFCB+FN ;write filename CALL WFNC LXI H,MSG6 ;write ' - ' CALL WASC LHLD IFNTP ;DE = ifntp XCHG JMP MFT4 ;continue reading previous file ; ;Parse off next name from cbuf ; MFT3: LHLD IFNTP ;fetch input fnt pointer MOV A,M ;jump if end of table CPI 0FFH JZ MFT9 MVI M,1 ;set 'file read' flag INX H LXI D,TFCB+FN ;copy filename into tfcb MVI B,11 CALL MOVE SHLD IFNTP ;save input fnt pointer LXI H,TFCB+FN ;write filename CALL WFNC LXI H,MSG6 ;write ' - ' CALL WASC XRA A ;setup tfcb STA TFCB STA TFCB+EX STA TFCB+NR CALL OPEN ;open file LHLD IFNTP XCHG ; MFT4: LHLD MBUFP MOV A,H ;copy into fnt entry STAX D INX D MOV A,L STAX D INX D XCHG ;save fnt pointer SHLD IFNTP LXI H,0 ;file size (in sectors) = 0 SHLD FSIZE ; ;Read next file from input disk ; MFT6: LHLD MBUFP XCHG CALL SETDMA CALL READ ;read next sector ORA A ;jump if normal transfer JZ MFT7 ; Next file instructions are for compatibility with CP/M Plus CPI MEDCH ; is error media change ? JNZ MFT6A ; no, branch around CALL RESET ; else, reset and reopen CALL OPEN JMP MFT6 ; and try read again ; MFT6A: CPI 1 ;jump if EOF JZ MFT8 LXI H,MSG8 ;write 'read error - ' CALL WASC JMP MFT8 ;continue as if EOF ; MFT7: LHLD MBUFP ;mbufp = mbufp + 128 LXI D,128 DAD D SHLD MBUFP LHLD FSIZE ;fsize = fsize + 1 INX H SHLD FSIZE LHLD MSIZE ;decrement msize DCX H SHLD MSIZE MOV A,H ;loop if still positive ORA L JNZ MFT6 LXI H,TFCB ;copy tfcb into ifcb LXI D,IFCB MVI B,33 CALL MOVE MVI A,1 ;set ibflg STA IBFLG ; MFT8: LXI D,DBUF ;reset dma pointer CALL SETDMA CALL CLOSE ;close file LHLD FSIZE ;write file size CALL WDWC LXI H,MSG9 ;write ' sectors read' CALL WASC ; ;Update fnt, loop ; LHLD FSIZE ;DE = file size XCHG LHLD IFNTP ;store file size in fnt entry MOV M,D INX H MOV M,E INX H SHLD IFNTP ;save fnt pointer LDA IBFLG ;loop if ibflg not set ORA A JZ MFT3 ; ;Flag that the memory buffer has been exceeded, and ;tell user that duplicate copies cannot be made ; LDA NDFLG ;told him already? ORA A JNZ MFT9 ;jump if so LXI H,MSGH ;if not, tell him CALL WASC MVI A,1 ;set NDFLG this time STA NDFLG ; ;Ask user to mount output disk ; MFT9: LXI H,MSGA ;write 'Mount destination disk, type CR' CALL WASC CALL RACC ;read response CPI 03 ;CTL-C? JZ MFTL ;abort with message if so CPI CR ;loop if anything but CR JNZ MFT9 CALL WEOLC ;echo CR,LF CALL RESET ;reset disk system ;make r/w and check density LDA OBFLG ;jump if obflg not set ORA A JZ MFTA LXI H,OFCB ;copy ofcb into tfcb LXI D,TFCB MVI B,33 CALL MOVE CALL OPEN ;open previous file LHLD OFNTP ;backup output fnt pointer 4 bytes LXI D,-4 DAD D SHLD OFNTP LXI H,TFCB+FN ;write file name CALL WFNC LXI H,MSG6 ;write ' - ' CALL WASC JMP MFTB ;continue writing previous file ; ;Write next file to output disk ; MFTA: LHLD OFNTP MOV A,M ORA A JZ MFTF CPI 0FFH JZ MFTF INX H LXI D,TFCB+FN MVI B,11 CALL MOVE SHLD OFNTP ; LDA CPM2O3 RRC ; Is this cpm 2 or cpm 3 ? JNC NORO ; No, don't reset $R/O bit LXI H,TFCB+FT ;pt to $R/O byte MOV A,M ;get it from storage ANI 7FH ;force it to $R/W MOV M,A ;put it back ; NORO: LXI H,TFCB+FN CALL WFNC LXI H,MSG6 CALL WASC XRA A STA TFCB STA TFCB+EX STA TFCB+NR CALL DELT ;try to create output file CALL MAKE CPI 255 ;jump if ok JNZ MFTB LXI H,MSGB ;write 'unable to create' CALL WASC JMP MFTG ; MFTB: LHLD OFNTP MOV D,M ;fetch fwa of file from fnt INX H MOV E,M INX H XCHG SHLD MBUFP ;save it XCHG MOV D,M ;fetch size of file from fnt INX H MOV E,M INX H XCHG SHLD FSIZE ;save it SHLD XSIZE ;save for printout XCHG SHLD OFNTP LHLD FSIZE ;jump if fsize=0 MOV A,H ORA L JZ MFTDA ; MFTC: LHLD MBUFP ;set dma address to mbufp XCHG CALL SETDMA CALL WRITE ;write next sector ORA A ;jump if ok JZ MFTD LXI H,MSGC ;write 'error writing file' CALL WASC JMP MFTG ; MFTD: LHLD MBUFP ;mbufp = mbufp + 128 LXI D,128 DAD D SHLD MBUFP LHLD FSIZE ;fsize = fsize - 1 DCX H SHLD FSIZE MOV A,H ;loop until zero ORA L JNZ MFTC ; MFTDA: LXI H,TFCB ;copy tfcb into ofcb LXI D,OFCB MVI B,33 CALL MOVE LXI D,DBUF ;reset dma pointer CALL SETDMA CALL CLOSE ;try to close file CPI 255 ;jump if ok JNZ MFTE LXI H,MSGD ;write 'unable to close' CALL WASC ; MFTE: LHLD XSIZE ;write number of sectors written CALL WDWC LXI H,MSGE ;write ' sectors written' CALL WASC JMP MFTA ; MFTF: LDA IBFLG ;loop if ibflg set ORA A JNZ MFT1 ; ;Terminate program here on unrecoverable error or ;when all files have been copied. Must reload system ;disk to avoid crash when copying to someone else's disk. ;If normal end, and if buffer has not been exceeded, give ;user the option of making another copy of the same ;set of files. ; MFTG: LXI H,MSGF ;see if option is allowed LDA NDFLG ORA A JNZ MFTH ;jump if not allowed CALL WASC ;else tell about option ; MFTH: LXI H,MSGG ;ask for system disk CALL WASC CALL RACC ;wait for response CPI 03H ;warm boot if ^C JZ 0 CPI CR ;attempt repeat if JZ MFTJ JMP MFTG ;else loop till good response ; MFTJ: CALL WEOLC ;acknowledge command LDA NDFLG ;repeat allowed? ORA A JNZ MFTK ;jump if not LXI H,FNT ;else reset FNT pointer SHLD OFNTP LXI H,MBUF ;reset MEM BUF pointer SHLD MBUFP XRA A ;reset output interrupted flag STA OBFLG JMP MFT9 ;and do again ; MFTK: LXI H,MSGH ;cannot repeat, tell him again CALL WASC JMP MFTG ;and wait for system disk ; MFTL: LXI H,MSGJ ;abort message CALL WASC JMP 0000H ;warm boot ;Subroutines ; MOVE: MOV A,M INX H STAX D INX D DCR B JNZ MOVE RET ; ;GFN - get file name ; GFN: MOV A,M ORA A RZ CPI ' ' JNZ GFN0 INX H JMP GFN ; GFN0: LXI D,XFCB XRA A STAX D INX D PUSH D MVI B,11 MVI A,' ' ; GFN6: STAX D INX D DCR B JNZ GFN6 POP D MVI B,9 ; GFN1: MOV A,M ORA A JZ GFN4 INX H CPI ' ' JZ GFN4 CPI '.' JZ GFN2 CPI '*' JZ GFN7 STAX D INX D DCR B JZ GFN5 JMP GFN1 ; GFN7: DCR B JZ GFN9 MVI A,'?' STAX D INX D JMP GFN7 ; GFN9: MOV A,M CPI '.' JNZ GFN4 INX H ; GFN2: LXI D,XFCB+FT MVI B,4 ; GFN3: MOV A,M ORA A JZ GFN4 INX H CPI ' ' JZ GFN4 CPI '*' JZ GFN8 STAX D INX D DCR B JZ GFN5 JMP GFN3 ; GFN8: DCR B JZ GFN4 MVI A,'?' STAX D INX D JMP GFN8 ; GFN4: XRA A RET ; GFN5: STC RET ; ;CFNT - create file name table ; CFNT: CALL RESET ;reset disk system LXI H,FNT ;reset ifntp SHLD IFNTP MVI M,0FFH ; CFNT1: LHLD CBUFP ;get cbufp MOV A,M ;exit if end of list ORA A RZ CALL GFN ;get next afn SHLD CBUFP ;save command buffer ptr JNC CFNT2 ;jump if filename ok LXI H,MSG5 ;write 'Syntax error in filename' CALL WASC JMP CFNT1 ;loop ; CFNT2: XRA A ;clear xfcb extent field STA XFCB+EX LXI D,XFCB ;search for first occurance CALL SRCHF CPI 255 ;jump if found JNZ CFNT3 LXI H,XFCB+FN ;write filename CALL WFNC LXI H,MSG7 ;write ' not found' CALL WASC JMP CFNT1 ;loop ; CFNT3: ANI 3 ;index into cbuf MOV L,A MVI H,0 DAD H DAD H DAD H DAD H DAD H LXI D,DBUF DAD D ; LDA IGN$SYS ; Supposed to ignore "system" files RRC JNC CFNT3A ; Jump if no, ie. do copy sys files PUSH H PUSH D LXI D,10 DAD D MOV A,M ;get 't2' ANI 80H ;look at sys bit POP D POP H JNZ CFNT4 ;'sys file'-ignore ; CFNT3A: XCHG ;copy filename into fnt LHLD IFNTP XCHG MVI B,12 CALL MOVE LXI H,ZEROS ;zero fill rest of entry MVI B,4 CALL MOVE XCHG SHLD IFNTP ;save input fnt pointer MVI M,0FFH ;insure FF byte at end ; CFNT4: LXI D,XFCB ;search for next occurance CALL SRCHN CPI 255 ;jump if found JNZ CFNT3 JMP CFNT1 ;go get next afn ; ;WASC - write ascii string to console ; WASC: MOV A,M ORA A RZ CALL WACC INX H JMP WASC ; ;WFNC - write file name to console ;printing 11 characters starting at ; WFNC: PUSH B ; save registers used MVI B,8 ; number of characters in file name CALL WFNC1 ; print file name MVI A,'.' ; print "." between file name and type CALL WACC MVI B,3 ; number of characters in file type CALL WFNC1 ; print file type POP B ; restore RET WFNC1: MOV A,M ; get character CALL WACC ; go print it INX H DCR B ; last character ? JNZ WFNC1 ; loop if not RET ; ;WEOLC - write end of line to console ; WEOLC: MVI A,CR CALL WACC MVI A,LF JMP WACC ; ;WDWC - write decimal word to console ; WDWC: PUSH H PUSH D PUSH B MVI B,0 ;clear 'digit written' flag LXI D,10000 ;write 1st digit CALL WNDD LXI D,1000 ;write 2nd digit CALL WNDD LXI D,100 ;write 3rd digit CALL WNDD LXI D,10 ;write 4th digit CALL WNDD LXI D,1 ;write 5th digit MVI B,1 ;force last digit to print CALL WNDD POP B POP D POP H RET ; WNDD: MVI C,0 ;c=0 ; WNDD1: MOV A,L ;hl = hl - de SUB E MOV L,A MOV A,H SBB D MOV H,A JC WNDD2 ;jump if < 0 INR C ;c = c + 1 JMP WNDD1 ;loop ; WNDD2: DAD D ;hl = hl + de MOV A,C ;jump if c non-zero ORA C JNZ WNDD4 MOV A,B ;jump if digit written ORA B JNZ WNDD4 MVI A,' ' ;write one space JMP WACC ; WNDD4: MVI B,1 ;set 'digit written' flag MOV A,C ;encode c into decimal ascii ADI '0' JMP WACC ;go write it ; ;WACC - write ascii character to console ; WACC: PUSH H PUSH D PUSH B PUSH PSW MVI C,WCFC MOV E,A CALL ENTRY POP PSW POP B POP D POP H RET ; ;RACC - read ascii character from console ; RACC: PUSH H PUSH D PUSH B MVI C,RCFC CALL ENTRY POP B POP D POP H RET ; ;RESET - reset disk system and make ;sure current default disk will ;remain after reset operation ; RESET: PUSH H PUSH D PUSH B ; LDA CPM2O3 ; Can we request current disk ? RRC JNC RESET5 ; Jump around if no MVI C,CDFC ;request current disk CALL ENTRY STA CURDSK ;Save it for after reset ; RESET5: MVI C,RDFC CALL ENTRY ; LDA CPM2O3 ; Can we select disk ? RRC JNC RESET10 ; Jump around if no MVI C,SDFC ;Select disk LDA CURDSK ;Get previous disk MOV E,A MVI D,0 CALL ENTRY ; RESET10: POP B POP D POP H RET ; ;OPEN - open disk file ; OPEN: PUSH H PUSH D PUSH B LXI D,TFCB MVI C,OFFC CALL ENTRY POP B POP D POP H RET ; ;READ - read record from disk file ; READ: PUSH H PUSH D PUSH B LXI D,TFCB MVI C,RRFC CALL ENTRY POP B POP D POP H RET ; ;CLOSE - close disk file ; CLOSE: PUSH H PUSH D PUSH B LXI D,TFCB MVI C,CFFC CALL ENTRY POP B POP D POP H RET ; ;DELT - delete disk file ; DELT: PUSH H PUSH D PUSH B LXI D,TFCB MVI C,DFFC CALL ENTRY POP B POP D POP H RET ; ;MAKE - make new disk file ; MAKE: PUSH H PUSH D PUSH B LXI D,TFCB MVI C,MFFC CALL ENTRY POP B POP D POP H RET ; ;WRITE - write record to file ; WRITE: PUSH H PUSH D PUSH B LDA TFCB+NR ;LAST RECORD IN EXTENT? CPI 7FH JNZ WRITE1 ;NO, CONTINUE LHLD MBUFP ;EXISTING DATA AREA LXI D,DBUF ;POINT TO SAFE AREA CALL SETDMA ;TELL CP/M WHERE TO GET DATA MVI B,80H ;LENGTH TO MOVE CALL MOVE ;MOVE DATA AWAY SO... ;CP/M DOESN'T OVERWRITE THE REAL ;DATA IN OPENING NEXT EXTENT ; WRITE1: LXI D,TFCB MVI C,WRFC CALL ENTRY POP B POP D POP H RET ; ;SETDMA - set dma address ; SETDMA: PUSH H PUSH D PUSH B MVI C,SAFC CALL ENTRY POP B POP D POP H RET ; ;SRCHF - search for first occurance of afn ; SRCHF: PUSH H PUSH D PUSH B MVI C,SFFC CALL ENTRY POP B POP D POP H RET ; ;SRCHN - search for next occurance of afn ; SRCHN: PUSH H PUSH D PUSH B MVI C,SNFC CALL ENTRY POP B POP D POP H RET ; MSG1: DB 'MFT V' DB VERSION+'0' ; Version # DB '.',MODLEV+'0',0 ; Modification level CPMV1: DB ' for CP/M ',0 CPMV2: DB 'Plus, ',0 CPMV3: DB 'V' CPMVN: DB '1.4',CR,LF DB 'Multi-File-Transfer for single disk drive, ' DB 'with multiple copy option.',CR,LF,0 MSG2: DB 'Buffer size = ',0 MSG3: DB ' sectors',CR,LF,LF,0 MSG4: DB 'Mount SOURCE disk, type RETURN (or ^C to reboot)',0 MSG5: DB 'Syntax error in filename',CR,LF,0 MSG6: DB ' - ',0 MSG7: DB ' not found',CR,LF,0 MSG8: DB 'read error - ',0 MSG9: DB ' sectors read',CR,LF,0 MSGA: DB 'Mount DESTINATION disk, type RETURN (or ^C to reboot)',0 MSGB: DB 'unable to create',CR,LF,0 MSGC: DB 'error writing file',CR,LF,0 MSGD: DB 'unable to close',CR,LF,0 MSGE: DB ' sectors written',CR,LF,0 MSGF: DB CR,LF,'Completed. ' DB 'Type RETURN for another copy, OR...',0 MSGG: DB CR,LF,'type ^C to reboot.',CR,LF,0 MSGH: DB CR,LF,'++ Memory buffer exceeded, cannot make duplicate ',CR,LF DB 'copies this time...last output file is incomplete ++' DB CR,LF,LF,0 MSGJ DB CR,LF,'++ PROGRAM ABORTED ++',CR,LF,0 MSGK DB CR,LF,'No file name specified',CR,LF,0 ; ; ZEROS: DB 0,0,0,0 ; ORG ($+15)/16*16 ; FNT: DS 16*NUM$FLS+1 ; STACK: DS 64 SPACE: DS 2 ;available space MSIZE: DS 2 ;memory size CBUF: DS 80 ;command buffer CBUFP: DS 2 ;command buffer pointer FSIZE: DS 2 ;file size in sectors XSIZE: DS 2 ;file size for printout IFNTP: DS 2 ;input fnt pointer OFNTP: DS 2 ;output fnt pointer MBUFP: DS 2 ;memory buffer pointer IFCB: DS 33 ;input fcb OFCB: DS 33 ;output fcb XFCB: DS 33 ;temporary fcb IBFLG: DS 1 ;input break flag OBFLG: DS 1 ;output break flag NDFLG: DS 1 ;no duplicate allowed flag CURDSK: DS 1 ;save location for current disk CPM2: DS 1 ; Flag for CP/M 2.x CPM3: DS 1 ; Flag for CP/M Plus (V3.x) CPM2O3: DS 1 ; Flag for CP/M 2 or 3 ; MBUF EQU $ ; END MFT  MFT - Multiple File Transfer Utility - User's Guide for version 4.8 MFT is a transient program which runs under the Digital Research CP/M operating system. It is used for transferring one or more arbitrarily large files from one diskette to another on a single drive, not necessarily drive A. It is run by typing its name followed by a file specification. That specification can be a list of unambiguous file names separated by spaces or an ambiguous file name. No drive id is allowed in the file specification since the files are read from and written to the logged drive. Any valid drive may be used. It will attempt to read all specified files into memory, up to the start of the BDOS. If any file extends past the available memory area, any files and/or part thereof which were read will be written to the output disk, and a further pass will be requested. MFT will continue read/write passes until all files have been transferred. The general syntax for MFT is as follows: d>MFT where: d is the logged drive (any legal drive) can be an ambiguous file name or a list of one or more unambiguous file names or ambiguous file names separated by spaces. Examples: To copy just ASM, PIP, and DDT from drive A to drive A: A>MFT ASM.COM PIP.COM DDT.COM To copy MFT itself from drive B to drive B: A>B: B>MFT MFT.COM The following example shows MFT copying an entire disk from drive B to drive B. Note that MFT.COM resides on drive A in this case. B>A:MFT *.* MFT V4.8 for CP/M Plus, V3.1 Multi-File-Transfer for single disk drive, with multiple copy option. Buffer size = 331 sectors Mount SOURCE disk, type RETURN (or ^C to reboot) MFTX48 .ASM - 163 sectors read MFTX48 .SAV - 161 sectors read MFTX48A .BAK - 7 sectors read ++ Memory buffer exceeded, cannot make duplicate copies this time...last output file is incomplete ++ Mount DESTINATION disk, type RETURN (or ^C to reboot) MFTX48 .ASM - 163 sectors written MFTX48 .SAV - 161 sectors written MFTX48A .BAK - 7 sectors written Mount SOURCE disk, type RETURN (or ^C to reboot) MFTX48A .BAK - 151 sectors read MFTX48 .COM - 16 sectors read MFTX48A .ASM - 159 sectors read RSXDEMO .AQM - 5 sectors read Mount DESTINATION disk, type RETURN (or ^C to reboot) MFTX48A .BAK - 151 sectors written MFTX48 .COM - 16 sectors written MFTX48A .ASM - 159 sectors written RSXDEMO .AQM - 5 sectors written Mount SOURCE disk, type RETURN (or ^C to reboot) RSXDEMO .AQM - 34 sectors read RSXDEMO .DQC - 52 sectors read MFTX48 .AQM - 111 sectors read RSXDEMO .ASM - 57 sectors read MFTX48A .HEX - 44 sectors read MFTX48A .COM - 16 sectors read MFTX48A .PRN - 17 sectors read Mount DESTINATION disk, type RETURN (or ^C to reboot) RSXDEMO .AQM - 34 sectors written RSXDEMO .DQC - 52 sectors written MFTX48 .AQM - 111 sectors written RSXDEMO .ASM - 57 sectors written MFTX48A .HEX - 44 sectors written MFTX48A .COM - 16 sectors written MFTX48A .PRN - 17 sectors written Mount SOURCE disk, type RETURN (or ^C to reboot) MFTX48A .PRN - 269 sectors read RSXDEMO .RSX - 6 sectors read RSXINIT .ASM - 8 sectors read MFTX48A .AQM - 48 sectors read Mount DESTINATION disk, type RETURN (or ^C to reboot) MFTX48A .PRN - 269 sectors written RSXDEMO .RSX - 6 sectors written RSXINIT .ASM - 8 sectors written MFTX48A .AQM - 48 sectors written Mount SOURCE disk, type RETURN (or ^C to reboot) MFTX48A .AQM - 65 sectors read MFT .DQC - 18 sectors read MFT .DOC - 25 sectors read RSXINIT .COM - 7 sectors read 950FUNC .AQM - 17 sectors read Mount DESTINATION disk, type RETURN (or ^C to reboot) MFTX48A .AQM - 65 sectors written MFT .DQC - 18 sectors written MFT .DOC - 25 sectors written RSXINIT .COM - 7 sectors written 950FUNC .AQM - 17 sectors written type ^C to reboot. ^C B> Note that five passes were required to transfer all files. Also note that MFTX48A.BAK was partially transferred in pass one (7 of its 158 sectors) with the remainder (151 sectors) being transferred in pass two. Note that the name MFTX48A.BAK occurs both as the last file of pass one and as the first file of pass two. The file RSXDEMO.AQM was split in a similar manner between passes two and three. A number of self-explanatory error messages may print out during normal use, if read or write errors occur at any point, for example if the disk fills up during a write. No checks are made to prevent overwiting an existing file on the output disk. As MFT creates its filename table, it may issue diagnostics which indicate that a particular filename was not found, or a syntax error was detected. MFT will struggle bravely on and ignore any such attempts at levity. Just those files which are legal names and present on the disk will be listed as it reads them into memory. As distributed, MFT.OBJ will run on most systems without changes. The only user configurable options are whether or not MFT will copy "system" files (files with $SYS attribute set) and the maximum number of files your disk can have. To allow MFT to copy "system" files as well as "non-system" files, reset the least significant bit of the byte at 103H. The released version of the object code has this bit set. The maximum number of files it will copy is 128, so if a disk on your system is capable of containing more than 128 files, you must obtain the source code (MFT48.AQM), "unsqueeze" it and modify the symbol NUM$FLS. You should "EQU" it to be the maximum number of files your system is capable of having on one disk. Then MFT48.ASM must be reassembled by ASM (or equivalent) and "LOAD"ed. The following commands will set MFT.COM to copy "system" files along with "non-system" files: A>DDT MFT.COM DDT VERS 2.2 NEXT PC 0980 0100 -S103 0103 FF 00 0104 00 . -G0 A>SAVE 9 MFT.COM LEH - 79/09/23. DM - 19 August 1983.