                .386
		ideal
	        assume	cs:code,ds:code,es:code,ss:code

segment		code public use16
                org	100h

;==============================================================================
;		constants
;==============================================================================

                Treshold  = 2;
                Lookahead = 16;
                MaxLen    = Lookahead+Treshold;
		ariEOF	  = 256;
		BPOT	  = 256+LOOKAHEAD+1;

;***********************************************
;* Discript. : init the order 0 model          *
;* Destroys  : all                             *
;* Length    : 13 bytes                        *
;***********************************************
macro		initModel
		mov	ax,BPOT
                mov     bx,offset cumProbs+2*BPOT
imloop:		mov	[word ptr bx],ax
		dec	bx
		dec	bx
		dec	ax
                jns	short imloop
endm		initModel

;***********************************************
;* Discript. : decode from ds:si to es:di      *
;* Destroys  : all                             *
;* Length    : --- bytes                       *
;***********************************************
macro		decoder
                initModel
                lodsw
                xchg    ah,al
                mov	cx,ax
                mov	bp,-1
repeat:		call	decodeChar
		cmp	ax,ariEOF
		je	short quit
		jg	short lz77
		stosb
		jmp	short repeat
lz77:		sub	ax,257-treshold
		push	ax
		call	decodeChar
		pop	dx
		neg	ax
		mov	bx,ax
lz77loop:	mov	al,[byte ptr es:di+bx]
		stosb
		dec	dx
		jne	short lz77loop
		jmp	short repeat
quit:
endm		decoder

;***********************************************
;* Discript. : copy decoder 8192 bytes forward *
;*             and jump to it	               *
;* Destroys  : all                             *
;* Length    : 30 bytes (without decoder macro)*
;***********************************************
proc		start
                xor     si,si
                mov     di,02000h
                mov	ch,16			; copy 8192 bytes
                rep     movsw
                mov     ax,cs
                add	ax,0200h		; + 8192 bytes
                push    ax
                push    offset decode
                retf                            ; jmp decoder

decode:		push	cs
		pop	ds
                mov     si,offset packedcomfile
                mov	di,0100h
                push    es			;
		push	di			;
		decoder
		retf				; start the comfile

endp		start

;***********************************************
;* Discript. : get and remove one symbol       *
;* Destroys  : all                             *
;* Length    : --- Bytes                       *
;***********************************************
proc		decodeChar
                push	di
                mov     bx,offset cumProbs+2*BPOT
                mov	ax,cx
                inc	ax
            	mul	[word ptr bx]
;		sub	ax,1
;		sbb	dx,0
		div	bp

                mov	di,bx
                mov	dx,BPOT
findchar:	dec     di
		dec     di
		dec	dx
		cmp     [word ptr di],ax
                jg      short findchar
                push	dx

            	mov	ax,bp
		mul	[word ptr di]
            	div	word ptr bx]
		sub	cx,ax

                xchg	ax,bp
            	mul	[word ptr di+2]
            	div	[word ptr bx]
                xchg	ax,bp
            	sub	bp,ax

removebits:	dec	[byte ptr bitsLeft]
		jns	short nonewbyte
		mov	[byte ptr bitsLeft],7
		inc	si
nonewbyte:	rcl	[byte ptr si],1
		rcl	cx,1
		shl	bp,1
                jns	short removebits

                pop	dx	;{ Char}

		mov     ax,Bpot
updmodel:	inc     [word ptr bx]
		dec     bx
		dec     bx
		dec	ax
		cmp	dx,ax
                jne    	short updmodel
                pop	di
                ret
endp		decodeChar

packedcomfile:
include		"omnicent.inc"
bitsleft:	db	8
cumProbs:	dw      BPOT+1 dup (?)
ends		code
	        end	start

