;***********************************************
;	maketbl_.asm -- makes decoding table
;***********************************************
			page	0, 128

include	amscls.inc
$_init	GEN

TEXT	segment	byte	public	'CODE'
TEXT	ends

DATA	segment word	public	'DATA'
DATA	ends

BSS		segment word	public	'DATA'
extrn	nchar:word
extrn	bitlen:word
extrn	tablebits:word
extrn	table:word
extrn	avail_mt:word
extrn	len_cnt:word
extrn	start:word
extrn	weight:word

extrn	right_:word
extrn	left_:word
extrn	BROKENARC_:byte
extrn	error_:near
BSS		ends

DGROUP	group	DATA, BSS

TEXT	segment	byte	public	'CODE'
		assume	cs:TEXT, ds:DGROUP
;---------------------------------------------------------------
;	void make_table(short nchar, uchar bitlen[],
;	                         ax            bx
;					short tablebits, ushort table[])
;	                             cx            dx
;---------------------------------------------------------------
	public	make_table_
make_table_	proc	near
	push	cx
	push	dx
	push	si
	push	di
	push	bp

	mov		nchar, ax
	shl		ax, 1
	mov		avail_mt, ax
	mov		bitlen, bx
	mov		tablebits, cx
	mov		table, dx

	push	ds
	pop		es
	cld

;	/* clear len_cnt */
	xor		ax, ax
	mov		cx, 16
	mov		di, offset DGROUP:len_cnt + 2
	rep		stosw

;	/* count bitlen into len_cnt */
	xor		bx, bx
	mov		cx, nchar
	mov		si, bitlen
	$_do
		mov		bl, [si]
		inc		si
		shl		bx, 1
		inc		len_cnt[bx]
	$_until <LOOP>

;	/* initialize weight, start, table */
	mov		cx, tablebits
	mov		bp, 1
	shl		bp, cl
	mov		bx, offset DGROUP:len_cnt + 2
	mov		si, offset DGROUP:weight + 2
	mov		di, offset DGROUP:start + 2
	mov		ax, table
	$_do
		stosw
		mov		dx, [bx]
		add		bx, 2
		shl		dx, cl
		add		ax, dx
		shr		bp, 1
		mov		[si], bp
		add		si, 2
	$_until <LOOP>
	push	ax
	sub		ax, table
	mov		cl, 15
	sub		cx, tablebits
	shl		ax, cl
	shl		bp, cl
	$_do
		stosw
		mov		dx, [bx]
		add		bx, 2
		shl		dx, cl
		add		ax, dx
		mov		[si], bp
		add		si, 2
		dec		cx
	$_until <shr bp, 1>, Z
	$_if <or ax, ax>, NZ
		mov		ax, offset DGROUP:BROKENARC_
		xor		bx, bx
		call	error_
	$_endif
	pop		di
	mov		ax, di
	sub		ax, table
	shr		ax, 1
	mov		bx, 1
	mov		cx, tablebits
	shl		bx, cl
	mov		cx, bx
	sub		cx, ax
	xor		ax, ax
	rep		stosw

;	/* make table & additional tree */
	xor		ax, ax
	$_do
		mov		si, ax
		add		si, bitlen
		mov		bl, [si]

		or		bl, bl
		jz		make_table_1
		xor		bh, bh

		mov		dx, bx
		shl		bx, 1
		mov		di, start[bx]
		mov		cx, weight[bx]
		$_if <cmp dx, tablebits>, BE
			rep		stosw
			mov		start[bx], di
		$_else
			add		start[bx], cx

			mov		si, di
			mov		bx, tablebits
			mov		cl, 16
			sub		cl, bl

			shr		di, cl
			shl		di, 1
			add		di, table

			mov		cl, bl
			shl		si, cl

			xor		cx, cx
			mov		cl, dl
			sub		cx, tablebits
;		/* 高さ n の tree を作る */
			$_do
				$_if <cmp word ptr [di], 0>, E
;				/* 枝がまだ延びていなければ作る */
					mov		bx, avail_mt
					mov		right_[bx], 0
					mov		left_[bx], 0
;;					shr		bx, 1
					mov		[di], bx
					add		avail_mt, 2
				$_endif
				mov		di, [di]
;;				shl		di, 1
				$_if <shl si, 1>, C
					add		di, offset DGROUP:right_
				$_else
					add		di, offset DGROUP:left_
				$_endif
			$_until <LOOP>
			mov		[di], ax
		$_endif
make_table_1:
		inc		ax
	$_until <cmp ax, nchar>, AE

	pop		bp
	pop		di
	pop		si
	pop		dx
	pop		cx
	ret
make_table_	endp
TEXT	ends
		end
