;
;		CRCK.ASM version 3.0
;		 (revised 8/10/80)
;
;PROGRAM TO READ ANY CP/M FILE AND PRINT A
;CYCLIC-REDUNDANCY-CHECK NUMBER BASED ON THE
;CCITT STANDARD POLYNOMINAL:
;   X^16 + X^15 + X^13 + X^7 + X^4 + X^2 + X + 1
;
;USEFUL FOR CHECKING ACCURACY OF FILE TRANSFERS.
;MORE ACCURATE THAN A SIMPLE CHECKSUM.
;
;COMMANDS:   (drive name may be specified)
;	CRCK FILENAME.FILETYPE
;	CRCK *.ASM
;	CRCK *.*
;
;06/27/79 FIRST WRITTEN BY KEITH PETERSEN, W8SDZ
;
;08/19/79 ADD CONDITIONAL ASSEMBLY FOR CP/M
;	  ON H8 OR TRS-80.  (KBP)
;
;08/20/79 FIX BUG IN READIT ROUTINE WHICH
;	  SHOWED UP ONLY ON ALTCPM OPTION. (KBP)
;
;04/21/80 ADD MULTIPLE FILENAME FEATURE, PRINT
;	  NAME OF CURRENT FILE BEING READ, AND
;	  ALLOW OPERATOR ABORT. (KBP)
;
;04/23/80 CORRECT OMISSION OF SHR 8 IN MFA ROUTINE.
;	  ERROR ONLY SHOWED UP FOR ALTCPM ASSEMBLY
;	  ADD COLON AFTER ---> FILE:    (KBP)
;
;08/10/80 ADD ROUTINES TO ALLOW CONDITIONAL ASSEMBLY
;         OF WILDCARD ROUTINES AND TO ALLOW "SYSTEM"
;         FILES TO BE EXCLUDED FROM WILDCARD OPTION.
;         (BY DAVE HARDY)
;
TRUE	EQU	1
FALSE	EQU	0
;
;
STDCPM	EQU	TRUE	;TRUE IS STANDARD CP/M
ALTCPM	EQU	FALSE	;TRUE IS H8 OR TRS-80
WILDCD	EQU	TRUE	;WANT WILDCARDS IN FILENAME?
SYSFILE	EQU	FALSE	;WANT SYS FILES IN WILDCARDS?
;
BASE	SET	0
;
	IF	ALTCPM
BASE	SET	4200H
	ENDIF		;ALTCPM
;
CR	EQU	0DH
LF	EQU	0AH
TAB	EQU	09H
;
	ORG	BASE+100H
;
	JMP	BEGIN	;JUMP AROUND IDENTIFICATION
	DB	'CRCK ver 3.0 8/3/80 '
;
BEGIN:	LXI	H,0	;GET STACK...
	DAD	SP	;POINTER SO WE CAN...
	SHLD	STACK	;SAVE IT
	LXI	SP,STACK ;INITIALIZE LOCAL STACK
	CALL	START
	DB	'CRCK ver 3.0'
	DB	CR,LF,CR,LF,'$'
;
START	POP	D	;GET ID
	MVI	C,PRINT
	CALL	BDOS	;PRINT ID
;
	IF	WILDCD
AGAIN	CALL	MFNAME	;SEE IF FILE NAME TO READ
	ENDIF
	IF	WILDCD AND NOT SYSFILE
	JC	AGEND
	LDA	FCB+10	;GET SYS ATTRIBUTE
	ANI	80H
	JNZ	AGAIN	;IGNORE IF SYSTEM FILE
	ENDIF
	IF	WILDCD
	JNC	NAMEPR	;YES, GO READ IT
	ENDIF
	IF	NOT WILDCD
	JMP	NAMEPR	;READ SINGLE FILE NAME
	ENDIF
AGEND	CALL	MSGEXIT	;NONE, PRINT MSG THEN EXIT
	DB	'DONE$'
	IF	NOT WILDCD
AGEND2	CALL	MSGEXIT	;BAD FILENAME MSG
	DB	'++ WILDCARDS NOT ALLOWED$'
	ENDIF
;
NAMEPR:	;PRINT FILENAME.TYPE
;MOVE 8 CHARACTERS FROM FCB+1 TO FNAME
	LXI	H,FCB+1
	LXI	D,FNAME
	LXI	B,8
	CALL	MOVER
;MOVE 3 CHARACTERS FROM FCB+9 TO FNAME+9
	LXI	H,FCB+9
	LXI	D,FNAME+9
	LXI	B,3
	CALL	MOVER
	IF	NOT	WILDCD	;WEED OUT WILDCARDS
	MVI	C,11
	LXI	H,FNAME	;POINT TO FILENAME
NEXTCH	MOV	A,M	;CHECK FOR * OR ?
	CPI	'*'
	JZ	AGEND2	;JUMP OUT IF WILDCARD
	CPI	'?'
	JZ	AGEND2
	DCR	C
	INX	H
	JNZ NEXTCH	;TRY ALL 11 CHARS IN FILENAME
	ENDIF
	CALL	NAMEP2
	DB	'--> FILE:  '
FNAME:	DB	'XXXXXXXX.XXX',TAB,TAB,'CRC = $'
;
NAMEP2:	POP	D	;GET ADRS OF STRING
	MVI	C,PRINT
	CALL	BDOS	;PRINT FILENAME.TYPE
;
;OPEN THE FILE
	LXI	D,FCB
	MVI	C,OPEN
	CALL	BDOS
	INR	A
	JNZ	INITIT
	CALL	ERXIT
	DB	CR,LF,'++OPEN FAILED++$'
;
;INITIALIZE THINGS
INITIT:	LXI	H,0
	SHLD	REM	;INIT CRC REMAINDER TO ZERO
	LXI	H,BASE+100H
	SHLD	BUFAD	;FORCE INITIAL READ
;
READIT:	LHLD	BUFAD
	MOV	A,H	;TIME TO READ?
	CPI	BASE SHR 8
	JZ	NORD	;NO READ
	MVI	C,CONST
	CALL	BDOS	;CHECK FOR OPERATOR ABORT
	ORA	A
	JZ	READ2	;NOTHING FROM OPERATOR
	MVI	C,RDCON
	CALL	BDOS	;GET CHARACTER INPUTTED
	CPI	'C'-40H	;CONTROL C?
	JZ	EXIT	;YES EXIT
;
READ2:	LXI	D,FCB
	MVI	C,READ
	CALL	BDOS
	ORA	A
	JNZ	FINISH	;ERROR OR EOF
	LXI	H,BASE+80H ;BUFFER LOCATION
NORD	MOV	A,M
	STA	MESS	;SAVE FOR DIVP
	INX	H
	SHLD	BUFAD
	CALL	DIVP
	JMP	READIT
;
FINISH:	LDA	REM+1	;GET MSP OF CRC
	CALL	HEXO	;PRINT IT
	MVI	A,' '
	CALL	TYPE	;TYPE A SPACE
	LDA	REM	;GET LSP OF CRC
	CALL	HEXO	;PRINT IT
	LXI	D,NEWLIN ;POINT TO CRLF
	MVI	C,PRINT
	CALL	BDOS	;PRINT IT
	IF	NOT WILDCD
	JMP	AGEND	; DONE IF SINGLE FILE NAME
	ENDIF
	IF	WILDCD
	JMP	AGAIN	;SEE IF MORE FILES TO DO
	ENDIF
;
NEWLIN:	DB	CR,LF,CR,LF,'$'
;
;---------------------------------------------
;AN 8080 ROUTINE FOR GENERATING A CYCLIC-
;REDUNDANCY-CHECK.  CHARACTER LEAVES THAT
;CHARACTER IN LOCATION REM.  BY FRED GUTMAN.
;FROM 'EDN' MAGAZINE, JUNE 5, 1979 ISSUE, P84.
;
DIVP:	LHLD	REM	;GET REMAINDER
	MOV	A,H
	ANI	128	;Q-BIT MASK
	PUSH	PSW	;SAVE STATUS
	DAD	H	;2 X R(X)
	LDA	MESS	;MESSAGE BIT IN LSB
	ADD	L
	MOV	L,A
	POP	PSW
	JZ	QB2	;IF Q-BIT IS ZERO
QB:	MOV	A,H
	XRI	0A0H	;MS HALF OF GEN. POLY
	MOV	H,A
	MOV	A,L
	XRI	97H	;LS HALF OF GEN. POLY
	MOV	L,A
QB2:	SHLD	REM
	RET
;--------------------------------------------
;
;HEX OUTPUT
;
HEXO	PUSH	PSW	;SAVE FOR RIGHT DIGIT
	RAR		;RIGHT..
	RAR		;..JUSTIFY..
	RAR		;..LEFT..
	RAR		;..DIGIT..
	CALL	NIBBL	;PRINT LEFT DIGIT
	POP	PSW	;RESTORE RIGHT
NIBBL	ANI	0FH	;ISOLATE DIGIT
	CPI	10	;IS IS <10?
	JC	ISNUM	;YES, NOT ALPHA
	ADI	7	;ADD ALPHA BIAS
ISNUM	ADI	'0'	;MAKE PRINTABLE
;
TYPE	PUSH	B
	PUSH	D
	PUSH	H
	MOV	E,A
	MVI	C,WRCON
	CALL	BDOS
	POP	H
	POP	D
	POP	B
	RET
;
;
;	MFA.LIB		(revised 4/23/80)
;
;MULTI-FILE ACCESS SUBROUTINE.  ALLOWS PROCESSING
;OF MULTIPLE FILES (I.E. *.ASM) FROM DISK.  THIS
;ROUTINE BUILDS THE PROPER NAME IN THE FCB EACH
;TIME IT IS CALLED.  JUST CALL "MFNAME" (MULTIPLE
;FILE NAME) AND THE FCB WILL BE SET UP WITH THE NEXT
;NAME, READY TO DO NORMAL PROCESSING (OPEN, READ, ETC.)
;
;CARRY IS SET IF NO MORE NAMES CAN BE FOUND
;
;------------------------------------------------
;
;	MULTI-FILE ACCESS SUBROUTINE
;
;THE ROUTINE IS COMMENTED IN PSEUDO CODE,
;EACH PSEUDO CODE STATEMENT IS IN <<...>>
;
MFNAME:	;<<INIT DMA ADDR, FCB>>
	PUSH	B
	PUSH	D
	PUSH	H
	MVI	C,STDMA
	LXI	D,BASE+80H
	CALL	BDOS
	POP	H
	POP	D
	POP	B
	XRA	A
	STA	FCBEXT
	STA	FCBRNO
;<<IF FIRST TIME>>
	LDA	MFFLG1
	ORA	A
	JNZ	MFN01
;<<TURN OFF 1ST TIME SW>>
	MVI	A,1
	STA	MFFLG1
;<<SAVE THE REQUESTED NAME>>
;SAVE ORIG REQ
	LXI	H,FCB
	LXI	D,MFREQ
	LXI	B,12
	CALL	MOVER
	LDA	FCB
	STA	MFCUR	;SAVE DISK IN CURR FCB
;<<SRCHF REQ NAME>>
	LXI	H,MFREQ
	LXI	D,FCB
	LXI	B,12
	CALL	MOVER
	PUSH	B
	PUSH	D
	PUSH	H
	MVI	C,SRCHF
	LXI	D,FCB
	CALL	BDOS
	POP	H
	POP	D
	POP	B
;<<ELSE>>
	JMP	MFN02
;
MFN01:	;<<SRCHF CURR NAME>>
	LXI	H,MFCUR
	LXI	D,FCB
	LXI	B,12
	CALL	MOVER
	PUSH	B
	PUSH	D
	PUSH	H
	MVI	C,SRCHF
	LXI	D,FCB
	CALL	BDOS
	POP	H
	POP	D
	POP	B
;<<SRCHN REQ NAME>>
	LXI	H,MFREQ
	LXI	D,FCB
	LXI	B,12
	CALL	MOVER
	PUSH	B
	PUSH	D
	PUSH	H
	MVI	C,SRCHN
	LXI	D,FCB
	CALL	BDOS
	POP	H
	POP	D
	POP	B
;<<ENDIF>>
MFN02:	;<<RETURN CARRY IF NOT FOUND>>
	INR	A
	STC
	RZ
;<<MOVE NAME FOUND TO CURR>>
	DCR	A
	ANI	3
	ADD	A
	ADD	A
	ADD	A
	ADD	A
	ADD	A
	ADI	81H
	MOV	L,A
	MVI	H,BASE SHR 8
	PUSH	H	;SAVE NAME POINTER
	LXI	D,MFCUR+1
	LXI	B,11
	CALL	MOVER
;<<MOVE NAME FOUND TO FCB>>
	POP	H
	LXI	D,FCB+1
	LXI	B,11
	CALL	MOVER
;<<SETUP FCB>>
	XRA	A
	STA	FCBEXT
	STA	FCBRNO
;<<RETURN>>
	RET
;
;MOVE SUBROUTINE
;
MOVER	MOV	A,M
	STAX	D
	INX	H
	INX	D
	DCX	B
	MOV	A,B
	ORA	C
	JNZ	MOVER
	RET
;
;------------------------------------------
;
;EXIT WITH MESSAGE
;
MSGEXIT	EQU	$	;EXIT W/"INFORMATIONAL" MSG
ERXIT	POP	D	;GET MSG
	MVI	C,PRINT
	CALL	BDOS
;
;EXIT, RESTORING STACK AND RETURN
;
EXIT:	LHLD	STACK
	SPHL
	RET		;TO CCP
;
REM:	DW	0	;REMAINDER STORAGE
BUFAD	DS	2	;BUFFER ADDRESS
MESS:	DS	1	;MESSAGE CHAR GOES HERE
;
;MULTI-FILE ACCESS WORK AREA
;
MFFLG1	DB	0	;1ST TIME SW
MFREQ	DS	12	;REQ NAME
MFCUR	DS	12	;CURR NAME
;
	DS	64	;STACK AREA
STACK	DS	2
;
;BDOS/CBIOS EQUATES
RDCON	EQU	1
WRCON	EQU	2
PRINT	EQU	9
CONST	EQU	11
OPEN	EQU	15
CLOSE	EQU	16
SRCHF	EQU	17
SRCHN	EQU	18
ERASE	EQU	19
READ	EQU	20
WRITE	EQU	21
MAKE	EQU	22
REN	EQU	23
STDMA	EQU	26
BDOS	EQU	BASE+5
FCB	EQU	BASE+5CH 
FCB2	EQU	BASE+6CH
FCBEXT	EQU	FCB+12
FCBRNO	EQU	FCB+32
;
	END

