;********************************************************
;*                                                      *
;*              BINARY FILE COMPARE UTILITY             *
;*                                                      *
;********************************************************
;
;
;       Portions Copyright (C) 1980
;
;       Bill Bolton,
;       Software Tools,
;       P.O. Box 80,
;       Newport Beach,,
;       NSW, 2106
;       AUSTRALIA
;
;       History:
;
;       1/Oct/77         Version 1.00 by Ward Christensen
;
;       31/Jan/80        Version 1.10 by Bill Bolton, improved
;                        error messages and optional file display
;
;       6/Sept/80        Version 1.20 by Bill Bolton, copy second
;                        filename from first, if second blank
;
;
       MACLIB  MACRO3          ;OFTWARE TOOLS SPECIAL MACROS
;
       ORG     100H
;
       CALL    START   ;PRINT ID MESSAGE
;
       DB      0DH,0AH,'Binary File Compare '
       DB      'Utility : Version 1.20'
       DB      0DH,0AH
       DB      'DDH Compatible Display by Bill Bolton'
       DB      0DH,0AH
       DB      'Software Tools, Australia'
       DB      0DH,0AH,'$'
;
START:
       POP     D
       CALL    PRINT$MESSAGE
       LXI     H,0
       DAD     SP      ;HL=CP/M'S STACK
       SHLD    STACK   ;SAVE IT
       LXI     SP,STACK ;SET UP NEW STACK
;
       LDA     FCB+17  ;POINT TO FILENAME IN SECOND FCB
       CPI     ' '     ;EMPTY?
       JNZ     SAVE$NAME ;NO, JUST MOVE IT
       LXI     D,FCB+1 ;YES, POINT TO FILENAME IN FIRST FCB
       LXI     H,FCB+17 ;POINT TO FILENAME IN SECOND FCB
       MVI     B,11    ;LENGTH OF FILE NAME
       CALL    MOVEIT  ;MOVE FILENAME
;
;MOVE THE SECOND FCB SO OPENING THE FIRST
;WON'T WIPE IT OUT
;
SAVE$NAME:
       CALL    MOVE$FCB
;
;PRINT OPENING MESSAGE
;
       LXI     D,FIRST
       CALL    PRINT$MESSAGE
       CALL    CONSOLE
       CPI     'Y'
       JNZ     BLANK
       MVI     A,0FFH
       STA     PRFLAG
BLANK:
       LXI     D,NEWLINE
       CALL    PRINT$MESSAGE
;
;OPEN BOTH FILES, EXITING IF EITHER DOESN'T EXIST
;
       CALL    OPEN$FILES
;
;READ EACH FILE 1 BYTE AT A TIME, COMPARING THEM
;
COMPARE:
       CALL    READ1
       MOV     B,A     ;SAVE CHAR READ
       CALL    READ2
       CMP     B       ;SAME?
       JZ      COMPARE
;
;UNEQUAL COMPARE
;
       LXI     D,UNEQ$MSG
       CALL    PRINT$MESSAGE
       LHLD    SECTOR$COUNT
       DECOUT
       LXI     D,SPACEIT
       CALL    PRINT$MESSAGE
       LXI     D,BYTE$MSG
       CALL    PRINT$MESSAGE
       LDA     BUFAD1  ;GET FIRST BUFF ADDR
       SUI     81H     ;SUBTRACT BIAS
       CALL    XO      ;PRINT IN HEX
       LXI     D,SPACEIT
       CALL    PRINT$MESSAGE
       CALL    CONSTAT
       ORA     A
       JZ      COMPARE
       CALL    CONSOLE
       CPI     3               ;IS ^C?
       JZ      EXIT
       CPI     20H             ;IS IT SPACE?
       JNZ     COMPARE
EXIT:
       LHLD    STACK   ;GET CP/M'S STACK
       SPHL            ;RESTORE IT
       RET             ;..AND RETURN
;
ERXIT:
       POP     D       ;GET MESSAGE
       CALL    PRINT$MESSAGE
       JMP     EXIT
;
UNEQ$MSG:
       DB      0DH,0AH,'++ FILES UNEQUAL IN SECTOR    $'
;
BYTE$MSG:
       DB      'AT BYTE    $'
;
SPACEIT:
       DB      '    $'
;
NEWLINE:
       DB      0DH,0AH,'$'
;
FIRST:  DB      0DH,0AH,'Do you want file 1 printed '
       DB      'as it is compared ?'
       DB      '....[Y/N] (CR="N")   ' ,'$'
;
; * * * * * * * * * * * * * * * * * * * * * * * *
;                                               *
;               SUBROUTINES                     *
;                                               *
; * * * * * * * * * * * * * * * * * * * * * * * *
;
PRINT$MESSAGE:
       MVI     C,STRING
       JMP     BDOS    ;PRINT, RETURN
;
PRINT$HEX$HL:
       MOV     A,H
       CALL    XO
       MOV     A,L
       CALL    XO
       MVI     A,' '
;FALL INTO 'TYPE'
;
TYPE:
       PUSH    B
       PUSH    D
       PUSH    H
       MOV     E,A     ;AS REQ'D BY CP/M
       MVI     C,WRCON
       CALL    BDOS
       POP     H
       POP     D
       POP     B
       RET
;
XO:
       PUSH    PSW     ;HEX OUT
       RAR
       RAR
       RAR
       RAR
       CALL    NIBBL   ;LEFT NIBBL
       POP     PSW
NIBBL:
       ANI     0FH
       CPI     10
       JC      ISNUM
       ADI     7
ISNUM:
       ADI     '0'
       JMP     TYPE
;
OPEN$FILES:
       LXI     D,FCB
       MVI     C,OPEN
       CALL    BDOS
       INR     A       ;OPEN OK?
       JNZ     FILE$1$OPEN
       CALL    ERXIT
       DB      0DH,0AH,'***** CANT OPEN FILE 1 ***** ',0DH,0AH,'$'
FILE$1$OPEN:
       LXI     D,FCB2
       MVI     C,OPEN
       CALL    BDOS
       INR     A
       RNZ
       CALL    ERXIT
       DB      0DH,0AH,'***** CANT OPEN FILE 2 *****',0DH,0AH,'$'
;
READ1:
       LHLD    BUFAD1  ;TIME TO READ?
       DCR     H       ;AT 100H?
       JNZ     NO$READ$1
;
;PHYSICALLY READ FILE 1
;
       LXI     H,80H   ;BUFFER ADDR
       SHLD    BUFAD1
       XCHG            ;TO D,E
       MVI     C,STDMA
       CALL    BDOS
       LXI     D,FCB
       MVI     C,READ
       CALL    BDOS
       ORA     A       ;OK?
       JNZ     EOF$FILE$1
       LHLD    SECTOR$COUNT
       INX     H
       SHLD    SECTOR$COUNT
NO$READ$1:
       LHLD    BUFAD1
       MOV     A,M     ;GET CHAR
       INX     H       ;POINT TO NEXT
       SHLD    BUFAD1
;
;REQUEST TO PRINT?
;
       MOV     L,A     ;SAVE CHAR
       LDA     PRFLAG  ;SET IF FILE 1 TO BE PRINTED ON CONSOLE
       CPI     0       ;PRINT?
       MOV     A,L     ;RESTORE CHAR FOR RET
       RZ              ;RET IF NO PRINT REQ
;
;SHOW THE CHARACTER
;
       CPI     0DH     ;C/R?
       JZ      SHOWIT
       CPI     0AH     ;L/F?
       JZ      SHOWIT
       CPI     9       ;TAB?
       JZ      SHOWIT
       CPI     ' '     ;PRINTABLE?
       JC      SHOWHEX ;HEX IF NOT PRINTABLE
       CPI     7FH
       JC      SHOWIT
;SHOW IN HEX
SHOWHEX:
       MVI     A,'('
       CALL    TYPE
       MOV     A,L     ;GET CHAR
       MVI     A,')'
SHOWA:
       CALL    TYPE
       MOV     A,L     ;GET CHAR
       RET
SHOWIT:
       MOV     A,L     ;GET CHAR
       JMP     SHOWA
       RET
;
;GOT EOF ON FILE 1 - SHOULD GET EOF ON FILE 2
;
EOF$FILE$1:
       MVI     A,1     ;GET FLAG
       STA     EOF$FLAG
       CALL    READ2   ;SHOULD NOT RETURN
       CALL    ERXIT
       DB      0DH,0AH,0AH,'***** EOF ON FILE 1, NOT FILE 2 *****$'
;
READ2:
       LHLD    BUFAD2  ;GET SECOND BUFF
       MOV     A,L     ;GET ADDR
       CPI     (BUF2+128) AND 0FFH ;END?
       JNZ     NO$READ$2
;
;DO PHYSICAL READ ON FILE 2
;
       LXI     H,BUF2
       SHLD    BUFAD2
       XCHG            ;TO DE
       MVI     C,STDMA
       PUSH    B       ;SAVE CHAR FROM FILE 1
       CALL    BDOS
       LXI     D,FCB2
       MVI     C,READ
       CALL    BDOS
       POP     B
       ORA     A
       JNZ     EOF$FILE$2
NO$READ$2:
       LHLD    BUFAD2
       MOV     A,M     ;GET CHAR
       INX     H       ;POINT TO NEXT
       SHLD    BUFAD2  ;SAVE BACK
       RET
;
EOF$FILE$2:
;SHOULD HAVE EOF ON 1, THUS EOF$FLAG SHOULD BE ON
       LDA     EOF$FLAG
       ORA     A       ;ON?
       JNZ     A$OK
       CALL    ERXIT
       DB      0DH,0AH,0AH,'***** EOF ON FILE 2 BEFORE FILE 1 *****$'
A$OK:
       LXI     D,MATCH$MSG
       CALL    PRINT$MESSAGE
       LHLD    SECTOR$COUNT
       DECOUT
       CALL    ERXIT
       DB      ' SECTORS .....',0DH,0AH,0AH,'$'
MATCH$MSG:
       DB      0DH,0AH,0AH,'..... FILES MATCH, LENGTH IS $'
;
MOVE$FCB:
       LXI     H,FCB2
       LXI     D,FCB+16
       MVI     B,16    ;FCB LENGTH
MOVEIT:
       LDAX    D
       MOV     M,A
       INX     D
       INX     H
       DCR     B
       JNZ     MOVEIT
       RET
;
CONSTAT:
       MVI     C,11
       CALL    BDOS
       RET
;
CONSOLE:
       MVI     C,1
       CALL    BDOS
       RET
;
       DS      40      ;STACK AREA
STACK:  DS      2
SECTOR$COUNT:
       DW      0
EOF$FLAG:
       DB      0       ;=1 IF EOF FILE 1
FCB2:   DB      0,'XXXXXXXXYYY',0,0,0
       DB      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
PRFLAG: DB      0
BUFAD1: DW      80H+128 ;INIT TO READ FIRST
BUFAD2: DW      BUF2+128 ;LIKEWISE
BUF2:   DS      128
;
; * * * * * * * * * * * * * * * * * * * * * * * *
;                                               *
;BDOS/CBIOS EQUATES (VERSION 5)                 *
;                                               *
RDCON   EQU     1       ;                       *
WRCON   EQU     2       ;                       *
STRING  EQU     9       ;                       *
OPEN    EQU     15      ;0FFH=NOT FOUND         *
CLOSE   EQU     16      ;   "   "               *
SRCHF   EQU     17      ;   "   "               *
SRCHN   EQU     18      ;   "   "               *
ERASE   EQU     19      ;NO RET CODE            *
DELT    EQU     ERASE   ;                       *
READ    EQU     20      ;0=OK, 1=EOF            *
WRITE   EQU     21      ;0=OK, 1=ERR, 2=?,      *
;                       0FFH=NO DIR SPC         *
MAKE    EQU     22      ;0FFH=BAD               *
REN     EQU     23      ;0FFH=BAD               *
STDMA   EQU     26      ;                       *
BDOS    EQU     5       ;                       *
FCB     EQU     5CH     ;                       *
; * * * * * * * * * * * * * * * * * * * * * * * *