mirror of https://github.com/wwarthen/RomWBW.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1072 lines
22 KiB
1072 lines
22 KiB
; 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
|
|
|