home *** CD-ROM | disk | FTP | other *** search
Text File | 1984-04-29 | 34.6 KB | 1,723 lines |
- ; PROGRAM: MCOPY
- ; AUTHOR: RICHARD CONN
- ; VERSION: 3.0
- ; DATE: 16 JAN 83
- ; PREVIOUS VERSIONS: 2.8 (14 JAN 83), 2.7 (11 JAN 83)
- ; PREVIOUS VERSIONS: 2.6 (9 JAN 83), 2.5 (8 JAN 83), 2.4 (7 JAN 83)
- ; PREVIOUS VERSIONS: 2.3 (6 JAN 83), 2.2 (19 DEC 82)
- ; PREVIOUS VERSIONS: 2.1 (7 DEC 82), 2.0 (14 NOV 82), 1.7 (21 JULY 82)
- ; PREVIOUS VERSIONS: 1.6 (12 JULY 82), 1.5 (12 JULY 82)
- ; PREVIOUS VERSIONS: 1.4 (10 JULY 82), 1.3 (9 JULY 82)
- ; PREVIOUS VERSIONS: 1.0 (27 Oct 80), 1.1 (2 NOV 80), 1.2 (11 APR 81)
- VERS equ 30
-
- ;
- ; This program is Copyright (c) 1982, 1983 by Richard Conn
- ; All Rights Reserved
- ;
- ; ZCPR2 and its utilities, including this one, are released
- ; to the public domain. Anyone who wishes to USE them may do so with
- ; no strings attached. The author assumes no responsibility or
- ; liability for the use of ZCPR2 and its utilities.
- ;
- ; The author, Richard Conn, has sole rights to this program.
- ; ZCPR2 and its utilities may not be sold without the express,
- ; written permission of the author.
- ;
-
-
- ;
- ; 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. If CP/M 2.x or MP/M, 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. If CP/M 2.x or MP/M, 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
- ;
-
- ; CP/M Constants
- CPM EQU 0 ; CP/M WARM BOOT
- BDOSE EQU CPM+5 ; BDOS ENTRY POINT
- FCB EQU CPM+5CH ; SPECIFIED FCB
- BUFF EQU CPM+80H ; DEFAULT BUFFER AND INPUT LINE
-
- ; 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
- DIV EQU '!' ; COPY/VERIFY PHASE DELIMITER
- FLIMIT EQU 1024 ; 1024 FILES PERMITTED
-
- ;
- ; SYSLIB ROUTINES
- ;
- EXT CLINE,COMPHD,ZGPINS,RETUD,LOGUD,BLINE
- EXT ZFNAME,DPARAMS,DIRF,DIRFS,FSIZE,DFREE
- EXT DIRPACK,INITFCB,F$EXIST
- EXT EVAL,CRCCLR,CRCUPD,CRCDONE
- EXT BDOS,CIN,COUT
- EXT F$DELETE,F$OPEN,F$MAKE,F$CLOSE,F$READ,F$WRITE
- EXT PHLDC,PADC,PSTR,PRINT
- EXT MOVEB,CAPS,CRLF
- EXT CODEND
-
- ;
- ; Branch to Start of Program
- ;
- JMP START
-
- ;
- ;******************************************************************
- ;
- ; SINSFORM -- ZCPR2 Utility Standard General Purpose Initialization Format
- ;
- ; This data block precisely defines the data format for
- ; initial features of a ZCPR2 system which are required for proper
- ; initialization of the ZCPR2-Specific Routines in SYSLIB.
- ;
-
- ;
- ; EXTERNAL PATH DATA
- ;
- EPAVAIL:
- DB 0FFH ; IS EXTERNAL PATH AVAILABLE? (0=NO, 0FFH=YES)
- EPADR:
- DW 40H ; ADDRESS OF EXTERNAL PATH IF AVAILABLE
-
- ;
- ; INTERNAL PATH DATA
- ;
- INTPATH:
- DB 0,0 ; DISK, USER FOR FIRST PATH ELEMENT
- ; DISK = 1 FOR A, '$' FOR CURRENT
- ; USER = NUMBER, '$' FOR CURRENT
- DB 0,0
- DB 0,0
- DB 0,0
- DB 0,0
- DB 0,0
- DB 0,0
- DB 0,0 ; DISK, USER FOR 8TH PATH ELEMENT
- DB 0 ; END OF PATH
-
- ;
- ; MULTIPLE COMMAND LINE BUFFER DATA
- ;
- MCAVAIL:
- DB 0FFH ; IS MULTIPLE COMMAND LINE BUFFER AVAILABLE?
- MCADR:
- DW 0FF00H ; ADDRESS OF MULTIPLE COMMAND LINE BUFFER IF AVAILABLE
-
- ;
- ; DISK/USER LIMITS
- ;
- MDISK:
- DB 4 ; MAXIMUM NUMBER OF DISKS
- MUSER:
- DB 31 ; MAXIMUM USER NUMBER
-
- ;
- ; FLAGS TO PERMIT LOG IN FOR DIFFERENT USER AREA OR DISK
- ;
- DOK:
- DB 0FFH ; ALLOW DISK CHANGE? (0=NO, 0FFH=YES)
- UOK:
- DB 0FFH ; ALLOW USER CHANGE? (0=NO, 0FFH=YES)
-
- ;
- ; PRIVILEGED USER DATA
- ;
- PUSER:
- DB 10 ; BEGINNING OF PRIVILEGED USER AREAS
- PPASS:
- DB 'chdir',0 ; PASSWORD FOR MOVING INTO PRIV USER AREAS
- DS 41-($-PPASS) ; 40 CHARS MAX IN BUFFER + 1 for ending NULL
-
- ;
- ; CURRENT USER/DISK INDICATOR
- ;
- CINDIC:
- DB '$' ; USUAL VALUE (FOR PATH EXPRESSIONS)
-
- ;
- ; DMA ADDRESS FOR DISK TRANSFERS
- ;
- DMADR:
- DW 80H ; TBUFF AREA
-
- ;
- ; NAMED DIRECTORY INFORMATION
- ;
- NDRADR:
- DW 00000H ; ADDRESS OF MEMORY-RESIDENT NAMED DIRECTORY
- NDNAMES:
- DB 64 ; MAX NUMBER OF DIRECTORY NAMES
- DNFILE:
- DB 'NAMES ' ; NAME OF DISK NAME FILE
- DB 'DIR' ; TYPE OF DISK NAME FILE
-
- ;
- ; REQUIREMENTS FLAGS
- ;
- EPREQD:
- DB 0FFH ; EXTERNAL PATH?
- MCREQD:
- DB 0FFH ; MULTIPLE COMMAND LINE?
- MXREQD:
- DB 0FFH ; MAX USER/DISK?
- UDREQD:
- DB 0FFH ; ALLOW USER/DISK CHANGE?
- PUREQD:
- DB 0FFH ; PRIVILEGED USER?
- CDREQD:
- DB 0FFH ; CURRENT INDIC AND DMA?
- NDREQD:
- DB 0FFH ; NAMED DIRECTORIES?
- Z2CLASS:
- DB 2 ; CLASS 2
- DB 'ZCPR2'
- DS 10 ; RESERVED
-
- ;
- ; END OF SINSFORM -- STANDARD DEFAULT PARAMETER DATA
- ;
- ;******************************************************************
- ;
-
- ;
- ; 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 OPTION
- DINSP:
- DB OFF ; SET NO INSPECT
- DQUIET:
- DB OFF ; SET NO QUIET OPERATION
- DNCOPY:
- DB OFF ; SET NO MULTIPLE COPIES BY DEFAULT
- DDDISK:
- DB 'C'-'A' ; DEFAULT DESTINATION DISK IS C
- DDUSER:
- DB 0 ; DEFAULT DESTINATION USER IS 0
-
- ;
- ; BEGINNING OF MCOPY PROGRAM
- ;
- START:
- CALL ZGPINS ; INIT ZCPR2 BUFFERS
- ;
- ; PRINT BANNER
- ;
- CALL BANNER
- ;
- ; SET DEFAULT FLAGS
- ;
- LDA DVERFLG ; VERIFY
- STA VERFLG
- LDA DINSP ; INSPECT
- STA INSP
- LDA DQUIET ; QUIET
- STA QUIET
- LDA DNCOPY ; MULTIPLE COPIES
- STA NCOPY
- 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
- ;
- CALL RETUD ; GET USER/DISK
- MOV A,B ; SAVE DISK
- STA CDISK
- STA SDISK ; SET DEFAULT SOURCE DISK
- MOV A,C ; SAVE USER
- STA CUSER
- STA SUSER ; SAVE DEFAULT SOURCE USER
- LXI H,BUFF ; PT TO COMMAND LINE CHAR COUNT
- CALL CLINE ; SAVE COMMAND LINE AS STRING
- ;
- ; 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 MRUNNER ; INTERACTIVE COMMAND SESSION
- 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
- CALL CAPS ; CAPITALIZE COMMAND
- 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 PRINT
- DB 'MCOPY -- Multiple File Copy Program',CR,LF
- DB ' MCOPY copies files from the disk on Drive A: to several'
- DB CR,LF,'other disks, successively mounted on Drive '
- DB 'B:',CR,LF
- DB ' MCOPY command line is:',CR,LF,LF
- DB ' MCOPY [dir:=][dir:]filename.typ[,[dir:]fn.typ][,...]'
- DB ' [ooo]',CR,LF,LF
- DB 'where options are enclosed by "[]", "dir:" is a named dir of '
- DB 'the form:',CR,LF
- DB ' direct: (named dir) or du: (disk/user)',CR,LF
- DB '"filename.typ" is the ambiguous file spec of the files to '
- DB 'copy ',CR,LF
- DB 'and "o" is none or more of:',CR,LF
- DB ' E -- Test of Existence of File and Allow User to '
- db 'Approve',CR,LF
- DB ' I -- Allow User to Approve Each File (Inspect)',CR,LF
- DB ' M -- Enable Multiple Copy Feature',CR,LF
- DB ' Q -- Quiet Operation (No Activity Display)',CR,LF
- DB ' V -- Disable Automatic Verify',CR,LF
- DB ' ? -- Print this HELP information',CR,LF
- DB ' If "dir:=" is specified, MCOPY copies to the indicated '
- DB 'directory,',CR,LF
- DB 'else it copies to the default directory.',CR,LF
- DB ' The user may interact directly with MCOPY by using just'
- DB CR,LF,'"MCOPY" as his command.',CR,LF
- DB 0
- RET ; RETURN TO ZCPR2
-
- ; VERIFY FLAG TOGGLE OPTION
- OPTV:
- CALL VT ; TOGGLE VERFLG
- ; SKIP OPTION
- OPTS:
- RET
-
- ; EXIST TEST TOGGLE OPTION
- OPTE:
- CALL ET ; TOGGLE EXIST
- RET
-
- ; NCOPY FLAG TOGGLE OPTION
- OPTM:
- CALL MT ; TOGGLE NCOPY
- RET
-
- ; INSPECT FLAG TOGGLE OPTION
- OPTI:
- CALL IT ; TOGGLE INSPECT
- RET
-
- ; QUIET FLAG TOGGLE OPTION
- OPTQ:
- CALL QT ; TOGGLE QUIET
- RET
-
- ;
- ; **** INTERACTIVE MCOPY LOOP ****
- ;
- MRUNNER:
- LXI SP,STACK ; RESET STACK
- CALL PRINT
- DB CR,LF,'MCOPY Status: ',0
- LDA EXIST ; EXISTENCE TEST
- ORA A ; 0=NO
- MVI A,'E' ; PREP FOR CHAR
- CALL PMODE
- LDA INSP ; FILE INSPECTION
- ORA A ; 0=NO
- MVI A,'I' ; PREP FOR CHAR
- CALL PMODE
- LDA NCOPY ; MULTIPLE COPIES
- ORA A ; 0=NO
- MVI A,'M' ; PREP FOR CHAR
- CALL PMODE
- LDA QUIET ; QUIET MODE
- ORA A ; 0=NO
- MVI A,'Q' ; PREP FOR CHAR
- CALL PMODE
- LDA VERFLG ; VERIFY
- ORA A ; 0=NO
- MVI A,'V' ; PREP FOR CHAR
- CALL PMODE
- CALL PRINT
- DB ' -- MCOPY Command (? for Help)? ',0
- CALL CIN ; GET RESPONSE
- CALL COUT ; ECHO
- LXI H,CMDTBL ; PT TO MCOPY COMMAND TABLE
- CALL CMDER ; PROCESS COMMANDS
- JMP MRUNNER ; CONTINUE
- ;
- ; MCOPY COMMAND TABLE AND EXECUTED ROUTINES
- ;
- CMDTBL:
- DB 'C' ; COPY
- DW CMDC
- DB 'D' ; DIRECTORY
- DW CMDD
- DB 'E' ; EXISTENCE TEST
- DW CMDE
- DB 'F' ; FREE SPACE
- DW CMDF
- DB 'I' ; INSPECT
- DW CMDI
- DB 'L' ; LOG IN DISK
- DW CMDL
- DB 'M' ; MULTIPLE COPIES
- DW CMDM
- DB 'Q' ; QUIET
- DW CMDQ
- DB 'S' ; STATUS
- DW CMDS
- DB 'V' ; VERIFY
- DW CMDV
- DB 'X' ; EXIT
- DW CMDX
- DB 'C'-'@' ; ^C
- DW CMDX
- DB 0 ; END OF TABLE
- DW MCPYHLP ; HELP MESSAGE
-
- ; COPY COMMAND TO COPY A SET OF FILES
- CMDC:
- CALL PRINT
- DB 0DH,0AH,' File Spec (<CR>=Abort)? ',0
- LXI H,INBUF ; INPUT LINE BUFFER
- MVI A,0FFH ; CAPITALIZE INPUT
- CALL BLINE ; GET LINE FROM USER
- ORA A ; ABORT IF NONE
- RZ
- CMDC1:
- MOV A,M ; SKIP OVER SPACES
- INX H ; PT TO NEXT
- CPI ' '
- JZ CMDC1
- DCX H ; PT TO NON-SPACE CHAR
- ORA A ; EOL?
- RZ
- SHLD MFPTR ; PT TO FIRST CHAR OF FILE NAME SPEC
- CALL COPY ; COPY FILES
- RET
-
- ; DISPLAY DIRECTORY
- CMDD:
- CALL PRINT
- DB CR,LF,'** Directory Display **',0
- MVI C,13 ; RESET SYSTEM
- CALL BDOS
- LXI H,0 ; SET TOTAL FILE SIZES
- SHLD FTOTAL
- CALL PRINT
- DB CR,LF,' File Spec (<CR>=',0
- LDA DDISK ; PRINT DISK/USER
- ADI 'A'
- CALL COUT
- LDA DUSER
- CALL PADC
- CALL PRINT
- DB ':*.*)? ',0
- LXI H,INBUF ; INPUT LINE BUFFER
- MVI A,0FFH ; CAPITALIZE INPUT
- CALL BLINE ; GET LINE FROM USER
- ORA A ; WILD IF NONE
- JNZ CMDD1
- LXI D,WILD ; MAKE FILE SPEC WILD
- XCHG ; COPY INTO BUFFER
- MVI B,4 ; 4 BYTES
- CALL MOVEB
- XCHG ; PT TO FIRST CHAR WITH HL
- CMDD1:
- PUSH H ; SAVE PTR
- CALL CODEND ; GET SCRATCH AREA ADDRESS
- MOV B,H ; ... IN BC
- MOV C,L
- POP H
- LXI D,FCBS ; LOAD FCB
- CALL ZFNAME ; EXTRACT FILE NAME INFO
- JZ CMDUDER ; ERROR?
- MOV A,B ; GET DISK
- CPI 0FFH ; CURRENT DISK?
- JNZ CMDD2
- LDA DDISK ; GET DEST DISK
- INR A ; ADJUST
- CMDD2:
- DCR A ; ADJUST FOR SELECT
- STA DDISK ; SET DEST DISK
- MOV A,C ; GET USER
- CPI '?' ; '?' IS INVALID
- JZ CMDUDER
- CPI 0FFH ; CURRENT USER?
- JNZ CMDD3
- LDA DUSER ; GET DEST USER
- CMDD3:
- STA DUSER ; SET DEST USER
- CALL LOGD ; LOG IN DEST
- CALL CODEND ; HL PTS TO BUFFER
- LXI D,FCBS ; DE PTS TO FCB
- LDA DUSER ; GET USER
- ORI 0C0H ; SELECT BOTH NON-SYS AND SYS FILES
- CALL DIRFS ; LOAD WITH SIZING INFO
- JZ CMDTPA ; TPA OVERFLOW
- MOV A,B ; ANY FILES?
- ORA C ; 0=NONE
- JNZ CMDD4
- CALL PRINT
- DB CR,LF,'No Matching Files',0
- RET
- CMDD4:
- XRA A ; SET COUNT
- STA BCNT
- CALL CRLF ; NEW LINE
- CMDD5:
- INX H ; PT TO FILE NAME
- CALL PRFN ; PRINT FILE NAME
- DCX H ; PT TO USER
- CALL FSIZE ; COMPUTE FILE SIZE
- PUSH H ; SAVE HL
- LHLD FTOTAL ; GET ACCUMULATED TOTAL
- DAD D ; ADD IN NEW FILE
- SHLD FTOTAL ; NEW TOTAL
- POP H ; GET PTR
- XCHG ; FILE SIZE IN HL
- CALL PHLDC ; PRINT AS DECIMAL
- MVI A,'K'
- CALL COUT
- LXI H,16 ; PT TO NEXT ENTRY
- DAD D ; HL PTS TO NEXT ENTRY
- DCX B ; COUNT DOWN
- MOV A,B ; DONE?
- ORA C
- JZ CMDD6
- LDA BCNT ; NEW LINE COUNT
- INR A
- STA BCNT
- ANI 3 ; NEW LINE EVERY 4 ENTRIES
- JZ CMDD5A
- CALL PRINT ; PRINT FENCE SINCE NOT NEW LINE
- DB ' ',0
- JMP CMDD5
- CMDD5A:
- CALL CRLF ; NEW LINE
- JMP CMDD5
- CMDD6:
- CALL PRINT
- DB CR,LF,'** ',0
- LHLD FTOTAL ; PRINT TOTAL SPACE USED
- CALL PHLDC ; PRINT AS DECIMAL
- CALL PRINT
- DB 'K Occupied by Displayed Files, ',0
- CALL DFREE ; COMPUTE AMOUNT OF FREE SPACE LEFT ON DISK
- XCHG ; HL=FREE SPACE
- CALL PHLDC ; PRINT AS DEC
- CALL PRINT
- DB 'K Remaining on Disk ',0
- LDA DDISK ; PRINT DISK LETTER
- ADI 'A'
- CALL COUT
- CALL PRINT
- DB ' **',0
- RET
- CMDUDER:
- CALL PRINT
- DB CR,LF,'Invalid User or Disk Specified',0
- RET
- CMDTPA:
- CALL PRINT
- DB CR,LF,'TPA Overflow',0
- RET
- WILD: DB '*.*',0
-
- ; COMPUTE AMOUNT OF FREE SPACE LEFT ON DESTINATION DISK
- CMDF:
- CALL PRINT
- DB CR,LF,'** Free Space Data **',0
- MVI C,13 ; RESET SYSTEM
- CALL BDOS
- CALL PRINT
- DB CR,LF,' Disk (<CR>=',0
- LDA DDISK ; GET DEST DISK
- ADI 'A' ; CONVERT TO LETTER
- CALL COUT
- CALL PRINT
- DB ')? ',0
- CALL CIN ; GET RESPONSE
- CALL CAPS
- CALL COUT
- CALL CRLF ; NEW LINE
- CPI CR ; SOURCE DISK?
- JZ CMDF1
- CPI ' ' ; SOURCE DISK?
- JZ CMDF1
- SUI 'A' ; CONVERT TO DISK NUMBER
- STA DDISK ; SET DISK
- JC CMDFER
- MOV B,A ; SAVE IN B
- LDA MDISK ; COMPARE AGAINST MAX
- CMP B
- JC CMDFER
- CMDF1:
- CALL LOGD ; LOG IN DEST
- CALL DPARAMS ; GET DISK PARAMETERS
- CALL DFREE ; COMPUTE FREE SPACE
- XCHG ; HL=SPACE
- CALL CRLF
- CALL PHLDC ; PRINT AS DECIMAL
- CALL PRINT
- DB 'K Bytes Remaining on Disk ',0
- LDA DDISK
- ADI 'A'
- CALL COUT
- RET
- CMDFER:
- CALL PRINT
- DB CR,LF,'Error -- Disk Letter Invalid',0
- RET
-
- ; TOGGLE INSPECT
- CMDI:
- CALL ITOG ; TOGGLE WITH MESSAGE
- RET
-
- ; LOG IN NEW USER/DISK
- CMDL:
- CALL PRINT
- DB CR,LF,'Select Current Disk/User --',0
- LXI H,CDISK ; PT TO ENTRY
- CALL CMDL0
- CALL PRINT
- DB CR,LF,'Select Source Disk/User --',0
- LXI H,SDISK ; PT TO ENTRY
- CALL CMDL0
- CALL PRINT
- DB CR,LF,'Select Destination Disk/User --',0
- LXI H,DDISK ; PT TO ENTRY
- CMDL0:
- CALL PRINT
- DB CR,LF,' New Disk (<CR>=',0
- MOV A,M ; GET DISK
- ADI 'A'
- CALL COUT
- CALL PRINT
- DB ')? ',0
- CALL CIN ; GET RESPONSE
- CALL CAPS
- CALL COUT
- CALL CRLF
- CPI CR
- JZ CMDL1
- CPI ' '
- JZ CMDL1
- SUI 'A' ; CONVERT TO NUMBER
- JC CMDLER
- MOV B,A
- LDA MDISK ; CHECK AGAINST MAX
- CMP B
- JC CMDLER
- MOV A,B ; GET SELECTED DISK
- MOV M,A ; PUT DISK
- CMDL1:
- INX H ; PT TO USER
- CMDL2:
- PUSH H ; SAVE PTR
- CALL PRINT
- DB ' New User (<CR>=',0
- MOV A,M ; GET USER NUMBER
- CALL PADC
- CALL PRINT
- DB ')? ',0
- LXI H,INBUF ; GET INTO INPUT LINE BUFFER
- MVI A,0FFH ; CAPITALIZE
- CALL BLINE
- POP D ; GET PTR TO USER
- ORA A ; ANY RESPONSE?
- RZ
- PUSH D ; SAVE PTR TO USER
- CALL EVAL ; EVALUATE
- POP H ; GET PTR TO USER
- MOV A,D ; GET RESULT
- ORA A ; MUST BE ZERO HIGH
- JNZ CMDLUER
- LDA MUSER ; CHECK AGAINST MAX
- CMP E
- JC CMDLUER
- MOV A,E ; GET NUMBER
- MOV M,A ; PUT USER
- RET
- CMDLER:
- CALL PRINT
- DB CR,LF,'Invalid Disk -- Reenter',0
- JMP CMDL0
- CMDLUER:
- CALL PRINT
- DB CR,LF,'Invalid User -- Reenter',0
- JMP CMDL2
-
- ; TOGGLE EXIST
- CMDE:
- CALL ETOG ; TOGGLE WITH MESSAGE
- RET
-
- ; TOGGLE NCOPY
- CMDM:
- CALL MTOG ; TOGGLE WITH MESSAGE
- RET
-
- ; TOGGLE QUIET
- CMDQ:
- CALL QTOG ; TOGGLE WITH MESSAGE
- RET
-
- ; DISPLAY STATUS
- CMDS:
- CALL PRINT
- DB CR,LF,'Current Disk/User is ',0
- LXI H,CDISK
- CALL CMDS1
- CALL PRINT
- DB CR,LF,'Source Disk/User is ',0
- LXI H,SDISK
- CALL CMDS1
- CALL PRINT
- DB CR,LF,'Destination Disk/User is ',0
- LXI H,DDISK
- CMDS1:
- MOV A,M ; GET DISK
- ADI 'A'
- CALL COUT
- INX H
- MOV A,M ; GET USER
- CALL PADC
- MVI A,':'
- CALL COUT
- RET
-
- ; TOGGLE VERIFY
- CMDV:
- CALL VTOG ; TOGGLE WITH MESSAGE
- RET
-
- ; EXIT TO CP/M
- CMDX:
- CALL PRINT
- DB CR,LF,'** MCOPY Exiting **',0
- JMP CPM
-
- ; TOGGLE QUIET FUNCTION
- QT:
- LDA QUIET ; GET FLAG
- CMA ; FLIP IT
- STA QUIET ; PUT FLAG
- RET
-
- ; TOGGLE EXIST TEST FUNCTION
- ET:
- LDA EXIST ; GET FLAG
- CMA ; FLIP IT
- STA EXIST ; PUT FLAG
- RET
-
- ; TOGGLE NCOPY FUNCTION (MULTIPLE COPIES)
- MT:
- LDA NCOPY ; GET FLAG
- CMA ; FLIP IT
- STA NCOPY ; PUT FLAG
- RET
-
- ; TOGGLE INSPECT FUNCTION
- IT:
- LDA INSP ; GET FLAG
- CMA ; FLIP IT
- STA INSP ; PUT FLAG
- RET
-
- ; TOGGLE VERIFY FUNCTION
- VT:
- LDA VERFLG ; GET FLAG
- CMA ; FLIP IT
- STA VERFLG ; PUT FLAG
- RET
-
- ; TOGGLE INSPECT MODE AND PRINT MESSAGE
- ITOG:
- CALL IT ; TOGGLE AND FALL THRU TO PRINT
- ; PRINT INSPECT MESSAGE
- IMSG:
- CALL PRINT
- DB CR,LF,' File Selection Inspect Mode ',0
- LDA INSP
- ENPRT:
- ORA A ; 0=NO
- JZ ENPRT1
- CALL PRINT
- DB 'Enabled',0
- RET
- ENPRT1:
- CALL PRINT
- DB 'Disabled',0
- RET
-
- ; TOGGLE EXIST TEST AND PRINT MESSAGE
- ETOG:
- CALL ET ; TOGGLE AND FALL THRU TO PRINT
- ; PRINT EXIST STATUS
- EMSG:
- CALL PRINT
- DB CR,LF,' Existence Test Function ',0
- LDA EXIST
- JMP ENPRT
-
- ; TOGGLE MULTIPLE COPY AND PRINT MESSAGE
- MTOG:
- CALL MT ; TOGGLE AND FALL THRU TO PRINT
- ; PRINT MCOPY STATUS
- MMSG:
- CALL PRINT
- DB CR,LF,' Multiple Copy Function ',0
- LDA NCOPY
- JMP ENPRT
-
- ; TOGGLE QUIET AND PRINT MESSAGE
- QTOG:
- CALL QT ; TOGGLE AND FALL THRU TO PRINT
- ; PRINT QUIET STATUS
- QMSG:
- CALL PRINT
- DB CR,LF,' Quiet Operation ',0
- LDA QUIET
- JMP ENPRT
-
- ; TOGGLE VERIFY AND PRINT MESSAGE
- VTOG:
- CALL VT ; TOGGLE AND FALL THRU TO PRINT
- ; PRINT VERIFY STATUS
- VMSG:
- CALL PRINT
- DB CR,LF,' Copy Verification ',0
- LDA VERFLG
- JMP ENPRT
-
- ; PRINT MCOPY COMMAND HELP MESSAGE
- MCPYHLP:
- CALL PRINT
- DB CR,LF,' MCOPY Status: E I M Q V'
- DB CR,LF,'These Status Characters have the following meanings:'
- DB CR,LF,' E - File Existence Test Mode is ON'
- DB CR,LF,' I - File Selection Inspect Mode is ON'
- DB CR,LF,' M - Multiple Copy Function Mode is ON'
- DB CR,LF,' Q - Quiet Mode is ON'
- DB CR,LF,' V - Verify Mode is ON'
- DB CR,LF
- DB CR,LF,'The Status Characters, as commands, toggle their '
- DB 'respective modes.'
- DB CR,LF,'Other valid MCOPY Commands are:'
- DB CR,LF,' C - Copy a File or Set of Files'
- DB CR,LF,' D - Directory Display'
- DB CR,LF,' F - Compute Amount of Free Space on Disk'
- DB CR,LF,' L - Log in New User/Disks'
- DB CR,LF,' S - Display MCOPY Status (Cur and Dest User/Disk)'
- DB CR,LF,' X or ^C - Exit MCOPY'
- DB 0
- RET
-
- ; PRINT CHAR IN A IF NZ, ELSE PRINT <SP>
- PMODE:
- JZ PMODE1 ; PRINT <SP>
- JMP COUT ; PRINT CHAR
- PMODE1:
- MVI A,' ' ; PRINT <SP>
- JMP COUT
-
- ;
- ; PRINT MCOPY BANNER
- ;
- BANNER:
- CALL PRINT
- DB 'MCOPY Version '
- DB VERS/10+'0','.',(VERS MOD 10)+'0',0
- RET
-
- ;
- ; **** MCOPY of COMMAND LINE ****
- ;
- MCOPY0:
- LXI SP,STACK ; SET STACK
- 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
- JMP CPM ; WARM BOOT WHEN DONE
-
- ;
- ; **** Begin Multiple Copy Procedure ****
- ;
- COPY:
- LHLD MFPTR ; PT TO FIRST FILE NAME
- SHLD NXTPTR ; SET PTR TO NEXT FILE NAME
- LXI H,0 ; HL=0
- SHLD FCOUNT ; ZERO FILE COUNT
- SHLD 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:
- CALL PRINT
- DB CR,LF,'**** MCOPY Complete ****',CR,LF,' ',0
- LHLD FCOUNT ; GET FILE COUNT
- CALL PHLDC ; PRINT AS DECIMAL
- CALL PRINT
- DB ' File',0
- MOV A,H ; 1 FILE?
- ORA A
- JNZ COPYT1
- MOV A,L
- CPI 1 ; 1 FILE?
- JZ COPYT2
- COPYT1:
- MVI A,'s' ; ENDING S
- CALL COUT
- COPYT2:
- CALL PRINT
- DB ' Copied ',0
- LHLD VERCNT ; GET ERROR COUNT
- CALL PHLDC ; PRINT AS DECIMAL
- CALL PRINT
- DB ' Copy Errors',0
- 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
- PUSH H ; SAVE PTR TO NEXT FILE NAME
- CALL CODEND ; GET ADDRESS OF SCRATCH AREA
- MOV B,H ; BC=ADDRESS OF SCRATCH AREA
- MOV C,L
- LXI D,FCBS ; GET POSSIBLE SOURCE FCB
- POP H ; GET PTR TO NEXT FILE SPEC
- CALL ZFNAME ; EXTRACT FILE NAME DATA
- JZ UDERR ; ERROR?
- 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 ; CHECK FOR ANY DISK OR USER CHANGE
- ANA C ; IF BOTH FF, THEN NO CHANGE
- CPI 0FFH ; BOTH FF?
- JZ MCPY2
- LDA CDISK ; SET DEST TO CURRENT SINCE A CHANGE IS EXPECTED
- STA DDISK ; ... IN THIS WAY, A NEW DEST OF U: OR D: IS
- LDA CUSER ; ... INTERPRETED AS $U: OR D$: (I.E., IF LOGGED INTO
- STA DUSER ; ... B, A DEST OF 1: IS B1:)
- MOV A,B ; CHECK FOR DISK CHANGE
- CPI 0FFH ; 0FFH=NO CHANGE
- JZ MCPY1
- DCR A ; ADJUST
- STA DDISK ; SET NEW DEFAULT DISK
- MCPY1:
- MOV A,C ; CHECK FOR USER CHANGE
- CPI 0FFH ; 0FFH=NO CHANGE
- JZ MCPY2
- CPI '?' ; ALL USERS NOT PERMITTED
- JZ UDERR
- 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
- PUSH H ; SAVE PTR
- CALL CODEND ; GET END OF CODE
- MOV B,H ; ... IN BC
- MOV C,L
- POP H ; GET PTR TO NAME
- LXI D,FCBS ; LOAD FCB
- CALL ZFNAME ; GET SOURCE NAME
- JZ UDERR ; ERROR?
- ;
- ; 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 ; CHECK FOR NO DISK OR USER CHANGE
- ANA C
- CPI 0FFH ; BOTH FF?
- JZ MCPY22
- LDA CDISK ; IF CHANGE IN EITHER, ASSUME OLD SOURCE TO BE CURRENT
- STA SDISK
- LDA CUSER
- STA SUSER
- MOV A,B ; CHECK FOR DISK CHANGE
- CPI 0FFH ; 0FFH=NO CHANGE
- JZ MCPY21
- DCR A ; ADJUST
- STA SDISK ; SET NEW DEFAULT DISK
- MCPY21:
- MOV A,C ; CHECK FOR USER CHANGE
- CPI 0FFH ; 0FFH=NO CHANGE
- JZ MCPY22
- CPI '?' ; ALL USERS NOT PERMITTED
- JZ UDERR
- STA SUSER ; SET NEW DEFAULT USER
- MCPY22:
- CALL PRINT
- 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
- LXI H,FCBS+1 ; PRINT FILE SPEC
- CALL PRFN
- CALL PRINT
- 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
- LXI D,FCBS ; PT TO SOURCE FCB
- CALL INITFCB ; INIT FCB
- CALL CODEND ; PT TO BUFFER AREA
- LDA SUSER ; PREPARE FLAG FOR SELECTION
- ANI 1FH ; ONLY USER NUMBER
- ORI 0C0H ; SELECT NON-SYS AND SYS FILES
- CALL DIRF ; 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 PRINT
- DB CR,LF,'** NO Files Selected **'
- DB CR,LF,'** Strike ^C to Abort, Anything Else to Continue: ',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,16 ; 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,64 ; SET PAGE LIMIT TO 16K
- 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 64 ; 64 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 MCOPYX ; COPY SOURCE (HL) TO DESTINATION USING WORK BUFFER
- LDA QUIET ; CHECK FOR QUIET
- ORA A ; NZ=QUIET
- JNZ MCPY27
- CALL PRINT
- DB CR,LF,' Copy Complete',0
- MCPY27:
- LDA LSTCPY ; LAST FILE COPIED?
- ORA A ; 0=NO
- JZ MCPY28
- LDA VERFLG ; VERIFY?
- ORA A ; 0=NO
- CNZ MCOPYV ; DO VERIFY
- LHLD FCOUNT ; COUNT FILES
- INX H
- SHLD FCOUNT
- MCPY28:
- POP B ; GET REGS
- POP H
- LXI D,16 ; 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
- ;
- ; COPY SOURCE FILE PTED TO BY HL TO DESTINATION
- ;
- MCOPYX:
- XRA A ; SET NO COPY OF LAST FILE
- STA LSTCPY ; SET FLAG
- LXI D,FCBS ; SET SOURCE FCB
- MVI B,12 ; 12 BYTES
- CALL MOVEB
- CALL INITFCB ; INIT SOURCE FCB
- LXI D,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
- LXI D,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 PRINT
- DB CR,LF,'Original File ',0
- LXI H,FCBD+1 ; PRINT FILE NAME
- CALL PRFN
- CALL PRINT
- DB ' on Destination',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 PRINT
- DB CR,LF,'No Original File ',0
- LXI H,FCBD+1 ; PRINT FILE NAME
- CALL PRFN
- CALL PRINT
- DB ' on Destination',0
- CALL EATEST ; EXIST APPROVED?
- RZ ; NO?
- FNF1:
- MVI A,0FFH ; SET COPY OF LAST FILE
- STA LSTCPY ; SET FLAG
- CALL F$MAKE ; CREATE NEW FILE
- ;
- ; OPEN SOURCE FILE IN PREP FOR COPY
- ;
- CALL CRCCLR ; CLEAR CRC VALUE
- CALL LOGS ; LOG IN SOURCE DISK
- LXI D,FCBS ; INIT FCB
- CALL INITFCB
- CALL F$OPEN ; OPEN FILE
- CALL CRLF ; NEW LINE
- LXI H,0
- SHLD RKCNT ; SET READ K COUNT
- SHLD WKCNT ; SET WRITE K COUNT
- ;
- ; THIS LOOP, WHICH STARTS AT MCPYX, COPIES THE FILE FROM SOURCE TO DEST
- ;
- MCPYX:
- CALL LOGS ; LOG IN SOURCE
- LXI D,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
- LDA QUIET ; CHECK FOR QUIET
- ORA A ; Z=NOT QUIET
- JNZ MCPYD0
- CALL PRINT
- DB ' Writing .....K',0
- MCPYD0:
- LHLD WORKBF ; PT TO BUFFER
- MCPYD1:
- LXI D,BUFF ; COPY DATA TO BUFFER
- MVI B,128 ; 128 BYTES
- CALL MOVEB ; COPY IT
- LXI D,128 ; INCR HL BY 128
- DAD D ; HL PTS TO NEXT BLOCK
- LXI D,FCBD ; WRITE TO DESTINATION FILE
- CALL F$WRITE
- ORA A ; OK?
- JNZ MCPYDERR
-
- ; COUNT DOWN TO NEXT BLOCK
- LDA BCNT ; PRINT BLIPS
- ANI 7 ; MASK
- JNZ MCPYD2
- LDA QUIET ; CHECK FOR QUIET
- ORA A ; Z=NOT QUIET
- JNZ MCPYD2
- PUSH H ; SAVE HL
- LHLD WKCNT ; INCREMENT WRITE K COUNT
- INX H
- SHLD WKCNT
- CALL PRKCNT ; PRINT K COUNT
- POP H
- MCPYD2:
- LDA BCNT ; GET BLOCK COUNT
- DCR A ; COUNT DOWN
- STA BCNT
- JNZ MCPYD1
- LDA QUIET ; CHECK FOR QUIET OPERATION
- ORA A ; Z=NOT QUIET
- CZ CRLF ; NEW LINE
- LDA CONT ; CONTINUE?
- ORA A ; CONT IF NOT ZERO
- JNZ MCPYX
- ;
- ; END OF COPY LOOP
- ;
- MC2DONE:
- CALL LOGS ; LOG IN SOURCE
- LXI D,FCBS ; CLOSE SOURCE
- CALL F$CLOSE
- CALL LOGD ; LOG IN DESTINATION
- LXI D,FCBD ; CLOSE DESTINATION
- CALL F$CLOSE
- CALL CRCDONE ; GET CRCK VALUE
- SHLD CRCVAL ; SAVE CRC VALUE
- CALL LOGS ; LOG IN SOURCE DRIVE
- LXI D,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
- LXI D,FCBT
- MVI B,16 ; MOVE 16 BYTES
- CALL MOVEB
- CALL LOGD ; LOG IN DESTINATION DRIVE
- LXI D,FCBT
- CALL INITFCB ; INIT FCB
- MVI C,30 ; SET FILE ATTRIBUTES
- CALL BDOS
- RET ; MCOPYX RETURN
-
- ; FORMAT ERROR
- FORMERR:
- CALL PRINT
- DB CR,LF,'MCOPY -- Format Error in Command Line'
- DB CR,LF,'Error Starts at: ',0
- CALL PSTR ; PRINT ERROR
- RET
-
- ; USER/DISK ERROR
- UDERR:
- CALL PRINT
- DB CR,LF,'MCOPY -- Error in User Number or Disk Letter',0
- RET
-
- ; TPA OVERFLOW
- TPAOVFL:
- CALL PRINT
- DB CR,LF,'MCOPY -- TPA Overflow -- Aborting',0
- JMP CPM
-
- ; WRITE ERROR
- MCPYDERR:
- CALL PRINT
- DB CR,LF,'MCOPY -- Error in Creating Destination File',0
- JMP CPM
-
- ; TEST FOR EXISTENCE REQUIREMENT AND GET USER RESPONSE
- EATEST:
- LDA EXIST ; EXISTENCE TEST ON?
- ORA A ; 0=NO
- JZ EAT1
- CALL PRINT
- DB CR,LF,' -- Approve Copy (Y/N/other=Y)? ',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
- CALL PRINT
- DB ' -- Disapproved',0
- 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:
- LXI H,FCBD+9 ; CLEAR ATTRIBUTES OF DEST
- 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
- LXI D,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
- LDA QUIET ; QUIET?
- ORA A ; 0=NO
- JNZ MCPY
- CALL PRINT
- DB 'Reading .....K',0
-
- ; MAIN COPY LOOP
- MCPY:
- 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
- LXI D,BUFF ; PT TO BUFFER TO COPY FROM
- MVI B,128 ; COPY 128 BYTES
- XCHG ; HL PTS TO SOURCE, DE PTS TO DESTINATION
- MCPYCRC:
- MOV A,M ; GET BYTE
- STAX D ; PUT BYTE
- CALL CRCUPD ; UPDATE CRC
- INX H ; PT TO NEXT
- INX D
- DCR B ; COUNT DOWN
- JNZ MCPYCRC
- XCHG ; HL PTS TO DESTINATION AGAIN
- POP D ; GET PTR TO FCB
- LDA BCNT ; GET BLOCK COUNT
- INR A ; INCREMENT IT
- STA BCNT ; SET IT
- PUSH PSW ; PRINT BLIP FOR EVERY 1K
- ANI 7 ; CHECK FOR EVERY 8 BLOCKS
- JNZ NOBLIP
- LDA QUIET ; CHECK FOR QUIET
- ORA A ; Z=NOT QUIET
- JNZ NOBLIP
- PUSH H ; SAVE HL
- LHLD RKCNT ; INCREMENT READ K COUNT
- INX H
- SHLD RKCNT
- CALL PRKCNT ; PRINT K COUNT
- POP H
- NOBLIP:
- LDA PAGLIM ; GET PAGE LIMIT
- ADD A ; DOUBLE IT FOR BLOCKS
- MOV B,A ; LIMIT IN B
- POP PSW ; GET BLOCK COUNT
- CMP B ; BUFFER FULL?
- JNZ MCPY
- STA CONT ; SET CONTINUATION FLAG
- RET
-
- ;
- ; VERIFY PHASE
- ;
- MCOPYV:
- LDA QUIET ; CHECK FOR QUIET
- ORA A ; NZ=QUIET
- JNZ MCPYV
- CALL PRINT
- DB ', Verify Phase --',CR,LF,0
- LXI H,0 ; SET READ K COUNT
- SHLD RKCNT
- MCPYV:
- CALL CRCCLR ; CLEAR CRCK VALUE
- CALL LOGD ; LOG IN DESTINATION
- LXI D,FCBD ; CLEAR DESTINATION FCB
- CALL INITFCB ; INIT FCB
- CALL F$OPEN ; OPEN FILE
-
- ; **** MAIN VERIFY LOOP ****
- VERLOOP:
- LHLD WORKBF ; LOAD INPUT BUFFER FROM DESTINATION
- LXI D,FCBD
- CALL LOAD ; LOAD AND COMPUTE CRC VALUE
- LDA BCNT ; DONE IF NO BYTES LOADED
- ORA A
- JZ VERCRC
- LDA QUIET ; NEW LINE IF NOT QUIET
- ORA A ; 0=NOT QUIET
- CZ CRLF
- 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
- JNZ VERERR
- LDA QUIET ; CHECK FOR QUIET
- ORA A ; NZ=QUIET
- RNZ
- CALL PRINT
- DB ' Verify Complete',0
- RET
-
- ; VERIFY ERROR
- VERERR:
- LHLD VERCNT ; INCREMENT ERROR COUNT
- INX H
- SHLD VERCNT
- CALL PRINT
- DB ' ** Verify Error **',7,0
- RET
-
- ;
- ; **** MCOPY Utilities ****
- ;
-
- ;
- ; PRINT K COUNT -- BACK UP 6 SPACES AND PRINT NUMBER IN HL FOLLOWED BY A K
- ;
- PRKCNT:
- PUSH B ; SAVE BC
- MVI B,6 ; BACK UP
- MVI A,'H'-'@' ; ^H=BACKSPACE
- PRKCNT1:
- CALL COUT ; BACK UP
- DCR B ; COUNT DOWN
- JNZ PRKCNT1
- CALL PHLDC ; PRINT AS DECIMAL
- MVI A,'K' ; PRINT ENDING K
- CALL COUT
- POP B
- RET
-
- ;
- ; CHECK TO SEE IF USER WANTS TO CONTINUE
- ;
- SAKCHK:
- CALL PRINT
- DB CR,LF,' Strike RETURN when Ready or ^C or A to Abort - ',0
- CALL CIN ; GET RESPONSE
- CALL CRLF ; NEW LINE
- CALL CAPS ; CAPITALIZE
- CPI 'C'-'@' ; ^C?
- RZ
- CPI 'A' ; ABORT?
- 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:
- PUSH H ; SAVE PTR TO FIRST FILE
- PUSH B ; SAVE FILE COUNT
- LXI D,16 ; ENTRIES ARE 16 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 PRINT
- DB ' -- Copy (Y/N/S=Skip Rest/<CR>=Y)? ',0
- CALL CIN ; GET RESPONSE
- CALL CAPS ; CAPITALIZE
- CALL COUT ; ECHO
- CPI 'S' ; SKIP?
- JZ INSPFA
- CPI 'N' ; NO?
- JZ INSPF2
- MOV A,M ; GET USER NUMBER
- ORI 80H ; MARK FILE
- MOV M,A ; SET USER NUMBER
- INSPF2:
- LXI D,16 ; 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 ****
- ;
-
- ; COMMAND LINE BUFFER
- BUFSIZ EQU 200 ; SIZE OF COMMAND LINE BUFFER
- INBUF: DB BUFSIZ ; FOR USE WITH INPUT LINE EDITOR
- DB 0
- DS BUFSIZ+1 ; INPUT COMMAND LINE
-
- ; 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 -- ORDER IS IMPORTANT -- cUSER MUST FOLLOW cDISK
- CDISK: DS 1 ; CURRENT DISK
- CUSER: DS 1 ; CURRENT USER
- 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 40 ; SOURCE FCB
- FCBD: DS 40 ; DESTINATION FCB
- FCBT: DS 40 ; TEMPORARY FCB FOR ATTRIBUTE SETTINGS
-
- ; COUNTS AND FLAGS
- RKCNT: DS 2 ; READ K COUNT
- WKCNT: DS 2 ; WRITE K COUNT
- 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
- FTOTAL: DS 2 ; TOTAL SIZE OF FILES
- FCOUNT: DS 2 ; NUMBER OF FILES
- VERCNT: DS 2 ; ERROR COUNT
- BCNT: DS 1 ; BLOCK COUNT
- CONT: DS 1 ; CONTINUE FLAG (0=NO, 0FFH=YES)
-
- ; STACK AREA
- DS 100 ; 50-ELEMENT STACK
- STACK EQU $
- DB 0 ; END OF MAINLINE
-
- END
-