*******************************************************************************
* CrunchMania LZ-Huffman "TURBO" DATA-DECRUNCH! (Standard MC68000 Version)
* ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ
*	Allows decrunching of CrunchMania LZ-Huffman Datafiles! This source is
* NOT from any official 'release' archive. Its an optimised resourced version
* which contains no nasty slow 'mulu's & has been speeded up in several ways.
* Resourced, optimised & address error fixed by LSD! CALL OUR BOARDS!
*
* INPUTS:	a0=source (packed data)
*		a1=destination (depack destination)
*
* OUTPUTS:	a1=destination (start of decrunched data)
*******************************************************************************

;-------------- LZData Decrunch

Example:	lea	source(pc),a0	;a0=source	
		lea	16(a0),a1	;a1=dest
		bsr.b	UnpackLZ	;call the decruncher
		rts

;-------------- Actual Decruncher
					
UnpackLZ:	move.l	a0,a2		;make copy of source address
;		cmp.l	#"CrM2",(a2)+	;Check for "CrM2" LZ-Huffman Header
;		beq.s	LZDecrunch	;yes it is packed, lets depack it!
;not_crm:	rts
		
LZDecrunch:	;tst.w	(a2)+		;skip minimum 2nd distance
		move.l	(a2)+,d1	;original size
		move.l	(a2)+,d2	;packed length
		move.l	a1,a5		;Decrunched Anfang (hier Ende des Decrunchens)
		add.l	d1,a1
		add.l	d2,a2
		lea	128(a1),a6	;128 bytes (of minimum safe distance!)
		move.l	a6,d7
		andi.b	#%11111110,d7	;mask out odd address errors on mc68k!
		move.l	d7,a6
		move.w	-(a2),d0	;Anz Bits in letztem Wort
		move.l	-(a2),d6	;1.LW
		moveq	#16,d7		;Anz Bits
		sub.w	d0,d7		;Anz Bits, die rotiert werden müssen
		lsr.l	d7,d6		;1.Bits an Anfang bringen
		move.w	d0,d7		;Anz Bits, die noch im Wort sind

		moveq	#16,d3
LZ20A:		lea	$49E(a6),a0
		moveq	#4-1,d2
		moveq	#0,d4
LZ210:		move.l	d4,(a0)+
		move.l	d4,(a0)+
		move.l	d4,(a0)+
		move.l	d4,(a0)+
		dbra	d2,LZ210

		lea	$4BE(a6),a0
		lea	$9E(a6),a4
		moveq	#9,d2
		bsr.w	LZ300
		lea	$49E(a6),a0
		lea	$80(a6),a4
		moveq	#4,d2
		bsr.w	LZ300

		lea	$4BE(a6),a3
		lea	-2(a6),a4
		bsr.w	lzfast

		lea	$49E(a6),a3
		lea	$1E(a6),a4
		bsr.w	lzfast

		moveq	#$10,d1
		bsr.w	LZ2C8
		move.w	d0,d5
		lea	$9E(a6),a0
		lea	-$1E(a0),a5

LZ258:		move.l	a6,a4
		bsr.s	LZ29C
		btst	#8,d0
		bne.s	LZ28A
		move.w	d0,d4
		lea	$20(a6),a4
		exg	a0,a5
		bsr.s	LZ29C
		exg	a0,a5
		move.w	d0,d1
		move.w	d0,d2
		bne.s	LZ278
		moveq	#1,d1
		moveq	#$10,d2
LZ278:		bsr.b	LZ2C8
		bset	d2,d0
		lea	1(a1,d0.w),a3
LZ280:		move.b	-(a3),-(a1)
		dbra	d4,LZ280
		move.b	-(a3),-(a1)
		move.b	-(a3),d0
LZ28A:		move.b	d0,-(a1)
		dbra	d5,LZ258

		moveq	#1,d1
		bsr.s	LZ2C8
		bne.w	LZ20A
		rts				;exit decrunch... bye bye
		
;----------------------------------------------------------------------------
LZ29C:		moveq	#0,d1
		moveq	#1,d0
		
lz_loop:	sub.w	d0,d7
		beq.s	lz_reloop
		lsr.l	d0,d6
		addx.w	d1,d1
		cmp.w	(a4)+,d1
		bhs.s	lz_loop
		add.w	$3E(a4),d1
		add.w	d1,d1
		move.w	0(a0,d1.w),d0
		rts

LZ_reloop	moveq	#17-1,d7
		lsr.l	d0,d6

		swap	d6
		move.w	-(a2),d6
		swap	d6

		addx.w	d1,d1
		cmp.w	(a4)+,d1
		bhs.s	lz_loop
		add.w	$3E(a4),d1
		add.w	d1,d1
		move.w	0(a0,d1.w),d0
		rts
;----------------------------------------------------------------------------

LZ2C8:		move.w	d6,d0
		lsr.l	d1,d6
		sub.w	d1,d7
		bgt.s	LZ2D8
		add.w	d3,d7
		ror.l	d7,d6
		move.w	-(a2),d6
		rol.l	d7,d6
LZ2D8:		add.w	d1,d1			;x2
		and.w	.AndData-2(pc,d1.w),d0
		rts
*----------
.AndData:	dc.w	1,3,7,15,$1F,$3F,$7F,$FF,$1FF,$3FF
		dc.w	$7FF,$FFF,$1FFF,$3FFF,$7FFF,$FFFF,$4C53,$4421

LZ300:		movem.l	d1-d5/a3,-(sp)
		moveq	#4,d1
		bsr.s	LZ2C8
		move.w	d0,d5
		subq.w	#1,d5
		moveq	#0,d4
		move.l	d4,a3
LZ310:		addq.w	#1,d4
		move.w	d4,d1
		cmp.w	d2,d1
		ble.s	LZ31A
		move.w	d2,d1
LZ31A:		bsr.s	LZ2C8
		move.w	d0,(a0)+
		add.w	d0,a3
		dbra	d5,LZ310
		move.w	a3,d5
		subq.w	#1,d5
LZ328:		move.w	d2,d1
		bsr.s	LZ2C8
		move.w	d0,(a4)+
		dbra	d5,LZ328
		movem.l	(sp)+,d1-d5/a3
		rts
 
lzfast:		moveq	#0,d2
		move.w	d2,d1
		move.w	d2,(a4)+
		moveq	#15-1,d4
loop:		move.w	-2(a4),d0
		add.w	d0,d0			;x2
		sub.w	d0,64(a4)
		add.w	(a3),d1
		move.w	d1,66(a4)
		add.w	(a3)+,d2
		move.w	d2,(a4)+
		add.w	d2,d2
		dbra	d4,loop
		rts

;-------------- Actual LZHuffman packed datafile

source:		incbin	'work:1.pak'
dest:		ds.b	400*1024		;length of file unpacked (buffer)
