;COMPARE DISK'S FOR SAME FILE'S AND DELETE THEM FROM DISK 2
; 8-29-83
;
; fixes in reverse order
;	8-29-83
;	Incorectly put file on destination user under default. Now
;	put on default user.
;	^C abort corrected so it won't lock up at abext2:
;
; Portions extracted from
; CRCK.ASM Version 5.1 (Originally by: Keith Petersen, W8SDZ)
; 
;           x^16 + x^15 + x^13 + x^7 + x^4 + x^2 + x + 1
; 
; Commands:   same drive[user]:name.typ drive[user]:name.type [$f,e,n,c,x,w,d]
;	commas are just used here for diferentiating instrusctions
;
;    Options	Descriptionns
;	$	start options
;	F	Write compare text to SAMELIST.PRN and crc data
;		to CRCKLIST.CRC on each disk and default user if
;		no user selected
;	E	Erase files that are equal
;	N	Don't promt operator to erase file
;	C	Display CRCKLIST.CRC files on console
;	X	Use existing CRCKLIST.CRC files from selected
;		user or default user. Uses old crc generation if
;		old CRCKLIST.CRC encounteredss
;	W	Wait and promt operator for disk change
;	D	Default to F,N,X,W options
; 
; Examples:
; 
; same a: b: compare all file's all user's on a: to same on b:
; same a0: b0: compare all file's user 0 on a: to same on b:
; same a:*.asm b:*.asm $fwn
; 
; I found that i had many disks with the same files on them. Long ago
; I had put together a basic program to compare out of sequence CRCKLIST.CRC
; files and list out same files, the basic program took quite a while to
; compare the data so i put this together just for fun. I started thinking
; of all kinds of neet options to put in it, shortly it got out of hand. The
; original file comparison formating does not look the best but it tells
; the operator what he was after to start with.
;
; Any questions or fixes please send then to
; Joe Cutler
; 2340 Alice Ann Rd.
; Newbury Park,CA.
; (805) 498-1141
;
; I'm also periodicaly on Trevors RBBS
; (805) 492-5472
; 
; define true and false
; 
false	equ	0
true	equ	not false
; 
; define write buffer size (presently set for 8k)
; 
bsize	equ	8*1024	; disk write buffer size
; 
; bdos equates
; 
rdcon	equ	1
wrcon	equ	2
dcon	equ	6
cstat	equ	11
open	equ	15
close	equ	16
srchf	equ	17
srchn	equ	18
delet	equ	19
read	equ	20
write	equ	21
make	equ	22
renam	equ	23
stdma	equ	26
;
bdos	equ	5
;
fcb	equ	5ch 
fcbext	equ	fcb+12
fcbrno	equ	fcb+32
fcb2	equ	6ch
;
tbuf	equ	80h; temporary buffer (default) address
buf$siz	equ	80h	; buffer size (128 bytes)
;
sfilesiz	equ	2000h
;
CR	EQU	0DH
LF	EQU	0AH
TAB	EQU	9
eof	equ	'Z'-40h	; end-of-file character
;
; CCIT CRC polynomial mask bytes
;
himsk	equ	0a0h	; high mask byte
lomsk	equ	097h	; low mask byte
FBUFF	EQU	80H
FLEN	EQU	16	;FILE BUFFER LENGTH
;
TRUE	EQU	-1
FALSE	EQU NOT TRUE
;
SIZE	EQU	FALSE
;
	ORG	0100H
START:	LXI	SP,STACK;SET UP NEW STACK
	xra	a
	sta	active
	LDA	FBUFF	;SEE IF ANYTHING SELECTED
	ORA	A
	JZ	HELP	;NO
	lxi	d,signon;tell them we're here
	call	print
	CALL	GLOOK	;GENERATE FAST CRC LOOKUP TABLE
	LXI	D,FBUFF+1;INPUT STRING
	LXI	H,SFCB	;SOURCE FCB
	CALL	MAKFCB
	JC	BADFCB	;ERROR
	MOV	A,B	;GET USER #
	STA	SUSER	;SAVE SOURCE USER
	LXI	H,DFCB	;DESTINATION FCB
	CALL	MAKFCB
	JC	BADFCB	;ERROR
	MOV	A,B	;GET USER #
	STA	DUSER	;DESTINATION USER
	LXI	H,SFCB+1;FILENAME
	LDA	SFCB+9	;TYPE
	ORA	M	;SEE IF NO FILE SELECTED
	CPI	' '
	CZ	FILLFCB	;FILL FCB NAME.TYPE WITH ?
	LXI	H,DFCB+1;FILENAME
	LDA	DFCB+9	;TYPE
	ORA	M	;SEE IF NO FILE SELECTED
	CPI	' '
	CZ	FILLFCB	;FILL FCB NAME.TYPE WITH ?
;
	CALL	DECOPT	;DECODE OPTIONS
;
	LDA	SFCB	;SOURCE DISK
	DCR	A	;DIRECT SELECT
	JP	GETD
	JNZ	GETD
	MVI	C,25	;GET LOGGED IN DISK
	CALL	BDOS
GETD:	STA	SDISK	;SOURCE DISK
	MOV	C,A	;SAVE SOURCE DISK
	LDA	DFCB	;DESTINATION DISK
	DCR	A	;ACTUAL SELECT
	JP	CMPD	;DIRECT SELECTED
	MVI	C,25	;GET LOGGED IN DISK
	CALL	BDOS
CMPD:	STA	DDISK	;SET UP AS DESTINATION ALSO
	CMP	C	;SAME DISK?
	JNZ	GETU	;NO GET USER #
	LDA	SUSER
	LXI	H,DUSER
	CMP	M
	JZ	SAMDSK	;SAME DISK AND USER
GETU:	MVI	E,0FFH	;GET USER #
	MVI	C,32
	CALL	BDOS
	STA	OLDUSR	;OLD USER #
	LDA	SUSER	;SOURCE USER
	STA	SFCB	;SET IN FCB FOR COMPARE
	LDA	DUSER	;DESTINATIN USER
	STA	DFCB	;SET IN FCB FOR COMPARE
;LOGIN IN SELECTED DRIVES
	CALL	LOGIN	;LOG IN DISKS
;GET FILES FROM SOURCE DISK
	LXI	H,NAMBUF
	SHLD	SBUFF	;SOURCE BUFFER
	LDA	SDISK	;SELECT SOURCE DISK
	XCHG
	LXI	H,SFCB	;SOURCE FCB
	CALL	SFILES	;SET UP FILES
	JC	NOFILE	;NO FILES THERE
	LHLD	NAMPTR	;GET POINTER
	SHLD	DBUFF	;SET UP DESTINATION BUFFER
	LHLD	ACT$CRCK;CRCKLIST.CRC FILE FLAGS
	SHLD	S$ACT	;SET SOURCE ACTIVE FLAGS
	CALL	NSORT	;SORT NAMES
	JC	NSAME	;DIFFERENT USER HAS SAME FILE NAME.TYPE
;GET FILES FROM DESTINATION DISK
	LHLD	DBUFF	;DESTINATION BUFFER POINTER
	XCHG
	LXI	H,DFCB	;DESTINATION FCB
	LDA	DDISK	;SELECT DESTINATION DISK
	CALL	SFILES	;SET UP FILES
	JC	NOFILE	;NO DESTINATION FILES
	LHLD	NAMPTR	;END OF DESTINATION BUFFER
	SHLD	EDBUFF
	LHLD	ACT$CRCK;CRCKLIST.CRC FILE FLAGS
	SHLD	D$ACT	;SET DESTINATION ACTIVE FLAGS
	CALL	NSORT	;SORT FILES
	JC	NSAME	;DIFFERENT USER HAS SAME FILE NAME.TYPE
;COMPARE FILES FROM BOTH DISKS
	CALL	CFILES	;COMPARE FILES
;
	LXI	D,WAIT?	;WAIT FOR KEYBOARD
	CALL	PRINT
	MVI	C,1	;GET CHARACTER
	CALL	BDOS
;
	CALL	DFILES	;DISPLAY FILE COMPARES
;
	CALL	ERASE	;ERASE SAME FILES
;
	CALL	DISPCRC	;WRITE CRC DATA
;
	LXI	D,DONE	;THATS ALL FOLKS
	LDA	WFLAG	;WAIT IN PROGRESS
	ORA	A
	JZ	ERROR	;NO ERROR BUT NORMAL RETURN
	LXI	D,FWAIT	;WAIT FOR SYSTEM DISK
	CALL	PRINT
	MVI	C,1	;WAIT FOR RESPONSE
	CALL	BDOS
	JMP	RETURN
;LOGIN IN SELECTED DRIVES
LOGIN:	LDA	SDISK
	ORA	A	;DISK A
	JZ	WLOGIN
	LDA	DDISK
	ORA	A	;DISK A ?
	JZ	WLOGIN
	CALL	RLOGIN	;RE-LOGIN SYSTEM
WLOGIN:	LDA	WFLAG	;WAIT FOR OPERATOR RESPONSE
	ORA	A
	JZ	RLOGIN	;YES
	LXI	D,WAIT	;WAIT MESSAGE
	CALL	PRINT
	MVI	C,1	;ANY CHARACTER
	CALL	BDOS
RLOGIN:	MVI	C,13	;RESET DISK SYSTEM
	CALL	BDOS
	RET
;GET FILES IN BUFFER
;HL=FILE NAME COMPARE BUFFER,A=DISK
SFILES:	SHLD	CMPFCB	;COMPARE FCB POINTER
	XCHG
	SHLD	BUFF	;BUFFER POINTER
	MOV	E,A
	MVI	C,14
	CALL	BDOS	;LOG IN NEW DISK
	LXI	H,0	;RESET FILE COUNT
	SHLD	NAMCNT
	CALL	GETSAME	;GET FILES
	CMC
	RNC		;GOT FROM CRCKLIST.CRC
	MVI	A,'?'	;SET UP USER FCB
	STA	UFCB
	MVI	C,17	;SEARCH FOR FIRST
	LXI	D,UFCB	;ALL USER SEARCH
	CALL	BDOS
	CPI	-1	;NO FILES THERE
	STC		;SET UP FOR NO FILE
	RZ
	JMP	GOTFILE
SNFILE:	MVI	C,18	;NOW NEXT FILE
	CALL	BDOS
	CPI	-1	;NO MORE FILES
	JNZ	GOTFILE	;FILE HERE
	LHLD	NAMCNT	;ANY FILES IN BUFFER
	MOV	A,H
	ORA	L
	RNZ		;YES
	STC		;NO, ERROR RETURN
	RET		;THATS ALL FOLKS
GOTFILE:
	ADD	A	;COMPUTE OFFSET TO NAME
	ADD	A
	ADD	A
	ADD	A
	ADD	A
	MOV	E,A
	MVI	D,0
	LXI	H,FBUFF
	DAD	D
	XCHG
	LDAX	D	;SEE IF NUL FILES
	CPI	0E5H
	JZ	SNFILE	;YES NULL
	PUSH	D	;SAVE NAME POINTER
	LHLD	CMPFCB	;NAME POINTER
	MVI	B,13	;USER #,FILENAME.TYPE,EXTENT
	XCHG
	CALL	NCOMP	;COMPARE NAMES
	POP	D
	JNZ	SNFILE	;NOT SAME FILE NAME
	LHLD	NAMPTR	;GET PRESENT NAME POINTER
	MVI	M,0	;PRESET FILE STATUS FLAG
	INX	H
	MVI	B,12	;GET FILE NAME
	CALL	MOVE
	XRA	A
	MOV	M,A
	INX	H	;FILE LENGTH BUFFER
	MOV	M,A
	INX	H
	MOV	M,A
	INX	H
	SHLD	NAMPTR	;SAVE FOR NEXT NAME
	LHLD	NAMCNT	;NAME COUNTER
	INX	H
	SHLD	NAMCNT
	JMP	SNFILE	;TRY NEXT FILE
;
NCOMP:	LDAX	D	;FROM ADDRESS
	CPI	'?'	;ANY CHARACTER
	JZ	NCOMP0
	CMP	M
	RNZ		;NOT SAME ERROR
NCOMP0:	INX	D	;INCREMENT POINTER
	INX	H
	DCR	B	;COUNTER
	JNZ	NCOMP	;KEEP COMPAREING
	RET
;
;SORT NAMES IN BUFFER
;
NSORT:	XRA	A	;RESET MULTIPLE FILES FLAG
	STA	MFILES
	LXI	D,SORTING
	CALL	PRINT
	MVI	C,-1	;JUST FOR FIRST PASS
NEXTS:	MOV	A,C	;GET SWAPPED FLAG
	ORA	A
	JZ	NSORT$END;DIDN'T SWAP, END OF SORT
	LHLD	NAMCNT	;# OF FILES IN BUFFER
	DCX	H	;DECRIMENT COUNT
	SHLD	NAMCNT
	MOV	A,H	;TEST FOR 0
	ORA	L
	JZ	NSORT$END
	PUSH	H
	MVI	C,0	;INITIALIZE SWAPPED FLAG
;
;PASS THRU THE BUFF, SORTING IT.
;
	LHLD	BUFF	;GET BUFFER POINTER
	XCHG
COMPR:	LXI	H,FLEN	;NAME LENGHT
	DAD	D
	PUSH	D
	PUSH	H
	INX	H	;GET PAST FLAG AND USER
	INX	H
	INX	D
	INX	D
	MVI	B,11	;COMPARE LENGTH
CLCLP:	LDAX	D
	CMP	M
	JC	NEXTC	;first name smaller
	JNZ	DIFF
SAME:	INX	D
	INX	H
	DCR	B
	JNZ	CLCLP
	MVI	A,-1	;SET MULITPLE FILE FLAG
	STA	MFILES
	POP	H
	POP	D
	LDAX	D	;GET PREVIOS FLAG
	ORA	A
	JNZ	NEXTC1	;ALREADY DISPLAYED
	PUSH	D	;SAVE AGAIN
	PUSH	H
	PUSH	B	;SAVE SWAPPED FLAG
	SHLD	SSFCB
	XCHG
	SHLD	SDFCB
	MVI	A,0010$0000B
	ORA	M	;OR IN FLAG
	MOV	M,A
	LDAX	D	;GET EXISTING FLAG
	ORI	0010$0000B
	STAX	D	;SET UP DISPLAYED FLAG
	INX	D	;GET TO USER #
	INX	H
	LDAX	D	;SECOUND USER #
	MOV	L,M	;FIRST USER #
	MOV	H,A
	CALL	DFNAME	;DISPLAY FILE NAME
	POP	B	;GET SWAPPED FLAG BACK
NEXTCº	POÐ	H
	POP	D
NEXTC1:	XCHG
NEXTC2:	POP	H	;FILE COUNT
	DCX	H
	MOV	A,H	;END OF LOOP
	ORA	L
	JZ	NEXTS	;COMPLETED PASS THRU BUFF
	PUSH	H	;SAVE COUNT
	JMP	COMPR	;CHECK NEXT 2
;
;UNEQUAL COMPARE
;
DIFF:	POP	H
	POP	D	;GET POINTERS
;SWAP
	MVI	B,FLEN
SWAP:	MOV	C,M
	LDAX	D
	MOV	M,A
	MOV	A,C
	STAX	D
	INX	D
	INX	H
	DCR	B
	JNZ	SWAP
	MVI	C,-1	;SET SWAPED FLAG
	JMP	NEXTC2
NSORT$END:
	LDA	MFILES	;MULTIPLE FILES
	INR	A	;SET CARRY IF MULTIPLE FILES
	RET
;
;COMPARE SOURCE AND DESTINATION FILE BUFFERS
;
CFILES:	XRA	A	;SET UP PASS COUNT
	STA	CPASS
CMPASS:	LDA	CPASS	;WHICH PASS
	INR	A
	STA	CPASS
	IF	SIZE
	CPI	4	;# OF PASSES
	ELSE
	CPI	3	;# OF PASSES
	ENDIF
	RNC		;ALL DONE
	ANI	1	;TEST FOR WHICH DISK TO SELECT
	LDA	SDISK	;SELECT SOURCE DISK
	JZ	CDISK	;SELECT DISK
	LDA	DDISK	;SELECT DESTINATION DISK
CDISK:	MOV	E,A
	MVI	C,14	;SELECT DISK
	CALL	BDOS
	LHLD	SBUFF	;SOURCE BUFFER
	SHLD	SSBUFF	;SEARCH SOURCE BUFFER
	LHLD	DBUFF	;DESTINATIN BUFFER
	SHLD	SDBUFF	;SEARCH DESTINATION BUFFER
CNFILE:	LHLD	SSBUFF	;SEE IF END
	XCHG
	LHLD	DBUFF	;SEE IF END OF BUFFER
	CALL	SUBDHC
	JNC	CMPASS	;NEXT PASS
	LHLD	SDBUFF	;DESTINION BUFFER
	XCHG
	LHLD	EDBUFF	;END DBUFF
	CALL	SUBDHC
	JNC	CMPASS	;NEXT PASS
	LHLD	SSBUFF	;SOURCE BUFFER
	CALL	CFILE	;COMPARE FILE
	JZ	FEQU	;FILE NAMES EQUAL
	JC	INCD	;INCREMENT DESTINATION
	LXI	D,FLEN	;NAME BUFFER LENGTH
	DAD	D
	SHLD	SSBUFF
	JMP	CNFILE	;LOOP ON COMPARE
INCD:	LXI	H,FLEN	;NAME BUFFER LENGTH
	DAD	D
	SHLD	SDBUFF
	JMP	CNFILE	;LOOP ON COMPARE
FEQU:	SHLD	SSFCB
	XCHG
	SHLD	SDFCB
	PUSH	D
	LXI	D,FLEN	;NAME BUFFER LENGTH
	DAD	D
	SHLD	SDBUFF	;NEW DESTINAITION BUFFER
	POP	H
	DAD	D
	SHLD	SSBUFF	;NEW SOURCE BUFFER
	LHLD	SSFCB	;SEE IF ALREADY NO COMPARE
	MOV	A,M
	ANI	0100$0000B;ALREADY NOT COMPARED
	JNZ	CNFILE	;YES
	LDA	CPASS	;COMPARE PASS
	DCR	A	;FIRST PASS
	JZ	CPASS1
	IF	SIZE
	DCR	A	;SECOUND PASS
	JZ	CPASS2
CPASS3:	LHLD	SDFCB	;SET SOURCE FILE
	SHLD	CRCFCB	;SOURCE NAME POINTER
	CALL	GENCRC	;GENERATE CRC FOR FILE
	JMP	CSIZE
CPASS1:	LHLD	SDFCB	;SOURCE FILE NAME
	CALL	SETSIZE	;SET FILE SIZE
	JMP	CNFILE	;LOOP ON COMPARE
CPASS2:	LHLD	SSFCB	;DESTINATION FILE NAME
	SHLD	CRCFCB	;SET UP POINTER
	CALL	SETSIZE	;SET FILE SIZE
CSIZE:	LXI	B,13	;OFFSET TO SIZE
	LHLD	SDFCB	;DESTINATION NAME
	DAD	B
	XCHG
	LHLD	SSFCB	;SOURCE NAME
	DAD	B
	MVI	B,3	;LENGTH OF COMPARE
CMPSIZE:
	LDAX	D	;DESTINATION
	CMP	M
	JNZ	FNEQU	;NOT EQU
	INX	D	;INCREMENT POINTERS
	INX	H
	DCR	B
	JNZ	CMPSIZE	;STILL SAME
	LDA	CPASS	;ONLY ON PASS 1
	CPI	2
	JNZ	CNFILE	;ONLY GENERATE ON SECOUND PASS
	CALL	GENCRC	;DESTINATION CRC
	JMP	CNFILE	;LOOP ON COMPARE
	ELSE
CPASS2:	LHLD	SSFCB	;DESTINATION FILE NAME
	SHLD	CRCFCB	;SET UP POINTER
	CALL	GENCRC	;GENERATE CRC FOR FILE
	LXI	B,13	;OFFSET TO CRC
	LHLD	SDFCB	;DESTINATION NAME
	DAD	B
	XCHG
	LHLD	SSFCB	;SOURCE NAME
	DAD	B
	MVI	B,3	;LENGTH OF COMPARE
CMPSIZE:
	LDAX	D	;DESTINATION
	CMP	M
	JNZ	FNEQU	;NOT EQU
	INX	D	;INCREMENT POINTERS
	INX	H
	DCR	B
	JNZ	CMPSIZE	;STILL SAME
	JMP	CNFILE	;LOOP ON COMPARE
CPASS1:	LHLD	SDFCB	;SET SOURCE FILE
	SHLD	CRCFCB	;SOURCE NAME POINTER
	CALL	GENCRC	;GENERATE CRC FOR FILE
	JMP	CNFILE
	ENDIF
;
FNEQU:	LHLD	SSFCB	;GET SOURCE FILE POINTER
	MOV	A,M	;GET FLAG
	ANI	0011$1111B;MASK OUT EQU
	ORI	0100$0000B;NOT EQU BIT
	MOV	M,A
	LHLD	SDFCB
	MOV	A,M	;GET FLAG
	ANI	0011$1111B;MASK OUT EQU
	ORI	0100$0000B;NOT EQU BIT
	MOV	M,A
	JMP	CNFILE	;LOOP ON COMPARE
;
CFILE:	PUSH	H	;SOURCE
	PUSH	D	;DESTINATION
	MVI	B,11	;COMPARE LENGTH
	INX	H
	INX	H
	INX	D
	INX	D
COMP:	LDAX	D
	CMP	M
	JNZ	CMPEND
	INX	D
	INX	H
	DCR	B
	JNZ	COMP	;KEEP COMPARING
CMPEND:	POP	D	;DESTINATIN
	POP	H
	RNZ		;NOT SAME FILES
	INX	D	;GET TO USER
	LDAX	D	;GET DESTINATION USER #
	ORI	1000$0000B;SET ACTIVE FLAG
	MOV	B,A
	MOV	A,M	;GET EXISTING FLAG
	ANI	0100$0000B;SEE IF ALREADY NON-ZERO
	JNZ	CMPN
	MOV	A,B
	ORA	M	;OR IN FLAGS
	MOV	M,A
CMPN:	DCX	D
	INX	H	;GET TO USER
	MOV	A,M
	ORI	1000$0000B;SET ACTIVE FLAG
	MOV	B,A
	LDAX	D	;GET EXISTING FLAG
	ANI	0100$0000B;SEE IF ALREADY NON-ZERO
	JNZ	CMPL	;YES
	LDAX	D
	ORA	B
	STAX	D	;SET FLAG
CMPL:	DCX	H
	XRA	A	;RESET CARRY
	RET
	IF	SIZE
;GET FILE SIZE
SETSIZE:
	CALL	SETFCB	;SET UP USER AND LFCB
	PUSH	D	;SAVE SIZE POINTER
	LXI	D,LFCB
	MVI	C,35	;COMPUTE FILE SIZE
	CALL	BDOS
	POP	H	;GET NAME POINTER BACK
	LXI	D,LFCB+33;GET FILE SIZE
	MVI	B,3
	CALL	MOVE	;MOVE TO NAME
	RET
	ENDIF
;
SETFCB:	INX	H	;GET TO USER #
	MOV	A,M
	PUSH	H	;SAVE POINTER
	CALL	SETUSR
	POP	D
	INX	D	;GET TO FILE NAME
	LXI	H,LFCB+1
	MVI	B,11
	CALL	MOVE
	XRA	A
	STA	LFCB+12	;EXTENT
	STA	LFCB+15	;RC
	STA	LFCB+32	;CR
	RET
;
setfile:
	lda	fflag	; get option
	sta	active	;active flag
	ora	a	; file wanted?
	rz		; no, skip file init
	push	h	;save user
	push	d	;save pointer
	lxi	h,fcbfinal+1;file to delete
	mvi	b,11	;move full name
	call	move
	lxi	h,samfcb+1;file name
	pop	d
	mvi	b,8	;just move filename
	call	move
	mov	e,c	;get disk
	mvi	c,14	;select disk
	call	bdos
	pop	psw	;get user #
	cpi	'?'	;default user
	jnz	setf0	;no
	lda	oldusr	;default user
setf0:	call	setusr	;set up for default user
	xra	a
	sta	samfcb+12	; clear extent
	sta	samfcb+32	; clear current record count
	lxi	h,sfilesiz	; set buffer size
	shld	sfilelen
	lxi	h,0		; set next to fill
	shld	sfileptr
	mvi	c,delet		; delete file function
	lxi	d,samfcb	; delete 'old' crcklist file
	call	bdos
	mvi	c,make		; make file function
	lxi	d,samfcb	; make 'new' crcklist file
	call	bdos
	inr	a		; make ok?
	rnz			;yes
	lxi	d,dir$full	; indicate that directory is full
	call	print
	jmp	filerr
;
putsfile:
;
	push	psw		; save output character
	lda	active		;see if active
	ora	a
	jz	noput		;not active
	lhld	sfilelen	; get current buffer length
	xchg			; de has length
	lhld	sfileptr	; load next to get/put to hl
	mov	a,l		; compute current length
	sub	e 	
	mov	a,h
	sbb	d		; carry if next < length
	jc	putcrc4		; carry if length > current
	lxi	h,0		; end of buffer, fill (empty) buffers	
	shld	sfileptr	; clear next to get/put
;
putcrc1:			; process next disk sector
;
	xchg			; file pointer to de
	lhld	sfilelen	; hl is maximum buffer length
	mov	a,e		; compute next length
	sub	l		; to get carry, if more fill
	mov	a,d
	sbb	h		
	jnc	putcrc3
	lhld	sfileadr	; got carry, more to fill yet
	dad	d		; hl is next buffer address
	xchg
	mvi	c,stdma		; set dma address
	call	bdos
	lxi	d,samfcb	; fcb address to de
	mvi	c,write		; file write
	call	bdos
	ora	a		; check return code
	jnz	putcrc2		; end-of-file yet?
	lxi	d,buf$siz	; not eof, increment length by 128
	lhld	sfileptr	; next to fill
	dad	d
	shld	sfileptr	; save new pointer
	jmp	putcrc1		; process another sector
;
putcrc2:			; got end-of-file
;
	lxi	d,dsk$full	; disk is full
	call	print
	pop	psw		; clean stack
	jmp	filerr		; file error, exit
;
putcrc3:			; end of buffer, reset dma and pointer
;
	lxi	d,tbuf		; point to temporary buffer
	mvi	c,stdma		; set dma function
	call	bdos
	lxi	h,0		; reset pointer for next to get
	shld	sfileptr
;
putcrc4:			; process the next character
;
	xchg			; index to get/put in de
	lhld	sfileadr	; base of buffer
	dad	d		; address of character in hl
	xchg			; and swap to de
	pop	psw		; get save character
	stax	d		; character to buffer
	lhld	sfileptr	; index to get/put
	inx	h		; and update for next character
	shld	sfileptr
	ret
;
noput:	pop	psw		;get character back
	ret
; 
; close crcklist.$$$
;
closecrc:
;
	lda	active	;see if file active
	ora	a
	rz		;yes
close0:	lhld	sfileptr
	mov	a,l
 	ani	07fh
	jnz	close1
	shld	sfilelen
close1:	mvi	a,eof
	push	psw
	call	putsfile
	pop	psw
	jnz	close0
	xra	a
	sta	active	;clear active flag
	mvi	c,close
	lxi	d,samfcb
	call	bdos
	inr	a
	jnz	cerase
	lxi	d,no$close
	call	print
; 
; erase any existing old file
;
cerase:	mvi	c,delet
	lxi	d,fcbfinal
	call	bdos
; 
; rename crcklist.$$$ to crcklist.crc
;
	lxi	h,samfcb
	lxi	d,fcbfinal
	push	h
	lxi	b,16
	dad	b
;
mov$name:
;
	ldax	d
	mov	m,a
	inx	d
 	inx	h
	dcr	c
	jnz	mov$name
	pop	d
	mvi	c,renam
	call	bdos
	ret
;
gencrc:
	lhld	crcfcb	;get file name pointer
	mov	a,m	;get flag byte
	ani	0001$0000b;see if crc already generated
	rnz		;yes
; 
; open the file
;
	call	setfcb
	lxi	d,lfcb
	mvi	c,open
	call	bdos
	inr	a
	jnz	rdinit
	call	abexit
	db	'++Open Failed++$'
; 
; initialize crc to zero and set bufad to cause initial read
;
rdinit:	lxi	h,0
 	shld	rem	; init remainder to zero
	lxi	h,100h
	shld	bufad	; init buffer adrs
; 
; this is the read loop
;
readit:	lhld	bufad
	mov	a,h	; time to read?
	ora	a
	jz	nord	; no read
	mvi	e,-1	; get console status/character
	mvi	c,dcon
	call	bdos	; check for operator abort
	cpi	'C'-40h	; control c?
	jz	abext2	; yes exit
; 
read2:	lxi	d,lfcb
	mvi	c,read	; read another sector of file
	call	bdos
	ora	a	; check return code
	jnz	finish	; error or eof
	lxi	h,tbuf	; buffer location
; 
nord:	lda	crctype
	cpi	' '	;delimeter for old crck.com
	mov	a,m	; get file character
	inx	h
	shld	bufad
	lhld	rem	; pick up the partial remainder
	jz	oldcrc
; 
; table lookup method for crc generation
;
	xchg		; de now has the partial
	mvi	b,0
	xra	d
	mov	c,a
	lxi	h,hitab
	dad	b
	mov	a,m
	xra	e
	mov	d,a
	inr	h
	mov	e,m
	xchg
	shld	rem
	jmp	readit	; go read more characters
;old crck.com crc generation
;'a' the character to be crc'd
oldcrc:	mov	c,a	;save new byte
	mov	a,h
	ani	80h
	push	psw
	dad	h
	mov	a,c
	add	l
	mov	l,a
	pop	psw
	jz	ocend
	mov	a,h
	xri	himsk
	mov	h,a
	mov	a,l
	xri	lomsk
	mov	l,a
ocend:	shld	rem
	jmp	readit	; go read more characters
; 
;
finish:	cpi	1	; normal end-of-file?
	jnz	filerr	; no, it was a read error
	lhld	rem	; get crc
	xchg
	lhld	crcfcb	; get name pointer
	mov	a,m	;get atributes
	ori	0001$0000b;set crc generated bit
	mov	m,a
	lxi	b,13	; offset to length
	dad	b
	mov	m,e
	inx	h
	mov	m,d
	inx	h
	mvi	m,0	;set to 0
	ret
; 
filerr:	call	abexit	; abort because of file read error
	db	'++File Read Error++$'
;
; generate the lookup table for fast crc
;
glook:	lxi	h,hitab
	mvi	c,0	; the table index
gloop:	xchg
	lxi	h,0	; init the crc
	mov	a,c
	call	lcrc
	xchg		; de now has the crc, hl pointing into table
	mov	m,d	; store the high byte of crc
	inr	h
	mov	m,e	; store the low byte
	dcr	h
	inx	h	; move to next table entry
	inr	c	; next index
	jnz	gloop
	ret
;
;  hl contains the partial, 'a' the character to be crc'd
; 
lcrc:	push	b
	mvi	b,8
	xra	h
	mov	h,a
loop:	dad	h
	jnc	skip
	mvi	a,himsk
	xra	h
	mov	h,a
	mvi	a,lomsk
	xra	l
	mov	l,a
skip:	dcr	b
	jnz	loop
	pop	b
	ret
;
;
; send carriage return, line feed to output
; 
crlf:	mvi	a,cr	; carriage return
	call	outchr
	mvi	a,lf	; line feed, fall into 'type'
	call	outchr
	xra	a
	ret
; 
; send character in a register to output
; 
outchr:	push	b
	push	d
	push	h
	ani	7fh	; strip parity bit
	mov	e,a
	push	d
	call	putsfile; write to file if requested
	pop	d
	lda	cflag	;console flag
	ora	a
	mvi	c,wrcon	; send character to console
	cnz	bdos
	pop	h
	pop	d
	pop	b
	ret
;
;
; aborted - print reason.  if making output file,
; close the incomplete file to update cp/m's bit map,
; then erase it.
; 
abexit:	pop	d	; get msg adrs
	call	print
; 
abext2:	lda	active	; see if we are making file
	ora	a
	jz	abext5	; no file, skip file stuff
abext3:	lhld	sfileptr
	mov	a,l
	ani	07fh
	jnz	abext4
	shld	sfilelen
abext4:	mvi	a,eof
	push	psw
	call	putsfile
	pop	psw
	jnz	abext3
 	mvi	c,close
	lxi	d,samfcb
	call	bdos
	inr	a
	jnz	era$same
	lxi	d,no$close
	call	print
;
; erase incomplete file
;
era$same:
;
	mvi	c,delet
	lxi	d,samfcb
	call	bdos
; 
abext5:	call	erxit	; print msg, exit
	db	cr,lf,cr,lf,'++Aborted++$'
;
; exit with message
; 
msgexit:equ	$	; exit with "informational" message
erxit:	pop	d	; get msg
	call	print
; 
; exit, restoring stack and return to ccp
; 
exit:	jmp	0
;
;
DFILES:	LDA	SDISK	;PUT ON SOURCE DISK
	MOV	C,A
	LDA	SUSER	;source user
	MOV	H,A
	LXI	D,SAMB	;SAME FILE NAME
	CALL	SETFILE	;SET UP SAME FILE ON SOURCE
	CALL	CCRLF
;SOURCE/DESTINATION FILE MATCH
	LHLD	SBUFF	;SOURCE BUFFER
	SHLD	BUFF	;START OF BUFFER
	LHLD	DBUFF	;DESTINATIN BUFFER
	SHLD	NAMPTR	;END OF BUFFER
	MVI	A,1000$0000B;FILES THAT MATCH
	LXI	D,SDSAME
	CALL	PDFILE	;DISPLAY FILES THAT MATCH FLAG
;SOURCE/DESTINATION FILE NAME MATCH BUT NOT CONTENTS
	LHLD	SBUFF
	SHLD	BUFF
	LHLD	DBUFF
	SHLD	NAMPTR
	MVI	A,0100$0000B;SAME FILE NAME DIFFERENT COMTENTS
	LXI	D,SDNSAME
	CALL	PDFILE
;SOURCE FILES NOT ON DESTINATION DISK
	LHLD	SBUFF
	SHLD	BUFF
	LHLD	DBUFF
	SHLD	NAMPTR
	MVI	A,0	;FILES THAT DON'T MATCH
	LXI	D,SNOTD
	CALL	PDFILE
;DESTINATION FILES NOT ON SOURCE DISK
	LHLD	DBUFF
	SHLD	BUFF
	LHLD	EDBUFF
	SHLD	NAMPTR
	MVI	A,0	;FILES THAT DON'T MATCH
	LXI	D,DNOTS
	CALL	PDFILE	;FILES THAT DON'T MATCH
	CALL	CRLF
	CALL	CLOSECRC;CLOSE FILE
	RET
;
PDFILE:	STA	FLAG	;SET UP FLAG
	CALL	OUTST	;PRINT MESSAGE
DFILE:	LHLD	BUFF	;NEXT POINTER
	XCHG
	LHLD	NAMPTR	;END OF BUFFER
	CALL	SUBDHC
	RNC		;THATS ALL FOLKS
	LXI	H,FLAG
	LDAX	D	;GET FLAG
	ANI	1100$0000B;TEST FOR FLAGS ONLY
	CMP	M	;TEST FOR THIS FLAG
	JNZ	DNFILE	;NO
	LDAX	D	;GET DESTINATION USER AND FLAG
	INX	D	;PAST FLAG
	ANI	0FH	;MASK OUT FLAGS
	MOV	H,A
	LDAX	D	;GET SOURCE USER
	MOV	L,A
	CALL	DFNAME	;DISPLAY FILE NAME
DNFILE:	LHLD	BUFF	;BUFFER POINTER
	LXI	D,FLEN	;NEXT NAME OFFSET
	DAD	D
	SHLD	BUFF
	JMP	DFILE	;DISPLAY NEXT FILE
;DISPLAY FILE NAME FROM BUFFER
;DE=FILE NAME STARTING WITH USER #
;H=DESTINATION USER #, L=SOURCE USER #
DFNAME:	PUSH	H	;SAVE USER'S
	PUSH	H
	INX	D	;PAST USER
	LXI	H,SAMEP+1
	MVI	B,8
	CALL	MOVE
	INX	H	;FILE NAME.TYPE DELIMETER
	MVI	B,3
	CALL	MOVE
	LDA	HCOUNT	;HORIZONTAL COUNT
	ANI	3	;MASK OUT JUNK
	STA	HCOUNT
	CZ	CRLF
	LXI	D,DELIM
	CNZ	OUTSTL
	POP	H	;GET USER #
	MVI	H,0	;ZERO SECOUND USER
	CALL	DECOUT
	MVI	A,' '	;DELIMETER
	CALL	OUTCHR
	POP	H
	MOV	L,H	;SECOUND USER
	MVI	H,0
	CALL	DECOUT
	LXI	D,SAMEP	;PRINT FILE NAME
	CALL	OUTSTL
	LDA	HCOUNT
	INR	A	;INCREMENT TAB COUNTER
	STA	HCOUNT
	RET
;
DECOPT:	LDAX	D	;GET CHARACTER
	ORA	A	;END OF STRING
	RZ		;THATS ALL FOLKS
	CPI	'$'
	JZ	GOT$
	INX	D
	JMP	DECOPT
GOT$:	INX	D
	LDAX	D
	ORA	A	;END OF STRING
	RZ		;NO MORE OPTIONS
	CPI	'F'	;DISK FLAG
	JNZ	GOT1	;NO
	STA	FFLAG
GOT1:	CPI	'E'	;ERASE EQUAL FILES
	JNZ	GOT2
	STA	EFLAG
GOT2:	CPI	'N'	;DON'T PROMT ERASE
	JNZ	GOT3
	STA	EFLAG	;WHY ENABLE DON'T PROMT W/O ERASE
	STA	NFLAG
GOT3:	CPI	'X'	;USER CRCKLIST.CRC FILE
	JNZ	GOT4
	STA	XFLAG
GOT4:	CPI	'C'	;DISPLAY FILE OPTION
	JNZ	GOT5
	STA	OCFLAG
GOT5:	CPI	'W'	;WAIT FOR DISK CHANGE FLAG
	JNZ	GOT6
	STA	WFLAG
GOT6:	CPI	'D'	;DEFAULT OPTION
	JNZ	GOT7
	STA	DFLAG	;DEFAULT FLAG
	STA	FFLAG	;WRITE FILE
	STA	EFLAG	;ERASE FILES
	STA	NFLAG	;DON'T PROMT
	STA	XFLAG	;USER CRCKLIST.CRC FILE
	STA	WFLAG	;WAIT FLAG
GOT7:	JMP	GOT$
;
FILLFCB:
	MVI	B,11	;FILL LENGTH
FILOOP:	MVI	M,'?'	;FILL CHARACTER
	INX	H	;INCREMENT POINTER
	DCR	B	;COUNTER
	JNZ	FILOOP
	RET
;
;MAKE FCB 8-12-83
;INPUT
; HL=FCB ,DE=INPUT STRING
;OUTPUT
; CARRY = FILE NAME ERROR
; NO CARRY, DE=NEXT CHARACTER ON INPUT STRING
;MAKE FCB WITH COMAND LINE
MAKFCB:	MVI	A,'?'	;SET FLAG
	STA	SUSR	;SELECTED USER
	CALL	SCAN	;GET TO NON SPACE
	ORA	A
	JZ	MAKE1	;END OF STRING
	SBI	40H	;TEST FOR DISK SELECT
	MOV	B,A
	INX	D
	LDAX	D
	CPI	':'	;DISK DELIMETER
	JZ	MAKE3	;YES
	ORA	A	;END OF STRING
	JZ	MAKE1	;YES
	CALL	USERIN	;GET USER #
	RC		;OOPS ERROR
	JZ	MAKE2	;GOT USER #
MAKE0:	DCX	D
MAKE1:	XRA	A	;DEFAULT DRIVE
	MOV	M,A	;SAVE IN FCB
	JMP	MAKE4
MAKE2:	MOV	A,C	;GET USER #
	STA	SUSR	;SELECTED USER
MAKE3:	MOV	M,B	;SAVE SELECTED DISK
	INX	D
MAKE4:	LXI	B,800H	;FILE NAME LENGHT
	CALL	FIELD	;MOVE FILE NAME
	RC		;ERROR
	MVI	B,3	;FILE TYPE LENGHT
	CALL	FIELDT	;MOVE FILE TYPE
	RC		;ERROR
	MVI	A,3	;FILL EX,S1,S2 WITH 0
MAKE5:	INX	H
	MOV	M,B
	DCR	A
	JNZ	MAKE5
	LDA	SUSR
	MOV	B,A	;SAVE POSIBLE USER #
	MOV	A,C
	ORA	A
	RET
;
FIELDT:	CPI	'.'	;NAME.TYPE DELIMETER
	JNZ	BLANKF	;FILE TYPE WITH BLANKS
	INX	D	;GET PAST DELIMETER
FIELD:	CALL	DELIM?
	RC		;ERROR
	JZ	BLANKF	;FILL REST WITH BLANKS
	INX	H
	CPI	'*'
	JNZ	FIELD0	;NON '*'
	MVI	M,'?'	;FILE REST OF NAME
	INR	C	;INCREMENT AMBIGIOUS COUNT
	JMP	FIELD1	;WITH '?'
FIELD0:	MOV	M,A	;MOVE TO FCB
	INX	D	;INCREMENT COMAND LINE
FIELD1:	DCR	B	;DECRIMENT COUNT
	JNZ	FIELD	;CONTINUE WITH FILE NAME
EATUP:	CALL	DELIM?	;EAT UP EXCESS CHARACTER
	RC
	RZ		;TEST DELIMETER
	INX	D
	JMP	EATUP	;CONTINUE UNTIL FOUND
BLANKF:	INX	H	;FILE REST OF FILE NAME W BLANKS
	MVI	M,' '
	DCR	B
	JNZ	BLANKF
	ORA	A	;RESET FLAGS
	RET
;
DELIM?:	LDAX	D	;TEST FOR DELIMETER
	ORA	A	;END OF STRING
	RZ
	CPI	'='
	RZ
	CPI	5FH	;BACK ARROW
	RZ
	CPI	'.'
	RZ
	CPI	':'
	RZ
	CPI	';'
	RZ
	CPI	'<'
	RZ
	CPI	'>'
	RZ
	CPI	' '
	RET
;
SCAN:	LDAX	D	;SCAN TO NEXT CHARACTER >= 30H
	ORA	A
	RZ		;END OF STRING
	CPI	'0'
	RNC
	INX	D
	JMP	SCAN
;
USERIN:	PUSH	H	;SAVE POINTERS
	PUSH	D
	PUSH	B	;SAVE DISK
	LXI	H,0	;ZERO DE
	CALL	ULOOP
	POP	B
	JC	DERR	;OOPS
	MOV	A,H
	ORA	A
	JNZ	DERR	;TO LARGE
	MOV	A,L
	CPI	16	;MAX USER
	JNC	DERR	;>15
	INX	SP	;
	INX	SP
	POP	H	;FCB
	MOV	C,A	;SAVE USER #
	XRA	A	;FLAGS FOR NORMAL RETURN
	RET
DERR:	CMC		;SET UP IF ERROR RETURN
	POP	D	;GET POINTERS BACK
	POP	H
	MVI	A,0
	INR	A	;SET UP NZ W/O CHANGING CARRY
	RET
;
ULOOP:	LDAX	D	;GET A ASCII DIGIT
	CPI	':'	;TERMINATOR
	RZ		;ALL OK
	SUI	'0'	;CONVERT TO BCD AND TEST
	ANA	A	;RESET CARRY
	RM		;TERMINATE CONVERSION IF < ZERO
	CPI	10	;CHECK LEGITIMATE DIGIT (0-9)
	CMC		;COMPLEMENT CARRY
	RC		;RET WITH CARRY SET IF ERROR
	INX	D	;INCR ADDR POINTER
	DAD	H	;SHIFT LEFT 1
	PUSH	H	;SAVE RESULT
	DAD	H
	DAD	H	;SHIFT LEFT 2
	POP	B	;NO * 2 TO B
	DAD	B	;HL NOW CONTAINS 10*NO
	MOV	C,A	;ADD PRODUCT TO DIGIT
	MVI	B,0
	DAD	B
	JMP	ULOOP	;BACK FOR ANOTHER DIGIT
;
ERASE:	LDA	EFLAG
	ORA	A
	RZ
	LDA	DDISK	;SELECT DESTINATION DISK
	MOV	E,A
	MVI	C,14
	CALL	BDOS
	LHLD	DBUFF	;JUST ERASE DESTINATION FILES
	SHLD	BUFF
	LHLD	EDBUFF	;END
	SHLD	NAMPTR
ERASEL:	LHLD	BUFF	;NEXT POINTER
	XCHG
	LHLD	NAMPTR	;END OF BUFFER
	CALL	SUBDHC
	RNC		;THATS ALL FOLKS
	LDAX	D	;GET FLAG
	ANI	1000$0000B;JUST LOOK FOR EQUAL FILES
	JZ	ERASEN	;ONLY ERASE EQAUL FILES
	LHLD	BUFF	;GET TO NAME
	CALL	SETFCB	;GENERATE FCB
	LHLD	BUFF	;GET TO NAME
	XCHG
	INX	D
	INX	D
	LXI	H,SAMEP+1
	MVI	B,8
	CALL	MOVE
	INX	H	;FILE NAME.TYPE DELIMETER
	MVI	B,3
	CALL	MOVE
	LDA	NFLAG	;SEE IF WE PROMT
	ORA	A
	JNZ	ERA	;NO
	LXI	D,ERAFILE
	CALL	PRINT	;ERASE FILE
	MVI	C,1	;GET ANSWER
	CALL	BDOS
	CPI	'y'
	JZ	ERA
	CPI	'Y'
	JNZ	ERASEN	;NO
ERA:	LXI	D,LFCB
	MVI	C,DELET	;ERASE IT
	CALL	BDOS
	CPI	-1	;ERROR
	JZ	ERASER	;CLOSE ERROR
	LHLD	BUFF	;SET ERASED FLAG
	INX	H	;GET TO USER
	MOV	A,M
	ORI	1000$0000B
	MOV	M,A
	LDA	NFLAG	;DON'T PROMT FLAG
	ORA	A
	JZ	ERA
	CALL	CCRLF
	LXI	D,SAMEP+1;GET FILENAME POINTER
	CALL	PRINT
	LXI	D,ERASED
	CALL	PRINT
ERASEN:	LHLD	BUFF	;BUFFER POINTER
	LXI	D,FLEN	;NEXT NAME OFFSET
	DAD	D
	SHLD	BUFF
	JMP	ERASEL
	RET
;
ERASER:	LXI	D,CLOSEM;CAN'T CLOSE FILE
	CALL	PRINT
	JMP	ABEXT5	;ABORT
;
CCRLF:	MVI	E,CR
	MVI	C,2
	CALL	BDOS
	MVI	E,LF
	MVI	C,2
	CALL	BDOS
	RET
;
DISPCRC:
;	LDA	FFLAG
;	ORA	A
;	RZ		;DON'T WRITE FILE
	LDA	OCFLAG	;OPTION FLAG
	STA	CFLAG
	ORA	A
	LXI	D,SFMESG
	CNZ	PRINT
	LDA	S$ACT	;CRCKLIST.CRC ACTIVE FLAG
	ORA	A
	LDA	SDISK	;SOURCE DISK
	MOV	C,A
	LDA	SUSER	;SOURCE USER
	MOV	H,A
	LXI	D,CRCK	;FILE NAME
	CZ	SETFILE	;OPEN FILE
	LHLD	SBUFF	;SOURCE BUFFER START
	XCHG
	LHLD	DBUFF	;END OF SOURCE BUFFER
	CALL	WRTCRC	;WRITE SOURCE FILES
	CALL	CLOSECRC;CLOSE SOURCE FILE
;
	LDA	CFLAG
	ORA	A
	LXI	D,DFMESG
	CNZ	PRINT
	LDA	D$ACT	;CRCKLIST.CRC ACTIVE FLAG
	ORA	A
	LDA	DDISK	;DESTINATION DISK
	MOV	C,A
	LDA	DUSER	;destination user
	MOV	H,A
	LXI	D,CRCK	;FILE NAME
	CZ	SETFILE	;OPEN FILE
	LHLD	DBUFF	;DESTINATION
	XCHG
	LHLD	EDBUFF	;END
	CALL	WRTCRC	;WRITE DESINTATION FILE
	CALL	CLOSECRC;CLOSE DESTINATION FILE
	RET
;
WRTCRC:	SHLD	NAMPTR	;END
	XCHG
	SHLD	BUFF	;START
WCRCLP:	LHLD	BUFF	;NEXT POINTER
	XCHG
	LHLD	NAMPTR	;END OF BUFFER
	CALL	SUBDHC
	RNC		;THATS ALL FOLKS
	LDAX	D	;GET FLAG
	ANI	0001$0000B;JUST SAVE CRC FILES
	STA	FLAG	;SAVE FOR LATER CONVERSION
	INX	D	;PAST FLAG
	LDAX	D	;GET USER #
	ORA	A	;SEE IF ERASED
	JM	WCRCN	;YES, DON'T WRITE
	PUSH	PSW	;SAVE USER #
	INX	D	;GET TO FILE NAME
	LXI	H,FILEN
	MVI	B,8
	CALL	MOVE
	INX	H	;GET PAST .
	MVI	B,3
	CALL	MOVE
	XCHG		;HL=CRC WORD
	XTHL
	PUSH	H	;SAVE USER #
	LXI	D,FILEN	;PRINT LENGHT
	CALL	OUTST
	POP	PSW	;GET USER BACK
	MOV	L,A
	MVI	H,0
	CALL	DECOUT
	LXI	D,CRCM
	LDA	FLAG	;SEE IF WE PRINT CRC
	ORA	A
	CNZ	OUTST
	POP	H	;GET CRC BYTES
	MOV	E,M	;LSB
	INX	H
	MOV	D,M	;MSB
	XCHG
	LDA	FLAG
	ORA	A
	CNZ	HEXHL	;DISPLAY CRC WORD
	CALL	CRLF
WCRCN:	LHLD	BUFF	;BUFFER POINTER
	LXI	D,FLEN	;NEXT NAME OFFSET
	DAD	D
	SHLD	BUFF
	JMP	WCRCLP	;DISPLAY NEXT FILE
;
GETSAME:
	LXI	H,0	;RESET FLAGS
	SHLD	ACT$CRCK
	LDA	XFLAG
	ORA	A	;ACTIVE
	RZ		;NO
	XRA	A
	STA	FCBFINAL+12;EXTENT
	STA	FCBFINAL+15;RC
	STA	FCBFINAL+32;CR
	LXI	D,FCBFINAL
	MVI	C,OPEN
	CALL	BDOS	;OPEN FILE
	CPI	-1
	RZ		;DO NORMAL SORT
	MVI	A,-1	;SET CRCKLIST.CRC ACTIVE ON DISK
	STA	ACT$CRCK
	LHLD	BUFF	;GET BUFFER POINTER
	XCHG
	INX	D	;PUT NAME AT CORRECT OFFSET FROM START
	INX	D
READ$SAME:
	LXI	H,80H	;DMA OFFSET
	DAD	D
	PUSH	H	;SAVE NEXT POINTER
	MVI	C,STDMA
	CALL	BDOS
	LXI	D,FCBFINAL
	MVI	C,READ
	CALL	BDOS	;READ NEXT RECORD
	ORA	A	;END OF DATA
	POP	D	;NEXT DMA ADDRESS
	JZ	READ$SAME;CONTINUE LOOP
	MVI	B,16	;FILL NEXT NAME WORTH
	MVI	A,'Z'-40H
FILL$NEXT:
	STAX	D
	INX	D
	DCR	B
	JNZ	FILL$NEXT
	LHLD	BUFF	;START OF BUFFER
	MOV	D,H	;DE=HL
	MOV	E,L
	INX	D
	INX	D
NEXT$NAME:
	CALL	NSCAN	;GET TO START OF NAME
	JC	END$SAME;THATS ALL FOLKS
	PUSH	H	;SAVE FLAG POINTER
	PUSH	H	;SAVE POINTER
	LHLD	NAMCNT
	INX	H	;INCREMENT NAME COUNT
	SHLD	NAMCNT
	POP	H
	MVI	M,0	;ZERO OUT FLAGS & USER
	INX	H
	LDA	OLDUSR	;PRESET TO OLD USER
	MOV	M,A	;DEFAULT USER
	PUSH	H	;USER POINTER #
	INX	H
	MVI	B,8
	CALL	MOVE
	INX	D	;GET PAST DELIMETER
	MVI	B,3
	CALL	MOVE
	POP	B	;USER POINTER
	LDAX	D	;NEXT CHARACRE
	CPI	TAB	;CRCK GENERATED
	JZ	GET$CRC
	PUSH	H	;SAVE BUFFER POINTER
	LXI	H,USROF	;OFFSET TO USER #
	DAD	D
	XCHG
	CALL	DECIN	;GET USER
	POP	H	;DESTINATIN BACK
	STAX	B
	MVI	A,-1	;SET SAME.COM GENERATED FLAG
	STA	SFLAG	;SAME FLAG
GET$CRC:
	LDAX	D	;GET CHARACTER
	CPI	'Z'-40H	;END OF DATA
	JZ	NO$CRC
	CPI	CR	;END OF STRING
	JZ	NO$CRC
	INX	D	;POINT TO NEXT CHARACTER
	CPI	'='
	JNZ	GET$CRC	;NOT YET
	CALL	NSCAN	;GET TO CRC WORD
	JC	NO$CRC	;OOPS
	PUSH	H	;SAVE DESTINATION POINTER
	CALL	HEXIN	;GET CRC DATA
	LDAX	D
	INX	D	;POINT TO NEXT CHARACTER
	STA	CRCTYPE	;CRC TYPE
	CPI	' '
	CZ	IN1	;YES
	MOV	B,H	;BC=HL
	MOV	C,L
	POP	H	;DESTINATION POINTER
	MVI	A,0001$0000B;CRC ACTIVE FLAG
	JMP	SET$CRC
NO$CRC:	LXI	B,0	;ZERO OUT CRC
	MVI	A,0	;CRC INACTIVE FLAG
SET$CRC:
	MOV	M,C	;SET CRC
	INX	H
	MOV	M,B
	INX	H
	MVI	M,0
	INX	H
	POP	B	;GET CRC FLAG POINTER
	STAX	B
	JMP	NEXT$NAME
END$SAME:
	SHLD	NAMPTR	;END OF BUFFER
	LXI	D,80H	;SET DEFAULT DMA
	MVI	C,STDMA
	CALL	BDOS
	LHLD	NAMCNT	;NAMES IN BUFFER
	MOV	A,H
	ORA	L
	RZ		;NO NAMES IN BUFFER
	LDA	DTYPE	;DEFAULT
	ORA	A
	STC		;RETURN FLAG
	RZ
	LDA	SFLAG	;SAME GENERATED FLAG
	ORA	A
	RZ		;NOT SAME.COM GENERATED
	STC
	RET
;
NSCAN:	LDAX	D	;SCAN TO NEXT CHARACTER >= 30H
	CPI	'Z'-40H	;END OF STRING
	STC		;END OF DATA
	RZ		;END OF STRING
	CPI	'0'
	RNC
	INX	D
	JMP	NSCAN
;
DECIN:	PUSH	B	;SAVE POINTERS
	LXI	H,0
	CALL	DLOOP
	MOV	A,L	;SINGLE BYTE
	POP	B
	RET
;
DLOOP:	LDAX	D	;GET A ASCII DIGIT
	SUI	'0'	;CONVERT TO BCD AND TEST
	ANA	A	;RESET CARRY
	RM		;TERMINATE CONVERSION IF < ZERO
	CPI	10	;CHECK LEGITIMATE DIGIT (0-9)
	CMC		;COMPLEMENT CARRY
	RC		;RET WITH CARRY SET IF ERROR
	INX	D	;INCR ADDR POINTER
	DAD	H	;SHIFT LEFT 1
	PUSH	H	;SAVE RESULT
	DAD	H
	DAD	H	;SHIFT LEFT 2
	POP	B	;NO * 2 TO B
	DAD	B	;HL NOW CONTAINS 10*NO
	MOV	C,A	;ADD PRODUCT TO DIGIT
	MVI	B,0
	DAD	B
	JMP	DLOOP	;BACK FOR ANOTHER DIGIT
;
HEXIN:	LXI	H,0	;ZERO NUMBER
IN1:	LDAX	D	;GET A CHAR
	ORA	A	;CHECK FOR END OF BUFFER
	RZ
	SUI	'0'	;CHECK < 0 AND CONVERT TO HEX
	RC
	ADI	'0'-'G'	;CHECK > F
	RC
	ADI	6
	JP	IN2	;NO BETWEEN A AND F
	ADI	7
	RC
IN2:	ADI	10
	ORA	A	;CLEAR CARRY
	PUSH	B	;SAVE REG
	MOV	C,A	;HEX DIGIT TO C
	MVI	B,0	;ZERO TO B
	DAD	H
	DAD	H
	DAD	H
	DAD	H	;SHIFT LEFT 4
	DAD	B	;ADD IN NEW DIGIT
	POP	B
	INX	D	;INCR BUFFER POINTER
	JMP	IN1	;RETURN FOR MORE INPUT
;
HEXHL:	MOV	A,H
	PUSH	H
	CALL	HEXOUT
	POP	H
	MOV	A,L
HEXOUT:	PUSH	PSW
	RRC
	RRC
	RRC
	RRC		;SHIFT RIGHT 4
	CALL	NIBBLE
	POP	PSW
NIBBLE: ANI	0FH	;MASK 4 BITS
	ADI	90H	;ADD OFFSET
	DAA		;DEC ADJUST
	ACI	40H	;ADD OFFSET
	DAA		;DEC ADJUST
	JMP	OUTCHR
;
SUBDHC:	CALL	SUBDH	;SUBTRACT
	RZ		;NC ALRIGHT
	CMC		;SET UP FOR NC END OF COMPARE
	RET
;HL=HL-DE
SUBDH:	MOV	A,L
	SUB	E
	MOV	L,A
	MOV	A,H
	SBB	D
	MOV	H,A
	RC		;PAST END
	ORA	L	;TEST FOR 0
	RET
;
SETUSR:	MOV	E,A	;SET TO OLD
	MVI	C,32
	CALL	BDOS
	RET
;
SAMDSK:	LXI	D,SDSKM
	JMP	ERROR
BADFCB:	LXI	D,BFCBM	;BAD FCB ERROR
	JMP	ERROR
NSAME:	LXI	D,SAMEM
	JMP	ERROR
NOFILE:	LXI	D,NFILES
ERROR:	CALL	PRINT
RETURN:	LDA	OLDUSR
	CALL	SETUSR
	JMP	0
;
HELP:	MVI	A,0	;CHANGE DELIMETER CHARACTER
	STA	OUTSTL+2;SELF MODIFYING CODE TO DISPLAY DOLLAR SIGNS
	LXI	D,HELPM
	CALL	OUTSTL	;PRINT MESSAGE
	JMP	0	;THATS ALL FOLKS
;
OUTST:	XRA	A
	STA	HCOUNT
OUTSTL:	LDAX	D	;GET CHARACTER
	CPI	'$'
	RZ
	CALL	OUTCHR
	INX	D
	JMP	OUTSTL
;
PRINT:	PUSH	H	;SAVE REGS
	PUSH	D
	PUSH	B
	XRA	A
	STA	HCOUNT
	MVI	C,9
	CALL	BDOS
	POP	B
	POP	D
	POP	H
	RET
;
DECOUT:	PUSH	H	;SAVE REGS
	PUSH	D
	PUSH	B
	LXI	B,-10	;RADIX FOR CONVERSION
	LXI	D,-1	;THIS BECOMES NO DIVIDED BY RADIX
DX:	DAD	B	;SUBTRACT 10
	INX	D
	JC	DX
	LXI	B,10
	DAD	B	;ADD RADIX BACK IN ONCE
	XCHG
	MOV	A,H
	ORA	L	;TEST FOR ZERO
	CNZ	DECOUT	;RECURSIVE CALL
	MOV	A,E
	ADI	'0'	;CONVERT FROM BCD TO HEX
	CALL	OUTCHR
	POP	B	;RESTORE REGISTERS
	POP	D
	POP	H
	RET
;
MOVE:	LDAX	D	;FROM
	MOV	M,A	;TO
	INX	H
	INX	D
	DCR	B
	JNZ	MOVE
	RET
;
SIGNON:	DB	'Same vers 1.01$'
NFILES:	DB	CR,LF,'Directory empty$'
OOPSM:	DB	CR,LF,'File not found that was found last pass$'
SDSKM:	DB	CR,LF,'Same disk and user$'
WAIT:	DB	      'Insert disks to compare and hit any key$'
DONE:	DB	      'Search and Destroy complete$'
FWAIT:	DB	CR,LF,'Insert systemd disk then hit any key$'
BFCBM:	DB	CR,LF,'Bad filename in comand line$'
SAMEM:	DB	CR,LF,'Same file name in different user #$'
SORTING:DB	CR,LF,'Sorting Directory entries$'
ERAFILE: DB	CR,LF,'Erase file <Y,?> '
SAMEP:	DB	' FILENAME',' ','TYP',' $'
DELIM:	DB	'| $'
ERASED:	DB	'file erased$'
SDSAME:	DB	      'Source/Destination file''s same$'
SDNSAME:DB	CR,LF,'Source/Destination file name''s same, '
	DB	'file''s different$'
SNOTD:	DB	CR,LF,'Source name''s not found on destination disk$'
DNOTS:	DB	CR,LF,'Destination name''s not found on source disk$'
WAIT?:	DB	CR,LF,'Hit any key to display results$'
CLOSEM:	DB	CR,LF,'Erase error$'
SFMESG:	DB	CR,LF,'Source disk files',CR,LF,'$'
DFMESG:	DB	      'Destinaion disk files',CR,LF,'$'
;
dir$full:	db	cr,lf
	db	'++No Directory Space for CRC File++'
	db	'$'
;
dsk$full:	db	cr,lf
	db	'++No Disk Space for CRC File++'
	db	'$'
;
no$close:	db	cr,lf
	db	'++Cannot Close CRC File++'
	db	'$'
HELPM:	DB	'Commands:   same drive[user]:name.typ '
	DB	'drive[user]:name.type [$f,e,n,c,x,w,d]',CR,LF
	DB	'	commas are just used here for diferentiating instrusctions',CR,LF
	DB	CR,LF
	DB	'    Options	Descriptionns',CR,LF
	DB	'	$	start options',CR,LF
	DB	'	F	Write compare text to SAMELIST.PRN and crc data',CR,LF
	DB	'		to CRCKLIST.CRC on each disk and default user if',CR,LF
	DB	'		no user selected',CR,LF
	DB	'	E	Erase files that are equal',CR,LF
	DB	'	N	Don''t promt operator to erase file',CR,LF
	DB	'	C	Display CRCKLIST.CRC files on console',CR,LF
	DB	'	X	Use existing CRCKLIST.CRC files from selected',CR,LF
	DB	'		user or default user. Uses old crc generation if',CR,LF
	DB	'		old CRCKLIST.CRC encounteredss',CR,LF
Y	DB	'	W	Wait and promt operator for disk change',CR,LF
	DB	'	D	Default to F,E,N,X,W options',CR,LF
	DB	CR,LF
	DB	'Examples:',CR,LF
	DB	CR,LF
	DB	' same a: b: compare all file''s all user''s on a: to same on b:',CR,LF
	DB	' same a0: b0: compare all file''s user 0 on a: to same on b:',CR,LF
	DB	' same a:*.asm b:*.asm $fwn'
	DB	0
FILEN:	DB	'FILENAME.TYP'
USER:	DB	'    USER $'
USROF	EQU	$-USER
CRCM:	DB	9,' CRC = $'
;
ACT$CRCK DB	0	;CRCKLIST.CRC FILE ACTIVE
CRCTYPE	DB	0	;FLAG FOR CRC TYPE
;
BUFF:	DW	NAMBUF	;BUFFER POINTER
NAMPTR:	DW	NAMBUF	;BUFFER POINTER
NAMCNT:	DW	0	;NAME'S IN BUFFER
;
MFILES:	DB	0	;MULTIPLE FILES FLAG
OLDUSR:	DB	0	;OLD USER #
;
CMPFCB:	DW	0	;COMPARE FCB
SUSR:	DB	0	;SELECTED USER #
;
SDISK:	DB	0	;SOURCE DISK
SUSER:	DB	0	;SOURCE USER
S$ACT:	DB	0	;CRCKLIST.CRC ACTIVE
S$TYPE:	DB	0	;CRCK TYPE
SBUFF:	DW	NAMBUF	;NAME BUFFER
SSBUFF:	DW	NAMBUF	;SEARCH NAME BUFFER
SSFCB:	DW	NAMBUF	;SOURCE FILE NAME POINTER
;
DDISK:	DB	0	;DESINATION DISK
DUSER:	DB	0	;DESINTION USER
D$ACT:	DB	0	;CRCKLIST.CRC ACTIVE FLAG
D$TYPE:	DB	0	;CRCK TYPE
DBUFF:	DW	NAMBUF	;NAME BUFFER
SDBUFF:	DW	NAMBUF	;SEARCH NAME BUFFER
SDFCB:	DW	NAMBUF	;DESTINATION FILE NAME POINTER
EDBUFF:	DW	NAMBUF	;END NAME BUFFER
;
FLAG:	DB	0	;DISPLAY COMPARE FLAG
HCOUNT:	DB	0
CPASS:	DB	0	;COMPARE PASS
CRCFCB:	DW	0	;CRC GENERATION NAME POINTER
;
; program storage area
; 
active:	db	0	; fcb active
dflag:	db	0	; default option
sflag:	db	0	; same.com generted crcklist.crc flag
cflag:	db	-1	; display file flag
ocflag:	db	0	; option selected display file flag
wflag:	db	0	; wait for operator to change disk's flag
fflag:	db	0	; file write request flag
eflag:	db	0	; erase equal files flag
nflag:	db	0	; don't promt erase file
xflag:	db	0	; use crcklist.crc for files
rem:	dw	0	; crc remainder storage
bufad:	ds	2	; read buffer address
;
hitab:	ds	512	; the 2 tables for crc lookup
;
sfilelen:
;
	dw	sfilesiz
;
sfileptr:
;
	ds	2
;
SAMB:	DB	'SAMELISTPRN'
CRCK:	DB	'CRCKLISTCRC'
; 
; build fcb for final name of crcklist.crc
;
fcbfinal:
;
	db	0,'CRCKLISTCRC'
	db	0
	ds	20
;
; 'declare' fcb for output file (temporarily named crcklist.$$$)
;
samfcb:
;
	db	0,'????????$$$'
	db	0
	ds	20
;
sfileadr:
;
	dw	sfilebuff	; buffer all crc file data here
;
SFCB:	DB	0,'????????','???',0,0,0,0
	DB	0,0,0,0,0,0,0,0
	DB	0,0,0,0,0,0,0,0
	DB	0,0,0,0
;
DFCB:	DB	0,'????????','???',0,0,0,0
	DB	0,0,0,0,0,0,0,0
	DB	0,0,0,0,0,0,0,0
	DB	0,0,0,0
;
UFCB:	DB	'?','????????','???',0,0,0,0
	DB	0,0,0,0,0,0,0,0
	DB	0,0,0,0,0,0,0,0
	DB	0,0,0,0
;
LFCB:	DB	0,'????????','???',0,0,0,0
	DB	0,0,0,0,0,0,0,0
	DB	0,0,0,0,0,0,0,0
	DB	0,0,0,0
;
	DS	40
STACK:
sfilebuff:
	ds	sfilesiz
	DS	16-($ AND 0FH)
NAMBUF:
	END
