; ; 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 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 jr z,prdot cp ' ' ; PRINT DOT IF LESS THAN 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: - 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: ; 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: - 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 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