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
/
CPM
/
ZCPR33
/
A-R
/
DIFF30.LBR
/
DIFF30.ZZ0
/
DIFF30.Z80
Wrap
Text File
|
2000-06-30
|
27KB
|
1,307 lines
;
; Program: DIFF
; Author: Carson Wilson
; Version: 3.0
; Date: 16 February 89
vers equ 30
; Changes: Linked to corrected ZSGSTPCP routine.
; Added "(no stamp)" informative message.
; Cleaned up and organized code.
; Author: Carson Wilson
; Version: 2.9
; Date: 29 December 88
; Changes: Corrected premature termination error message - said
; "Source 1 .." when source 2 terminated prematurely,
; and "Source 2 .." for source 1.
; Fixed bugs which caused DIFF to abort during multiple
; compares when the files were different or with datestamp
; only (/D) option.
; Fixed bug introduced by Quiet code which caused files with
; same name, different stamp to be treated as equal files.
; Swapped OPEN12 and OPEN21 for greater efficiency.
; Slash before options now optional if three parameters are
; specified.
; Added terminating CR to restore cursor on exit.
; Linked with new version of ZSLIB which supports Z3PLUS
; datestamps.
; Note: Could use reorganization for clarity around CABORT:
; Author: Carson Wilson
; Version: 2.7
; Date: 4 September 88
;
; Changes: Changed /D option to /I (ignore datestamps) option.
; Added /D option (use datestamps only).
; Added /Q (quiet) option.
; Patchable options label now "[DIMQV>".
; Use ZSLIB PRDAT2 instead of PRDAT3.
; Help now does not show ZSDOS options unless ZSDOS present.
; Changed "File n is more recent" to "Source n...."
; Linked with SYSLIB 3.6 SCOMP routine due to SYSLIB4 bug.
; No longer gives "advance" prompt unless multiple compare.
; Author: Carson Wilson
; Version: 2.6
; Date: 24 August 88
; Changes: TPA overflow test for high-memory versions.
;
; Register 0 set according to file date comparison:
; REG 0 0 if one or both stamps missing or /I,
; REG 0 1 if file 1 more recent,
; REG 0 2 if file 2 more recent,
; REG 0 3 if file dates match.
;
; ZCPR program error flag set by default & reset only if both
; files found and names and dates, or data match (at EQUAL).
;
; Added local stack and QUIT routine.
;
; Use SETDMA for fast buffer loading.
;
; Allow abort during VERIFY with ^c.
;
; Use IX for file offset. NOTE: assumes OS preserves IX.
;
; Patchable options shown in help.
;
; FCBs now parsed by Z33 CCP, so can use options with only
; one file name, e.g., "DIFF myfile /d", and directory/user
; parse is same as CCP. This also saves considerable code.
;
; Implemented DSEG for shorter program length.
;
; Added patchable option defaults.
;
; Changed C(ompare) option to V(erbose) option, making brief
; output the default.
;
; Use (z3eadr) to detect ZCPR 3.3 environment,
; so that we can run with BGii. NOTE: if installed with Z3INS,
; will now run under ANY environment, with unpredictable results.
;
; Added "loaded at nnnn hex" message.
;
; Chains to Z33 error handler on wildcard names or bad directory.
;
; Removed reference to CAPS routine, shortening code length.
;
; Translated to lower case and Z80 opcodes.
;
; Added datestamp comparison for ZSDOS or DosDisk systems. Idea
; based on DATSWEEP by Bridger Mitchell. See DIFF26.DOC for
; details.
;
; Assembly: Z80ASM, SLRNK, Z3LIB, ZSLIB, SYSLIB.
;
; AUTHOR: Richard Conn
; VERSION: 2.0
; DATE: 18 MAY 84
; PREVIOUS VERSIONS: 1.6 (16 JAN 83)
; PREVIOUS VERSIONS: 1.5 (9 JAN 83), 1.4 (6 JAN 83), 1.3 (4 JAN 83)
; PREVIOUS VERSIONS: 1.2 (19 DEC 82), 1.1 (8 DEC 82), 1.0 (24 JULY 82)
; DERIVATION: COMPARE, VERSION 1.1
; SIZE OF BUFFER
blimit equ 32 ; NUMBER OF 128-BYTE BLOCKS
bsize equ blimit*128 ; 4K
false equ 0
true equ not false
no equ false
yes equ true
; CP/M Constants
cpm equ 0 ; CP/M Warm Boot
fcb1 equ 05ch
fcb2 equ 06ch
defdma equ 80h
buff equ cpm+80h ; Temporary Buffer
cr equ 0dh
lf equ 0ah
tab equ 9
bell equ 7
ctrlc equ 'C'-'@'
ctrlx equ 'X'-'@'
; BDOS functions
prints equ 9 ; Print string
setdmaf equ 26
; ZCPR constants
;
; Z33 error codes
;
ecambig equ 8 ; Ambiguous file specification
ecbaddir equ 2 ; Bad directory specification
ecnofile equ 10 ; File not found
public $memry ; SLRNK fills in
; Externals
ext getstp,prdat2,ptimm1 ; ZSLIB
ext dostyp,cpmver,gstpcp
ext retcst,puter3 ; Z33LIB (or new Z3LIB)
ext z3init,getcrt,puter2,putreg ; Z3LIB
ext phl4hc,phldc,pa2hc,padc ; SYSLIB
ext bdos,initfcb,sksp,sknsp
ext logud,retud
ext f$open,f$close,f$read
ext cin,cout,crlf,moveb,print,pstr
ext compb,condin,setdma
; ======================================================
;
; CODE BEGINS
;
entry:
jp start
db 'Z3ENV'
db 3 ; Type-3 environment
z3eadr:
dw 0 ; Filled in by CCP
loadadr:
dw entry
;
; Patchable option defaults
;
db '[DIMQV>' ; Label for patcher
donlyd: db no ; D atestamp only
ignord: db no ; I gnore datestamps
multd: db no ; M ultiple runs
quietd: db no ; Q uiet
verbd: db no ; V erbose
;
start:
ld hl,(z3eadr) ; Point to ZCPR3 environment
;
; Start of Program -- Initialize ZCPR3 Environment
;
ld a,h
or l
jr nz,gotz33 ; Filled in at run time if Z33
call print
db bell,'Need ZCPR 3.3 or greater',0
ret
gotz33:
ld (stksav),sp
ld sp,ourstk
call z3init ;initialize the ZCPR3 Env and the VLIB Env
;
; Set operations flags from patchable defaults
;
ld bc,5 ; 5 options
ld de,donly ; Target in data segment
ld hl,donlyd ; Source at top of file
ldir ; Copy defaults for GO
call getcrt ; GET CRT CHARACTERISTICS
inc hl ; PT TO TEXT LINE COUNT
inc hl
ld a,(hl) ; GET line COUNT
ld (lset),a ; SET COUNTER
;
; Extract command line information
;
ld a,(fcb1+1)
cp ' ' ; No parameters?
jp z,prhelp ; PRINT HELP IF SO
cp '/' ; ASKING FOR HELP?
jp z,prhelp
;
; Abort to error handler on illegal directories
;
ld a,(06bh) ; Get Z33 bad dir. flag (0=ok)
ld b,a
ld a,(07bh) ; Flag for FCB2
or b
jr z,zdirsok
ld a,ecbaddir ; Error code
jp z33err ; Chain to EH
;
; Warm boot if TPA overflow
;
zdirsok:
ld hl,(6) ; Get BDOS/RSX addr.
$memry equ $+1 ; Initialized by linker
ld bc,0 ; Get last byte used by DIFF
or a ; Clear carry
sbc hl,bc ; Last address < max. TPA?
jr nc,tpaok ; Yes
call print
db bell,'TPA overflow',0
jp 0 ; Warm boot
;
; Parse command line
;
tpaok:
call retud ; B = current disk 0..15
ld ix,fcb1
ld iy,fcb2
;
; Store drives, users for display
;
ld a,(ix) ; Source drive
or a
jr nz,stores
ld a,b ; Disk from RETUD above
inc a ; To 1..16
stores:
ld (sdisk),a
ld a,(iy)
or a
jr nz,stored
ld a,b
inc a ; To 1..16
stored:
ld (ddisk),a
ld a,(ix+13) ; Store users
ld (suser),a
ld a,(iy+13)
ld (duser),a
;
; Move FCB2 to high memory
;
ld hl,fcb2
ld de,fcbd
ld b,12 ; Drive, name
call moveb
;
ld a,(iy+1)
cp '/' ; 2nd name given?
jr z,onename ; No
cp ' '
jr nz,twoname ; Yes
;
; No 2nd name, so copy 1st to 2nd
;
onename: ; Set 2nd name to same as first
ld hl,fcb1+1
ld de,fcbd+1
ld b,11 ; 11 BYTES
call moveb
twoname:
ld hl,fcb1 ; SET UP SOURCE FCB
call qcheck ; NO AMBIGUOUS ENTRIES PERMITTED
ld hl,fcbd ; SET UP DESTINATION FCB
call qcheck ; NO AMBIGUOUS ENTRIES PERMITTED
;
ld hl,buff+1
call sksp ; Skip parm1...
call sknsp
call sksp
ld a,'/'
cp (hl) ; "/"parm2?
jr z,gotopt ; Yes, parse options
call sknsp
call sksp
gotopt: inc (hl)
dec (hl) ; Terminator?
call nz,opts ; No, parse option(s)
; ----------------------------------------------------
;
; Compare files (re-enter here for multiple compares)
mloop:
; Set program error flag and register 0 to defaults
ld a,0ffh
call puter2 ; Set program error flag TRUE
xor a
ld b,a
call putreg ; Set register 0 to 0
; Print banner
call banner
ld a,(mult) ; Multiple runs?
or a
jr z,mloop1 ; No, print names (and dates if used)
call qtest
jr nz,mloop1 ; Override /M if quiet
call print
db cr,lf,' Strike ^C to Abort or RETURN to Proceed: ',0
call cin ; GET RESPONSE
cp ctrlc ; ABORT?
jp z,dabort1
ld c,13 ; RESET DISKS
call bdos
mloop1:
;
; Use datestamps?
;
call prs1 ; Print source file name one
ld a,(ignor) ; Test flag
or a
jr z,dodate ; If stamps, don't show second name now
mloop1a:
call prs2 ; Print name two
jp open12 ; And go compare if needed
;
; Test if names equal
;
dodate:
ld de,fcb1+1
ld hl,fcbd+1
ld b,11
call compb ; SYSLIB
ld a,0
jr z,storen ; Names match
ld a,0ffh
storen:
ld (names),a ; 0=names match
;
; Display stamps
;
call space1
call logs ; Log to source disk/user
ld de,fcb1
ld hl,sdatbuf
call getstp
jr z,dodat0 ; Got stamp
call gstpcp ; Try for CP/M Plus stamp
jr z,dodat0 ; Got stamp
call noserr ; Say no stamp
jr mloop1a ; Skip stamps
dodat0:
ld hl,smodbuf
call qprdat2 ; Try to print modify
ld (smodok),a ; Save as flag (0=ok)
jr z,dodat1 ; Modify ok
ld hl,sdatbuf ; Try to print create
call qprdat2
jr z,dodat1 ; Got stamp
call noserr ; Say no stamp
jr mloop1a ; Skip stamps
dodat1:
call space1
call qtest
call z,ptimm1 ; Show time
ld a,(smodok) ; Got source modify?
or a
ld hl,cstring
jr nz,dodat2 ; No, say create
ld hl,mstring
dodat2:
call qtest ; If not quiet
call z,pstr ; ..say create or modify
;
; Got source stamp, now look for dest.
;
call prs2 ; Print name 2
call space1
call logd ; Log to dest. disk/user
ld de,fcbd ; Search for dest. stamp
ld hl,ddatbuf
call getstp
jr z,dodat3 ; Got stamp
call gstpcp ; Try for CP/M Plus stamp
jr z,dodat3 ; Got stamp
call noserr
jp open21 ; No dest stamp, skip compare
dodat3: ld hl,dmodbuf
call qprdat2
ld (dmodok),a ; Save (0=ok)
jr z,dodat4
ld hl,ddatbuf
call qprdat2
jr z,dodat4 ; Got stamp
call noserr ; Say no stamp
jr open21 ; Skip stamps
dodat4:
call space1
call qtest
call z,ptimm1 ; Show time
ld hl,mstring ; Say modify
ld a,(dmodok) ; Using modify?
or a
jr z,dodat5 ; Yes
ld hl,cstring ; No, say create
dodat5:
call qtest
call z,pstr ; Say create or modify
ld hl,smodbuf ; Point to modify
ld a,(smodok) ; Got source modify stamp?
or a
jr z,dodat6 ; Yes
ld hl,sdatbuf ; No, use create
dodat6:
ld de,dmodbuf ; Point to dest. modify
ld a,(dmodok) ; ok?
or a
jr z,dodat7 ; Yes
ld de,ddatbuf ; No, use dest. create
dodat7:
ld b,5 ; Test 5 bytes yy mm dd hh mm
call compb ; SYSLIB
ld b,0 ; Set register 0
ld a,3 ; Dates match
ld hl,dmatstr
jr z,dodat8
ld a,2 ; File 2 more recent
ld hl,twostr
jr c,dodat8
ld a,1 ; File 1 more recent
ld hl,onestr
dodat8:
call putreg
push af ; Save flags
call qtest
jr nz,dodat9 ; No display if quiet
call crlf
call pstr ; Show dates status
dodat9:
pop af ; Get flags
jp nz,open21 ; Stamps don't match, compare data
ld a,(names)
or a ; Names match?
jp z,equal1 ; Yes, exit or loop back for next test
; --------------------------------------------
;
; Open files for data compare
;
; Open source 2, then source 1
;
open21:
ld a,(donly)
or a
jp nz,mloop2 ; Quit if datestamp only test
call logd ; Log in dest
ld de,fcbd ; TRY TO OPEN SOURCE 2
call initfcb ; INIT FCB
call f$open
jp nz,f2err
call logs ; LOG IN SOURCE
ld de,fcb1 ; TRY TO OPEN SOURCE 1
call initfcb ; Init FCB in case /i option used
call f$open ; Z IF NO ERROR
jp nz,f1err
jr compare
;
; Open source 1, then source 2
;
open12:
ld a,(donly)
or a
jp nz,mloop2 ; Quit if datestamp only test
call logs ; LOG IN SOURCE
ld de,fcb1 ; TRY TO OPEN SOURCE 1
call initfcb ; Init FCB in case /i option used
call f$open ; Z IF NO ERROR
jp nz,f1err
;
call logd ; LOG IN DEST DISK/USER
ld de,fcbd ; TRY TO OPEN SOURCE 2
call initfcb ; INIT FCB
call f$open
jp nz,f2err
;
; Both files open. Compare data.
;
compare:
xor a ; A=0
ld (first),a ; SET FLAG FOR FIRST ERROR
ld ix,0 ; Init offset
call verify ; PERFORM VERIFICATION
ld a,(first) ; ANY ERRORS?
or a ; Match?
jp nz,mloop2 ; No
;
; Files identical. Tell user.
;
equal:
call qtest
jr nz,equal1 ; No display if quiet
call print
db cr,lf,' Files are identical',0
;
; Files identical or names and dates match. Reset program error flag
;
equal1:
xor a ; No errors, so files match
call puter2 ; Reset ZCPR program error flag
mloop2:
ld a,(mult) ; CHECK FOR MULTIPLE RUNS
cpl
ld b,a ; 0ffh=single
ld a,(quiet) ; 0ffh=quiet
or b ; Single or quiet?
jp nz,quitlf ; Yes, exit
;
; Back for next test (multiple run)
;
call crlf ; NEW LINES
jp mloop
; -----------------------------------------
;
; File open errors
;
f1err:
call prs1a
jr ferr
f2err:
call prs2a
ferr:
call print
db '- not found',0
jp mloop2
; No stamp error
noserr:
call qtest
ret nz ; Don't print if quiet
call print
db '(no stamp) ',0
ret
; ----------------------------------------------
;
; Parse command line options
;
opts:
ld a,(hl) ; GET NEXT OPTION CHAR
inc hl ; PT TO NEXT
or a ; END OF LINE?
ret z
cp ' ' ; SKIP SPACES
jr z,opts
cp ',' ; ..commas..
jr z,opts
cp '/' ; ..and slashes
jr z,opts
ld de,otab ; PT TO OPTION TABLE
ld b,a ; OPTION CHAR IN B
opts1:
ld a,(de) ; GET TABLE CHAR
or a ; OPTION NOT FOUND?
jp z,prhelp
cp b ; MATCH?
jr z,opts2
inc de ; SKIP TO NEXT
inc de
inc de
jr opts1
opts2:
ex de,hl ; USE HL
inc hl ; GET ADDRESS
ld a,(hl) ; GET LOW
inc hl
ld h,(hl) ; GET HIGH
ld l,a ; PUT LOW
ex de,hl ; DE PTS TO OPTION ADDRESS, HL TO NEXT BYTE
ld bc,opts ; SET UP RETURN ADDRESS
push bc
push de ; SET UP OPTION ADDRESS
ret ; "RUN" OPTION
;
; Option table
;
otab:
db 'D' ; Test dates only
dw sdonlyf
db 'I'
dw signorf
db 'M' ; Multiple run
dw smultf
db 'Q' ; Quiet
dw squietf
db 'V' ; Verbose
dw sverbf
db 0 ; End of table
;
; Set use dates only
;
sdonlyf:
ld a,(donlyd)
cpl ; Reverse default
ld (donly),a
ret
;
; Set ignore date flag
;
signorf:
ld a,(ignord)
cpl ; Reverse default
ld (ignor),a
ret
;
; Set multiple run flag
;
smultf:
ld a,(multd)
cpl ; Reverse default
ld (mult),a
ret
;
; Set DIFF quiet flag
;
squietf:
ld a,(quietd)
cpl ; Reverse default
ld (quiet),a
ret
;
; Set verbose flag
;
sverbf:
ld a,(verbd)
cpl ; Reverse default
ld (verb),a
ret
;
; Skip to non-blank char
;
sblank:
ld a,(hl) ; GET CHAR
inc hl ; PT TO NEXT
cp ' ' ; BLANK?
jr z,sblank
dec hl ; PT TO NON-BLANK
ret
; ------------------------------------------------
;
; Print help message
;
prhelp:
call banner1 ; PRINT BANNER
call print
db cr,lf
db ' Syntax:',cr,lf
db tab,'DIFF /',tab,tab,tab,tab,tab,'- help',cr,lf
db tab,'DIFF [dir:]ufn [dir:][ufn] [/][options]'
db tab,'- compare',cr,lf
db ' Options:',cr,lf,0
call dostyp ; Extended BDOS?
jr z,prhelp1 ; No
cp 'S' ; Yes
jr z,prhelp2 ; Ok if ZSDOS,
cp 'D'
jr z,prhelp2 ; ..or ZDDOS..
jr prhelp3 ; Else forget it
prhelp1:
ld a,(cpmver) ; We have CP/M
cp 30h ; Plus?
jr c,prhelp3 ; No
prhelp2:
call print
db tab,'D - test Datestamps only',tab,tab,0 ; tab to col 49
ld a,(donlyd)
call printd ; Show patched default
call print
db tab,'I - Ignore datestamps',tab,tab,tab,0
ld a,(ignord)
call printd
prhelp3:
call print
db tab,'M - Multiple runs with disk change',tab,0
ld a,(multd)
call printd
call print
db tab,'Q - Quiet',tab,tab,tab,tab,0
ld a,(quietd)
call printd
call print
db tab,'V - Verbose',tab,tab,tab,tab,0
ld a,(verbd)
call printd
call print
db ' Results stored in Program Error Flag and Register 0.'
db 0
jp quitlf
;
; PRINTD - Show default option in help screen.
;
; 0 = (off)
;
printd:
or a
jr z,prind1 ; Off if zero, else on
call print
db '(on)',cr,lf,0
ret
prind1:
call print
db '(off)',cr,lf,0
ret
; ---------------------------------------------------
;
; Check for any question marks from HL+1 to HL+11
; Affect only AF registers if OK
;
qcheck:
push hl ; SAVE HL
push bc ; SAVE BC
inc hl ; PT TO FIRST CHAR
ld b,11 ; 11 BYTES
ld c,'?' ; SCAN FOR '?'
qc:
ld a,(hl) ; GET BYTE
cp c ; '?'?
jr z,qc1
inc hl ; PT TO NEXT
dec b ; COUNT DOWN
jr nz,qc
pop bc ; RESTORE
pop hl
ret
qc1:
pop bc ; RESTORE AND ABORT
pop hl
pop de ; DROP RETURN ADDRESS
; fall thru
ld a,ecambig ; Ambiguous file spec. error
;
; Chain to Z33 error handler.
; Set error, ECP, and external program bits of command status flag
; to tell CCP there is an error, to go straight to the error handler
; (not the ECP), and not to alter the command error byte at z3msg+0:
;
z33err:
call retcst ; Z33LIB return command status byte
ld (hl),00001110b
call puter3 ; Z33LIB set command error byte
jp quit ; Return to CCP with bits set
; -------------------------------------------------
;
; Print banner
;
banner:
call qtest
ret nz ; Don't print if quiet
banner1:
call print
db cr,lf
db 'DIFF, Version ',vers/10+'0','.',(vers mod 10)+'0'
db ' - Compare files (loaded at ',0
ld hl,(loadadr)
call phl4hc
call print
db 'h)'
db 0
ret
; ----------------------------------------------------
;
; Print names of source files
; PRS1 -- source file 1
; PRS2 -- source file 2
;
prs1:
call qtest
ret nz
prs1a:
call print
db cr,lf,' Source 1: ',0
ld hl,sdisk ; PT TO FIRST BYTE
call prud
ld de,fcb1 ; SOURCE FCB
jp prfna ; PRINT FILE NAME
prs2:
call qtest
ret nz
prs2a:
call print
db cr,lf,' Source 2: ',0
ld hl,ddisk ; PT TO FIRST BYTE
call prud
ld de,fcbd ; DESTINATION FCB
jp prfna ; PRINT FILE NAME
; ---------------------------------------------
;
; MAIN VERIFY ROUTINE
;
verify:
ld a,(quiet)
ld b,a
ld a,(verb)
or b ; Quiet or verbose mode?
call z,prdot ; No, show progress with '.'
;
ld hl,buff1 ; Point for load
push hl ; SAVE PTR
call logs ; LOG IN SOURCE 1
ld de,fcb1 ; SOURCE 1 FCB
call load ; READ IN BLOCK
ld a,(bcnt) ; GET OLD BLOCK COUNT
ld (bcnt1),a ; SAVE IT - bcnt1 stores blocks for fcb1
ld hl,buff2 ; Point for load
push hl ; SAVE PTR
call logd ; LOG IN SOURCE 2
ld de,fcbd ; SOURCE 2 FCB
call load ; READ IN BLOCK
pop de ; DE PTS TO BUFF 2
pop hl ; HL PTS TO BUFF 1
ld a,(bcnt) ; CHECK FOR NO BLOCK READ - bcnt = fcbd blks
ld b,a
ld a,(bcnt1)
or b
ret z ; DONE IF NONE READ
;
; Verify loaded buffers by comparing them and printing differences
;
verblock:
call condin ; Get input, if any
cp ctrlc ; Abort?
jp z,dabort
ld b,128 ; SCAN ONE BLOCK
verbl:
ld a,(de) ; GET BYTE
cp (hl) ; COMPARE
call nz,nomatch ; PRINT DIFFERENCE or quit
inc ix ; Inc offset <crw>
inc hl ; PT TO NEXT
inc de
djnz verbl ; Count down bytes
;
ld a,(bcnt) ; COUNT DOWN blocks
dec a
ld (bcnt),a
ld a,(bcnt1)
dec a
ld (bcnt1),a
jr z,vereq
ld a,(bcnt) ; CHECK FIRST BUFFER COUNT
or a
jr nz,verblock ; CONTINUE COMPARE IF NOT EMPTY
vereq:
ld a,(bcnt) ; CHECK FOR BOTH DONE
ld b,a
ld a,(bcnt1)
or b ; IF ZERO, BOTH DONE AT SAME TIME AND CONTINUE
jp z,verify
ld a,(bcnt1) ; CHECK FOR ONE DONE BEFORE THE OTHER
or a ; 2ND DONE?
ld c,'1' ; GET LETTER
jr z,done1
ld c,'2' ; GET LETTER
; One file is shorter than the other -- say so and quit or return
done1:
call qtest
jp nz,quit ; Don't print if quiet
call print
db cr,lf,' Source ',0
ld a,c
call cout ; PRINT LETTER
call print
db ' has terminated prematurely',0
cabort: ; Abort this compare
ld a,0ffh
ld (first),a ; Flag shows files were different
call print
db cr,lf,' Files are different',0
ret ; Back for next or quit
;
; Match error
;
nomatch:
call qtest
jp nz,quit ; Don't print if quiet
;
ld a,(verb) ; Get verbose flag
or a ; Z=simple compare
jr nz,nmat0
pop hl ; Drop return address (VERIFY)
jr cabort ; Abort or back for next
nmat0:
push hl ; SAVE REGS
push de
push bc
ld a,(first) ; FIRST TIME THRU?
or a ; 0=YES
jp z,nmat3
ld a,(lcnt) ; CHECK FOR NEW SCREEN
or a ; ZERO IF DONE
jp nz,nmat4
call print
db cr,lf,' DIFF: Strike RETURN to Continue, ^C to Abort',0
ld a,(mult) ; In multiple run?
or a
jr z,nmat1 ; No
call print
db ', or ^X to Advance',0
nmat1: call print
db ' - ',0
call cin ; GET RESPONSE
cp ctrlc ; ABORT?
jr z,nmat2
cp ctrlx ; ADVANCE?
jp nz,nmat3 ; No
ld a,(mult) ; Yes, see if multiple run
or a
jp z,nmat3 ; No, ignore ^x
pop bc ; Yes, advance. CLEAR REGS
pop de
pop hl
pop de ; CLEAR STACK
call print
db cr,lf,' DIFF Advancing',0
ret ; RETURN TO VERIFY CALLER
nmat2:
pop bc ; CLEAR REGS
pop de
pop hl
dabort: pop de ; Clear stack
dabort1:call print
db cr,lf,' DIFF Aborting',0
quitlf: ld a,cr ; Quit with CRLF
call qcout
ld a,lf
call qcout
quit: ld sp,(stksav)
ret ; RETURN TO OPSYS
nmat3:
ld a,0ffh ; CLEAR FIRST TIME FLAG
ld (first),a
call header ; PRINT HEADING AND RETURN NEW LINE COUNT
nmat4:
dec a ; COUNT DOWN 1 LINE
ld (lcnt),a ; NEW LINE COUNT
call crlf
push hl ; SAVE HL
push ix ; Get offset to HL
pop hl
call phl4hc ; PRINT AS HEX
call spacer ; PRINT SPACES
call phldc ; PRINT AS DEC
pop hl ; RESTORE HL
call spacer
call spacer
ld a,' '
call cout
ld a,(hl) ; GET SOURCE 1 VALUE
call prval ; PRINT AS HEX, DEC, ASCII
call spacer ; 10 SPACES
call spacer
call spacer
call spacer
call spacer
ld a,(de) ; GET SOURCE 2 VALUE
call prval ; PRINT AS HEX, DEC, ASCII
pop bc ; RESTORE REGS
pop de
pop hl
ret
; ----------------------------------------------
; Print header and return new line count in A
header:
push de ; SAVE REGS
push hl
call print
db cr,lf,' Rel Offset ',0
ld hl,sdisk ; PRINT DISK/USER
call prud
ld de,fcb1
call prfn ; PRINT FILE NAME
call spacer ; 5 SPACES
call spacer
ld hl,ddisk ; PRINT DISK/USER
call prud
ld de,fcbd
call prfn ; PRINT FILE NAME
call print
db cr,lf,' Hex Dec Hex Dec Asc Hex Dec Asc',0
ld a,(lset) ; SET LINE COUNT
sub 1 ; ADJUST FOR HEADING AND FOOTER
ld (lcnt),a
pop hl
pop de ; RESTORE REGS
ret
; ------------------------------------
; Print A as hex, dec, and ASCII
prval:
call spacer ; 3 SPACES
call space1
call pa2hc ; PRINT AS HEX
call spacer
call padc ; PRINT AS DEC
call spacer
and 7fh ; MASK OUT MSB
cp 7fh ; DOT FOR <DEL>
jr z,prdot
cp ' ' ; PRINT DOT IF LESS THAN <SP>
jp nc,cout
prdot:
ld a,'.' ; PRINT DOT
jp cout
; -----------------------------
; Print 2 spaces
spacer:
call space1
space1:
push af
ld a,' '
call qcout
pop af
ret
; --------------------------------------------------------
;
; Load buffer at HL from file whose FCB is pted to by DE
; On output, bcnt=number of blocks loaded (up to blimit)
;
load:
xor a ; A=0
ld (bcnt),a ; SET BLOCK COUNT
; Main load loop
load1:
call setdma ; To (hl)
call f$read ; READ A BLOCK
or a ; END OF FILE?
ret nz ; RETURN IF DONE
ld bc,128
add hl,bc ; Point to next block
ld a,(bcnt) ; GET BLOCK COUNT
inc a ; INCREMENT IT
ld (bcnt),a ; SET IT
cp blimit ; LAST BLOCK READ?
jr nz,load1
ret
; ----------------------------------------------------------
;
; Log in source (logs) and destination (logd) drives/users
;
logs:
ld a,(sdisk) ; GET DISK
dec a ; A=0
ld b,a
ld a,(suser) ; GET USER
ld c,a
call logud ; LOG IN
ret
logd:
ld a,(ddisk) ; GET DISK
dec a ; A=0
ld b,a
ld a,(duser) ; GET USER
ld c,a
call logud ; LOG IN
ret
; -----------------------------------------------
;
; Print disk/user pted to by HL (2 bytes)
;
prud:
ld a,(hl) ; GET DISK
add a,'A'-1 ; CONVERT TO LETTER
call cout
inc hl ; PT TO USER
ld a,(hl) ; GET USER
call padc ; PRINT AS DEC
call print
db ': ',0
ret
; ----------------------------------------------
;
; Print file name whose fcb is pted to by DE
;
prfn:
call qtest
ret nz ; Don't print if quiet
prfna:
push hl ; SAVE REGS
push de
push bc
ex de,hl ; FN PTED TO BY HL
inc hl ; PT TO FIRST CHAR
ld b,8 ; 8 CHARS
call prfn1
ld a,'.'
call cout
ld b,3 ; 3 CHARS FOR FILE TYPE
call prfn1
call space1
pop bc ; RESTORE REGS
pop de
pop hl
ret
prfn1:
ld a,(hl) ; GET CHAR
inc hl ; PT TO NEXT
call cout ; PRINT
dec b ; COUNT DOWN
jr nz,prfn1
ret
; ----------------------------------------------------
; Special Quiet Output Routines for /Q option
;
; QTEST - Test quiet flag
;
; Exit: (NZ) if quiet active
; Uses: - <F>
qtest:
push bc
ld b,a
ld a,(quiet)
or a ; Set Z flag
ld a,b
pop bc
ret
;
; QCOUT - Print char. in A unless quiet option active
; Uses: <F>
;
qcout:
call qtest
ret nz ; Quit if quiet
jp cout ; Print char & return
;
; QPRDAT2 - Print date at HL, or just test if quiet option
;
; Exit: (Z) and A=0 if month ok.
; (NZ) and A=0FFh if not ok.
; Date printed if not quiet.
; Uses: - <AF>
qprdat2:
call qtest
jp z,prdat2 ; Print & return if not quiet
push hl
inc hl ; Test month
ld a,(hl)
or a
jr z,errexit
cp 13h
jr nc,errexit
xor a ; No error return
jr exit
errexit:
or 0ffh ; Error return
exit:
pop hl
ret
; =================================================
;
; DATA AREAS
;
; Initialized data
;
cstring:
db ' - created ',0
mstring:
db ' - last modified ',0
dmatstr:
db ' File dates match ',0
twostr:
db ' Source 2 is more recent ',0
onestr:
db ' Source 1 is more recent ',0
; ------------------------------------------------
;
; Uninitialized RAM
;
DSEG
; The next five data items must be contiguous and in the same
; order as the patchable default options at label DONLYD.
donly: ds 1 ; Test datstamps only (0=test data also)
ignor: ds 1 ; Ignore dates flag (0=use dates)
mult: ds 1 ; Multiple run flag (0=no mult runs)
quiet: ds 1 ; Quiet mode (0=not quiet)
verb: ds 1 ; Verbose flag (0=simple compare)
names: ds 1 ; 0=names match
smodok: ds 1 ; Source modify year flag
dmodok: ds 1 ; Dest.
offset: ds 2 ; RELATIVE OFFSET
first: ds 1 ; ERROR INDIC
lset: ds 1 ; NUMBER OF TEXT LINES ON SCREEN
lcnt: ds 1 ; LINE COUNT
sdisk: ds 1 ; SOURCE DISK (MUST BE FOLLOWED BY SUSER)
suser: ds 1 ; SOURCE USER
ddisk: ds 1 ; DEST DISK (MUST BE FOLLOWED BY DUSER)
duser: ds 1 ; DEST USER
fcbd: ds 36 ; DESTINATION FCB
bcnt: ds 1 ; BUFFER COUNT
bcnt1: ds 1 ; SECOND BUFFER COUNT
sdatbuf: ; Buffer for 1st file's stamp <crw>
ds 10 ; Create, access stamps
smodbuf:ds 5 ; Modify stamp
ds 113 ; For future ZSDOS compat.
ddatbuf:
ds 10 ; Create, access stamps
dmodbuf:ds 5 ; Modify stamp
ds 113
stksav: ds 2 ; Entry stack
ds 60 ; Local stack
ourstk:
buff1:
ds bsize+1 ; File compare buffers
buff2:
ds bsize+1
end
; END DIFF.Z80