	XDEF	_compress_slow

;On entry:
;	a0 = InBuf
;	a1 = OutBuf
;	a2 = HashTab
;	d0 = InLen

	CODE

COMPRESSREGS	reg	a3-a6/d1-d7
_compress_slow:
	movem.l	COMPRESSREGS,-(sp)
	move.l	a0,d1
	add.l	d0,d1		; d1=src+src_len

	moveq.l	#$FFFFFFFC,d2
	and.l	d0,d2
	add.l	a1,d2
	move.l	d2,a4		; a4=(dst+src_len) & ~3

	movem.l	a1/a4,-(sp)	; save dst and dst_end for later use
	
	moveq.l	#1,d0
	swap	d0
	move.l	a2,a6
	add.l	d0,a6
;;;	lea	$10000(a2),a6	; a6=hh a6-$10000 == hash

	moveq.l	#0,d0
	move.w	#$9FF,d2
hfill:	move.l	d0,(a2)+	; fill hash with $00000000
	move.l	d0,(a2)+	; hash is $A00*8 = $5000 longs big
	move.l	d0,(a2)+
	move.l	d0,(a2)+
	move.l	d0,(a2)+
	move.l	d0,(a2)+
	move.l	d0,(a2)+
	move.l	d0,(a2)+
	dbra	d2,hfill	

	move.l	a0,a2		; d0 = 4*hash_fkt(s,s+1,s+2)
	moveq.l	#-1,d0
	move.b	(a2)+,d0
	asl.w	#3,d0
	add.b	(a2)+,d0
	asl.w	#3,d0
	add.b	(a2),d0
	asl.w	#2,d0

	move.l	a0,0(a6,d0.l)	;hash[hash_val]=s

	move.l	#$00000FFF,d4

	bra.s	entry_point

				;REGISTER MAP
				;============

;	a0 source
;	a1 destination byte stream	(post increment)
;	a2 Temporary
;	a3 work pointer into LZ77-window
;	a4 destination word stream	(pre decrement)
;	a5 Temporary
;	a6 hashtable
;	a7 Stack pointer. Don't touch!

;	d0 Temporary
;	d1 End of input
;	d2 src - 4095
;	d3 match_offset , match_len
;	d4 Constant 4095
;	d5 place to put control word in output
;	d6 Counter of Controlbits to insert into the control word.
;	d7 Buffers the current control word.

;;;---------------------------------------------------------------------------

newctl:	move.l	d5,a2
	move.w	d7,(a2)		; write ctrl_word to it's place
entry_point:
	subq.l	#2,a4
	move.l	a4,d5		; get place to put next ctrl_word

	moveq.l	#15,d6		; reinitialize ctrl_bit_counter
	moveq.l	#-1,d7		; fill ctrl_word with $FFFF

oloop:	move.l	a0,a3		; wrk=s
	move.l	a0,d2
	sub.l	d4,d2		; limit = src - 4095
	moveq.l	#2,d3		; match_ofs,match_len = 0,2

iloop:	move.l	a3,d0			; d0=$00000FFF
	and.l	d4,d0			; d0=wrk & $00000FFF
	asl.w	#2,d0
	move.l	0(a6,d0.l),a3		; p=hh[p & $00000FFF]

	cmp.l	d2,a3			; has src reached the limit
	bcs.s	finished_chain		; is a3 < d2

	move.l	a0,a2
	move.l	a3,a5

MATCH	MACRO
	cmp.b	(a2)+,(a5)+
	bne.s	\1
	ENDM
	MATCH	iloop	; 0
	MATCH	iloop	; 1
	MATCH	iloop	; 2
	MATCH	mism	; 3
	MATCH	mism	; 4
	MATCH	mism	; 5
	MATCH	mism	; 6
	MATCH	mism	; 7
	MATCH	mism	; 8
	MATCH	mism	; 9
	MATCH	mism	;10
	MATCH	mism	;11
	MATCH	mism	;12
	MATCH	mism	;13
	MATCH	mism	;14
	MATCH	mism	;15
	MATCH	mism	;16
	MATCH	mism	;17
	addq.l	#1,a5	;18
mism:	move.l	a5,d0
	sub.l	a3,d0
	subq.w	#1,d0		; d0=match_len

	cmp.w	d0,d3
	bcc.s	iloop		; new match is not longer than old one
	
	move.l	a0,d3
	sub.l	a3,d3		; d4 = src - wrk = match_ofs
	swap	d3
	move.w	d0,d3		; match_ofs,match_len is updated.

	cmp.b	#18,d3
	bcs.s	iloop		; match_len < 18

finished_chain:
	cmp.b	#3,d3
	bcs.s	do_literal

	moveq.l	#18,d0
	sub.b	d3,d0		; d0=18-match_len

	swap	d3
	asl.w	#4,d3
	or.b	d0,d3		; d3 = OOOOOOOO OOOOLLLL
	
	move.w	d3,-(a4)	; write copyinfo

	swap	d3		; d3.w = match_len
	subq.w	#1,d3		; d3 = match_len - 1

	rol.w	#1,d7		; inject a 1 into control word
	bra.s	incsrc

do_literal:
	moveq.l	#0,d3		; d4 = [pseudo]match_len - 1
	move.b	(a0),(a1)+	; write literal
	add.w	d7,d7		; inject 0 into ctrl_word

incsrc:	addq.l	#1,a0		; increment src

	move.l	a0,a2
	moveq.l	#-1,d0
	move.b	(a2)+,d0
	lsl.w	#3,d0
	add.b	(a2)+,d0
	lsl.w	#3,d0
	add.b	(a2)+,d0
	asl.w	#2,d0		; d0 = hash_fkt(src[0],src[1],src[2])

	move.l	0(a6,d0.l),a2	; a2 = hash[hash_val]
	move.l	a0,0(a6,d0.l)	; hash[hash_val] = src

	move.l	a0,d0
	and.l	d4,d0
	asl.w	#2,d0
	move.l	a2,0(a6,d0.l)	; hh[src&$FFF] = src - [old]hash[hash_val]
	dbra	d3,incsrc

	cmp.l	a0,d1		; Has src reached src_end?
	bcs.s	end_compress_loop
	dbra	d6,oloop
	bra	newctl

;;; The rest is copied from compress_fast !!!! FIXME !!!!
;;; Only the registers are renamed :-(

;;;The main loop ends here.
;;;---------------------------------------------------------------------------
				;FINALIZATION
				;============

FillControl:			;Fill the rest of the control word with 0
	add.w	d7,d7		;0 means literal items.
end_compress_loop:
	dbra	d6,FillControl

	move.l	d5,a2
	move.w	d7,(a2)		;Write it to its output position

	movem.l	(sp)+,d6/d7	; Pop dst and dst_end

	;Copy the literals after the word stream pointed to by a1.
	move.l	a4,d0		;d0:=Number of Bytes to increase a1
	sub.l	a1,d0		;till a1 and a4 are equally aligned.
	bcc.s	did_compress

;byte- and wordstream together do exceede the size of the output buffer.
	moveq	#0,d0		; return 0 to indicate overrun
	bra.s	finish

did_compress:
	moveq	#3,d1
	and.w	d0,d1

	moveq.l	#0,d0		;pad a1 up to make a1 and a4 equally aligned.
	bra.s	EFLoop
FLoop:	move.b	d0,(a1)+
EFLoop:	dbra	d1,FLoop

	sub.l	a4,d7		;d7:=size of wordstream

	lsr.l	#2,d7
	bcc.s	ECLoop		;make sure we do the move.l longword aligned.
	move.w	(a4)+,(a1)+
NoWord:	bra.s	ECLoop
CLoopH:	swap	d7
CLoop:	move.l	(a4)+,(a1)+
ECLoop:	dbra	d7,CLoop
	swap	d7
	dbra	d7,CLoopH

	move.l	a1,d0
	sub.l	d6,d0			;d0:=Final output length
finish:	movem.l	(sp)+,COMPRESSREGS
	rts

;;;---------------------------------------------------------------------------

    END

