; Program: BCOMP ; Purpose: Screen oriented binary file comparison ; Author: Rob Friefeld ; Version: 1.1c ; Date: 30 Mar 1988 ;* ; Assemble with SLR assembler and linker. ; Link DSEG to 1800H, i.e SLRNK /D:1800,BCOMP11,BCOMP/N/E ;* ;----------------------------------------------------------------------------- ; ATTRIBUTION: ; The backbone of BCOMP is composed of routines lifted and modified from MU3 by ; Richard Conn. ; BCOMP also routines copyright 1987 by Steven M. Cohen from ZPATCH. ; These have been slightly modified. (See EDNIB.LIB & OFFSET.LIB) ;----------------------------------------------------------------------------- vers equ 11 ; Version number tstrev equ 'c' ; Debug version true equ -1 Y equ true false equ 0 N equ false .accept "Help Screen (Y/N)?",helpon ; Include help screen if helpon .printx Link Command: SLRNK /D:1800,BCOMP11,BCOMP/N/E else .printx Link Command: SLRNK /D:1500,BCOMP11,BCOMP/N/E endif ;helpon ;ASCII DISPLAY OPTION ; The ascii field can mask the high bit before display, which makes many more ; bytes printable. (Done by PEEK and most others.) To see only ascii ; in the ascii field, set the following equate TRUE. asciich equ false ; ASCII field shows Chars only ; ;LIBRARY ROUTINES ; .request vlib,z3lib,syslib ; VLIB ext z3vinit,tinit,dinit,stndout,stndend,gotoxy,cls,ereol ; Z3LIB ext getvid,getcrt,getefcb if helpon ext getquiet endif ;helpon ; ;PROGRAM EQUATES ; eolch equ 0 ; End of line char sepch equ ',' ; Separator char fcol equ 4 ; First col of file display fcolc equ fcol+16*3+8 ; First col of file char display offcol equ 24 ; Offset display col reccol equ 49 ; Record number display hexcol equ 11 ; First col of hex display frow1 equ 4 ; File1 display row prrow1 equ 12 ; Prompt row homrow1 equ 1 ; Home cursor row frow2 equ 16 ; File2 display row prrow2 equ 24 ; Prompt homrow2 equ 13 ; Cursor echor equ 1 ; Echo display row echoc equ 70 ; " col fstring equ 20 ; Max length of find string ; ;STANDARD SYSTEM EQUATES ; include sysdef.lib ; ;FLAG TESTING MACRO ; echo? macro ld a,(eflag) or a endm ; ;START OF CODE ; ; jp start ; Supplied by linker db 'Z3ENV' ; Z-tool header db 1 z3eadr: dw 0fe00h ; Installed by z3ins ; ; ALTVID: In active window, differing bytes are highlighted ; The feature is nice if files are very similar. ; 'V'ideo command changes this on-the-fly. altvid: db false ; True = use it ; ; BEGINNING OF PROGRAM ; start: ld (stksav),sp ; Set up local stack ld sp,stack ; ; ENV INITIALIZATION ; ld hl,(z3eadr) ; Initialize vlib routines call z3vinit call getvid jp z,novid ; Exit with message if no tcap support call getcrt ld a,(hl) cp 80 jp c,novid inc hl ld a,(hl) cp 24 jp c,novid call tinit ; ; INIT POINTER TABLES ; ld b,stksav-bufptr ; Size of table area ld hl,bufptr call zfill ; Zero the whole thing ld hl,frw1 ; Load cursor location info for each window ld (hl),frow1 inc hl ld (hl),prrow1 inc hl ld (hl),homrow1 ld hl,frw2 ld (hl),frow2 inc hl ld (hl),prrow2 inc hl ld (hl),homrow2 ; ; SET UP BUFFER SPACES ; Divide remaining TPA in half and set up pointers for each file ; setbuf: call topram ; Get top page of free ram in a ld (top2),a ; Top of file2 ld hl,stack ; End of code inc h ; Assure page boundary ld l,0 ld (fil1),hl ; First buffer at end of code ld (blk1),hl ; Also, init display to start sub h ; Buffer space = top2-top code page srl a ; Halve it push af ; Carry -> A was odd add h ; Top of file1 buffer ld (top1),a ; Save ld h,a pop af jr nc,sbuf1 inc h ; Round up to balance buffer spaces sbuf1: ld (fil2),hl ; Start of file2 buff ld (blk2),hl ; And init location for file2 ; ; SET UP FCB's ; call filspecs ; Which files were specified? ; ; SAVE FCB's ; ; ld hl,fcb ; File1 ; ld de,fcb1buf ; ld bc,10h ; ldir ld a,(fcb+13) ; Save user # ld (usr1),a ld hl,fcb2 ; File2 ld de,fcb2buf ld bc,10h ldir ld a,(fcb2+13) ld (usr2),a ; ; LOAD FIRST FILE POINTERS TO ACTIVE TABLE ; ld hl,blk1 ld de,block call movptr ; ; READ IN FILES ; call rfile ; Load file1 call sw0 ; Switch to file2 call rfile ; Load it call sw0 ; Back to file1 ; ; DISPLAY INITIAL SCREEN ; scrn1: call cls call pheader ; Print header info call prnscr ; Print the first screen of file 1 call sw0 ; Same for file2 call pheader call prnscr call sw0 ; Back to file1 call shadow ; Only differing bytes shown call echo1 ; Display ECHO state ; ; COMMAND INPUT ROUTINE ; command: call clrpr ; Clear prompt line call getc ; Get command clist: call case ; Scan following command list include defctl.lib ; Default command list (mine) ; ; CODE TO EXECUTE THE COMMANDS - ; ; ; TOGGLE ECHO STATE ; echo: ld a,(eflag) ; Toggle echo flag cpl ld (eflag),a call echo1 ; Display state echox: jp command echo1: ld h,echor ; Go to right upper corner ld l,echoc call gotoxy echo? jr nz,echo11 call vprint db 1,'ECHO',2,0 ret echo11: call vprint db ' ',0 ret ; ; PRINT ONE SCREEN OF SELECTED FILE ; prnscr: call adrplot ; Address skeleton and record number call hexplot1 ; Set up for hexplot call hexplota ; Show all bytes jp asciiplot ; Show ascii ; ; BOTH SCREENS UPDATE ; ; (Enter while still in alternate file) dblnew: call adrplot ; Show addresses for alt screen call asciiplot ; Show ascii call sw0 ; Back to current screen ; ; CURRENT SCREEN UPDATE ; newscr: call prnscr ; Show current file call shadow ; Show only bytes different in other file jp command ; ; NEXT SCREEN ; next: echo? ld a,8 ; Advance 8 lines next0: jr z,nextN call plus ; Move pointers nextx: jr newscr ; Replot ; ; FORWARD A LINE ; nxtline: echo? ld a,1 jr next0 ; ; NEXT SCREEN, BOTH FILES ; dblnext: ld a,8 ; ; NEXT N LINES, BOTH FILES ; nextN: push af ; Save # lines call plus ; Move block pointer call sw0 ; Also for other file pop af call plus jr dblnew ; Update display ; ; PREVIOUS SCREEN ; prev: echo? ld a,8 prev0: jr z,prevN call minus prevx: jr newscr ; ; PREVIOUS LINE ; prevline: echo? ld a,1 jr prev0 ; ; PREVIOUS N LINES, BOTH FILES ; prevN: push af call minus call sw0 pop af call minus jr dblnew ; ; FIRST SCREEN ; top: ld hl,(filloc) ld (block),hl echo? jr z,top01 topx: jp newscr top01: call sw0 ld hl,(filloc) ld (block),hl jp dblnew ; ; LAST SCREEN ; last: ld hl,(eofptr) ld (block),hl echo? jr z,last0 lastx: jp newscr last0: call sw0 ld hl,(eofptr) ld (block),hl jp dblnew ; ; FORWARD 1 BYTE ; overbyte: call overb1 echo? jr z,overb0 overbx: jp newscr overb0: call sw0 call overb1 jp dblnew overb1: ld hl,(block) inc hl jp plus02 ; Boundary check ; ; BACK 1 BYTE ; backbyte: call backb1 echo? jr z,backb0 backbx: jp newscr backb0: call sw0 call backb1 jp dblnew backb1: ld hl,(block) dec hl jp minus02 ; Boundary check ; ; PLUS: Move forward # lines in A ; Return with BLOCK loaded with new address ; plus: or a ret z ld hl,0 ld de,16 ld b,a plus01: add hl,de djnz plus01 ld de,(block) add hl,de plus02: ld (block),hl ld de,(eofptr) ; Make sure eof not overrun xor a sbc hl,de ret c ; OK ld (block),de ret ; ; MINUS: Move back # lines in A ; Return with BLOCK loaded ; minus: or a ret z ld hl,0 ld de,-16 ld b,a minus01: add hl,de djnz minus01 ld de,(block) add hl,de minus02: ld (block),hl ld de,(filloc) ; Make sure start not overrun xor a sbc hl,de ret nc ld (block),de ret ; ; SET NEW RELATIVE ADDRESS ; newadr: call vprint dc 1,'Hex Address (#nn dec)>',2,' ' call rdbuf call sksp jp z,command call hexin jr nz,numerr ; Error condition ex de,hl ; User address to hl ld de,(offset) xor a sbc hl,de ; Subtract offset call bounds ; Check upper and lower bounds jp newscr bounds: ld (block),hl ; Real address updated ld de,(eofptr) ; Unless we are out of bounds xor a sbc hl,de jr c,bounds02 ; Not past end of file bounds01: ld (block),de ret bounds02: ld hl,(block) ld de,(filloc) xor a sbc hl,de ret nc ; Not before start of file jr bounds01 ; ; HEX ERROR ; numerr: call cr$clr call vprint dc 1,'Num?',2,' ',bell call wait jp command ; ; NEW OFFSET ; newoff: call vprint dc 1,'Offset >',2,' ' call rdbuf call sksp jp z,command call hexin jr nz,numerr ex de,hl call setof02 call prtoff ; Print it call adrplot ; Update address display jp command ; ; GO TO DECIMAL RECORD NUMBER ; gorec: call vprint ; Prompt input db dim,'Dec Record (#nn hex) > ',bright,0 call rdbuf ; Input text call cr$clr ; Clear prompt line call sksp ; Skip to non-space ld a,(hl) ; Any input? or a ; 0=no jp z,command call decin ; Evaluate number jp nz,numerr ex de,hl ; Put it in hl gorec2: ld bc,(filloc) ; Can enter here with record number in HL ld a,h or l jr z,gorec0 ; Go to first record, why quibble? dec hl ; Record 1 is first ld de,(maxrec) ; Add in offset from previous read xor a sbc hl,de jr c,gorec0 push bc call mult128 ; Convert to bytes pop bc add hl,bc ; HL = #bytes from start call bounds ; Boundary check gorec01: jp newscr gorec0: ld (block),bc jr gorec01 ; ; FIND NEXT DIFFERENCE ; auto: call sw0 ld ix,(block) ; Get alt position in ix ld iy,(eofptr) ; Get alt eof in iy call sw0 ld hl,(block) ; Get current pos in hl ld de,(eofptr) ; Get current eof in de push iy pop bc ; Now alt eof in bc auto01: call ovfl ; Make sure we are still in bounds jr nc,auto02 ; Overflow inc hl ; Start looking at next byte inc ix ld a,(hl) cp (ix) jr z,auto01 ; Still the same auto02: ld (block),hl ; Update pointers call sw0 ld (block),ix jp dblnew ; And display ovfl: push hl ; Check bounds xor a sbc hl,de jr nc,ovfl1 push ix pop hl xor a sbc hl,bc ovfl1: pop hl ret c push af call endmsg pop af ret ; ; FIND A SEQUENCE ; Use POKE-style input for hex and/or text ; find: call vprint dc 1,'Find >',2,' ' call rdbuf call poke ; Code for parsing args from POKE refind: call find00 ; Repeat find entry jp z,command ; No luck echo? jp nz,newscr call sw0 call find00 jp dblnew find00: ld bc,(findbuf+1) ; C = char count xor a or c ret z ; Empty ld hl,(eofptr) ; Set up last byte to check ld de,127 add hl,de ex de,hl ld hl,(block) find01: ld ix,findbuf+2 ; First byte to match ld a,(ix) find02: inc hl push hl or a sbc hl,de pop hl jr nc,find06 ; Ovfl cp (hl) jr nz,find02 ; Keep looking find03: ld b,c ; First byte matched dec b ; Dec string count jr z,find05 ; Only one to find, done find04: inc ix ; Check rest of string inc hl ld a,(hl) cp (ix) jr nz,find01 ; Mismatch djnz find04 find05: ld b,c ; Found it, point to start of string dec hl djnz $-1 inc hl call plus02 ; Boundary check or -1 ; Nz return = ok ret find06: call cr$clr ; Bad news call endmsg xor a ; Z return = no go ret ; ; FLIP ALT VID CONTROL BYTE ; avtoggle: ld a,(altvid) cpl ld (altvid),a call prnscr ; Update screen to new state jp command include bcedit.lib ; ; COMPUTE DEFAULT OFFSET (AFTER FILE READ IN) ; Ofsfig is routine adapated from ZPATCH, copyright S. Cohen setoffset: call ofsfig ; Return absolute offset in HL exx ; Check out possible Type 3 environment ld hl,(filloc) ; File in memory inc hl ; Point to Z3ENV inc hl inc hl ld de,type3 ; Type 3 ENV string ld bc,0606h call seven0 ; Byte comparison routine jr nz,setof01 ; Forget it inc hl ; Go to Type 3 load address inc hl ld e,(hl) ; Put it in DE inc hl ld d,(hl) ex de,hl ; Back to HL jr setof02 setof01: exx setof02: ld (uoffset),hl ; User's nominal offset ld bc,(filloc) ; DMA of file xor a sbc hl,bc ld (offset),hl ; Real offset ret ; ; SWITCH TO OTHER FILE ; switch: call sw0 ; Switch pointer tables call hexplot1 ; Reverse display of comparisons call hexplota call shadow jp command ;Switch pointers without affecting display sw0: ld a,(sflag) ; 0 = file1, ff = file2 or a jr nz,sw2 sw1: ld hl,block ; Save current pointer table ld de,blk1 call movptr ld hl,blk2 ; Load other pointer table ld de,block call movptr ld hl,fcb ; Save current fcb ld de,fcb1buf call movfcb1 ld hl,fcb2buf ; Load other fcb call movfcb or 0ffh ; Change flag jr swex sw2: ld hl,block ld de,blk2 call movptr ld hl,blk1 ld de,block call movptr ld hl,fcb ld de,fcb2buf call movfcb1 ld hl,fcb1buf call movfcb xor a swex: ld (sflag),a ret ; ; ROUTINES ADAPTED FROM MU3 BY RICHARD CONN ; ; ; PLOT BUFFER DATA ; adrplot: call precnum ; Print record number ld a,(frow) dec a ld h,a ; Set row ld l,fcol ; Set column call gotoxy ; Position cursor push hl ; Save position call vprint db dim db ' ',0 ld hl,(block) ; Pt to data ld bc,(offset) add hl,bc ; Pt to relative address ld a,l ; Low byte in A ld b,16 ; Print header offsets from block address padr0: push af call pa2hc1 ; Print low nibble only call vprint dc ' ' pop af inc a djnz padr0 call stndend pop hl ; Recover cursor position inc h ; Next row call gotoxy ; Position cursor ex de,hl ; Position in de ld hl,(block) ; Pt to data ld b,8 ; 8 lines ; ; Print Next Line on Screen ; call stndout ; Go dim adr00: push bc ; Save line count push hl ld bc,(offset) add hl,bc call phl4hc ; Print relative address pop hl call vprint dc ':' ex de,hl inc h call gotoxy ex de,hl ld bc,16 add hl,bc pop bc djnz adr00 jp stndend ; ; HEX PLOT ROUTINES ; Initialize cursor and data pointer hexplot1: ld hl,(frow-1) ; Locate cursor ld l,hexcol call gotoxy ex de,hl ; Save cursor pos in DE ld hl,(block) ; Data location ld c,8 ; # rows ret ; ; Display all bytes as hex ; hexplota: ld a,(sflag) ; File? or a jr z,hexa01 ld ix,(blk1) ; IX shadows HL as data pointer in alt file jr hexa02 hexa01: ld ix,(blk2) hexa02: ld b,16 ; # bytes/line hexa03: ld a,(hl) ; Compare two bytes cp (ix) push ix ; !! hexpsw equ $+1 ; In code mod may switch to hexb04 call hexa04 ; Print A as hex call print ; Print space dc ' ' pop ix ; !! inc ix ; Next pair of bytes inc hl djnz hexa03 ; Loop until row done ex de,hl ; Recover cursor position inc h ; Next row push ix ; !! call gotoxy pop ix ; !! ex de,hl ; Cursor back to DE dec c ; Dec row counter jr nz,hexa02 ret ; Done plotting ; Display current window hexa04: jp z,pa2hc ; Bytes the same pdim: push af ; Show it in dim vid if requested ld a,(altvid) cp true call z,stndout pop af call pa2hc jp stndend ; ; Display only different bytes in alt window ; hexplotb: push hl ld hl,hexb04 ; Switch to "b" routine ld (hexpsw),hl pop hl call hexplota push hl ld hl,hexa04 ; Switch back to "a" routine ld (hexpsw),hl pop hl ret hexb04: jp nz,pa2hc ; Bytes different, just print pstars: call vprint ; Bytes the same dc '**' ret ; ; Display ascii field ; asciiplot: ld hl,(frow-1) ; Reset row ld l,fcolc ; Reset col call gotoxy ; Position cursor ex de,hl ; Position in de ld hl,(block) ; Pt to data ld b,8 ; 8 lines aplot02: call bar ; Print bar ld c,16 ; 16 elements aplot03: ld a,(hl) ; Get byte call asciibyte ; Display byte inc hl ; Pt to next dec c ; Count down jr nz,aplot03 call bar ; Print ending bar ex de,hl ; Position again inc h ; Next row call gotoxy ex de,hl djnz aplot02 ret ; ; Output a byte in the ascii field ; asciibyte: if asciich cp 7fh jr nc,eda7f else and 7fh cp 7fh jr z,eda7f endif ;asciich cp ' ' jp nc,conout eda7f: ld a,'.' jp conout ; ; UPDATE ALT DISPLAY ; shadow: call sw0 ; Switch pointers call hexplot1 ; Set up block call hexplotb ; Alt display jp sw0 ; Switch back ; ; POSITION CURSOR TO PROMPT ; prcur: ld hl,(prrow-1) ld l,1 jp gotoxy ; Cursor to prompt line and clear clrpr: call prcur jp ereol ; ; PRINT AN BARISK IN REV VIDEO ; bar: call vprint db dim,'|',bright,0 ret ; ; CALCULATE SUM AND DIFFERENCES ; MU3 Routine ; calc: call vprint ; Prompt input db dim,'Enter Two Hex Numbers - ',bright,0 call rdbuf ; Input text call cr$clr ; Clear prompt line call sksp ; Skip to non-space ld a,(hl) ; Any input? or a ; 0=no jp z,command call hexin ; Evaluate first number call sksp ; Skip to 2nd number push de ; Save first number call hexin ; Evaluate 2nd number pop hl ; Get first number call stndout call phl4hc ; Print first number call vprint dc ' & ' ex de,hl call phl4hc ; Print 2nd number ex de,hl call vprint dc ' Sum = ' push hl add hl,de call numout pop hl call vprint dc ' Diff = ' ld a,l ; Hl=hl-de sub e ld l,a ld a,h sbc a,d ld h,a call numout call vprint dc bright,' ' call getc ; Pause push af call cr$clr pop af cp ' ' jr z,calcx cp cr jp nz,clist calcx: jp command ; ;Output number in HL in Hex and Decimal ; numout: call phl4hc ; Hex call vprint dc ' (' call phlfdc ; Decimal floating ld a,')' ; Close paren jp conout ; ; HEADER ROUTINES ; pheader: ld hl,(homrow-1) ld l,1 call gotoxy call vprint dc 'File: ' call prtfil call prtoff jp prtrec ; ; Print File Name ; prtfil: call stndout ld a,(mflag) ; Memory or real file? or a jr nz,prtf1 call pfil jp stndend prtf1: ld hl,specm call print1 jp stndend ; ; Print Offset ; prtoff: ld hl,(homrow-1) ld l,offcol call gotoxy call vprint dc 'Offset: ' call stndout ld hl,(uoffset) call phl4hc jp stndend ; ; Print Record Number ; prtrec: ld hl,(homrow-1) ld l,reccol call gotoxy call vprint dc 'Record: ' ret precnum: ld hl,(homrow-1) ld l,reccol+9 call gotoxy call stndout ld a,(mflag) ; Memory window? or a jr nz,prec00 call calcrec call phlfdc call vprint dc 2,' ' ret prec00: call vprint db 'MEM',2,0 ret ; ; Calculate record number ; calcrec: ld hl,(block) ; Current pos ld de,(filloc) ; Start of file xor a sbc hl,de call div128 inc hl ; Start with record 1 rather than 0 ld de,(maxrec) add hl,de ret ; ; FILE MANIPULAION ; ; ; CHECK COMMAND LINE SPECS ; filspecs: ld a,(fcb+1) ; Reject blank file spec cp ' ' jp z,nope cp '/' ; Help! jp z,nope call spec ; Parse command line into fcb's ret ;Scan for command line option designator spec: ld hl,tbuf ; Command tail ld c,(hl) ; Char count ld b,0 ld a,' ' ; Find blank inc hl ; First char cpir ; Skip leading blank cpir ; Look for another blank jr nz,spec00 ; Nothing after filename, set up memory window ld a,'/' ; Now look for option trigger cpir jr nz,spec1 ; No options, check 2nd file name spec01: ld a,(fcb2+1) ; Was second file name specified? cp '/' jr z,spec001 ; No, this is an option / cp ' ' ret nz ; Yes, done fils1: ld hl,fcb+1 ; Copy 1st file name ld de,fcb2+1 ld bc,11 ldir ld a,(fcb) ; If 1st d: default, leave 2nd d: alone or a ret z ld e,a ; Save it ld a,(fcb2) or a ret nz ; 2nd du: was specified ld a,e ld (fcb2),a ; If not, copy to 2nd du: ld a,(fcb+13) ld (fcb2+13),a ret spec00: ld hl,fcb1+1 ; Wild card first fcb call spec03 spec001: ld de,fcb2+1 ; Set 2nd fcb to memory ld hl,specm ld bc,11 ldir ld a,(top2) ; Let File1 take up all of buffer space ld (top1),a ld hl,0 ld (fil2),hl ; "File2" location ld (blk2),hl ; ... init location ld (uof2),hl ; ... user offset ld hl,0ff80h ; ... last screen pointer ld (eof2),hl or -1 ld (mfl2),a ; Memory flag ret specm: dc ' ' spec1: call spec01 ; Examine file names ld hl,fcb1+1 ; Wild card both of them call spec03 ld hl,fcb2+1 jr spec03 ;Convert filename @HL to wild card spec03: ld b,11 ld a,' ' spec031: cp (hl) jr nz,spec032 ld (hl),'?' spec032: inc hl djnz spec031 ret ; ; SET USER FROM USR ; setusr: ld a,(usr) ld e,a ld c,32 ; Select the new user code jp bdos ; ; READ FILE AT FCB UNTIL BUFFER FULL ; getfil: ld de,fcb ; Open the file ld c,openf call bdos inc a jp z,nofile ; Open fails xor a ld (eoflag),a ; 0 = eof not encountered. ld hl,(filloc) ; Place to put text getlp1: ld (filptr),hl ; Read text 128 byte record at a time ld a,(topmem) ; Have we reached top page of buffer? cp h jr z,toobig ; If yes, quit and mark end of text ex de,hl ld c,setdmaf ; File read into current position call bdos ld de,fcb ld c,readf call bdos or a ; Check for end of file encountered jr nz,geteof ; Yes ld hl,(filptr) ; Move pointer along one record worth ld de,128 add hl,de jr getlp1 geteof: ld (eoflag),a ; Note eof reached getf1: ld hl,(filptr) ; ; Set pointers to last screen file read ; seteof: ld de,-128 add hl,de ld (eofptr),hl ; Now set pointer ld a,(rflag) ; Previous read? or a call nz,increc ; Yes, add in offset ld hl,rflag inc (hl) ; Indicate file read one more time ret toobig: call pfil call print dc ' - Mem Full ',bell call wait call cr$clr jr getf1 increc: call bufsize call div128 ld de,(maxrec) add hl,de ld (maxrec),hl ret ; ; READ MORE FILE ; read: ld a,(eoflag) ; Has all of file been read? or a jr nz,reread ; Yes read1: call rfile ; Read in some more jp scrn1 ; Refresh entire display reread: call prcur call ereol call print dc 1,'EOF - Restart? (y/N)',2,' ' call getc cp 'Y' jp nz,command ; Start over not wanted call zbuf ; Reset fcb xor a ld (rflag),a ; Reset read flag jr read1 rfile: ld a,(mflag) or a ret nz ; This is memory call setusr ; Set user ld hl,(filloc) ; Reset pointers ld (filptr),hl ld (block),hl ld a,(rflag) ; Are we restarting? or a jr nz,rfile01 ; No, have to figure some offsets rfile00: ld hl,0 ld (maxrec),hl call getfil ; Restart jp setoffset ; And load default offset ; Preserve continuity of user offset ; New offset = [buffer size] + [old offset] + [user offset] rfile01: call bufsize ; Calc size ld bc,(offset) ; Real offset add hl,bc ld de,(uoffset) ; User offset add hl,de ld (offset),hl jp getfil ; Now read bufsize: ld hl,(topmem-1) ; Top mem byte to h ld l,0 ld de,(filloc) xor a sbc hl,de ; Buffer size ret ; ; Zero control bytes of fcb ; zbuf: ld hl,fcb+12 zfill1: ld b,24 zfill: ld (hl),0 inc hl djnz $-3 ret ; ; PRINT FILE NAME IN FCB ; pfil: call pdsk ; Print du:file.typ call pusr ld a,':' call conout jr pfn pdsk: ld a,(fcb) cp 0 jr nz,pdsk0 ld c,25 call bdos inc a pdsk0: add a,'A'-1 jp conout pusr: ld a,(usr) and 0fh pusr02: cp 10 jr c,pusr0 ld b,0 pusr1: sub 10 inc b cp 10 jr nc,pusr1 push af ld a,'0' add b call conout pop af pusr0: add a,'0' jp conout pfn: ld hl,fcb+1 ld b,8 ; Print file name call pfn0 ld a,'.' call conout ld b,3 pfn0: ld a,(hl) cp ' ' jr z,pfn1 call conout pfn1: inc hl djnz pfn0 ret nope: if helpon call getquiet ; Display entire help screen if not quiet jr nz,nope1 call info jr nopex endif ;helpon nope1: call pgmmsg nopex: jp exit pgmmsg: call print db 'BCOMP, Version ',vers/10+'0','.',vers mod 10+'0' db tstrev,' - Binary File Comparison' db cr,lf dc 'Syntax:',cr,lf,' ' call comnam call print db ' [dir:]file1 [dir:][file2] [/]',cr,lf db 'Options:',cr,lf db ' If no dir:file2, compare to memory.',cr,lf dc ' Automatic wild-card of files UNLESS "/" is used.' ret ; Print actual COMfile name if we can, ; otherwise print "BCOMP" comnam: call getefcb jr z,noefcb ld b,8 comnml: inc hl ld a,(hl) and 7fh cp ' ' call nz,conout djnz comnml ret ; noefcb: call print dc 'BCOMP' ret nofile: call pfil call print dc ' No file',lf jr exit novid: call print dc 'TCAP ERR' jr exit exit0: call cls exit: call dinit ld sp,(stksav) ; Restore stack pointer ret ; To ccp ; ; UTILITIES ; conout: push ix ; !! push hl push de push bc push af ld e,a ld c,wrconf call bdos pop af pop bc pop de pop hl pop ix ; !! ret cr$clr: ld a,cr ; Print cr, clreol call conout jp ereol vprint: print: ex (sp),hl ; Get address call print1 ex (sp),hl ; Put address ret ; ;Print String (terminated in 0) pted to by HL ; print1: ld a,(hl) ; Done? inc hl ; Pt to next or a ; 0 terminator ret z cp dim ; Standout? jr z,print1d cp bright ; Standend? jr z,print1b push af and 7fh call conout ; Print char pop af ret m jr print1 print1d: call stndout ; Dim jr print1 print1b: call stndend ; Bright jr print1 ; ; BDOS CONSOLE IN WITH NO ECHO ; cin: push hl push de push bc ld hl,(1) ld de,9 add hl,de ld (hl),0C9h ; Turn off BIOS for echo push hl ld c,1 call 5 pop hl ld (hl),0c3h ; Restore BIOS pop bc pop de pop hl ret ; ; CAPS CONSOLE IN ; getc: call cin caps: cp 'a' ret c cp 'z'+1 ret nc and 5fh ret ; ; CASE - jump table scanner ; Affect only alt registers ; Format: call case ;call with value to match in A ; db val1 ;first val to match ; dw addr1 ;jump address ; ... ; db 0 ;end table ; else next instuction executes if no match case: exx ; Save hl,de,bc ex (sp),hl ; Hl -> next addr after call ex af,af' ; Save char xor a case1: ex af,af' ; Restore char cp (hl) ; Match? inc hl ; Set pointer to val's jump addr jr z,case0 ; If match, jump inc hl ; Point to next val inc hl ex af,af' ; Check for list terminator cp (hl) jr nz,case1 ; Keep looking inc hl ; No match, execute next instruction ex af,af' ; Restore A casex: ex (sp),hl exx ; Restore regs ret case0: ld e,(hl) ; Load address inc hl ld d,(hl) ex de,hl jr casex ; Go ; ; FIND TOP OF AVAILABLE MEMORY ; topram: ld a,(7) ; Get bdos page ld b,a ; Stash it in b ld a,(2) ; Get bios page sub b ; Get offset cp 0eh ; Test for standard offset ld a,b ; Bdos page back in A ret nz ; Nz means ccp protected sub 9 ; Leave room for ccp ret ; ; BLOCK MOVES ; movptr: ld bc,stksav-block ; Size of pointer table ldir ret movfcb: ld de,fcb movfcb1: ld bc,36 ldir ret ; SKIP TO NEXT NON-BLANK sksp: ld a,(hl) ; Get char inc hl ; Pt to next cp ' ' ; Skip spaces jr z,sksp dec hl ; Pt to good char or a ; Set eol flag ret ; ; PRINT A AS 2 HEX CHARS ; pa2hc: push af push bc ld b,a ; Value in b rlca rlca rlca rlca call pa2hc1 ld a,b ; Get value call pa2hc1 pop bc pop af ret pa2hc1: and 0fh add '0' ; To ascii cp '9'+1 jr c,pa2hc2 add 7 ; To letter pa2hc2: jp conout ; ; PRINT HL AS 2 HEX CHARS ; phl4hc: push hl push af ld a,h call pa2hc ld a,l call pa2hc pop af pop hl ret ; ; PRINT HL AS DECIMAL, LEADING 0 SUPRRESSED. ; phlfdc: push hl push de push bc call hldc1 pop bc pop de pop hl ret ; Routine to convert HL to decimal number and display it hldc1: ld b,0 ; B holds leading zero suppression flag ld de,10000 call hldc2 ld de,1000 call hldc2 ld de,100 call hldc2 ld de,10 call hldc2 ld a,l add a,'0' jp conout hldc2: ld c,'0'-1 ; Count number of divisions by de hldc3: inc c xor a sbc hl,de jr nc,hldc3 ; Keep subtracting until negative add hl,de ; Then add one back ld a,c cp '1' jr nc,hldc4 ; > 0, turn off leading 0 flag and print ld a,b ; Check flag at b or a ld a,c ; Put character back in c jr nz,hldc5 ; If b not 0, this '0' is not leading ret ; Else skip hldc4: ld b,0ffh ; Turn the leading 0 flag off hldc5: jp conout ; Print the number ; ; DIVIDE HL BY 128 ; div128: push bc ld b,7 div00: srl h rr l djnz div00 pop bc ret ; ; MULTIPLY HL BY 128 ; mult128: push bc ld b,7 add hl,hl djnz $-1 pop bc ret ; ; Input Number from Command Line -- Assume it to be Hex ; Number returned in DE ; FROM MU3 hexin: ld de,0 ; Init value ld a,(hl) cp '#' ; Decimal? jr z,hdin ; Make decimal ; hinlp: ld a,(hl) ; Get char call caps ; Capitalize ; cp cr ; Eol? ; ret z cp eolch ; Eol? ret z ; cp sepch ; ret z cp ' ' ; Space? ret z ; cp '-' ; 'thru'? ; ret z ; cp '>' ; ret z inc hl ; Pt to next char cp '0' ; Range? jr c,serr cp '9'+1 ; Range? jr c,hinnum cp 'A' ; Range? jr c,serr cp 'F'+1 ; Range? jr nc,serr sub 7 ; Adjust from a-f to 10-15 ; hinnum: sub '0' ; Convert from ascii to binary ex de,hl add hl,hl ; Mult previous value by 16 add hl,hl add hl,hl add hl,hl add a,l ; Add in new digit ld l,a ex de,hl jr hinlp ; hdin: inc hl ; Skip '#' ; ; Input Number in Command Line as Decimal ; Number is returned in DE ; decin: ld de,0 ld a,(hl) ; Get 1st char cp '#' ; Hex? jr nz,dinlp inc hl ; Pt to digit jr hinlp ; Do hex processing ; dinlp: ld a,(hl) ; Get digit call caps ; Capitalize cp ' ' ret z cp eolch ret z cp '0' ; Range? jr c,serr cp '9'+1 ; Range? jr nc,serr sub '0' ; Convert to binary inc hl ; Pt to next push hl ld h,d ld l,e add hl,hl ; X2 add hl,hl ; X4 add hl,de ; X5 add hl,hl ; X10 add a,l ; Add in digit ld l,a ld a,h adc 0 ld h,a ex de,hl ; Result in de pop hl jr dinlp ; ; READ LINE FROM USER INTO INPUT LINE BUFFER ; rdbuf: ; Set up tbuf as buffer ld hl,tbuf ld (hl),60 ; Back to Conn's routine ex de,hl ; Set de as ptr to buffer ld c,10 ; Bdos readln push de ; Save ptr call bdos pop hl ; Pt to char count inc hl ld e,(hl) ; Get char count ld d,0 inc hl ; Pt to first char push hl ; Save ptr add hl,de ; Pt to after last char ld (hl),0 ; Store ending 0 pop hl ; Pt to first char ret serr: or -1 ret ; ; TRANSFER STRING TO FIND BUFFER, WITH HEX CONVERSION ; (Lifted from rcpiom.lib with mods) poke: ld b,0 ; Arg counter ld de,findbuf+2 ; Loop for storing hex values sequentially via poke code ; de -> destination address poke1: call sksp ; Skip to non-blank jr z,pokex ; Done cp '"' ; Quoted text? jr z,poke2 inc b ; Inc arg counter push de ; Save address call hexin ; Get number ld a,e ; Get low pop de ; Get address ld (de),a ; Store number inc de ; Pt to next jr poke1 ; ; Store ascii chars ; poke2: inc hl ; Pt to next char poke3: ld a,(hl) ; Get next char or a ; Done? jr z,pokex ld (de),a ; Put char inc b inc hl ; Pt to next inc de jr poke3 pokex: ld a,b ld (findbuf+1),a ; Store arg counter ret ; ; END MESSAGE ; Fall through to WAIT endmsg: call vprint dc 1,'End',2,' ',bell ; ; PAUSE ABOUT 1 SECOND ; wait: ld c,255 ld b,24 wait0: push bc call wait01 pop bc dec c jr nz,wait0 ret wait01: call wait02 djnz wait01 wait02: ld c,20 wait03: ex (sp),hl ex (sp),hl dec c jr nz,wait03 ret ; ; END UTILITIES ; ; ; HELP SCREEN (OR JUST REFRESH) ; help: call info jp scrn1 info: if helpon call cls call pgmmsg include defhlp.lib call cin endif ; Helpon ret ; ; ZPATCH ROUTINES ; EDNIB (edit nibbles) and TST for taking offset from file type ; include ednib.lib include offset.lib ; ; STORAGE ; findbuf: db fstring ; "FIND" buffer ds fstring+2 eflag db 0ffh ; Echo flag 0 = echo ff = no echo ; ; UNINITIALIZED DATA ; dseg eindex: ds 1 ; Editor byte index edflag: ds 1 ; Hex/ascii field flag edchnge: ds 1 ; Changes made while editing blkbuf: ds 128 ; Yank buffer for block edited wrecfcb: ds 36 ; FCB for random record writes edptr: ds 2 ; Start block pointer eblockf: ; Init to 0 on edit entry ds 1 ; Block set flag: MSB = start, LSB= end edblk: ds 1+128 ; Block count, 128 byte buffer bufptr equ $ ; SWITCH swaps pointer banks 1 and 2 into active pointer table ; POINTER BANK 1 blk1 ds 2 ;current screen eof1 ds 2 ;eof fil1 ds 2 ;start file top1 ds 1 ;top mem block efl1 ds 1 ;eof on file read rfl1 ds 1 ;file being read usr1 ds 1 ;user mfl1 ds 1 ;memory or file frw1 ds 1 ;cursor position file prr1 ds 1 ;prompt row hom1 ds 1 ;home row uof1 ds 2 ;user offset off1 ds 2 ;real offset mrc1 ds 2 ;max record read ; POINTER BANK 2 blk2 ds 2 eof2 ds 2 fil2 ds 2 top2 ds 1 efl2 ds 1 rfl2 ds 1 usr2 ds 1 mfl2 ds 1 frw2 ds 1 prr2 ds 1 hom2 ds 1 uof2 ds 2 off2 ds 2 mrc2 ds 2 filptr: ds 2 ; Scratch pointer fcb1buf: ds 36 fcb2buf: ds 36 sflag ds 1 ; Switch flag 0 = file1 ff = file2 ; ACTIVE POINTER TABLE block ds 2 ; Beginning of current screen eofptr ds 2 ; End of file pointer filloc ds 2 ; Start of file pointer topmem ds 1 ; Top of mem high byte eoflag ds 1 ; File completely read rflag ds 1 ; File being read usr ds 1 ; File user area mflag ds 1 ; Memory ... not reading a file frow ds 1 ; File display info ... prrow ds 1 homrow ds 1 uoffset ds 2 ; Display offset offset ds 2 ; Actual offset to file in memory maxrec ds 2 ; Maximum record read stksav ds 60 ; Save incoming stack pointer stack equ $ ; Top of local stack end start