*******************************************************
**   XFD external decruncher for Chryseis Cruncher   **
**        written and © 1994 by Georg Hörmann        **
*******************************************************
**
** 28.02.96 - Updated for xfdmaster.library v37
**

		OUTPUT	"LIBS:xfd/Chryseis"

		SECTION	Chryseis,CODE

		INCDIR	"dh0:Include_Asm"	;change this as you need it
		INCLUDE	"dh0:xfd/xfdmaster.i"

; xfdForeman structure MUST be first thing in all external decrunchers

F_Chryseis	moveq	#-1,d0		;security
		rts
		dc.l	XFDF_ID		;id
		dc.w	1		;version
		dc.w	0
		dc.l	0,0		;private
		dc.l	S_Chryseis09	;first slave

		dc.b	"$VER: XFD Chryseis decruncher by Georg Hörmann",13,10,0
		cnop	0,4

**************************************************

; xfdSlave structure: this one doesn't support segment decrunching

S_Chryseis09	dc.l	0		;no more slaves
		dc.w	2		;version
		dc.w	36		;master version
		dc.l	N_Chryseis09	;name
		dc.w	XFDPFF_RELOC	;flags
		dc.w	0
		dc.l	RB_Chryseis09	;recog buffer
		dc.l	DB_Chryseis09	;decrunch buffer
		dc.l	0		;recog segment
		dc.l	0		;decrunch segment
		dc.w	0,0		;slave/replace id
		dc.l	$4bc+32		;min. file length for header and data

N_Chryseis09	dc.b	'Chryseis Cruncher 0.9',0
		even

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

; Recog buffer function: receives buffer + length in a0/d0

RB_Chryseis09	;cmp.l	#$4bc+32,d0  --> obsolete (see slave v2)
		;ble.s	.Exit
		cmp.w	#$abcd,$2a(a0)	;some more verification
		bne.s	.Exit
		cmp.w	#$03f6,$4ba(a0)
		bne.s	.Exit

		cmp.l	#$208f205f,$42(a0)
		bne.s	.Exit
		cmp.l	#$4eba01c8,$46(a0)
		bne.s	.Exit
		cmp.l	#$49fa025c,$214(a0)
		bne.s	.Exit
		moveq	#1,d0
		rts

.Exit		moveq	#0,d0
		rts

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

;Decrunch buffer function: receives bufferinfo in a0

DB_Chryseis09	movem.l	d2-d7/a2-a6,-(a7)
		move.l	a0,a5
		move.l	xfdbi_SourceBuffer(a5),a2

; first of all, we calculate the length of the decrunched file

		moveq	#20,d2		;3f3,0,x,0,x-1
		lea	$4bc(a2),a0
		move.l	(a0),d0
		move.l	d0,d3		;amount hunks
		lsl.l	#2,d0
		add.l	d0,d2		;hunklens
		lea	12(a0,d0.l),a0
		
.CountAgain	addq.l	#8,d2		;3ex,x
		move.w	(a0)+,d0
		move.w	(a0)+,d1
		cmp.w	#$3eb,d1
		bne.s	.CountNoBSS
		addq.w	#4,a0
		bra.s	.CountReloc

.CountNoBSS	and.w	#$0fff,d0
		beq.s	.CountUncr

		move.l	(a0),d0
		add.l	d0,a0
		move.l	(a0)+,d0
		lsr.l	#8,d0
		add.l	d0,d2		;uncr hunklen
		bra.s	.CountReloc

.CountUncr	move.l	(a0)+,d0
		add.l	d0,d2
		add.l	d0,a0

.CountReloc	addq.l	#4,d2		;end|reloc
		cmp.l	#$3f2,(a0)+
		beq.s	.CountEnd

.CountNextRel	addq.l	#4,d2
		move.l	(a0)+,d0
		beq.s	.CountReloc
		addq.l	#1,d0
		lsl.l	#2,d0
		add.l	d0,d2
		add.l	d0,a0
		bra.s	.CountNextRel

.CountEnd	subq.l	#1,d3
		bne.s	.CountAgain

; now we have the desired length and allocate the buffer

		move.l	d2,d0
		move.l	d0,xfdbi_TargetBufSaveLen(a5)
		move.l	d0,xfdbi_TargetBufLen(a5)

		move.l	xfdbi_TargetBufMemType(a5),d1
		move.l	4.w,a6
		jsr	-198(a6)
		move.w	#XFDERR_NOMEMORY,xfdbi_Error(a5)
		move.l	d0,xfdbi_TargetBuffer(a5)
		beq	.Exit

; let's fill the buffer

		move.l	d0,a3
		move.l	#$3f3,(a3)+
		clr.l	(a3)+
		lea	$4bc(a2),a2
		move.l	(a2),d0
		move.l	d0,d3
		addq.w	#3-1,d0
.CopyHeader	move.l	(a2)+,(a3)+
		dbf	d0,.CopyHeader

.CopyAgain	move.w	(a2)+,d0
		move.w	(a2)+,d1
		clr.w	(a3)+
		move.w	d1,(a3)+
		cmp.w	#$3eb,d1
		bne.s	.NoBSS
		move.l	(a2)+,d0
		lsr.l	#2,d0
		move.l	d0,(a3)+
		bra.s	.CopyReloc

.NoBSS		and.w	#$0fff,d0
		beq.s	.CopyUncr
		move.l	(a2),d1
		add.l	d1,a2
		move.l	(a2)+,d1
		lsr.l	#8,d1
		lsr.l	#2,d1
		move.l	d1,(a3)+
		move.l	a2,a0
		move.l	a3,a1
		lsl.l	#2,d1
		add.l	d1,a3
		lsl.w	#2,d0
		move.l	a2,-(a7)
		lea	.EffTable-4(pc),a2
		add.w	d0,a2
		bsr	D_Chryseis
		move.l	(a7)+,a2
		bra.s	.CopyReloc

.CopyUncr	move.l	(a2)+,d0
		lsr.l	#2,d0
		move.l	d0,(a3)+
.CopyUncr1	move.l	(a2)+,(a3)+
		subq.l	#1,d0
		bne.s	.CopyUncr1

.CopyReloc	move.l	(a2)+,d0
		move.l	d0,(a3)+
		cmp.w	#$3f2,d0
		beq.s	.CopyEnd

.CopyNextRel	move.l	(a2)+,d0
		move.l	d0,(a3)+
		beq.s	.CopyReloc
		addq.l	#1,d0
.CopyEntries	move.l	(a2)+,(a3)+
		subq.l	#1,d0
		bne.s	.CopyEntries
		bra.s	.CopyNextRel

.CopyEnd	subq.l	#1,d3
		bne.s	.CopyAgain

; successful exit

		moveq	#1,d0
.Exit		movem.l	(a7)+,d2-d7/a2-a6
		rts

.EffTable	dc.b	9,9,9,9
		dc.b	9,10,10,10
		dc.b	9,10,11,11
		dc.b	9,10,12,12
		dc.b	9,10,12,13

**************************************************

D_Chryseis	movem.l	d2-d5/a2/a3,-(a7)
		moveq	#-1,d4
		moveq	#1,d5
		move.l	a1,a3
		move.l	-(a0),d1
		tst.b	d1
		beq.s	.Decr1
		bsr.s	.Decr5
		subq.b	#1,d1
		lsr.l	d1,d5
.Decr1		lsr.l	#8,d1
		add.l	d1,a1
.Decr2		bsr.s	.Decr5
		bcs.s	.Decr11
		moveq	#0,d2
.Decr3		moveq	#1,d0
		bsr.s	.Decr8
		add.w	d1,d2
		subq.w	#3,d1
		beq.s	.Decr3
.Decr4		moveq	#7,d0
		bsr.s	.Decr8
		move.b	d1,-(a1)
		cmp.l	a3,a1		; modified for
		dbeq	d2,.Decr4	; perfect error
		cmp.w	d4,d2		; detection
		beq.s	.Decr11
		bra.s	.Decr17

.Decr5		lsr.l	#1,d5
		beq.s	.Decr6
		rts
.Decr6		move.l	-(a0),d5
		roxr.l	#1,d5
		rts

.Decr7		subq.w	#1,d0
.Decr8		moveq	#0,d1
.Decr9		lsr.l	#1,d5
		bne.s	.Decr10
		move.l	-(a0),d5
		roxr.l	#1,d5
.Decr10		roxl.l	#1,d1
		dbra	d0,.Decr9
		rts

.Decr11		moveq	#1,d0
		bsr.s	.Decr8
		moveq	#0,d0
		move.b	(a2,d1.w),d0
		move.w	d1,d2
		subq.w	#3,d1
		bne.s	.Decr14
		bsr.s	.Decr5
		bcs.s	.Decr12
		moveq	#7,d0
.Decr12		bsr.s	.Decr7
		move.w	d1,d3
.Decr13		moveq	#2,d0
		bsr.s	.Decr8
		add.w	d1,d2
		subq.w	#7,d1
		beq.s	.Decr13
		bra.s	.Decr15

.Decr14		bsr.s	.Decr7
		move.w	d1,d3
.Decr15		addq.w	#1,d2
.Decr16		move.b	(a1,d3.w),-(a1)
		cmp.l	a3,a1		; modified
		dbeq	d2,.Decr16	; for perfect
		cmp.w	d4,d2		; error detection
		beq.s	.Decr2
.Decr17		movem.l	(a7)+,d2-d5/a2/a3
		rts

		END
