; PROGRAM: MCOPY ; AUTHOR: RICHARD CONN ; VERSION: 4.0 ; DATE: 18 MAY 84 ; PREVIOUS VERSIONS: 3.0 (16 JAN 83) ; PREVIOUS VERSIONS: NUMEROUS VERS equ 42 ; Use 16k buffer 14 Dec 84 jww ; Fix some bugs Joe Wright 28 Aug 84 ; 1. Add check for directory full after f$make z3env SET 0F400H ; ; MCOPY is a program which repeatedly copies a file from drive ; A: onto drive B:. It prompts the user to mount a disk in drive B:, ; copies the file from drive A: to drive B:, verifies the copy (if not ; overridden), and then performs the function again. ; ; MCOPY performs its function in the following steps: ; 1. MCOPY determines the attributes ; of the destination file (if it exists) and clears them (file becomes ; R/W and DIR) ; 2. MCOPY deletes the destination file (if it exists) ; 3. MCOPY copies the source file to the destination ; 4. MCOPY determines the attributes ; of the source file and makes the attributes of the destination file ; identical to those of the source ; 5. MCOPY reads both the source and destination files and ; compares them byte-for-byte ; ; SPECIAL Constants PLIM EQU 4*16 ; SIZE OF BUFFER IN PAGES (4 * nK) [may be changed] ESIZE EQU 16 ; NUMBER OF BYTES/ENTRY ; CP/M Constants WB EQU 0 ; CP/M WARM BOOT BDOSE EQU WB+5 ; BDOS ENTRY POINT FCB EQU WB+5CH ; SPECIFIED FCB BUFF EQU WB+80H ; DEFAULT BUFFER AND INPUT LINE SDMA EQU 26 ; SET DMA ADDRESS ; ASCII Constants, et al ON EQU 0FFH ; ON CODE OFF EQU 0 ; OFF CODE CR EQU 0DH ; LF EQU 0AH ; CTRLC EQU 'C'-'@' ; ^C CTRLZ EQU 'Z'-'@' ; ^Z OPTC EQU '/' ; OPTION DELIMITER ; ; LOAD @DE MACRO ; LDED MACRO ?ADR XCHG LHLD ?ADR XCHG ENDM ; ; SYSLIB ROUTINES ; EXT Z3INIT,ZFNAME,GETQUIET EXT COMPHD,RETUD,LOGUD,PUTUD,GETUD EXT DIRQ,DIRPACK,DIRTDU EXT INITFCB,F$EXIST EXT CRCCLR,CRCUPD,CRCDONE EXT BDOS,CIN,COUT,CONDIN EXT F$DELETE,F$OPEN,F$MAKE,F$CLOSE,F$READ,F$WRITE EXT PADC,EPSTR,EPRINT EXT MOVEB,CAPS,CRLF EXT CODEND ; ; Environment Definition ; if z3env ne 0 ; ; External ZCPR3 Environment Descriptor ; jmp start db 'Z3ENV' ;This is a ZCPR3 Utility db 1 ;External Environment Descriptor z3eadr: dw z3env start: lhld z3eadr ;pt to ZCPR3 environment ; else ; ; Internal ZCPR3 Environment Descriptor ; MACLIB Z3BASE.LIB MACLIB SYSENV.LIB z3eadr: jmp start SYSENV start: lxi h,z3eadr ;pt to ZCPR3 environment endif ; ; Start of Program -- Initialize ZCPR3 Environment ; call z3init ;initialize the ZCPR3 Env and the VLIB Env jmp startx ; ; USER-DEFINABLE INITIAL FLAG CONDITIONS ; THE DEFAULT CONDITIONS FOR MCOPY MAY BE READILY PATCHED BY THE USER ; VIA DDT FOR HIS DESIRED DEFAULT VALUES ; DVERFLG: DB ON ; SET VERIFY DINSP: DB OFF ; SET NO INSPECT DNCOPY: DB OFF ; SET NO MULTIPLE COPIES BY DEFAULT DDDISK: DB 'B'-'A' ; DEFAULT DESTINATION DISK IS B DDUSER: DB 0 ; DEFAULT DESTINATION USER IS 0 BACKDIR: DB 'BACKUP ' ; NAME OF BACKUP DIRECTORY ; ; BEGINNING OF MCOPY PROGRAM ; STARTX: ; ; PRINT BANNER ; CALL EPRINT DB 'MCOPY Version ' DB VERS/10+'0','.',(VERS MOD 10)+'0',0 ; ; SET UP DYNAMIC BUFFERS ; LXI H,0 ; GET SP DAD SP SHLD STACK ; SAVE IT CALL CODEND ; DETERMINE FREE SPACE SHLD INLINE ; PTR TO INPUT LINE INR H SHLD FCBT ; PTR TO FCB TEMP INR H SHLD FCBS ; PTR TO SOURCE FCB INR H SHLD FCBD ; PTR TO DEST FCB INR H SHLD FREEBUF ; FREE SPACE BUFFER ; ; SET DEFAULT FLAGS ; CALL GETQUIET ; GET QUIET FLAG STA QUIET LDA DVERFLG ; VERIFY STA VERFLG LDA DINSP ; INSPECT STA INSP LDA DNCOPY ; MULTIPLE COPIES STA NCOPY ; ; CHECK FOR BACKUP DIRECTORY AND ESTABLISH IT AS DEFAULT ; IF NO BACKUP DIRECTORY, SELECT DEFAULT STORED ; LXI H,BACKDIR ; PT TO DIRECTORY NAME CALL DIRTDU JZ DEFBACK ; NAME NOT FOUND, SO SELECT DEFAULT MOV A,B ; SET DEST DISK STA DDISK MOV A,C ; SET DEST USER STA DUSER JMP BACKSET DEFBACK: LDA DDDISK ; GET DEFAULT DEST DISK STA DDISK ; SET DEST DISK LDA DDUSER ; GET DEFAULT DEST USER STA DUSER ; SET DEST USER ; ; OBTAIN AND SAVE CURRENT USER AND DISK ; BACKSET: CALL PUTUD ; SAVE POSITION CALL RETUD ; GET USER/DISK MOV A,B ; SAVE DISK STA CDISK LHLD INLINE ; INPUT LINE SAVE BUFFER XCHG ; ... IN DE LXI H,BUFF+1 ; PT TO COMMAND LINE CHAR COUNT MVI B,128 ; SAVE 128 BYTES (ARBITRARY) CALL MOVEB XCHG ; HL PTS TO INPUT LINE ; ; SET OTHER FLAGS ; XRA A ; A=0 STA EXIST ; TURN OFF EXIST TEST ; ; CHECK FOR EMPTY COMMAND LINE AND PROCESS COMMAND MODE IF SO ; ON ENTRY, HL PTS TO FIRST CHAR OF STRING FROM CLINE ; START1: MOV A,M ; GET CHAR ORA A ; EOL? JZ MHELP ; PRINT HELP MESSAGE IF NO INPUT INX H ; PT TO NEXT CPI ' ' ; JUST SPACES? JZ START1 ; ; COMMAND LINE WAS NOT EMPTY -- CHECK FOR HELP REQUEST ; DCX H ; PT TO FIRST CHAR CPI '/' ; IF OPENING OPTION, MUST BE HELP JZ MHELP ; ; SEE IF OPTIONS ARE AVAILABLE IN THE COMMAND LINE ; SHLD MFPTR ; SET PTR TO FIRST CHAR OF FILE NAME SPECS ; ; SKIP TO END OF FILE NAME SPECS ; START2: MOV A,M ; SKIP TO OR EOL INX H ; PT TO NEXT CPI ' '+1 ; OR LESS? JNC START2 ORA A ; AT EOL? JZ MCOPY0 ; PERFORM DEFAULT MCOPY FUNCTION IF AT EOL ; ; SCAN FOR OPTION ; OPTION: MOV A,M ; GET OPTION CHAR ORA A ; EOL? JZ MCOPY0 ; DO MCOPY INX H ; PT TO NEXT PUSH H ; SAVE PTR LXI H,OPTTAB ; PT TO OPTION TABLE CALL CMDER ; PROCESS COMMAND POP H ; GET PTR JMP OPTION ; ; COMMAND PROCESSOR -- COMMAND LETTER IN A, HL PTS TO TABLE ; CMDER: PUSH B ; SAVE BC MOV B,A ; COMMAND IN B CMDER1: MOV A,M ; GET COMMAND LETTER ORA A ; DONE? JZ CMDER2 CMP B ; MATCH? JNZ CMDER3 CMDER2: INX H ; PT TO ADDRESS MOV E,M ; GET IT IN DE INX H MOV D,M XCHG ; HL PTS TO COMMAND ADDRESS POP B ; RESTORE BC PCHL ; RUN COMMAND CMDER3: INX H ; SKIP TO NEXT ENTRY IN TABLE INX H INX H JMP CMDER1 ; OPTION COMMAND TABLE OPTTAB: DB ' ' ; DONE DW OPTS DB OPTC ; SKIP OPTC DW OPTS DB 'E' ; EXIST TEST DW OPTE DB 'I' ; INSPECT DW OPTI DB 'M' ; MULTIPLE COPY DW OPTM DB 'Q' ; QUIET DW OPTQ DB 'V' ; VERIFY DW OPTV DB 0 ; END OF TABLE DW OHELP ; INVALID OPTION CHAR -- CLEAR STACK (RET ADR AND HL) AND PRINT HELP OHELP: POP H ; CLEAR RET ADR POP H ; CLEAR HL ; PRINT HELP MESSAGE MHELP: CALL EPRINT DB CR,LF,'Syntax:' DB cr,lf,' MCOPY dir:=dir:filename.typ,... o...' db cr,lf,'Options:' DB cr,lf,' E -- Existence Test' DB cr,lf,' I -- Inspect Files' DB cr,lf,' M -- Multiple Copy' DB cr,lf,' Q -- Toggle Quiet' DB cr,lf,' V -- No Verify' DB 0 RET ; RETURN TO ZCPR3 ; VERIFY FLAG TOGGLE OPTION OPTV: LDA VERFLG ; GET FLAG CMA ; FLIP IT STA VERFLG ; PUT FLAG ; SKIP OPTION OPTS: RET ; EXIST TEST TOGGLE OPTION OPTE: LDA EXIST ; GET FLAG CMA ; FLIP IT STA EXIST ; PUT FLAG RET ; NCOPY FLAG TOGGLE OPTION OPTM: LDA NCOPY ; GET FLAG CMA ; FLIP IT STA NCOPY ; PUT FLAG RET ; INSPECT FLAG TOGGLE OPTION OPTI: LDA INSP ; GET FLAG CMA ; FLIP IT STA INSP ; PUT FLAG RET ; QUIET FLAG TOGGLE OPTION OPTQ: LDA QUIET ; GET FLAG CMA ; FLIP IT STA QUIET ; PUT FLAG RET ; ; **** MCOPY of COMMAND LINE **** ; MCOPY0: LHLD FREEBUF ; STACK RESET SPHL LDA NCOPY ; MULTIPLE COPIES? ORA A ; 0=NO JZ NOPAUSE CALL SAKCHK ; STRIKE ANY KEY CHECK JZ CPM ; WARM BOOT IF ABORT NOPAUSE: CALL COPY ; DO THE COPY CPM: LHLD STACK ; RESET STACK SPHL RET ; RETURN TO OPSYS CPMA: CALL EPRINT DB CR,LF,'Abort',0 JMP CPM ; ; **** Begin Multiple Copy Procedure **** ; COPY: LHLD MFPTR ; PT TO FIRST FILE NAME SHLD NXTPTR ; SET PTR TO NEXT FILE NAME XRA A ; A=0 STA VERCNT ; ZERO ERROR COUNT LDA EXIST ; IF EXIST, THEN MUST NOT BE QUIET ORA A ; 0=NO EXIST JZ MCOPY XRA A ; SET NO QUIET STA QUIET ; ; **** MAIN COPY LOOP **** ; MCOPY: LHLD NXTPTR ; GET PTR TO NEXT FILE NAME MOV A,M ; GET FIRST CHAR CPI ' '+1 ; DONE IF OR LESS JNC MCOPY1 ; CONTINUE WITH PROCEDURE ; ; MCOPY OF FILE SPECS IS NOW DONE ; DONE WITH COPY PROCEDURE -- CONTINUE? ; COPYT: LDA VERFLG ; VERIFY? ORA A ; 0=NO JZ COPYT1 CALL CRLF ; NEW LINE LDA VERCNT ; GET ERROR COUNT CALL PADC ; PRINT AS DECIMAL CALL EPRINT DB ' Errors',0 COPYT1: LDA NCOPY ; MULTIPLE COPIES? ORA A ; 0=NO RZ CALL SAKCHK ; CHECK FOR STRIKE OF ANY KEY RZ ; RETURN IF ABORT JMP COPY ; COPY AGAIN FROM THE BEGINNING ; ; BEGIN COPY OF FILE GROUP ; MCOPY1: CPI ',' ; SKIP COMMA SEPARATOR IF THERE JNZ MCPY0 INX H ; PT TO CHAR AFTER COMMA MCPY0: MOV A,M ; GET NEXT CHAR CPI ' '+1 ; CHECK FOR ERROR JC FORMERR CALL GETUD ; RETURN HOME LDED FCBS ; PT TO SOURCE FCB MVI A,0 ; DIR BEFORE DU CALL ZFNAME ; EXTRACT FILE NAME DATA CALL DUCVRT ; CONVERT DU INTO BC MOV A,M ; GET DELIMITER CPI '=' ; IF '=', WE HAVE A NEW DISK/USER JNZ MCOPY2 ; FORM IS DIRS:FN.FT IF NO '=' ; ; FORM IS DIRD:=DIRS:FN.FT, SO SET DEST DISK/USER ; MOV A,B ; GET DISK STA DDISK ; SET NEW DEFAULT DISK MOV A,C ; GET USER STA DUSER ; SET NEW DEFAULT USER ; ; NOW DERIVE DIRS:FN.FT FORM AFTER THE '=' ; MCPY2: INX H ; PT TO CHAR BEYOND '=' MOV A,M ; GET CHAR CPI ' '+1 ; FORMAT ERROR? JC FORMERR LDED FCBS ; LOAD FCB MVI A,0 ; DIR BEFORE DU CALL ZFNAME ; GET SOURCE NAME CALL DUCVRT ; CONVERT TO DU IN BC ; ; SAVE PTR TO NEXT CHAR AFTER DIRS:FN.FT, AND SET SOURCE DISK/USER ; MCOPY2: SHLD NXTPTR ; SAVE PTR TO NEXT CHAR MOV A,B ; GET DISK STA SDISK ; SET NEW DEFAULT DISK MOV A,C ; GET USER STA SUSER ; SET NEW DEFAULT USER MCPY22: LDA DDISK ; DEST DIR MUST NOT EQUAL SOURCE DIR MOV B,A LDA SDISK CMP B JNZ MCPYOK LDA DUSER MOV B,A LDA SUSER CMP B JNZ MCPYOK CALL EPRINT DB CR,LF,'Src=Dest Err',0 RET MCPYOK: CALL EPRINT DB CR,LF,'Copy ',0 LDA SDISK ; GET NUMBER ADI 'A' ; CONVERT TO LETTER CALL COUT ; PRINT LDA SUSER ; PRINT USER NUMBER CALL PADC MVI A,':' ; SEPARATOR CALL COUT MVI A,' ' CALL COUT LHLD FCBS ; PRINT FILE SPEC INX H ; PT TO FILE NAME CALL PRFN CALL EPRINT DB ' to ',0 LDA DDISK ; GET NUMBER ADI 'A' ; CONVERT TO LETTER CALL COUT ; PRINT LDA DUSER ; PRINT USER NUMBER CALL PADC MVI A,':' CALL COUT MVI C,13 ; RESET DISK SYSTEM CALL BDOS CALL LOGS ; LOG IN SOURCE USER/DISK LDED FCBS ; PT TO SOURCE FCB CALL INITFCB ; INIT FCB LHLD FREEBUF ; PT TO BUFFER AREA MVI A,0C0H ; SELECT NON-SYS AND SYS FILES CALL DIRQ ; LOAD DIR, SELECT FILES, SORT, ETC JZ TPAOVFL ; TPA OVERFLOW ERROR? LDA INSP ; INSPECT FILES? ORA A ; 0=NO CNZ INSPF ; INSPECT FILES IF OPTION SELECTED MOV A,B ; CHECK FOR ANY FILES TO COPY ORA C ; 0=NONE JNZ MCPY24 MCPY23: CALL EPRINT DB CR,LF,' NO Files -- ^C to Abort ',0 CALL CIN ; GET RESPONSE CPI 'C'-'@' ; ABORT? JZ COPYT ; END TEST JMP MCOPY ; CONTINUE WITH NEXT MCPY24: PUSH H ; SAVE PTR AND COUNT PUSH B LXI D,ESIZE ; SKIP TO END OF LOADED FILES AND MARK BEGINNING OF ; WORK AREA MCPY25: DAD D ; PT TO NEXT DCX B ; COUNT DOWN MOV A,B ; DONE? ORA C JNZ MCPY25 MVI A,PLIM ; SET PAGE LIMIT STA PAGLIM SHLD WORKBF ; SAVE PTR TO BEGINNING OF WORK BUFFER LDA BDOSE+2 ; GET BASE PAGE OF BDOS SUI 10 ; GET BELOW BASE PAGE OF CCP SUB H ; COMPUTE SIZE OF BUFFER AREA CPI PLIM ; PLIM PAGES LEFT? JNC PAGOK STA PAGLIM ; SET PAGE LIMIT PAGOK: POP B ; RESTORE PTRS POP H ; ; MAIN COPYING LOOP ; FILE NAMES ARE PTED TO BY HL AND BC=NUMBER OF FILES ; MCPY26: PUSH H ; SAVE REGS PUSH B CALL ABORTCK ; CHECK FOR ABORT MCPY27: CALL MCOPYX ; COPY SOURCE (HL) TO DESTINATION USING WORK BUFFER CALL PRDONE ; PRINT DONE MESSAGE CALL ABORTCK ; CHECK FOR ABORT LDA LSTCPY ; LAST FILE COPIED? ORA A ; 0=NO JZ MCPY28 LDA VERFLG ; VERIFY? ORA A ; 0=NO CNZ MCOPYV ; DO VERIFY MCPY28: POP B ; GET REGS POP H LXI D,ESIZE ; PT TO NEXT FILE DAD D ; HL PTS TO NEXT FILE DCX B ; COUNT DOWN MOV A,B ORA C JNZ MCPY26 JMP MCOPY ; COPY NEXT FILE SPEC ; ; CHECK FOR ABORT ; ABORTCK: CALL CONDIN ; CONDITIONAL INPUT RZ CPI CTRLC ; ABORT? JZ CPMA RET ; ; PRINT DONE MESSAGE ; PRDONE: LDA QUIET ; CHECK FOR QUIET ORA A ; NZ=QUIET RNZ CALL EPRINT DB ' Done',0 RET ; ; COPY SOURCE FILE PTED TO BY HL TO DESTINATION ; MCOPYX: XRA A ; SET NO COPY OF LAST FILE STA LSTCPY ; SET FLAG LDED FCBS ; SET SOURCE FCB MVI B,12 ; 12 BYTES CALL MOVEB CALL INITFCB ; INIT SOURCE FCB LDED FCBD ; SET DESTINATION FCB MVI B,12 ; 12 BYTES CALL MOVEB CALL DRW ; CLEAR ATTRIBUTES IN FCB CALL INITFCB ; INIT DESTINATION FCB CALL LOGD ; LOG IN DESTINATION CALL EPRINT DB CR,LF,' File ',0 LHLD FCBD ; PRINT FILE NAME INX H ; PT TO FILE NAME CALL PRFN LDED FCBD ; PT TO FCB CALL F$EXIST ; DOES DEST EXIST? JZ FNF ; FILE NOT FOUND IF ZERO LDA QUIET ; QUIET? ORA A ; 0=NO JNZ FFND CALL EPRINT DB ' Replace',0 FFND: CALL EATEST ; EXIST APPROVED TEST? RZ ; NOT APPROVED, SO ABORT CALL DESTRW ; MAKE DESTINATION R/W IF NOT ALREADY CALL F$DELETE ; DELETE FILE CALL INITFCB ; REINIT FCB JMP FNF1 ; CREATE NEW FILE AND CONTINUE FNF: LDA QUIET ; QUIET? ORA A ; 0=NO JNZ FNF1 CALL EATEST ; EXIST APPROVED? RZ ; NO? FNF1: CALL EPRINT DB ' ...',0 MVI A,0FFH ; SET COPY OF LAST FILE STA LSTCPY ; SET FLAG CALL F$MAKE ; CREATE NEW FILE inr a ; check for full directory jz dirful ; report it ; ; OPEN SOURCE FILE IN PREP FOR COPY ; CALL CRCCLR ; CLEAR CRC VALUE CALL LOGS ; LOG IN SOURCE DISK LDED FCBS ; INIT FCB CALL INITFCB CALL F$OPEN ; OPEN FILE ; ; THIS LOOP, WHICH STARTS AT MCPYX, COPIES THE FILE FROM SOURCE TO DEST ; MCPYX: CALL LOGS ; LOG IN SOURCE LDED FCBS ; PT TO SOURCE FCB LHLD WORKBF ; PT TO BUFFER TO COPY INTO CALL LOAD ; LOAD FILE INTO WORKBF LDA BCNT ; IF COUNT=0, THEN DONE ORA A JZ MC2DONE ; ; COPY TO DISK ; MCPYD: CALL LOGD ; LOG IN DESTINATION LHLD WORKBF ; PT TO BUFFER MCPYD1: CALL SETDMA ; SET DMA ADDRESS PTED TO BY HL LXI D,128 ; INCR HL BY 128 DAD D ; HL PTS TO NEXT BLOCK LDED FCBD ; WRITE TO DESTINATION FILE CALL F$WRITE ORA A ; OK? JNZ MCPYDERR ; COUNT DOWN TO NEXT BLOCK LDA BCNT ; GET BLOCK COUNT DCR A ; COUNT DOWN STA BCNT JNZ MCPYD1 LDA CONT ; CONTINUE? ORA A ; CONT IF NOT ZERO JNZ MCPYX ; ; END OF COPY LOOP ; MC2DONE: CALL LOGS ; LOG IN SOURCE LDED FCBS ; CLOSE SOURCE CALL F$CLOSE CALL LOGD ; LOG IN DESTINATION LDED FCBD ; CLOSE DESTINATION CALL F$CLOSE CALL CRCDONE ; GET CRCK VALUE SHLD CRCVAL ; SAVE CRC VALUE ; ; SET ATTRIBUTES OF DESTINATION TO BE THE SAME AS THOSE OF SOURCE ; CALL LOGS ; LOG IN SOURCE DRIVE LDED FCBS ; FIND SOURCE MVI C,17 ; SEARCH FOR FIRST CALL BDOS RLC ; MULTIPLY BY 32 TO GET OFFSET RLC RLC RLC RLC ANI 0E0H ; MASK OUT LSB MOV L,A ; VALUE IN L MVI H,0 LXI D,BUFF ; ADD IN BUFFER BASE DAD D XCHG ; PT TO FCBT IN DE LHLD FCBT XCHG MVI B,16 ; MOVE 16 BYTES CALL MOVEB CALL LOGD ; LOG IN DESTINATION DRIVE CALL INITFCB ; INIT FCB PTED TO BY DE (FCBT) MVI C,30 ; SET FILE ATTRIBUTES CALL BDOS RET ; MCOPYX RETURN ; ; CONVERT Z3 FCB DU INTO DU IN BC ; DUCVRT: PUSH H ; SAVE REGS PUSH D LDAX D ; GET DISK ORA A ; CURRENT? JNZ DUCV1 LDA CDISK ; GET CURRENT INR A ; ADD 1 FOR A=1 DUCV1: DCR A ; A=0 MOV B,A LXI H,13 ; OFFSET TO USER DAD D MOV C,M ; GET USER POP D ; RESTORE REGS POP H RET ; FORMAT ERROR FORMERR: CALL EPRINT DB CR,LF,' Error: ',0 CALL EPSTR ; PRINT ERROR RET ; TPA OVERFLOW TPAOVFL: CALL EPRINT DB CR,LF,'TPA Ovfl',0 JMP CPM ; WRITE ERROR MCPYDERR: CALL EPRINT DB CR,LF,'Disk Full',0 JMP CPM ; Directory Full Error dirful: call eprint db cr,lf,'Directory Full',0 jmp cpm ; TEST FOR EXISTENCE REQUIREMENT AND GET USER RESPONSE EATEST: LDA EXIST ; EXISTENCE TEST ON? ORA A ; 0=NO JZ EAT1 CALL EPRINT DB ' -- (Y/N)? ',0 CALL CIN ; GET RESPONSE CALL CAPS CPI CR ; YES? JZ EAT1 ; COPY IF SO CALL COUT CPI 'N' ; NO? JNZ EAT1 ; COPY IF NOT NO XRA A ; ZERO FOR NOT APPROVED RET EAT1: MVI A,0FFH ; SET NZ FOR APPROVED ORA A ; SET FLAGS RET ; ; MAKE DESTINATION FCB ENTRY R/W AND DIR ; DRW: PUSH D LHLD FCBD ; CLEAR ATTRIBUTES OF DEST LXI D,9 DAD D POP D MOV A,M ; GET IT ANI 7FH ; CLEAR IT MOV M,A INX H ; SAME TO NEXT MOV A,M ; GET IT AND CLEAR IT ANI 7FH MOV M,A RET DESTRW: CALL DRW ; MAKE ATTRIBUTES R/W AND NON-SYS LDED FCBD ; SET ATTRIBUTES MVI C,30 CALL BDOS RET ; ; LOAD BUFFER PTED TO BY HL FROM FILE WHOSE FCB IS PTED TO BY DE ; ON OUTPUT, BCNT=NUMBER OF BLOCKS LOADED (UP TO 128) AND ; CONT=0 IF DONE OR 128 IF NOT DONE ; LOAD: XRA A ; A=0 STA BCNT ; SET BLOCK COUNT STA CONT ; TURN OFF CONTINUATION FLAG ; MAIN COPY LOOP MCPY: CALL SETDMA ; SET DMA TO BLOCK PTED TO BY HL CALL F$READ ; READ BLOCK ORA A ; END OF FILE? RNZ ; RETURN PUSH D ; SAVE PTR TO FCB XCHG ; SAVE PTR TO DESTINATION BUFFER IN DE LHLD BDOSE+1 ; GET TOP OF TPA XCHG ; ... IN DE, DEST IN HL MOV A,H ; IF SAME PAGE, WE ARE IN OVERFLOW CMP D ; D MUST BE > H JNC TPAOVFL ; OVERFLOW IF D<=H MVI B,128 ; UPDATE CRC FOR 128 BYTES MCPYCRC: MOV A,M ; GET BYTE CALL CRCUPD ; UPDATE CRC INX H ; PT TO NEXT DCR B ; COUNT DOWN JNZ MCPYCRC POP D ; GET PTR TO FCB LDA BCNT ; GET BLOCK COUNT INR A ; INCREMENT IT STA BCNT ; SET IT MOV B,A ; BLOCK COUNT IN B LDA PAGLIM ; GET PAGE LIMIT ADD A ; DOUBLE IT FOR BLOCKS CMP B ; BUFFER FULL? JNZ MCPY STA CONT ; SET CONTINUATION FLAG RET ; ; SET DMA ADDRESS TO THAT PTED TO BY HL ; SETDMA: PUSH H ; SAVE REGS PUSH D PUSH B XCHG ; ADDRESS IN DE MVI C,SDMA CALL BDOSE POP B ; RESTORE REGS POP D POP H RET ; ; VERIFY PHASE ; MCOPYV: LDA QUIET ; CHECK FOR QUIET ORA A ; NZ=QUIET JNZ MCPYV CALL EPRINT DB ' Verify ...',0 MCPYV: CALL CRCCLR ; CLEAR CRCK VALUE CALL LOGD ; LOG IN DESTINATION LDED FCBD ; CLEAR DESTINATION FCB CALL INITFCB ; INIT FCB CALL F$OPEN ; OPEN FILE ; **** MAIN VERIFY LOOP **** VERLOOP: LHLD WORKBF ; LOAD INPUT BUFFER FROM DESTINATION LDED FCBD CALL LOAD ; LOAD AND COMPUTE CRC VALUE LDA BCNT ; DONE IF NO BYTES LOADED ORA A JZ VERCRC LDA CONT ; CONTINUE? ORA A ; 0=NO JNZ VERLOOP ; VERIFY DONE VERCRC: LHLD CRCVAL ; GET OLD CRC VALUE XCHG ; ... IN DE CALL CRCDONE ; UPDATE COMPLETE CALL COMPHD ; COMPARE HL TO DE JZ PRDONE ; PRINT DONE MESSAGE OR FALL THRU TO ERROR MSG ; VERIFY ERROR VERERR: LXI H,VERCNT ; INCREMENT ERROR COUNT INR M CALL EPRINT DB ' Error',0 RET ; ; **** MCOPY Utilities **** ; ; ; CHECK TO SEE IF USER WANTS TO CONTINUE ; SAKCHK: CALL EPRINT DB ' ^C to Quit - ',0 CALL CIN ; GET RESPONSE CALL CRLF ; NEW LINE CALL CAPS ; CAPITALIZE CPI 'C'-'@' ; ^C? RET ; ; ALLOW USER TO INSPECT FILES FOR COPY ; FIRST FILE NAME PTED TO BY HL, BC = NUMBER OF FILES ; ON EXIT, BC = NUMBER OF SELECTED FILES ; INSPF: CALL EPRINT DB CR,LF,' Inspect -- ' db 'Yes, No (def), Skip Rest' db 0 PUSH H ; SAVE PTR TO FIRST FILE PUSH B ; SAVE FILE COUNT LXI D,ESIZE ; ENTRIES ARE ESIZE BYTES APART INSPF0: MOV A,M ; MARK FILE FOR NO COPY ANI 7FH ; CLEAR MSB FOR NO COPY MOV M,A DAD D ; PT TO NEXT DCX B ; COUNT DOWN MOV A,B ; DONE? ORA C JNZ INSPF0 POP B ; RESTORE AND SAVE AGAIN POP H PUSH H PUSH B INSPF1: PUSH H ; SAVE PTR TO FILE INX H ; PT TO FN CALL CRLF ; NEW LINE CALL PRFN ; PRINT IT POP H ; GET PTR TO FILE CALL EPRINT DB ' - (Y/N/S)? ',0 CALL CIN ; GET RESPONSE CALL CAPS ; CAPITALIZE CALL COUT ; ECHO CPI 'S' ; SKIP? JZ INSPFA CPI 'Y' ; Yes? JNZ INSPF2 MOV A,M ; GET USER NUMBER ORI 80H ; MARK FILE MOV M,A ; SET USER NUMBER INSPF2: LXI D,ESIZE ; PT TO NEXT FILE DAD D DCX B ; COUNT DOWN MOV A,B ; DONE? ORA C JNZ INSPF1 INSPFA: POP B ; GET COUNT POP H ; GET PTR TO FIRST FILE JMP DIRPACK ; REPACK DIRECTORY ; ; LOG IN SOURCE USER/DISK ; LOGS: LDA SUSER ; USER MOV C,A ; ... IN C LDA SDISK ; DISK MOV B,A ; ... IN B JMP LOGUD ; LOG IN USER/DISK ; ; LOG IN DESTINATION USER/DISK ; LOGD: LDA DUSER ; USER MOV C,A ; ... IN C LDA DDISK ; DISK MOV B,A ; ... IN B JMP LOGUD ; LOG IN USER/DISK ; ; PRINT FILE NAME ; PRFN: PUSH H ; SAVE REGS PUSH B MVI B,8 ; PRINT 8 CHARS CALL PRFN1 MVI A,'.' ; DOT CALL COUT MVI B,3 ; PRINT 3 CHARS CALL PRFN1 POP B ; GET REGS POP H RET PRFN1: MOV A,M ; GET CHAR INX H ; PT TO NEXT CALL COUT ; PRINT IT DCR B ; COUNT DOWN JNZ PRFN1 RET ; ; **** BUFFERS **** ; ; POINTERS MFPTR: DS 2 ; PTR TO FIRST CHAR OF NEXT FN SPEC NXTPTR: DS 2 ; PTR TO NEXT FN SPEC IN LINE WORKBF: DS 2 ; PTR TO BEGINNING OF WORK BUFFER ; FLAGS COPIED FROM DEFAULTS VERFLG: DS 1 ; VERIFY INSP: DS 1 ; INSPECT QUIET: DS 1 ; QUIET NCOPY: DS 1 ; MULTIPLE COPY ; DISKS AND USERS CDISK: DS 1 ; CURRENT DISK SDISK: DS 1 ; SOURCE DISK SUSER: DS 1 ; SOURCE USER DDISK: DS 1 ; DESTINATION DISK DUSER: DS 1 ; DESTINATION USER ; CRC VALUE CRCVAL: DS 2 ; CRC CHECK VALUE ; FCBS FCBS: DS 2 ; SOURCE FCB FCBD: DS 2 ; DESTINATION FCB FCBT: DS 2 ; PTR TO TEMPORARY FCB FOR ATTRIBUTE SETTINGS ; COUNTS AND FLAGS PAGLIM: DS 1 ; MAX NUMBER OF PAGES IN WORK BUFFER LSTCPY: DS 1 ; LAST FILE WAS COPIED FLAG EXIST: DS 1 ; TEST FOR EXISTENCE FLAG VERCNT: DS 1 ; ERROR COUNT BCNT: DS 1 ; BLOCK COUNT CONT: DS 1 ; CONTINUE FLAG (0=NO, 0FFH=YES) ; DYNAMIC BUFFERS INLINE: DS 2 ; INPUT LINE BUFFER FREEBUF: DS 2 ; FREE SPACE BUFFER STACK: DS 2 ; OPSYS STACK PTR END