;***********************************************
;	crcio_.asm -- input/output
;***********************************************
			page	0, 128

include	amscls.inc
$_init	GEN

CGROUP	GROUP	TEXT
DGROUP	GROUP	DATA,BSS

TEXT	segment byte public 'CODE'
	assume	cs:CGROUP, ds:DGROUP, ss:DGROUP
TEXT	ends

DATA	segment byte public 'DATA'
DATA	ends

BSS	segment byte public 'DATA'
			public	infile_
infile_		dw	1 dup (?)
			public	outfile_
outfile_	dw	1 dup (?)
			public	dispflg_
dispflg_	dw	1 dup (?)

crctable_	dw	100h dup (?)
			public	crc_
crc_		dw	1 dup (?)
			public	bitbuf_
bitbuf_		dw	1 dup (?)

subbitbuf_	db	1 dup (?)
bitcount_	db	1 dup (?)


BSS	ends
TEXT	segment byte public 'CODE'
	assume	cs:CGROUP, ds:DGROUP, ss:DGROUP

;
;void make_crctable(uchar crcpoly)
;

	public	make_crctable_
make_crctable_:
	cld
	push	ds
	pop		es
	push	cx
	push	dx
	push	di
	mov		bx, ax
	mov 	di, offset DGROUP:crctable_
	xor 	dx, dx
	$_do
		mov 	ax, dx
		mov 	cx, 8
		$_do
			$_if <shr ax, 1>, C
				xor 	ax, bx
			$_endif
		$_until <LOOP>
		stosw
	$_until <inc dl>, Z
	pop 	di
	pop 	dx
	pop 	cx
	ret

;
;ushort calccrc(uchar *p, uint n)
;

	public	calccrc_
calccrc_:		
	push	cx
	push	si
	mov		si, ax
	mov		cx, bx
	mov		bx, crc_
	jcxz	nofile
	xor		ah, ah
	cld
	$_do
		lodsb
		xor		bl, al
		mov		al, bh
		mov		bh, ah
		shl		bx, 1
		mov		bx, crctable_[bx]
		xor		bx, ax
	$_until <LOOP>
nofile:
	mov		ax, bx
	mov		crc_, ax
	pop		si
	pop		cx
	ret

;
;ushort getbits(uchar n)
;

	public	getbits_
getbits_:		
	push	cx
	mov		cl, 16
	sub		cl, al
	push	bitbuf_
	call	fillbuf_
	pop		ax
	shr		ax, cl
	pop		cx
	ret

;
;	stream control structure of LSI C-86
;

iob		struc
mode		db		?
ptr			dw		?
rcount		dw		?
wcount		dw		?
base		dw		?
bufsiz		dw		?
fd			dw		?
smallbuf	db		?
iob		ends

;
;void fillbuf(uchar n)  /* Shift bitbuf n bits left, read n bits */
;

	public	fillbuf_
fillbuf_:
	push	cx
	push	dx
	mov		ch, al
	mov		cl, bitcount_
	mov		dx, bitbuf_
	mov		al, subbitbuf_
	$_if <cmp ch, cl>, A
		sub		ch, cl
		shl		dx, cl
		rol		al, cl
		add		dl, al
		mov		cl, 8
fb1:
		xor		ax, ax
		sub		word ptr compsize_, 1
		sbb		word ptr compsize_ + 2, ax
		$_if , NS
			mov		bx, infile_
			$_if <dec rcount[bx]>, NS
				inc		ptr[bx]
				mov		bx, ptr[bx]
				mov		al, [bx - 1]
			$_else
				mov		ax, bx
				push	bx
				call	fgetc_
				pop		bx
				$_if <or ax, ax>, S
					mov		ax, offset DGROUP:RDERR_
					jmp		fileerror_
				$_endif
			$_endif
		$_endif
		$_if <cmp ch, cl>, A
			sub		ch, cl
			mov		dh, dl
			mov		dl, al
			jmp		fb1
		$_endif
	$_endif
	sub		cl, ch
	mov		bitcount_, cl
	mov		cl, ch
	xor		ah, ah
	shl		dx, cl
	shl		ax, cl
	add		dl, ah
	mov		bitbuf_, dx
	mov		subbitbuf_, al
	pop		dx
	pop		cx
	ret


;
;void putbits(uchar n, ushort x)  /* Write rightmost n bits of x */
;

	public	putbits_
putbits_:
	push	cx
	mov		cl, 16
	sub		cl, al
	shl		bx, cl
	pop		cx


;
;void putcode(uchar n, ushort x)  /* Write rightmost n bits of x */
;
	public	putcode_
putcode_:

	push	cx
	push	dx
	mov		ch, al
	mov		cl, bitcount_
	mov		al, subbitbuf_
	$_if <cmp ch, cl>, B
		rol		bh, cl
		or		al, bh
		mov		subbitbuf_, al
		sub		cl, ch
		mov		bitcount_, cl
		pop		dx
		pop		cx
		ret
	$_endif
	sub		ch, cl

	xor		dh, dh
	mov		dl, bh
	shl		dx, cl

	shl		bx, cl
	or		al, dh
	mov		dx, bx
	mov		cl, 8
pc1:
	sub		word ptr compsize_, 1
	sbb		word ptr compsize_ + 2, 0
	jb		disable
	mov		bx, outfile_
	$_if <dec wcount[bx]>, NS
		inc		ptr[bx]
		mov		bx, ptr[bx]
		mov		[bx - 1], al
	$_else
		xor		ah, ah
		inc		wcount[bx]
		call	fputc_
		$_if <or ax, ax>, S
			mov		ax, offset DGROUP:WTERR_
			mov		bx, outfile_
			jmp		fileerror_
		$_endif
	$_endif
	$_if <cmp ch, cl>, AE
		sub		ch, cl
		mov		al, dh
		mov		dh, dl
		jmp		pc1
	$_endif
	mov		subbitbuf_, dh
	sub		cl, ch
	mov		bitcount_, cl
	pop		dx
	pop		cx
	ret

disable:
	mov		unpackable_, 1
	inc		word ptr compsize_
	inc		word ptr compsize_ + 2
	pop		dx
	pop		cx
	ret


;
;int fread_crc(uchar *p, int n, FILE *f)
;

	public	fread_crc_
fread_crc_:
	push	cx
	push	dx
	mov		dx, ax
	xchg	bx, cx
	mov		bx, fd[bx]
	mov		ah, 3fh
	int		21h
	mov		bx, ax
	xchg	ax, dx
	$_if <or bx, bx>, NZ
		call	calccrc_
	$_endif
	mov		ax, dx
	pop		dx
	pop		cx
	ret


;
;void fwrite_crc(uchar *p, int n, FILE *f)
;

	public	fwrite_crc_
fwrite_crc_:
	push	cx
	push	dx
	mov		dx, ax
	push	bx
	call	calccrc_
	pop		bx
	jcxz	fc0
	xchg	bx, cx
	push	bx
	mov		bx, fd[bx]
	mov		ah, 40h
	int		21h
	pop		dx
	$_if <cmp ax, cx>, NE, AND
		mov		ax, bx
		call	isatty_
	$_c  <or ax, ax>, Z
		mov		ax, offset DGROUP:WTERR_
		mov		bx, dx
		jmp		fileerror_
	$_endif
fc0:
	pop		dx
	pop		cx
	ret


;
;void init_getbits(void)
;

	public	init_getbits_
init_getbits_:		
	xor		ax, ax
	mov		word ptr DGROUP:[bitbuf_], ax
	mov		byte ptr DGROUP:[subbitbuf_], al
	mov		byte ptr DGROUP:[bitcount_], al
	mov		al,16
	jmp		fillbuf_


;
;void init_putbits(void)
;

	public	init_putbits_
init_putbits_:		
	mov		byte ptr DGROUP:[bitcount_], 8
	mov		byte ptr DGROUP:[subbitbuf_], 0
	RET	


	EXTRN	fileerror_:near
	EXTRN	WTERR_:near
	EXTRN	RDERR_:near
	EXTRN	fgetc_:near
	EXTRN	fwrite_:near
	EXTRN	fread_:near
	EXTRN	fputc_:near
	EXTRN	isatty_:near
	EXTRN	dispmark_:near
TEXT	ends

	EXTRN	unpackable_:word
	EXTRN	origsize_:dword
	EXTRN	compsize_:dword
	EXTRN	_iob_:byte

	END
