;****************************************************** ;* * ;* MFT - Multiple File Transfer * ;* (for single drive systems) * ;* * ;* Based on an article in Dr. Dobbs Journal of * ;* Computer Calisthenics & Orthodontia #49, * ;* Box E, Menlo Park, Ca. 94025 * ;* * ;* Vers 5.0 - 2/10/83 by William King (Time-11:32pm) * ;* - Modified the main title (pretty). * ;* - Converted all code to Z-80 so it * ;* could be assembled with "EXASM.COM". * ;* - Optimised code for Z-80 (ie use * ;* LDIR,JR and DJNZ). * ;* - Added check on CP/M version No. * ;* - Using direct console I/O and using * ;* function No.30 (change file attributes)* ;* - Close after a read file bug fixed. * ;* - Error check on opening a previous * ;* output file added. * ;* *** - User response routine added so when * ;* a file exists on the output disk, you * ;* may either erase it or leave it (this * ;* routine includes erasure of R/O files) * ;* - MOVE routine deleted. * ;* - Fixed bug encounted when trying to * ;* copy r/o files (you couldn't!),by * ;* doing AND 07FH on ALL characters put * ;* into the filename table !! * ;* - Fixed filename printing stuff. * ;* - Spread out messages for readability. * ;* - Changed size of filename table from * ;* 64 entries to 128 entries, so large * ;* disk directories can be copied. * ;* - Added explanation of how each entry * ;* in the filename table is constructed. * ;* * ;* (***) = main bulk of code added. * ;* * ;* Vers 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) * ;* * ;* Vers 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) * ;* * ;* VERS 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. * ;* * ;* VERS 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. * ;* * ;* VERS 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 * ;* * ;* VERS 4.0 - BY LEWIS MOSELEY, JR. 12/79 * ;* ADDED OPTION FOR MULTIPLE OUTPUT * ;* COPIES ADDED REQUEST FOR SYSTEM DISK * ;* BEFORE REBOOT * ;* * ;* l.e. hughes (9/1979) * ;* mycroft labs * ;* atlanta, ga * ;* * ;* MODIFIED - FOR SOL & COMPATABLE COMPUTERS BY * ;* LEWIS MOSELEY, JR. - ATLANTA,GA. * ;* * ;****************************************************** ;* EQUATES * VERSION EQU 5 MODLEV EQU 0 ENTRY: EQU 0005H ;bdos entry point TFCB: EQU 005CH ;system file control blk DBUF: EQU 0080H ;system disk buffer CR: EQU 0DH LF: EQU 0AH RCFC: EQU 01 ;read console WCFC: EQU 02 ;write console CONSOL: EQU 06 ;direct console i/o VERS: EQU 12 ;version number function RDFC: EQU 13 ;reset 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 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 ORG 00100H MFT: LD SP,STACK+64 LD HL,MSG1 ;print 'MFT V5.0' CALL WASC LD C,VERS ;get version # CALL ENTRY LD A,L CP 020H ;vers >= 2.0 ? JR NC,OK1-$ ;yes,then go on LD HL,BADVER ;"Sorry you need 2.0" CALL WASC OK2: LD HL,MSGG ;"type ^c" CALL WASC CALL RACC CP 3 JR NZ,OK2-$ JP 00000H ;reboot OK1: XOR A ;clear break flags LD (IBFLG),A LD (OBFLG),A LD (NDFLG),A ;CLEAR NO DUP FLAG LD A,(TFCB+1) ;If no FCB specified CP ' ' ;then say so JR NZ,OK-$ LD HL,MSGK ;and bail out CALL WASC ;here JP 00000H ;* calculate buffer size = fwa(BDOS) - fwa(MBUF) * OK: LD HL,(ENTRY+1) ;hl = (entry+1) - 6 LD DE,-6 ADD HL,DE LD A,L AND 80H ;hl = hl mod 128 LD L,A LD DE,MBUF ;hl = hl - fwa(MBUF) LD A,L SUB E LD L,A LD A,H SBC A,D LD H,A ADD HL,HL ;hl = hl / 128 LD L,H LD A,0 ;don't touch cf ADC A,0 LD H,A DEC HL ;subtract one LD (SPACE),HL ;save as buffer size PUSH HL ;save size LD HL,MSG2 ;write 'Buffer size = ' CALL WASC POP HL ;get size back CALL WDWC ;print size of buffer LD HL,MSG3 ;write ' sectors' CALL WASC ;* ask user to mount input disk * MFT1: LD HL,MSG4 ;"Mount input disk," CALL WASC CALL RACC ;read response CP 03 ;CTL-C ? JP Z,MFTL ;ABORT WITH MESSAGE CP CR ;loop if anything but CR JR NZ,MFT1-$ CALL WEOLC ;echo CR,LF CALL RESET ;adjust density LD A,(IBFLG) ;jump if ibflg set OR A JR NZ,MFT2A-$ ;* copy command line into cbuf * LD HL,DBUF ;fwa of command line ;image LD DE,CBUF ;fwa of command buffer LD B,(HL) ;fetch comm. line length INC HL MFT2: LD A,(HL) ;fetch next byte from cli INC HL LD (DE),A ;store in dbuf INC DE DEC B ;decrement count JR NZ,MFT2-$ ;loop until zero XOR A ;store zero byte at end LD (DE),A LD HL,CBUF ;reset cbufp LD (CBUFP),HL CALL CFNT ;create file name table LD HL,FNT ;reset fnt pointers LD (IFNTP),HL LD (OFNTP),HL MFT2A: LD HL,MBUF ;reset mbuf pointer LD (MBUFP),HL LD HL,(SPACE) ;reset msize LD (MSIZE),HL LD A,(IBFLG) ;jump if ibflg not set OR A JR Z,MFT3-$ LD A,(NERAS) ;get last file not ;written flag OR A JR Z,MFT2B-$ ;not set the read more of ;previously opened file XOR A LD (NERAS),A LD (IBFLG),A LD (OBFLG),A JR MFT3-$ MFT2B: LD HL,IFCB ;copy IFCB into TFCB LD DE,TFCB LD BC,33 LDIR ;move the stuff XOR A ;clear ibflg LD (IBFLG),A INC A ;set obflg LD (OBFLG),A LD HL,(IFNTP) ;back ifntp up 4 bytes LD DE,-4 ADD HL,DE LD (IFNTP),HL LD HL,TFCB+FN ;write filename CALL WFNC LD HL,MSG6 ;write ' - ' CALL WASC LD HL,(IFNTP) ;DE = ifntp EX DE,HL JR MFT4-$ ;continue reading ;previous file ;* parse off next name from cbuf * MFT3: LD HL,(IFNTP) ;fetch input fnt pointer LD A,(HL) ;jump if end of table CP 0FFH JP Z,MFT9 LD (HL),1 ;set 'file has been read' ; flag INC HL LD DE,TFCB+FN ;copy filename into tfcb LD BC,11 LDIR ;move the stuff LD (IFNTP),HL ;save input fnt pointer LD HL,TFCB+FN ;write filename CALL WFNC LD HL,MSG6 ;write ' - ' CALL WASC XOR A ;setup tfcb LD (TFCB),A LD (TFCB+EX),A LD (TFCB+NR),A CALL OPEN ;open file LD HL,(IFNTP) EX DE,HL MFT4: LD HL,(MBUFP) LD A,H ;copy into fnt entry LD (DE),A INC DE LD A,L LD (DE),A INC DE EX DE,HL ;save fnt pointer LD (IFNTP),HL LD HL,0 ;file size (in secs.) = 0 LD (FSIZE),HL ;* read next file from input disk * MFT6: LD HL,(MBUFP) EX DE,HL CALL SETDMA CALL READ ;read next sector OR A ;jump if normal transfer JR Z,MFT7-$ CP 1 ;jump if EOF JR Z,MFT8-$ LD HL,MSG8 ;write 'read error - ' CALL WASC JR MFT8-$ ;continue as if EOF MFT7: LD HL,(MBUFP) ;mbufp = mbufp + 128 LD DE,128 ADD HL,DE LD (MBUFP),HL LD HL,(FSIZE) ;fsize = fsize + 1 INC HL LD (FSIZE),HL LD HL,(MSIZE) ;decrement msize DEC HL LD (MSIZE),HL LD A,H ;loop if still positive OR L JR NZ,MFT6-$ LD HL,TFCB ;copy tfcb into ifcb LD DE,IFCB LD BC,33 LDIR ;move the stuff LD A,1 ;set ibflg LD (IBFLG),A MFT8: LD DE,DBUF ;reset dma pointer CALL SETDMA ;deleted close file from ;here (don't close after ;a read !!) LD HL,(FSIZE) ;write file size CALL WDWC LD HL,MSG9 ;write ' sectors read' CALL WASC ;* update fnt, loop * LD HL,(FSIZE) ;DE = file size EX DE,HL LD HL,(IFNTP) ;store file size in fnt ;entry LD (HL),D INC HL LD (HL),E INC HL LD (IFNTP),HL ;save fnt pointer LD A,(IBFLG) ;loop if ibflg not set OR A JP Z,MFT3 ;* FLAG THAT THE MEMORY BUFFER HAS BEEN EXCEEDED, * ;* TELL USER THAT DUPLICATE COPIES CANNOT BE MADE * LD A,(NDFLG) ;TOLD HIM ALREADY? OR A JR NZ,MFT9-$ ;JUMP IF SO LD HL,MSGH ;IF NOT, TELL HIM CALL WASC LD A,1 ;SET NDFLG THIS TIME LD (NDFLG),A ;* Ask user to mount output disk * MFT9: LD HL,MSGA ;"Mount output disk," CALL WASC CALL RACC ;read response CP 03 ;CTL-C? JP Z,MFTL ;ABORT WITH MESSAGE IF SO CP CR ;loop if anything but CR JR NZ,MFT9-$ CALL WEOLC ;echo CR,LF CALL RESET ;reset disk system, make ; r/w and check density LD A,(OBFLG) ;jump if obflg not set OR A JR Z,MFTA-$ LD HL,OFCB ;copy ofcb into tfcb LD DE,TFCB LD BC,33 LDIR ;move the stuff CALL OPEN ;open previous file CP 255 ;previous file present? JR NZ,MFT9B-$ ;yes,then ok to go on LD HL,REOPER ;"Reopen error!!" CALL WASC MFT9A: LD HL,MSGG ;"press ^c to reboot" CALL WASC CALL RACC ;get a char CP 03 ;"^C"? JR NZ,MFT9A-$ ;no,then get proper ans. JP 00000H ;reboot MFT9B: LD HL,(OFNTP) ;backup output fnt ; pointer 4 bytes LD DE,-4 ADD HL,DE LD (OFNTP),HL LD HL,TFCB+FN ;write file name CALL WFNC LD HL,MSG6 ;write ' - ' CALL WASC JP MFTB ;continue writing ; previous file ;* write next file to output disk * MFTA: LD HL,(OFNTP) LD A,(HL) ;get file read flag OR A ;last read in file JP Z,MFTF ;yes,then end of write CP 0FFH ;end of filename table? JP Z,MFTF ;yes,then go INC HL LD DE,TFCB+FN LD BC,11 LDIR ;move the stuff LD (OFNTP),HL LD HL,TFCB+FN ;print "filename" CALL WFNC LD HL,MSG6 ;print " - " CALL WASC XOR A LD (TFCB),A LD (TFCB+EX),A LD (TFCB+NR),A ;* Start of version 5.0 erase mods * LD DE,TFCB CALL SRCHF ;does file already exist? CP 255 JP Z,MFTAA ;no,then normal write LD (SAVE),A ;save dir pointer LD HL,TFCB ;copy tfcb into ofcb LD DE,OFCB LD BC,33 LDIR ;move the stuff LD HL,MSGL ;"file exists. erase?" CALL WASC LOOK: LD C,CONSOL ;input char with no echo LD E,0FFH CALL ENTRY CP 'N' JR Z,LOOK1-$ CP 'Y' JR NZ,LOOK-$ LOOK1: PUSH AF ;save answer LD C,CONSOL ;echo the char LD E,A CALL ENTRY CALL WEOLC ;do cr-lf POP AF ;get answer back CP 'Y' JR Z,LOOK5-$ ;if yes then delete file LD A,1 LD (NERAS),A ;set last file not ;written flag LD HL,(OFNTP) ;get fnt pointer INC HL INC HL INC HL INC HL ;point to next entry LOOK2: PUSH HL ;save for later INC HL ;point to next filename LD DE,TFCB+FN ;point to last filename LD B,11 ;length to test LOOK3: LD A,(DE) ;compare the names CP (HL) JR NZ,LOOK4-$ ;if they are NOT the same ;then go ahead and use ;the name being compared INC HL INC DE DJNZ LOOK3-$ ;do whole name ;if here then both names ;are the same thus don't ;use this name in fnt. ;must point to next name ;after this name POP HL ;get this fnt pointer LD DE,16 ;offset ADD HL,DE LD A,(HL) ;check if this file read OR A JP Z,MFTF ;no,not read yet CP 0FFH ;end of table? JP Z,MFTF ;yes,end of fnt reached JR LOOK2-$ ;compare next file ;must keep comparing name ;until : a no-match ; ;or end of table or last ;read file is found. LOOK4: POP HL ;get fnt pointer back LD (OFNTP),HL ;save it for much later JP MFTA ;do next file LOOK5: LD HL,TFCB+FN ;"filename" CALL WFNC LD HL,MSG6 ;" - " CALL WASC LD A,(SAVE) ;get dir pointer back AND 3 LD L,A LD H,0 ADD HL,HL ADD HL,HL ADD HL,HL ADD HL,HL ADD HL,HL ;get offset into dir blk. LD DE,DBUF+FT ;point to filetype byte ;in found dir entry. ADD HL,DE LD A,(HL) ;1st filetype byte BIT 7,A ;check for r/o = set JR Z,LOOK7-$ ;not set,then erase ok ;here if file to be ;erased is r/o. Ask Q ;if want erase anyway? LD HL,FILERO ;"file is r/o. Erase?" CALL WASC LOOK6: LD C,CONSOL ;get char LD E,0FFH CALL ENTRY CP 'N' JP Z,LOOK1 ;don't erase it CP 'Y' JR NZ,LOOK6-$ LD C,CONSOL ;echo LD E,A CALL ENTRY CALL WEOLC ;cr-lf LD DE,TFCB LD C,30 ;set file attr. to r/w CALL ENTRY LD HL,TFCB+FN ;"filename" CALL WFNC LD HL,MSG6 ;" - " CALL WASC LOOK7: XOR A LD (TFCB),A LD (TFCB+EX),A LD (TFCB+NR),A CALL DELT ;delete existing file ;* End of version 5.0 erase mods * MFTAA: LD HL,TFCB ;copy tfcb into ofcb LD DE,OFCB LD BC,33 LDIR ;move the stuff CALL MAKE CP 255 ;jump if ok JR NZ,MFTB-$ LD HL,MSGB ;write 'unable to create' CALL WASC JP MFTG MFTB: LD HL,(OFNTP) LD D,(HL) ;fetch fwa of file from ; fnt INC HL LD E,(HL) INC HL EX DE,HL LD (MBUFP),HL ;save it EX DE,HL LD D,(HL) ;fetch size of file from ; fnt INC HL LD E,(HL) INC HL EX DE,HL LD (FSIZE),HL ;save it LD (XSIZE),HL ;save for printout EX DE,HL LD (OFNTP),HL LD HL,(FSIZE) ;jump if fsize=0 LD A,H OR L JR Z,MFTDA-$ MFTC: LD HL,(MBUFP) ;set dma address to mbufp EX DE,HL CALL SETDMA CALL WRITE ;write next sector OR A ;jump if ok JR Z,MFTD-$ LD HL,MSGC ;"error writing file" CALL WASC JP MFTG MFTD: LD HL,(MBUFP) ;mbufp = mbufp + 128 LD DE,128 ADD HL,DE LD (MBUFP),HL LD HL,(FSIZE) ;fsize = fsize - 1 DEC HL LD (FSIZE),HL LD A,H ;loop until zero OR L JR NZ,MFTC-$ MFTDA: LD HL,TFCB ;copy tfcb into ofcb LD DE,OFCB LD BC,33 LDIR ;move the stuff LD DE,DBUF ;reset dma pointer CALL SETDMA CALL CLOSE ;try to close file CP 255 ;jump if ok JR NZ,MFTE-$ LD HL,MSGD ;write 'unable to close' CALL WASC MFTE: LD HL,(XSIZE) ;number of sectors done CALL WDWC LD HL,MSGE ;write ' sectors written' CALL WASC XOR A LD (NERAS),A ;clear last file not ;writen flag JP MFTA MFTF: LD A,(IBFLG) ;loop if ibflg set OR A JP NZ,MFT1 ;* Terminate program here on irrecoverable 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: LD HL,MSGF ;SEE IF OPTION IS ALLOWED LD A,(NDFLG) OR A JR NZ,MFTH-$ ;JUMP IF NOT ALLOWED CALL WASC ;ELSE TELL ABOUT OPTION MFTH: LD HL,MSGG ;ASK FOR SYSTEM DISK CALL WASC CALL RACC ;wait for response CP 03H ;WARM BOOT IF ^C JP Z,00000H CP CR ;ATTEMPT REPEAT IF JR NZ,MFTG-$ ;LOOP TILL GOOD RESPONSE MFTJ: CALL WEOLC ;ACKNOWLEDGE COMMAND LD A,(NDFLG) ;REPEAT ALLOWED? OR A JR NZ,MFTK-$ ;JUMP IF NOT LD HL,FNT ;ELSE RESET FNT POINTER LD (OFNTP),HL LD HL,MBUF ;RESET MEM BUF POINTER LD (MBUFP),HL XOR A ;RESET OUTPUT INTERRUPTED ; FLAG LD (OBFLG),A JP MFT9 ;AND DO AGAIN MFTK: LD HL,MSGH ;CANNOT REPEAT, TELL HIM CALL WASC JR MFTG-$ ;AND WAIT FOR SYSTEM DISK MFTL: LD HL,MSGJ ;ABORT MESSAGE CALL WASC JP 00000H ;WARM BOOT ;* subroutines * ;MOVE deleted from here ;* gfn - get file name * GFN: LD A,(HL) OR A RET Z CP ' ' JR NZ,GFN0-$ INC HL JR GFN-$ GFN0: LD DE,XFCB XOR A LD (DE),A INC DE PUSH DE LD B,11 LD A,' ' GFN6: LD (DE),A INC DE DEC B JR NZ,GFN6-$ POP DE LD B,9 GFN1: LD A,(HL) OR A JP Z,GFN4 INC HL CP ' ' JP Z,GFN4 CP '.' JR Z,GFN2-$ CP '*' JR Z,GFN7-$ LD (DE),A INC DE DEC B JP Z,GFN5 JR GFN1-$ GFN7: DEC B JR Z,GFN9-$ LD A,'?' LD (DE),A INC DE JR GFN7-$ GFN9: LD A,(HL) CP '.' JR NZ,GFN4-$ INC HL GFN2: LD DE,XFCB+FT LD B,4 GFN3: LD A,(HL) OR A JR Z,GFN4-$ INC HL CP ' ' JR Z,GFN4-$ CP '*' JR Z,GFN8-$ LD (DE),A INC DE DEC B JR Z,GFN5-$ JR GFN3-$ GFN8: DEC B JR Z,GFN4-$ LD A,'?' LD (DE),A INC DE JR GFN8-$ GFN4: XOR A RET GFN5: SCF RET ;* cfnt - create file name table * CFNT: LD HL,FNT ;reset ifntp LD (IFNTP),HL LD (HL),0FFH ;VER 4.2 BUG FIX CFNT1: LD HL,(CBUFP) ;get cbufp LD A,(HL) ;exit if end of list OR A RET Z CALL GFN ;get next afn LD (CBUFP),HL ;save command buffer ptr JR NC,CFNT2-$ ;jump if filename ok LD HL,MSG5 ;"Syntax error in name" CALL WASC JR CFNT1-$ ;loop CFNT2: XOR A ;clear xfcb extent field LD (XFCB+EX),A LD DE,XFCB ;search for first occur. CALL SRCHF CP 255 ;jump if found JR NZ,CFNT3-$ LD HL,XFCB+FN ;write filename CALL WFNC LD HL,MSG7 ;write ' not found' CALL WASC JR CFNT1-$ ;loop CFNT3: AND 3 ;index into cbuf LD L,A LD H,0 ADD HL,HL ADD HL,HL ADD HL,HL ADD HL,HL ADD HL,HL LD DE,DBUF ADD HL,DE EX DE,HL ;copy filename into fnt LD HL,(IFNTP) EX DE,HL LD B,12 CFNT4: LD A,(HL) AND 07FH ;set bit 7 to 0 !!! LD (DE),A INC HL INC DE DJNZ CFNT4-$ LD HL,ZEROS ;zero fill rest of entry LD BC,4 LDIR ;move the stuff EX DE,HL LD (IFNTP),HL ;save input fnt pointer LD (HL),0FFH ;insure FF byte at end LD DE,XFCB ;search for next occur. CALL SRCHN CP 255 ;jump if found JR NZ,CFNT3-$ JP CFNT1 ;go get next afn ;* wasc - write ascii string to console * WASC: LD A,(HL) OR A RET Z CALL WACC INC HL JR WASC-$ ;* wfnc - write file name to console * ;* Note: Under SOLOS and CUTER, 01 is the cursor- * ;* left character. * ;* When MFTing a multi-extent file, the extent * ;* character must be filtered out of the file- * ;* name-block to avoid wierd console output. * WFNC: PUSH BC LD B,8 WFNC1: LD A,(HL) AND 07FH CALL WACC INC HL DJNZ WFNC1-$ LD A,'.' CALL WACC LD B,3 WFNC2: LD A,(HL) AND 07FH CALL WACC INC HL DJNZ WFNC2-$ POP BC RET ;* weolc - write end of line to console * WEOLC: PUSH AF LD A,CR CALL WACC LD A,LF CALL WACC POP AF RET ;* wdwc - write decimal word to console * WDWC: PUSH HL PUSH DE PUSH BC LD B,0 ;clear 'digit written' ; flag LD DE,10000 ;write 1st digit CALL WNDD LD DE,1000 ;write 2nd digit CALL WNDD LD DE,100 ;write 3rd digit CALL WNDD LD DE,10 ;write 4th digit CALL WNDD LD DE,1 ;write 5th digit LD B,1 ;force last digit to ;print CALL WNDD POP BC POP DE POP HL RET WNDD: LD C,0 ;c=0 WNDD1: LD A,L ;hl = hl - de SUB E LD L,A LD A,H SBC A,D LD H,A JR C,WNDD2-$ ;jump if < 0 INC C ;c = c + 1 JR WNDD1-$ ;loop WNDD2: ADD HL,DE ;hl = hl + de LD A,C ;jump if c non-zero OR C JR NZ,WNDD4-$ LD A,B ;jump if digit written OR B JR NZ,WNDD4-$ LD A,' ' ;write one space JR WACC-$ WNDD4: LD B,1 ;set 'digit written' flag LD A,C ;encode c into decimal ; ascii ADD A,'0' JR WACC-$ ;go write it ;* wacc - write ascii character to console * WACC: PUSH HL PUSH DE PUSH BC PUSH AF LD C,WCFC LD E,A CALL ENTRY POP AF POP BC POP DE POP HL RET ;* racc - read ascii character from console * RACC: PUSH HL PUSH DE PUSH BC LD C,RCFC CALL ENTRY POP BC POP DE POP HL RET ;* reset - reset disk system * RESET: PUSH HL PUSH DE PUSH BC LD C,RDFC CALL ENTRY POP BC POP DE POP HL RET ;* open - open disk file * OPEN: PUSH HL PUSH DE PUSH BC LD DE,TFCB LD C,OFFC CALL ENTRY POP BC POP DE POP HL RET ;* read - read record from disk file * READ: PUSH HL PUSH DE PUSH BC LD DE,TFCB LD C,RRFC CALL ENTRY POP BC POP DE POP HL RET ;* close - close disk file * CLOSE: PUSH HL PUSH DE PUSH BC LD DE,TFCB LD C,CFFC CALL ENTRY POP BC POP DE POP HL RET ;* delt - delete disk file * DELT: PUSH HL PUSH DE PUSH BC LD DE,TFCB LD C,DFFC CALL ENTRY POP BC POP DE POP HL RET ;* make - make new disk file * MAKE: PUSH HL PUSH DE PUSH BC LD DE,TFCB LD C,MFFC CALL ENTRY POP BC POP DE POP HL RET ;* write - write record to file * WRITE: PUSH HL PUSH DE PUSH BC ;* REVISION 4.3 MODS * LD A,(TFCB+NR) ;LAST RECORD IN EXTENT? CP 7FH JR NZ,WRITE1-$ ;NO, CONTINUE LD HL,(MBUFP) ;EXISTING DATA AREA LD DE,DBUF ;POINT TO SAFE AREA CALL SETDMA ;FROM HERE LD BC,80H ;LENGTH TO MOVE LDIR ;MOVE DATA AWAY SO... ;* CP/M DOESN'T OVERWRITE THE REAL DATA IN OPENING * ;* NEXT EXTENT * ;* END REVISION 4.3 MODS * WRITE1: LD DE,TFCB LD C,WRFC CALL ENTRY POP BC POP DE POP HL RET ;* setdma - set dma address * SETDMA: PUSH HL PUSH DE PUSH BC LD C,SAFC CALL ENTRY POP BC POP DE POP HL RET ;* srchf - search for first occurance of afn * SRCHF: PUSH HL PUSH DE PUSH BC LD C,SFFC CALL ENTRY POP BC POP DE POP HL RET ;* srchn - search for next occurance of afn * SRCHN: PUSH HL PUSH DE PUSH BC LD C,SNFC CALL ENTRY POP BC POP DE POP HL RET ;* mesages here * MSG1: DB CR,LF DB 'MFT V' DB VERSION+'0' ;VERSION # DB '.' DB MODLEV+'0' ;MODIFICATION LEVEL DB CR,LF DB 'Multi-File-Transfer for single ' DB 'disk,' DB CR,LF DB 'With multiple-copy option.' DB CR,LF,LF DB 0 MSG2: DB 'Buffer size = ' DB 0 MSG3: DB ' sectors.' DB CR,LF,LF DB 0 MSG4: DB 'Mount INPUT disk, type RETURN (or ^C ' DB 'to reboot)...' DB 0 MSG5: DB '-- Syntax error in filename --' DB CR,LF DB 0 MSG6: DB ' - ' DB 0 MSG7: DB ' not found !' DB CR,LF DB 0 MSG8: DB 'read error - ' DB 0 MSG9: DB ' sectors read.' DB CR,LF DB 0 MSGA: DB 'Mount OUTPUT disk, type RETURN (or ' DB '^C to reboot)...' DB 0 MSGB: DB '-- unable to create --' DB CR,LF DB 0 MSGC: DB '-- error writing file --' DB CR,LF DB 0 MSGD: DB '-- unable to close --' DB CR,LF DB 0 MSGE: DB ' sectors written.' DB CR,LF DB 0 MSGF: DB CR,LF DB 'Completed. ' DB 'Type RETURN for another copy, OR...' DB 0 MSGG: DB CR,LF DB 'Type ^C to reboot.' DB CR,LF DB 0 MSGH: DB CR,LF DB '++ Memory buffer exceeded, cannot ' DB CR,LF DB 'make duplicate copies this time ; ' DB CR,LF DB 'last ouput file is defective ++' DB CR,LF,LF DB 0 MSGJ: DB CR,LF DB '++ PROGRAM ABORTED ++' DB CR,LF DB 0 MSGK: DB CR,LF DB '-- No file name specified --' DB CR,LF DB 0 MSGL: DB 'exists. Erase it (Y/N) ? ' DB 0 FILERO: DB 'is a R/O file. Confirm erasure ' DB '(Y/N) ? ' DB 0 BADVER: DB 'Sorry, you need CP/M version 2.0 or ' DB 'higher.' DB CR,LF DB 0 REOPER: DB '-- Reopen error , insert correct ' DB 'output disk next time --' DB CR,LF DB 0 ZEROS: DB 0,0,0,0 ORG ($+15)/16*16 FNT: DEFS 16*128+1 ;changed fnt entries from ;64 to 128 !! STACK: DEFS 64 SPACE: DEFS 2 ;available space MSIZE: DEFS 2 ;memory size CBUF: DEFS 80 ;command buffer CBUFP: DEFS 2 ;command buffer pointer FSIZE: DEFS 2 ;file size in sectors XSIZE: DEFS 2 ;file size for printout IFNTP: DEFS 2 ;input fnt pointer OFNTP: DEFS 2 ;output fnt pointer MBUFP: DEFS 2 ;memory buffer pointer IFCB: DEFS 33 ;input fcb OFCB: DEFS 33 ;output fcb XFCB: DEFS 33 ;temporary fcb IBFLG: DEFS 1 ;input break flag OBFLG: DEFS 1 ;output break flag NDFLG: DEFS 1 ;NO DUPLICATE ALLOWED ; FLAG SAVE: DEFS 1 ;temp. store of directory ;pointer in erase routine NERAS: DEFS 1 ;last output file not ;written to disk flag ! MBUF: EQU $ END MFT ;****************************************************** ;* * ;* Explanation as to structure of entries in the FNT * ;* ------------------------------------------------- * ;* * ;* ------------------------------------- * ;* |00|01|02|..|..|..|10|11|12|13|14|15| * ;* ------------------------------------- * ;* * ;* 00 = read done flag ; set to 1 if this name has * ;* already been read in. * ;* * ;* 01-08 = filename. * ;* * ;* 09-11 = filetype. * ;* * ;* 12-13 = start address of data for this file. * ;* * ;* 14-15 = length of file in 128 byte sectors. * ;* * ;* Note : 00-15 are offset from start of FNT entry. * ;* * ;******************************************************