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
/
ZSYS
/
SIMTEL20
/
ZCPR3
/
MCOPY.MQC
/
MCOPY.MAC
Wrap
Text File
|
2000-06-30
|
22KB
|
1,072 lines
; 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 ; <CR>
LF EQU 0AH ; <LF>
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 <SP> OR EOL
INX H ; PT TO NEXT
CPI ' '+1 ; <SP> 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 <SP> 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