;
; UNPACK.ASM
;  hoch optimiertes unpackc()
;  funktional identisch zu unpack()c, aber doppelt so schnell
;
;
	TITLE   unpack.c
	NAME    unpack

	.286

_TEXT	SEGMENT  WORD PUBLIC 'CODE'
_TEXT	ENDS

	ASSUME CS: _TEXT
	ASSUME DS: NOTHING

_TEXT      SEGMENT
	PUBLIC	_unpack
_unpack		PROC FAR
	enter	WORD PTR 22,0
	push	di
	push	si
	push	ds

;	outbuffer = 4
;	pbuffer = 8
;	register di = packlen
;   packlen = 10
;	register ds:si = pbuffer
;	register packmask = dl
;   register uloop    = dh
;	length = temp cx
;	index  = temp ax
;	sbuffer = -14
;	s = -6

	les	di,DWORD PTR [bp+6]  ; es:di -> destination
	lds si,DWORD PTR [bp+10] ; ds:si -> source 
	mov bx,si
	add	bx,word ptr [bp+14]	  ; end = si+packlen

	mov	dh,1
	jmp	decode_next_group

copy_compressed:
	lodsw					; 	mov	ax,WORD PTR  [si++] ; pbuffer++
	mov	cx,ax				;index
	and	ah,15

	shr	cx,12
	add	cx,3

	cmp	cx,18				; if (length == MAXLENGTH+2)
	jne	@F

	mov	cl,BYTE PTR  [si]	;	 length = *pbuffer++
	sub	ch,ch				;
	inc si					;
@@:
	push	si				; memcpy(es:di,ds:si,cx)
	push	ds				; outbuffer += cx

	mov	si,di				;outbuffer
	sub	si,ax				; index
	mov ax,es
	mov ds,ax

	rep	movsb				; !!! not wordwise !!!
	pop	ds					; offset -1 possible
	pop si

							; done
							; next Lines are duplicate to save jumps
	cmp	si,bx				; word ptr [bp+12]	; packend
	jnb	terminate			; 

	dec	dh					; uloop
	je	fetch_new_mask

test_next_group:
	shl dl,1				; packmask
	jc	copy_compressed		; if highest bit was set it was compressed

	movsb					; *outbuffer++ = *pbuffer++

decode_next_group:
	cmp	si,bx				; if (pbuffer >= packend)
	jnb	terminate			; 	return;

	dec	dh					; if (--uloop == 0)
	jne	test_next_group		; 	{

fetch_new_mask:
	mov	dl,BYTE PTR [si]	;	packmask = *pbuffer++
	inc	si					;
	mov	dh,8				; 	uloop   = 8
	jmp short test_next_group	;	}

terminate:
	mov	ax,di				;outbuffer
	sub	ax,WORD PTR [bp+6]	;dbuffer
	pop ds
	pop	si
	pop	di
	leave	
	ret	

_unpack ENDP
_TEXT	ENDS
END
