*****************************************************************************
*   $Id: Imploder.a,v 1.2 2005/06/23 14:39:16 stoecker Exp $
*   Imploder and related types decrunching slave
*
*   XFD library system for cruncher handling
*   Copyright (C) 1994-1998 by Georg Hörmann
*   Copyright (C) 1998 by Dirk Stöcker <soft@dstoecker.de>
*
*   This library is free software; you can redistribute it and/or
*   modify it under the terms of the GNU Lesser General Public
*   License as published by the Free Software Foundation; either
*   version 2.1 of the License, or (at your option) any later version.
*
*   This library is distributed in the hope that it will be useful,
*   but WITHOUT ANY WARRANTY; without even the implied warranty of
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
*   Lesser General Public License for more details.
*
*   You should have received a copy of the GNU Lesser General Public
*   License along with this library; if not, write to the Free Software
*   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*****************************************************************************

S_Imploder	dc.l	S_ImploderLib-Xfd68KHeader
		dc.w	2
		dc.w	39
		dc.l	N_Imploder-Xfd68KHeader
		dc.w	XFDPFF_RELOC!XFDPFF_RELMODE
		dc.w	0
		dc.l	RB_Imploder-Xfd68KHeader
		dc.l	DB_Imploder-Xfd68KHeader
		dc.l	RS_Imploder-Xfd68KHeader
		dc.l	DS_Imploder-Xfd68KHeader
		dc.w	XFDID_Imploder
		dc.w	0
		dc.l	$294+4+16

N_Imploder	dc.b	'Imploder',0
		even

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

RB_Imploder	BSR	xfdCodeBeginRecog
		TST.L	D0
		BEQ.B	.Exit
		CMP.B	#$60,(A0)		* 2001-09-15 SDI
		BNE.B	.nobra
		MOVEQ	#2,D0			* skip start hiding BRA's
		ADD.B	1(A0),D0
		ADDA.L	D0,A0

.nobra		cmp.l	#$49fa0036,4(a0)	;3.1
		beq.s	.Next1
		cmp.l	#$49fa005e,4(a0)	;4.0
		beq.s	.Next1
		cmp.l	#$49fa0042,12(a0)	;3.1 pure
		bne.s	.Exit

.Next1		cmp.l	#$4e913c3c,14(a0)	;3.1
		beq.s	.Next2
		cmp.w	#$4e91,14(a0)		;4.0
		beq.s	.Next2
		cmp.l	#$4e913c3c,22(a0)	;3.1 pure
		bne.s	.Exit

.Next2		cmp.l	#$51892011,22(a0)	;3.1
		beq.s	.Ok
		cmp.l	#$51892011,30(a0)	;3.1 pure + 4.0
		bne.s	.Exit

.Ok		moveq	#1,d0
		rts

.Exit		moveq	#0,d0
		rts

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

Imp_UncrLen	SET	xfdBufferInfo_SIZE
Imp_UncrBuf	SET	xfdBufferInfo_SIZE+4
Imp_CrunchLen	SET	xfdBufferInfo_SIZE+8
Imp_CrunchBuf	SET	xfdBufferInfo_SIZE+12
Imp_HunkLens	SET	xfdBufferInfo_SIZE+16
Imp_SIZE	SET	xfdBufferInfo_SIZE+20

DB_Imploder	movem.l	d2-d7/a2-a6,-(a7)
		sub.w	#Imp_SIZE,a7
		move.l	a7,a5
		move.l	a0,-(a7)	;bufferinfo
		move.l	a5,a1
		moveq	#xfdBufferInfo_SIZE-1,d1
.CopyBI1	move.b	(a0)+,(a1)+
		dbf	d1,.CopyBI1

		move.l	xfdbi_SourceBuffer(a5),a0
		move.l	8(a0),d0
		move.l	d0,d5		;amount hunks
		subq.l	#4,d5

		lsl.l	#2,d0
		lea	28(a0,d0.l),a0
.SearchMove	cmp.w	#$3c3c,(a0)+
		bne.s	.SearchMove
		move.w	(a0),d0
		cmp.w	d5,d0
		bge.s	.SkipMove
		move.w	d0,d5

.SkipMove	move.l	xfdbi_SourceBuffer(a5),a0
		lea	24(a0),a0
		move.l	a0,Imp_HunkLens(a5)

		move.l	d5,d0
		addq.w	#2,d0
		lsl.w	#2,d0
		move.l	(a0,d0.w),d0	;uncrunch buffer len
		lsl.l	#2,d0
		move.l	d0,Imp_UncrLen(a5)
		moveq	#1,d1
		move.l	4.w,a6
		jsr	_LVOAllocMem(a6)
		move.w	#XFDERR_NOMEMORY,xfdbi_Error(a5)
		move.l	d0,Imp_UncrBuf(a5)
		beq	.Exit

		move.w	#XFDERR_CORRUPTEDDATA,xfdbi_Error(a5)
		move.l	xfdbi_SourceBuffer(a5),a0
		MOVE.L	xfdbi_SourceBufLen(A5),D0
		move.l	d5,d1
		addq.w	#1,d1
		bsr		xfdGetHunk
		tst.l	d0
		beq	.ErrorFree
		move.l	d0,a2

		cmp.l	#$3e9,(a2)+
		bne	.ErrorFree
		addq.w	#4,a2		;decruncher code

		cmp.w	#$d3fc,6(a2)	;wegen patch
		bne	.ErrorFree
		move.l	8(a2),Imp_CrunchLen(a5)
		
		move.l	-4(a2),d0
		lsl.l	#2,d0
		lea	4(a2,d0.l),a3
		cmp.l	#$3e9,(a3)
		beq.s	.Patch
		cmp.l	#$3ea,(a3)
		bne	.ErrorFree
.Patch		addq.w	#8,a3
		add.l	Imp_CrunchLen(a5),a3
		move.l	a3,Imp_CrunchBuf(a5)

		add.w	#$30,a2
		cmp.w	#$d080,(a2)
		beq.s	.Imp31
		add.w	#$10,a2
		cmp.w	#$d080,(a2)
		bne	.ErrorFree

.Imp31		sub.w	#54*2,a7
		move.l	a7,a4
				
		lea	$f6(a2),a0
		lea	8(a4),a1
		cmp.w	#$5007,-4(a0)	;Imp 1.0 ???
		bne.s	.NoImp101
		addq.w	#4,a0
		move.l	(a0)+,(a1)+
		addq.w	#4,a0
		bra.s	.Imp101
.NoImp101	move.l	(a0)+,(a1)+
.Imp101		move.l	(a0)+,(a1)+
		move.l	(a0),(a1)

		lea	$158(a2),a0
		lea	36(a4),a1
		move.l	(a0)+,(a1)+
		move.l	(a0)+,(a1)+
		move.l	(a0),(a1)

		lea	$1a6(a2),a0
		move.l	(a0)+,(a4)
		move.l	(a0),4(a4)

		lea	$148(a2),a0
		lea	20(a4),a1
		move.l	(a0)+,(a1)+
		move.l	(a0)+,(a1)+
		move.l	(a0)+,(a1)+
		move.l	(a0),(a1)

		move.l	4(a4),d0
		bclr	#31,d0
		move.l	d0,4(a4)
		move.w	d5,52(a4)	;amount hunks

		lea	54(a4),a0
		moveq	#54-1,d0
.CopyTab	move.b	(a4,d0.w),(a0,d0.w)
		dbf	d0,.CopyTab

		move.l	Imp_UncrBuf(a5),a6	;decrunch buffer
		move.l	Imp_UncrLen(a5),d0
		move.l	d0,d4
		add.l	d0,a6
		move.l	a6,a2
		move.l	Imp_CrunchBuf(a5),a0

		sub.l	a1,a1
		move.w	52(a4),d0
		lsl.w	#2,d0
		lea	20(a1,d0.w),a1	;wegen hunk header

		bsr	Count_Imploder

		add.w	#54,a7
		move.l	a7,a4

		tst.w	d0
		beq.s	.CountError

		move.l	a1,d0
		move.l	d0,xfdbi_TargetBufLen(a5)
		move.l	d0,xfdbi_TargetBufSaveLen(a5)
		move.l	xfdbi_TargetBufMemType(a5),d1
		move.l	4.w,a6
		jsr	_LVOAllocMem(a6)
		move.w	#XFDERR_NOMEMORY,xfdbi_Error(a5)
		move.l	d0,xfdbi_TargetBuffer(a5)
		bne.s	.MemOk
.CountError	add.w	#54,a7
		bra.s	.ErrorFree

.MemOk		move.l	Imp_UncrBuf(a5),a6	;decrunch buffer
		move.l	Imp_UncrLen(a5),d0
		move.l	d0,d4
		add.l	d0,a6
		move.l	a6,a2
		move.l	Imp_CrunchBuf(a5),a0
		move.l	xfdbi_TargetBuffer(a5),a1

		move.w	52(a4),d0
		lsl.w	#2,d0
		lea	20(a1,d0.w),a1	;wegen hunk header

		bsr	D_Imploder

		move.l	xfdbi_TargetBuffer(a5),a0
		move.l	xfdbi_SourceBuffer(a5),a1
		move.l	#$3f3,(a0)+
		clr.l	(a0)+
		moveq	#0,d0
		move.w	52(a4),d0
		move.l	d0,(a0)+
		clr.l	(a0)+
		subq.l	#1,d0
		move.l	d0,(a0)+
		lea	24(a1),a1
.CopyLens	move.l	(a1)+,(a0)+
		dbf	d0,.CopyLens	

		add.w	#54,a7

		move.l	Imp_UncrBuf(a5),a1
		move.l	Imp_UncrLen(a5),d0
		move.l	4.w,a6
		jsr	_LVOFreeMem(a6)
		moveq	#1,d0

.Exit		move.l	(a7)+,a1	;bufferinfo
		moveq	#xfdBufferInfo_SIZE-1,d1
.CopyBI2	move.b	(a5)+,(a1)+
		dbf	d1,.CopyBI2
		add.w	#Imp_SIZE,a7
		movem.l	(a7)+,d2-d7/a2-a6
		rts
		
.ErrorFree	move.l	Imp_UncrBuf(a5),a1
		move.l	Imp_UncrLen(a5),d0
		move.l	4.w,a6
		jsr	_LVOFreeMem(a6)
		moveq	#0,d0
		bra.s	.Exit

* a0: buffer

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

RS_Imploder	add.l	a0,a0
		add.l	a0,a0
		cmp.l	#($14*4)+8,-4(a0)
		blt.s	.Exit

		cmp.l	#$49fa0036,8(a0)	;3.1
		beq.s	.Next1
		cmp.l	#$49fa005e,8(a0)	;4.0
		beq.s	.Next1
		cmp.l	#$49fa0042,16(a0)	;3.1 pure
		bne.s	.Exit

.Next1		cmp.l	#$4e913c3c,18(a0)	;3.1
		beq.s	.Next2
		cmp.w	#$4e91,18(a0)		;4.0
		beq.s	.Next2
		cmp.l	#$4e913c3c,26(a0)	;3.1 pure
		bne.s	.Exit

.Next2		cmp.l	#$51892011,26(a0)	;3.1
		beq.s	.Ok
		cmp.l	#$51892011,34(a0)	;3.1 pure + 4.0
		bne.s	.Exit

.Ok		moveq	#1,d0
		rts

.Exit		moveq	#0,d0
		rts

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

DS_Imploder	moveq	#0,d0

DS_Imp		movem.l	d2-d7/a2-a6,-(a7)
		move.l	a0,a5
		sub.w	#54+2,a7
		move.l	a7,a4
		move.w	d0,54(a4)
		move.l	xfdsi_SegList(a5),48(a4)

		moveq	#-1,d6
		bsr	.GetSegment
.Search		cmp.w	#$3c3c,(a1)+
		bne.s	.Search
		move.w	(a1),d6		;code hunk + amount of hunks
		bsr	.GetSegment
		move.l	a1,a2

		move.w	#XFDERR_CORRUPTEDDATA,xfdsi_Error(a5)
		cmp.w	#$d3fc,6(a2)	;wegen patch
		bne	.Error
		move.l	8(a2),d5	;crunched length

		add.w	#$30,a2
		cmp.w	#$d080,(a2)
		beq.s	.Imp31
		add.w	#$10,a2
		cmp.w	#$d080,(a2)
		bne	.Error

.Imp31		move.l	48(a4),a0
		add.l	a0,a0
		add.l	a0,a0
		move.w	d6,d0
		move.w	xfdsi_RelMode(a5),d1
		bsr	xfdChangeHunkMemType
		move.w	d0,xfdsi_Error(a5)
		bne	.Error

		lea	$f6(a2),a0
		lea	8(a4),a1
		cmp.w	#$5007,-4(a0)	;Imp 1.0 ???
		bne.s	.NoImp101
		addq.w	#4,a0
		move.l	(a0)+,(a1)+
		addq.w	#4,a0
		bra.s	.Imp101
.NoImp101	move.l	(a0)+,(a1)+
.Imp101		move.l	(a0)+,(a1)+
		move.l	(a0),(a1)

		lea	$158(a2),a0
		lea	36(a4),a1
		move.l	(a0)+,(a1)+
		move.l	(a0)+,(a1)+
		move.l	(a0),(a1)

		lea	$1a6(a2),a0
		move.l	(a0)+,(a4)
		move.l	(a0),4(a4)

		lea	$148(a2),a0
		lea	20(a4),a1
		move.l	(a0)+,(a1)+
		move.l	(a0)+,(a1)+
		move.l	(a0)+,(a1)+
		move.l	(a0),(a1)

		move.l	4(a4),d0
		bclr	#31,d0
		move.l	d0,4(a4)
		move.w	d6,52(a4)	;amount hunks

		addq.w	#2,d6		;decrunch buffer
		bsr	.GetSegment
		move.l	a1,a6
		move.l	-8(a1),d0
		subq.l	#8,d0
		move.l	d0,d4
		add.l	d0,a6
		move.l	a6,a2

		subq.w	#1,d6
		bsr	.GetSegment
		move.l	a1,a0
		add.l	d5,a0		;crunched data

		move.l	a5,-(a7)
		moveq	#0,d5
.l3FC		move.w	d5,d6
		bsr	.GetSegment
		move.l	a1,a3
.l416		cmp.l	a6,a2
		bne.s	.l41E
		bsr	Imp_Decr16
.l41E		move.l	(a2)+,d0
		bpl.s	.l42E
		addq.w	#1,d5
		cmp.w	52(a4),d5
		bne.s	.l3FC
		move.l	(a7)+,a5
		bra.s	.FreeSegs

.l42E		add.l	d0,d0
		bpl.s	.l474
.l432		cmp.l	a6,a2
		bne.s	.l438
		bsr	Imp_Decr16
.l438		move.l	(a2)+,d0
		move.l	d0,d1
		beq.s	.l416
		cmp.l	a6,a2
		bne.s	.l444
		bsr	Imp_Decr16
.l444		move.l	(a2)+,d0
		move.w	d0,d6
		bsr	.GetSegment
		move.l	a1,d3
		moveq	#0,d2
.l462		cmp.l	a6,a2
		bne.s	.l468
		bsr	Imp_Decr16
.l468		add.l	(a2)+,d2
		add.l	d3,0(a3,d2.l)
		subq.l	#1,d1
		bne.s	.l462
		bra.s	.l432

.l474		lsr.l	#1,d0
		move.l	a3,a1
.l478		lea	-$20(a6),a6
		movem.l	d1-d7/a0,-(sp)
.l480		subq.l	#8,d0
		bmi.s	.l496
		cmp.l	a6,a2
		bhi.s	.l496
		movem.l	(a2)+,d1-d7/a0
		movem.l	d1-d7/a0,(a1)
		add.w	#$20,a1
		bra.s	.l480
.l496		movem.l	(sp)+,d1-d7/a0
		lea	$20(a6),a6
		addq.l	#8,d0
		beq.b	.l416
.l4A4		cmp.l	a6,a2
		beq.s	.l4B2
		move.l	(a2)+,(a1)+
		subq.l	#1,d0
		bne.s	.l4A4
		bra	.l416

.l4B2		bsr	Imp_Decr16
		bra.s	.l478

.FreeSegs	move.l	4.w,a6
		move.w	52(a4),d6
		addq.w	#2,d6
		moveq	#3-1,d2
.FreeBehind	bsr.s	.GetSegment
		subq.w	#8,a1
		move.l	(a1),d0
		jsr	_LVOFreeMem(a6)
		subq.w	#1,d6
		dbf	d2,.FreeBehind

		bsr.s	.GetSegment
		move.l	-(a1),d0	;wegen ovl
		clr.l	(a1)

		moveq	#-1,d6
		bsr.s	.GetSegment
		move.l	-(a1),xfdsi_SegList(a5)
		tst.w	54(a4)
		beq.s	.NoOvl
		move.l	20(a1),a0	;ovl hunktable
		add.l	a0,a0
		add.l	a0,a0
.SearchHunk	move.l	4(a0),(a0)	;delete first hunk
		cmp.l	(a0)+,d0
		bne.s	.SearchHunk
		clr.l	-4(a0)		;delete last hunks
		clr.l	(a0)+
		clr.l	(a0)+
		move.l	(a1),d0
		lsl.l	#2,d0
		move.l	d0,a0
		moveq	#12,d0
.CopyOvl	move.l	12(a1,d0.w),12(a0,d0.w)
		subq.w	#4,d0
		bge.s	.CopyOvl

.NoOvl		move.l	-(a1),d0
		jsr	_LVOFreeMem(a6)

		moveq	#1,d0
		bra.s	.Exit

.Error		moveq	#0,d0
.Exit		add.w	#54+2,a7
		movem.l	(a7)+,d2-d7/a2-a6
		rts

.GetSegment	move.w	d6,d7
		addq.w	#1,d7
		lea	48(a4),a1
.GetSegment1	move.l	(a1),a1
		add.l	a1,a1
		add.l	a1,a1
		dbf	d7,.GetSegment1
		addq.w	#4,a1
		rts

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

S_ImploderLib	dc.l	S_ImploderOvl-Xfd68KHeader
		dc.w	2
		dc.w	39
		dc.l	N_ImploderLib-Xfd68KHeader
		dc.w	XFDPFF_RELOC!XFDPFF_RELMODE
		dc.w	0
		dc.l	RB_ImploderLib-Xfd68KHeader
		dc.l	DB_ImploderLib-Xfd68KHeader
		dc.l	RS_ImploderLib-Xfd68KHeader
		dc.l	DS_ImploderLib-Xfd68KHeader
		dc.w	XFDID_ImploderLib
		dc.w	0
		dc.l	$68+4+16

N_ImploderLib	dc.b	'Imploder Library',0
		even

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

RB_ImploderLib	BSR	xfdCodeBeginRecog
		TST.L	D0
		BEQ.B	.Exit

		cmp.l	#$43fa001c,6(a0)	;3.1
		beq.s	.Next
		cmp.l	#$43fa001f,10(a0)	;4.0
		bne.s	.Exit

.Next		cmp.l	#$4eaefdd8,14(a0)	;3.1 + 4.0
		bne.s	.Exit
		cmp.l	#$4eaeffe2,24(a0)	;3.1 + 4.0
		bne.s	.Exit
		cmp.l	#$48e7ffff,(a0)		;3.1 + 4.0
		bne.s	.Exit

		moveq	#1,d0
		rts

.Exit		moveq	#0,d0
		rts

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

DB_ImploderLib	movem.l	d2-d7/a2-a6,-(a7)
		sub.w	#Imp_SIZE,a7
		move.l	a7,a5
		move.l	a0,-(a7)	;bufferinfo
		move.l	a5,a1
		moveq	#xfdBufferInfo_SIZE-1,d1
.CopyBI1	move.b	(a0)+,(a1)+
		dbf	d1,.CopyBI1

		move.l	xfdbi_SourceBuffer(a5),a0
		move.l	8(a0),d0
		subq.w	#2,d0
		move.w	d0,d5		;amount hunks

		lea	20(a0),a0
		move.l	a0,Imp_HunkLens(a5)

		lsl.w	#2,d0
		move.l	(a0,d0.w),d2	;crunched length
		lsl.l	#2,d2
		move.l	4(a0,d0.w),d0	;uncrunch buffer len
		lsl.l	#2,d0
		move.l	d0,Imp_UncrLen(a5)
		moveq	#1,d1
		move.l	4.w,a6
		jsr	_LVOAllocMem(a6)
		move.w	#XFDERR_NOMEMORY,xfdbi_Error(a5)
		move.l	d0,Imp_UncrBuf(a5)
		beq	.Exit

		move.w	#XFDERR_CORRUPTEDDATA,xfdbi_Error(a5)
		move.l	xfdbi_SourceBuffer(a5),a0
		MOVE.L	xfdbi_SourceBufLen(A5),D0
		moveq	#0,d1
		bsr		xfdGetHunk
		tst.l	d0
		beq	.ErrorFree
		move.l	d0,a2

		addq.w	#8,a2		;code begin
		tst.b	5(a2)		;im 1.hunk: moveq #xx,d0
		beq.s	.NoCorr
		subq.l	#4,d2
		or.b	5(a2),d2	;crunched len korrigieren
.NoCorr		move.l	d2,Imp_CrunchLen(a5)

		lea	28(a2),a3	;pointer to decinfo

		move.l	-4(a2),d1
		lsl.l	#2,d1
		add.l	d1,a2
		addq.w	#4,a2
		move.w	d5,d0		;get pointer to crunched data
		subq.w	#2,d0
		bmi.s	.NoHunks
.JmpBSS		lea	12(a2),a2
		dbf	d0,.JmpBSS

.NoHunks	cmp.l	#$3ea,(a2)+
		bne	.ErrorFree
		addq.w	#4,a2
		add.l	Imp_CrunchLen(a5),a2
		move.l	a2,Imp_CrunchBuf(a5)

		sub.w	#54*2,a7
		move.l	a7,a4
				
		lea	Imp_Tab1(pc),a0
		lea	8(a4),a1
		move.l	(a0)+,(a1)+
		move.l	(a0)+,(a1)+
		move.l	(a0)+,(a1)+
		move.b	(a3),d0
		lsr.b	#4,d0
		move.b	d0,-(a1)

		move.b	(a3)+,d0
		and.w	#15,d0
		mulu	#12,d0
		lea	Imp_Tab2(pc),a0
		add.w	d0,a0
		lea	36(a4),a1
		move.l	(a0)+,(a1)+
		move.l	(a0)+,(a1)+
		move.l	(a0)+,(a1)

		move.b	(a3)+,2(a4)
		move.w	(a3)+,(a4)
		move.l	(a3),4(a4)
		clr.b	3(a4)

		lea	36(a4),a0
		lea	20(a4),a1
		moveq	#7,d1
.Prep1		move.b	(a0)+,d0
		bpl.s	.Prep2
		and.b	#$7f,d0
		addq.b	#8,d0
.Prep2		moveq	#0,d2
		bset	d0,d2
		tst.l	4(a4)
		bpl.s	.Prep3
		subq.w	#1,d2
.Prep3		move.w	d2,(a1)+
		dbra	d1,.Prep1

		lea	20(a4),a0
		lea	28(a4),a1
		moveq	#3,d1
.Prep4		move.w	(a0)+,d0
		add.w	d0,(a1)+
		dbra	d1,.Prep4

		move.l	4(a4),d0
		bclr	#31,d0
		move.l	d0,4(a4)
		move.w	d5,52(a4)	;amount hunks

		lea	54(a4),a0
		moveq	#54-1,d0
.CopyTab	move.b	(a4,d0.w),(a0,d0.w)
		dbf	d0,.CopyTab

		move.l	Imp_UncrBuf(a5),a6	;decrunch buffer
		move.l	Imp_UncrLen(a5),d0
		move.l	d0,d4
		add.l	d0,a6
		move.l	a6,a2
		move.l	Imp_CrunchBuf(a5),a0

		sub.l	a1,a1
		move.w	52(a4),d0
		lsl.w	#2,d0
		lea	20(a1,d0.w),a1	;wegen hunk header

		bsr	Count_Imploder

		add.w	#54,a7
		move.l	a7,a4

		tst.w	d0
		beq.s	.CountError

		move.l	a1,d0
		move.l	d0,xfdbi_TargetBufLen(a5)
		move.l	d0,xfdbi_TargetBufSaveLen(a5)
		move.l	xfdbi_TargetBufMemType(a5),d1
		move.l	4.w,a6
		jsr	_LVOAllocMem(a6)
		move.w	#XFDERR_NOMEMORY,xfdbi_Error(a5)
		move.l	d0,xfdbi_TargetBuffer(a5)
		bne.s	.MemOk
.CountError	add.w	#54,a7
		bra.s	.ErrorFree

.MemOk		move.l	Imp_UncrBuf(a5),a6	;decrunch buffer
		move.l	Imp_UncrLen(a5),d0
		move.l	d0,d4
		add.l	d0,a6
		move.l	a6,a2
		move.l	Imp_CrunchBuf(a5),a0
		move.l	xfdbi_TargetBuffer(a5),a1

		move.w	52(a4),d0
		lsl.w	#2,d0
		lea	20(a1,d0.w),a1	;wegen hunk header

		bsr	D_Imploder

		add.w	#54,a7

		move.l	xfdbi_TargetBuffer(a5),a0
		move.l	xfdbi_SourceBuffer(a5),a1
		move.l	#$3f3,(a0)+
		clr.l	(a0)+
		move.l	8(a1),d0
		subq.l	#2,d0
		move.l	d0,(a0)+
		clr.l	(a0)+
		subq.l	#1,d0
		move.l	d0,(a0)+
		lea	20(a1),a1
.CopyLens	move.l	(a1)+,(a0)+
		dbf	d0,.CopyLens	

		move.l	Imp_UncrBuf(a5),a1
		move.l	Imp_UncrLen(a5),d0
		move.l	4.w,a6
		jsr	_LVOFreeMem(a6)
		moveq	#1,d0

.Exit		move.l	(a7)+,a1	;bufferinfo
		moveq	#xfdBufferInfo_SIZE-1,d1
.CopyBI2	move.b	(a5)+,(a1)+
		dbf	d1,.CopyBI2
		add.w	#Imp_SIZE,a7
		movem.l	(a7)+,d2-d7/a2-a6
		rts
		
.ErrorFree	move.l	Imp_UncrBuf(a5),a1
		move.l	Imp_UncrLen(a5),d0
		move.l	4.w,a6
		jsr	_LVOFreeMem(a6)
		moveq	#0,d0
		bra.s	.Exit

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

RS_ImploderLib	add.l	a0,a0
		add.l	a0,a0
		cmp.l	#($d*4)+8,-4(a0)
		blt.s	.Exit

		cmp.l	#$43fa001c,10(a0)	;3.1
		beq.s	.Next
		cmp.l	#$43fa001f,14(a0)	;4.0
		bne.s	.Exit

.Next		cmp.l	#$4eaefdd8,18(a0)	;3.1 + 4.0
		bne.s	.Exit
		cmp.l	#$4eaeffe2,28(a0)	;3.1 + 4.0
		bne.s	.Exit
		cmp.l	#$48e7ffff,4(a0)	;3.1 + 4.0
		bne.s	.Exit

		moveq	#1,d0
		rts

.Exit		moveq	#0,d0
		rts

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

DS_ImploderLib	movem.l	d2-d7/a2-a6,-(a7)
		move.l	a0,a5
		sub.w	#54,a7
		move.l	a7,a4
		move.l	xfdsi_SegList(a5),48(a4)

		moveq	#0,d6
		bsr	.GetSegment
		lea	28(a1),a3	;pointer to decinfo

		lea	Imp_Tab1(pc),a0
		lea	8(a4),a1
		move.l	(a0)+,(a1)+
		move.l	(a0)+,(a1)+
		move.l	(a0)+,(a1)+
		move.b	(a3),d0
		lsr.b	#4,d0
		move.b	d0,-(a1)

		move.b	(a3)+,d0
		and.w	#15,d0
		mulu	#12,d0
		lea	Imp_Tab2(pc),a0
		add.w	d0,a0
		lea	36(a4),a1
		move.l	(a0)+,(a1)+
		move.l	(a0)+,(a1)+
		move.l	(a0)+,(a1)

		move.b	(a3)+,2(a4)
		move.w	(a3)+,(a4)
		move.l	(a3),4(a4)
		clr.b	3(a4)

		lea	36(a4),a0
		lea	20(a4),a1
		moveq	#7,d1
.Prep1		move.b	(a0)+,d0
		bpl.s	.Prep2
		and.b	#$7f,d0
		addq.b	#8,d0
.Prep2		moveq	#0,d2
		bset	d0,d2
		tst.l	4(a4)
		bpl.s	.Prep3
		subq.w	#1,d2
.Prep3		move.w	d2,(a1)+
		dbra	d1,.Prep1

		lea	20(a4),a0
		lea	28(a4),a1
		moveq	#3,d1
.Prep4		move.w	(a0)+,d0
		add.w	d0,(a1)+
		dbra	d1,.Prep4

		move.l	4(a4),d0
		bclr	#31,d0
		move.l	d0,4(a4)

		move.l	48(a4),d0	;seglist
		lsl.l	#2,d0
		move.l	d0,a0
		moveq	#-1,d0
.CountHunks	addq.w	#1,d0
		move.l	(a0),d1
		add.l	d1,d1
		add.l	d1,d1
		move.l	d1,a0
		bne.s	.CountHunks
		move.w	d0,52(a4)
		subq.w	#1,52(a4)	;amount hunks
		move.w	d0,d6

		lea	48(a4),a0
		move.w	d6,d0
		move.w	xfdsi_RelMode(a5),d1
		bsr	xfdChangeHunkMemType
		move.w	d0,xfdsi_Error(a5)
		bne	.Error

		bsr	.GetSegment
		move.l	a1,a6
		move.l	-8(a1),d0
		subq.l	#8,d0
		move.l	d0,d4
		add.l	d0,a6
		move.l	a6,a2		;decrunch buffer

		subq.w	#1,d6
		bsr	.GetSegment
		move.l	-8(a1),d0
		subq.l	#8,d0
		tst.b	-$1b(a3)
		beq.s	.NoCorr
		subq.l	#4,d0
		or.b	-$1b(a3),d0
.NoCorr		move.l	a1,a0
		add.l	d0,a0		;crunched data

		move.l	a5,-(a7)
		moveq	#0,d5
.l3FC		move.w	d5,d6
		bsr	.GetSegment
		move.l	a1,a3
.l416		cmp.l	a6,a2
		bne.s	.l41E
		bsr	Imp_Decr16
.l41E		move.l	(a2)+,d0
		bpl.s	.l42E
		addq.w	#1,d5
		cmp.w	52(a4),d5
		bne.s	.l3FC
		move.l	(a7)+,a5
		bra.s	.FreeSegs

.l42E		add.l	d0,d0
		bpl.s	.l474
.l432		cmp.l	a6,a2
		bne.s	.l438
		bsr	Imp_Decr16
.l438		move.l	(a2)+,d0
		move.l	d0,d1
		beq.s	.l416
		cmp.l	a6,a2
		bne.s	.l444
		bsr	Imp_Decr16
.l444		move.l	(a2)+,d0
		move.w	d0,d6
		bsr	.GetSegment
		move.l	a1,d3
		moveq	#0,d2
.l462		cmp.l	a6,a2
		bne.s	.l468
		bsr	Imp_Decr16
.l468		add.l	(a2)+,d2
		add.l	d3,0(a3,d2.l)
		subq.l	#1,d1
		bne.s	.l462
		bra.s	.l432

.l474		lsr.l	#1,d0
		move.l	a3,a1
.l478		lea	-$20(a6),a6
		movem.l	d1-d7/a0,-(sp)
.l480		subq.l	#8,d0
		bmi.s	.l496
		cmp.l	a6,a2
		bhi.s	.l496
		movem.l	(a2)+,d1-d7/a0
		movem.l	d1-d7/a0,(a1)
		add.w	#$20,a1
		bra.s	.l480
.l496		movem.l	(sp)+,d1-d7/a0
		lea	$20(a6),a6
		addq.l	#8,d0
		beq.b	.l416
.l4A4		cmp.l	a6,a2
		beq.s	.l4B2
		move.l	(a2)+,(a1)+
		subq.l	#1,d0
		bne.s	.l4A4
		bra	.l416

.l4B2		bsr	Imp_Decr16
		bra.s	.l478

.FreeSegs	move.l	4.w,a6
		move.w	52(a4),d6
		addq.w	#1,d6
		moveq	#2-1,d2
.FreeBehind	bsr.s	.GetSegment
		subq.w	#8,a1
		move.l	(a1),d0
		jsr	_LVOFreeMem(a6)
		subq.w	#1,d6
		dbf	d2,.FreeBehind

		bsr.s	.GetSegment
		clr.l	-(a1)

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

.Error		moveq	#0,d0
		bra.s	.Exit

.GetSegment	move.w	d6,d7
		lea	48(a4),a1
.GetSegment1	move.l	(a1),a1
		add.l	a1,a1
		add.l	a1,a1
		dbf	d7,.GetSegment1
		addq.w	#4,a1
		rts

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

S_ImploderOvl	dc.l	S_FImp-Xfd68KHeader
		dc.w	2
		dc.w	39
		dc.l	N_ImploderOvl-Xfd68KHeader
		dc.w	XFDPFF_RELOC!XFDPFF_RELMODE
		dc.w	0
		dc.l	RB_ImploderOvl-Xfd68KHeader
		dc.l	DB_ImploderOvl-Xfd68KHeader
		dc.l	RS_ImploderOvl-Xfd68KHeader
		dc.l	DS_ImploderOvl-Xfd68KHeader
		dc.w	XFDID_ImploderOvl
		dc.w	0
		dc.l	$2c0+4+16

N_ImploderOvl	dc.b	'Imploder Overlayed',0
		even

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

RB_ImploderOvl	BSR	xfdCodeBeginRecog
		TST.L	D0
		BEQ.B	.Exit

		cmp.l	#$60000016,(a0)
		bne.s	.Exit
		cmp.w	#$abcd,6(a0)
		bne.s	.Exit
		cmp.l	#$49fa005e,28(a0)
		bne.s	.Exit
		cmp.l	#$4e913c3c,38(a0)
		bne.s	.Exit

		moveq	#1,d0
		rts

.Exit		moveq	#0,d0
		rts

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

Imp_UncrLen	SET	xfdBufferInfo_SIZE
Imp_UncrBuf	SET	xfdBufferInfo_SIZE+4
Imp_CrunchLen	SET	xfdBufferInfo_SIZE+8
Imp_CrunchBuf	SET	xfdBufferInfo_SIZE+12
Imp_HunkLens	SET	xfdBufferInfo_SIZE+16
Imp_OvlBuf	SET	xfdBufferInfo_SIZE+20
Imp_OvlLen	SET	xfdBufferInfo_SIZE+24
Imp_SIZE	SET	xfdBufferInfo_SIZE+28

DB_ImploderOvl	movem.l	d2-d7/a2-a6,-(a7)
		sub.w	#Imp_SIZE,a7
		move.l	a7,a5
		move.l	a0,-(a7)	;bufferinfo
		move.l	a5,a1
		moveq	#xfdBufferInfo_SIZE-1,d1
.CopyBI1	move.b	(a0)+,(a1)+
		dbf	d1,.CopyBI1

		move.l	xfdbi_SourceBuffer(a5),a0
		move.l	16(a0),d0
		sub.l	12(a0),d0
		subq.l	#4-1,d0
		move.l	d0,d5		;amount hunks

		lea	24(a0),a0
		move.l	a0,Imp_HunkLens(a5)

		addq.w	#2,d0
		lsl.w	#2,d0
		move.l	(a0,d0.w),d0	;uncrunch buffer len
		lsl.l	#2,d0
		move.l	d0,Imp_UncrLen(a5)
		moveq	#1,d1
		move.l	4.w,a6
		jsr	_LVOAllocMem(a6)
		move.w	#XFDERR_NOMEMORY,xfdbi_Error(a5)
		move.l	d0,Imp_UncrBuf(a5)
		beq	.Exit

		move.w	#XFDERR_CORRUPTEDDATA,xfdbi_Error(a5)
		move.l	xfdbi_SourceBuffer(a5),a0
		MOVE.L	xfdbi_SourceBufLen(A5),D0
		move.l	d5,d1
		addq.w	#1,d1
		bsr		xfdGetHunk
		tst.l	d0
		beq	.ErrorFree
		move.l	d0,a2

		cmp.l	#$3e9,(a2)+
		bne	.ErrorFree
		addq.w	#4,a2		;decruncher code

		cmp.w	#$d3fc,6(a2)	;wegen patch
		bne	.ErrorFree
		move.l	8(a2),Imp_CrunchLen(a5)
		
		move.l	-4(a2),d0
		lsl.l	#2,d0
		lea	4(a2,d0.l),a3
		cmp.l	#$3e9,(a3)
		beq.s	.Patch
		cmp.l	#$3ea,(a3)
		bne	.ErrorFree
.Patch		addq.w	#8,a3
		add.l	Imp_CrunchLen(a5),a3
		move.l	a3,Imp_CrunchBuf(a5)

		add.w	#$30,a2
		cmp.w	#$d080,(a2)
		beq.s	.Imp31
		add.w	#$10,a2
		cmp.w	#$d080,(a2)
		bne	.ErrorFree

.Imp31		sub.w	#54*2,a7
		move.l	a7,a4
				
		lea	$f6(a2),a0
		lea	8(a4),a1
		move.l	(a0)+,(a1)+
		move.l	(a0)+,(a1)+
		move.l	(a0)+,(a1)+

		lea	$158(a2),a0
		lea	36(a4),a1
		move.l	(a0)+,(a1)+
		move.l	(a0)+,(a1)+
		move.l	(a0)+,(a1)

		lea	$1a6(a2),a0
		move.l	(a0)+,(a4)
		move.l	(a0),4(a4)

		lea	$148(a2),a0
		lea	20(a4),a1
		move.l	(a0)+,(a1)+
		move.l	(a0)+,(a1)+
		move.l	(a0)+,(a1)+
		move.l	(a0),(a1)

		move.l	4(a4),d0
		bclr	#31,d0
		move.l	d0,4(a4)
		move.w	d5,52(a4)	;amount hunks

		lea	54(a4),a0
		moveq	#54-1,d0
.CopyTab	move.b	(a4,d0.w),(a0,d0.w)
		dbf	d0,.CopyTab

		move.l	Imp_UncrBuf(a5),a6	;decrunch buffer
		move.l	Imp_UncrLen(a5),d0
		move.l	d0,d4
		add.l	d0,a6
		move.l	a6,a2
		move.l	Imp_CrunchBuf(a5),a0

		sub.l	a1,a1
		move.w	52(a4),d0
		lsl.w	#2,d0
		lea	20(a1,d0.w),a1	;wegen hunk header

		bsr	Count_Imploder

		add.w	#54,a7
		move.l	a7,a4

		tst.w	d0
		beq.s	.CountError

		move.l	a1,-(a7)	;basic length
		move.l	xfdbi_SourceBuffer(a5),a0
		MOVE.L	xfdbi_SourceBufLen(A5),D0
		moveq	#3,d1
		add.w	52(a4),d1
		bsr		xfdGetHunk
		tst.l	d0
		beq	.ErrorFree
		movea.l	d0,a0
		cmp.l	#$3eb,(a0)+
		bne	.ErrorFree
		addq.w	#8,a0
		cmp.l	#$3f5,(a0)
		bne	.ErrorFree
		move.l	xfdbi_SourceBufLen(a5),d0
		sub.l	a0,d0
		add.l	xfdbi_SourceBuffer(a5),d0
		move.l	a0,Imp_OvlBuf(a5)
		move.l	d0,Imp_OvlLen(a5)
		add.l	(a7)+,d0	;basic length

		move.l	d0,xfdbi_TargetBufLen(a5)
		move.l	d0,xfdbi_TargetBufSaveLen(a5)
		move.l	xfdbi_TargetBufMemType(a5),d1
		move.l	4.w,a6
		jsr	_LVOAllocMem(a6)
		move.w	#XFDERR_NOMEMORY,xfdbi_Error(a5)
		move.l	d0,xfdbi_TargetBuffer(a5)
		bne.s	.MemOk
.CountError	add.w	#54,a7
		bra	.ErrorFree

.MemOk		move.l	Imp_UncrBuf(a5),a6	;decrunch buffer
		move.l	Imp_UncrLen(a5),d0
		move.l	d0,d4
		add.l	d0,a6
		move.l	a6,a2
		move.l	Imp_CrunchBuf(a5),a0
		move.l	xfdbi_TargetBuffer(a5),a1

		move.w	52(a4),d0
		lsl.w	#2,d0
		lea	20(a1,d0.w),a1	;wegen hunk header

		bsr	D_Imploder

		add.w	#54,a7

		move.l	a1,-(a7)
		move.l	Imp_OvlBuf(a5),a0
		move.l	Imp_OvlLen(a5),d0
		move.l	4.w,a6
		jsr	_LVOCopyMem(a6)
		move.l	(a7)+,a1

		move.l	a1,d0
		sub.l	xfdbi_TargetBuffer(a5),d0
		sub.l	Imp_OvlBuf(a5),d0
		add.l	xfdbi_SourceBuffer(a5),d0

		addq.w	#4,a1
		move.l	(a1)+,d1
		move.l	xfdbi_SourceBuffer(a5),a0
		move.l	Imp_OvlBuf(a5),d3
		sub.l	xfdbi_SourceBuffer(a5),d3

.NextCorr	subq.l	#1,d1
		bmi.s	.EndCorr
		move.l	(a1)+,d2
		cmp.l	xfdbi_SourceBufLen(a5),d2
		bcc.s	.NextCorr
		cmp.l	d3,d2
		bcs.s	.NextCorr
		cmp.l	#$3f3,(a0,d2.l)
		bne.s	.NextCorr
		add.l	d0,-4(a1)
		bra.s	.NextCorr

.EndCorr	move.l	xfdbi_TargetBuffer(a5),a0
		move.l	xfdbi_SourceBuffer(a5),a1
		move.l	#$3f3,(a0)+
		clr.l	(a0)+
		move.l	8(a1),d0
		subq.l	#1,d0
		move.l	d0,(a0)+
		clr.l	(a0)+
		move.l	16(a1),d0
		subq.l	#4,d0
		move.l	d0,(a0)+
		lea	24(a1),a1
.CopyLens	move.l	(a1)+,(a0)+
		dbf	d0,.CopyLens	

		move.l	Imp_UncrBuf(a5),a1
		move.l	Imp_UncrLen(a5),d0
		move.l	4.w,a6
		jsr	_LVOFreeMem(a6)
		moveq	#1,d0

.Exit		move.l	(a7)+,a1	;bufferinfo
		moveq	#xfdBufferInfo_SIZE-1,d1
.CopyBI2	move.b	(a5)+,(a1)+
		dbf	d1,.CopyBI2
		add.w	#Imp_SIZE,a7
		movem.l	(a7)+,d2-d7/a2-a6
		rts
		
.ErrorFree	move.l	Imp_UncrBuf(a5),a1
		move.l	Imp_UncrLen(a5),d0
		move.l	4.w,a6
		jsr	_LVOFreeMem(a6)
		moveq	#0,d0
		bra.s	.Exit

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

RS_ImploderOvl	add.l	a0,a0
		add.l	a0,a0
		cmp.l	#($24*4)+8,-4(a0)
		bne.s	.Exit

		cmp.l	#$60000016,4(a0)
		bne.s	.Exit
		cmp.w	#$abcd,10(a0)
		bne.s	.Exit
		cmp.l	#$49fa005e,32(a0)
		bne.s	.Exit
		cmp.l	#$4e913c3c,42(a0)
		bne.s	.Exit

		moveq	#1,d0
		rts

.Exit		moveq	#0,d0
		rts

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

DS_ImploderOvl	moveq	#1,d0
		bra	DS_Imp

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

S_FImp
		IFND	XFD_LASTSLAVE
		dc.l	S_Imploder_END-Xfd68KHeader
		ELSE
		dc.l	0
		ENDIF
		dc.w	2
		dc.w	39
		dc.l	N_FImp-Xfd68KHeader
		dc.w	XFDPFF_DATA!XFDPFF_RECOGLEN!XFDPFF_USERTARGET
		dc.w	0
		dc.l	RB_FImp-Xfd68KHeader
		dc.l	DB_FImp-Xfd68KHeader
		dc.l	SD_FImp-Xfd68KHeader
		dc.l	VD_FImp-Xfd68KHeader
		dc.w	XFDID_FileImploder
		dc.w	0
		dc.l	12+4+$2e

N_FImp		dc.b	'Imploder Data',0
		even

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

RB_FImp		bsr.s	SD_FImp
		beq.s	.Return
		move.l	4(a0),xfdrr_MinTargetLen(a1)
		move.l	4(a0),xfdrr_FinalTargetLen(a1)
		MOVEQ	#$2E,D1
		ADD.L	8(A0),D1
		MOVE.L	D1,xfdrr_MinSourceLen(A1)
		CMP.L	4(A0),D1
		BGT.B	.Exit
		tst.b	4(a0)
		bne.s	.Exit
		tst.b	8(a0)
		beq.s	.Return
.Exit		moveq	#0,d0
.Return		rts

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

SD_FImp		cmp.l	#'IMP!',(a0)
		beq.s	.Ok
		cmp.l	#'EDAM',(a0)
		beq.s	.Ok
		cmp.l	#'CHFI',(a0)
		beq.s	.Ok
		cmp.l	#'PARA',(a0)
		beq.s	.Ok
		cmp.l	#'RDC9',(a0)
		beq.s	.Ok
		cmp.l	#'FLT!',(a0)
		beq.s	.Ok
		cmp.l	#'Dupa',(a0)
		beq.s	.Ok
		cmp.l	#'ATN!',(a0)
		bne.s	.Exit
.Ok		moveq	#1,d0
		rts

.Exit		moveq	#0,d0
		rts

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

VD_FImp		moveq	#$2e,d1
		add.l	8(a0),d1	;crlen
		cmp.l	d0,d1		;crlen > buflen ??
		bgt.s	.Exit
		move.l	4(a0),d0
		sub.l	8(a0),d0	;cr > uncr ??
		bmi.s	.Exit
		move.l	d1,d0
		rts

.Exit		moveq	#0,d0
		rts

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

DB_FImp		MOVEM.L	D2-D7/A2-A6,-(A7)
		MOVE.L	A0,A5
		MOVE.L	xfdbi_SourceBuffer(A5),A0
		MOVE.L	xfdbi_UserTargetBuf(A5),A1
		MOVEQ	#$2E,D0
		ADD.L	8(A0),D0
		MOVE.L	xfdm_ExecBase(A6),A6
		JSR	_LVOCopyMem(a6)

		MOVE.L	xfdbi_UserTargetBuf(A5),A0
		BSR.B	D_FImp
		TST.W	D0
		BNE.B	.NoErr
		MOVE.W	#XFDERR_CORRUPTEDDATA,xfdbi_Error(A5)
.NoErr		MOVEM.L	(A7)+,D2-D7/A2-A6
		RTS

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

D_FImp		move.l	a0,a3
		move.l	a0,a4
		addq.w	#4,a0

		add.l	(a0)+,a4
		movea.l	a4,a6		; buffer end
		add.l	(a0)+,a3
		move.l	a3,a2
		move.l	(a2)+,-(a0)
		move.l	(a2)+,-(a0)
		move.l	(a2)+,-(a0)
		move.l	(a2)+,d2

		move.w	(a2)+,d3
		bmi.s	.Fimp_1be
		subq.w	#1,a3

.Fimp_1be	lea	-28(a7),a7
		move.l	a7,a1
		moveq	#7-1,d0
.Fimp_1c6	move.l	(a2)+,(a1)+
		dbra	d0,.Fimp_1c6

		move.l	a7,a1
		moveq	#0,d4

.Fimp_1d0	tst.l	d2
		beq.s	.Fimp_1da
.Fimp_1d4	cmp.l	a0,a4
		beq.b	.err
		move.b	-(a3),-(a4)
		subq.l	#1,d2
		bne.s	.Fimp_1d4
.Fimp_1da	cmp.l	a4,a0
		bcs.s	.Fimp_1f2

		moveq	#1,d0
		cmp.l	a3,a0
		beq.b	.end
.err		moveq	#0,d0
.end		lea	28(a7),a7
		rts

.Fimp_1f2	add.b	d3,d3
		bne.s	.Fimp_1fa
		move.b	-(a3),d3
		addx.b	d3,d3
.Fimp_1fa	bcc.s	.Fimp_260

		add.b	d3,d3
		bne.s	.Fimp_204
		move.b	-(a3),d3
		addx.b	d3,d3
.Fimp_204	bcc.s	.Fimp_25a

		add.b	d3,d3
		bne.s	.Fimp_20e
		move.b	-(a3),d3
		addx.b	d3,d3
.Fimp_20e	bcc.s	.Fimp_254

		add.b	d3,d3
		bne.s	.Fimp_218
		move.b	-(a3),d3
		addx.b	d3,d3
.Fimp_218	bcc.s	.Fimp_24e

		add.b	d3,d3
		bne.s	.Fimp_222
		move.b	-(a3),d3
		addx.b	d3,d3
.Fimp_222	bcc.s	.Fimp_22a

		move.b	-(a3),d4
		moveq	#3,d0
		bra.s	.Fimp_264

.Fimp_22a	add.b	d3,d3
		bne.s	.Fimp_232
		move.b	-(a3),d3
		addx.b	d3,d3
.Fimp_232	addx.b	d4,d4

		add.b	d3,d3
		bne.s	.Fimp_23c
		move.b	-(a3),d3
		addx.b	d3,d3
.Fimp_23c	addx.b	d4,d4

		add.b	d3,d3
		bne.s	.Fimp_246
		move.b	-(a3),d3
		addx.b	d3,d3
.Fimp_246	addx.b	d4,d4

		addq.b	#6,d4
		moveq	#3,d0
		bra.s	.Fimp_264

.Fimp_24e	moveq	#5,d4
		moveq	#3,d0
		bra.s	.Fimp_264

.Fimp_254	moveq	#4,d4
		moveq	#2,d0
		bra.s	.Fimp_264

.Fimp_25a	moveq	#3,d4
		moveq	#1,d0
		bra.s	.Fimp_264

.Fimp_260	moveq	#2,d4
		moveq	#0,d0
.Fimp_264	moveq	#0,d5
		move.w	d0,d1

		add.b	d3,d3
		bne.s	.Fimp_270
		move.b	-(a3),d3
		addx.b	d3,d3
.Fimp_270	bcc.s	.Fimp_288

		add.b	d3,d3
		bne.s	.Fimp_27a
		move.b	-(a3),d3
		addx.b	d3,d3
.Fimp_27a	bcc.s	.Fimp_284

		move.b	.Fimp_2e8(pc,d0.w),d5
		addq.b	#8,d0
		bra.s	.Fimp_288

.Fimp_284	moveq	#2,d5
		addq.b	#4,d0
.Fimp_288	move.b	.Fimp_2ec(pc,d0.w),d0

.Fimp_28c	add.b	d3,d3
		bne.s	.Fimp_294
		move.b	-(a3),d3
		addx.b	d3,d3
.Fimp_294	addx.w	d2,d2

		subq.b	#1,d0
		bne.s	.Fimp_28c

		add.w	d5,d2
		moveq	#0,d5
		move.l	d5,a2
		move.w	d1,d0

		add.b	d3,d3
		bne.s	.Fimp_2aa
		move.b	-(a3),d3
		addx.b	d3,d3
.Fimp_2aa	bcc.s	.Fimp_2c6

		add.w	d1,d1
		add.b	d3,d3
		bne.s	.Fimp_2b6
		move.b	-(a3),d3
		addx.b	d3,d3
.Fimp_2b6	bcc.s	.Fimp_2c0

		move.w	8(a1,d1.w),a2
		addq.b	#8,d0
		bra.s	.Fimp_2c6

.Fimp_2c0	move.w	(a1,d1.w),a2
		addq.b	#4,d0
.Fimp_2c6	move.b	16(a1,d0.w),d0

.Fimp_2ca	add.b	d3,d3
		bne.s	.Fimp_2d2
		move.b	-(a3),d3
		addx.b	d3,d3
.Fimp_2d2	addx.l	d5,d5

		subq.b	#1,d0
		bne.s	.Fimp_2ca

		addq.w	#1,a2
		add.l	d5,a2
		add.l	a4,a2
		cmp.l	a4,a2	; A2 must be greater than A4
		bls.w	.err
		cmp.l	a6,a2	; A2 must be lower or equal to A6
		bhi.w	.err
.Fimp_2de	cmp.l	a0,a4
		beq.w	.err
		move.b	-(a2),-(a4)
		subq.b	#1,d4
		bne.s	.Fimp_2de

		bra	.Fimp_1d0

.Fimp_2e8	dc.b	6,10,10,18
.Fimp_2ec	dc.b	1,1,1,1
		dc.b	2,3,3,4
		dc.b	4,5,7,14

;=================================================
Count_Imploder	move.l	a5,-(a7)
		move.l	Imp_HunkLens(a5),a3
		moveq	#0,d5
		sf	d7

.Decr1		cmp.l	a6,a2
		bne.s	.Decr2
		bsr	Imp_Decr16
.Decr2		move.l	(a2)+,d0
		bpl.s	.Decr4

		lsl.l	#2,d0
		bne.s	.Error
		tst.b	d7
		bne.s	.Decr3				
		addq.w	#8,a1		;hunk_bss

.Decr3		sf	d7
		addq.w	#4,a1		;hunk_end
		addq.w	#4,a3
		addq.w	#1,d5
		cmp.w	52(a4),d5
		bne.s	.Decr1
		move.l	(a7)+,a5
		moveq	#1,d0
		rts

.Error		move.l	(a7)+,a5
		moveq	#0,d0
		rts

.Decr4		st	d7
		btst	#30,d0
		beq.s	.Decr10

		lsl.l	#2,d0
		bne.s	.Error
		addq.w	#4,a1		;hunk_reloc
.Decr5		cmp.l	a6,a2
		bne.s	.Decr6
		bsr	Imp_Decr16
.Decr6		addq.w	#4,a1
		move.l	(a2)+,d0	;amount
		beq.s	.Decr1
		addq.l	#1,d0
		lsl.l	#2,d0
		add.l	d0,a1		;hunknum + entries
.Decr8		cmp.l	a6,a2
		bne.s	.Decr9
		bsr	Imp_Decr16
.Decr9		addq.w	#4,a2
		subq.l	#4,d0
		bne.s	.Decr8
		bra.s	.Decr5

.Decr10		lsl.l	#2,d0
		addq.w	#8,a1		;hunk_code
		add.l	d0,a1
		lsr.l	#2,d0
		move.l	(a3),d1
		lsl.l	#2,d1
		lsr.l	#2,d1
		cmp.l	d1,d0
		bhi.s	.Error
.Decr11		lea	-32(a6),a6
.Decr12		subq.l	#8,d0
		bmi.s	.Decr13
		cmp.l	a6,a2
		bhi.s	.Decr13
		add.w	#32,a2
		bra.s	.Decr12
.Decr13		lea	32(a6),a6
		addq.l	#8,d0
		beq	.Decr1
.Decr14		cmp.l	a6,a2
		beq.s	.Decr15
		addq.w	#4,a2
		subq.l	#1,d0
		bne.s	.Decr14
		bra	.Decr1

.Decr15		bsr	Imp_Decr16
		bra.s	.Decr11

;=================================================

D_Imploder	moveq	#0,d5
		sub.l	a3,a3
		move.l	a5,d7
.Decr1		cmp.l	a6,a2
		bne.s	.Decr2
		bsr	Imp_Decr16
.Decr2		move.l	(a2)+,d0
		bpl.s	.Decr4

		add.l	d0,d0
		bpl.s	.BSS
		move.l	a3,d0
		beq.s	.BSS
		move.b	#$ea,3(a3)
		sub.l	a3,a3

.BSS		bclr	#31,d7
		bne.s	.Decr3				
		move.l	#$3eb,(a1)+

		movem.l	a0/a5,-(a7)
		move.l	d7,a5
		move.l	Imp_HunkLens(a5),a0
		move.w	d5,d0
		lsl.w	#2,d0
		move.l	(a0,d0.w),d0
		and.l	#$3fffffff,d0
		move.l	d0,(a1)+	
		movem.l	(a7)+,a0/a5

.Decr3		move.l	#$3f2,(a1)+	;end
		addq.w	#1,d5
		cmp.w	52(a4),d5
		bne.s	.Decr1
		move.l	d7,a5
		rts			;ende

.Decr4		bset	#31,d7
		add.l	d0,d0
		bpl.s	.Decr10

		move.l	#$3ec,(a1)+	;reloc
.Decr5		cmp.l	a6,a2
		bne.s	.Decr6
		bsr.s	Imp_Decr16
.Decr6		move.l	(a2)+,d0	;amount
		move.l	d0,(a1)+
		beq.s	.Decr1
		cmp.l	a6,a2
		bne.s	.Decr7
		bsr.s	Imp_Decr16
.Decr7		move.l	(a2)+,(a1)+	;hunknum
		moveq	#0,d2
.Decr8		cmp.l	a6,a2
		bne.s	.Decr9
		bsr.s	Imp_Decr16
.Decr9		add.l	(a2)+,d2
		move.l	d2,(a1)+
		subq.l	#1,d0
		bne.s	.Decr8
		bra.s	.Decr5

.Decr10		lsr.l	#1,d0
		move.l	a1,a3
		move.l	#$3e9,(a1)+
		move.l	d0,(a1)+
.Decr11		lea	-$20(a6),a6
		movem.l	d1-d7/a0,-(sp)
.Decr12		subq.l	#8,d0
		bmi.s	.Decr13
		cmp.l	a6,a2
		bhi.s	.Decr13
		movem.l	(a2)+,d1-d7/a0
		movem.l	d1-d7/a0,(a1)
		add.w	#$20,a1
		bra.s	.Decr12
.Decr13		movem.l	(sp)+,d1-d7/a0
		lea	$20(a6),a6
		addq.l	#8,d0
		beq	.Decr1
.Decr14		cmp.l	a6,a2
		beq.s	.Decr15
		move.l	(a2)+,(a1)+
		subq.l	#1,d0
		bne.s	.Decr14
		bra	.Decr1

.Decr15		bsr.s	Imp_Decr16
		bra.s	.Decr11

Imp_Decr16	sub.l	d4,a2
		movem.l	d0-d3/d5-d7/a3,-(sp)
		move.l	a2,a3
		move.w	d4,d5
		move.w	(a4),d2
		move.b	2(a4),d1
		move.b	3(a4),d0
		bne	.Decr49
		bra	.Decr50

.Decr17		add.b	d1,d1
		bne.s	.Decr18
		move.b	-(a0),d1
		addx.b	d1,d1
.Decr18		bcc.s	.Decr30

		add.b	d1,d1
		bne.s	.Decr19
		move.b	-(a0),d1
		addx.b	d1,d1
.Decr19		bcc.s	.Decr29

		add.b	d1,d1
		bne.s	.Decr20
		move.b	-(a0),d1
		addx.b	d1,d1
.Decr20		bcc.s	.Decr28

		add.b	d1,d1
		bne.s	.Decr21
		move.b	-(a0),d1
		addx.b	d1,d1
.Decr21		bcc.s	.Decr27

		add.b	d1,d1
		bne.s	.Decr22
		move.b	-(a0),d1
		addx.b	d1,d1
.Decr22		bcc.s	.Decr23

		move.b	-(a0),d0
		moveq	#3,d7
		bra.s	.Decr31

.Decr23		add.b	d1,d1
		bne.s	.Decr24
		move.b	-(a0),d1
		addx.b	d1,d1
.Decr24		addx.b	d0,d0
		add.b	d1,d1
		bne.s	.Decr25
		move.b	-(a0),d1
		addx.b	d1,d1
.Decr25		addx.b	d0,d0
		add.b	d1,d1
		bne.s	.Decr26
		move.b	-(a0),d1
		addx.b	d1,d1
.Decr26		addx.b	d0,d0
		addq.b	#6,d0
		moveq	#3,d7
		bra.s	.Decr31

.Decr27		moveq	#5,d0
		moveq	#3,d7
		bra.s	.Decr31

.Decr28		moveq	#4,d0
		moveq	#2,d7
		bra.s	.Decr31

.Decr29		moveq	#3,d0
		moveq	#1,d7
		bra.s	.Decr31

.Decr30		moveq	#2,d0
		moveq	#0,d7

.Decr31		move.w	d7,d3
		add.b	d1,d1
		bne.s	.Decr32
		move.b	-(a0),d1
		addx.b	d1,d1
.Decr32		bcc.s	.Decr34

		add.b	d1,d1
		bne.s	.Decr33
		move.b	-(a0),d1
		addx.b	d1,d1
.Decr33		bcc.s	.Decr36

		moveq	#0,d6
		move.b	8(a4,d7.w),d6
		addq.b	#4,d7
		bra.s	.Decr37

.Decr34		add.b	d1,d1
		bne.s	.Decr35
		move.b	-(a0),d1
		addx.b	d1,d1
.Decr35		addx.w	d2,d2
		bra.s	.Decr40

.Decr36		moveq	#2,d6
.Decr37		move.b	12(a4,d7.w),d7
.Decr38		add.b	d1,d1
		bne.s	.Decr39
		move.b	-(a0),d1
		addx.b	d1,d1
.Decr39		addx.w	d2,d2
		subq.b	#1,d7
		bne.s	.Decr38
		add.w	d6,d2

.Decr40		moveq	#0,d6
		move.w	d6,a5
		move.w	d3,d7
		add.b	d1,d1
		bne.s	.Decr41
		move.b	-(a0),d1
		addx.b	d1,d1
.Decr41		bcc.s	.Decr44

		add.w	d3,d3
		add.b	d1,d1
		bne.s	.Decr42
		move.b	-(a0),d1
		addx.b	d1,d1
.Decr42		bcc.s	.Decr43

		move.w	28(a4,d3.w),a5
		addq.b	#8,d7
		bra.s	.Decr44

.Decr43		move.w	20(a4,d3.w),a5
		addq.b	#4,d7

.Decr44		move.b	36(a4,d7.w),d7
		bpl.s	.Decr45
		move.b	-(a0),d6
		and.b	#$7f,d7
		beq.s	.Decr47

.Decr45		add.b	d1,d1
		bne.s	.Decr46
		move.b	-(a0),d1
		addx.b	d1,d1

.Decr46		addx.w	d6,d6
		subq.b	#1,d7
		bne.s	.Decr45
.Decr47		addq.w	#1,d6
		add.w	a5,d6
		move.l	a3,a5
		sub.w	d6,a5
		cmp.l	a2,a5
		bcc.s	.Decr48
		add.w	d4,a5
.Decr48		cmp.l	a5,a6
		bne.s	.Decr49
		move.l	a2,a5
.Decr49		subq.w	#1,d5
		bmi.s	.Decr53
		move.b	(a5)+,(a3)+
		subq.b	#1,d0
		bne.s	.Decr48
.Decr50		tst.w	d2
		beq.s	.Decr52
.Decr51		subq.w	#1,d5
		bmi.s	.Decr53
		move.b	-(a0),(a3)+
		subq.w	#1,d2
		bne.s	.Decr51
.Decr52		subq.l	#1,4(a4)
		bne	.Decr17
.Decr53		move.b	d0,3(a4)
		move.b	d1,2(a4)
		move.w	d2,(a4)
		movem.l	(sp)+,d0-d3/d5-d7/a3
		rts

Imp_Tab1	dc.l	$060A0A12
		dc.l	$02030304
		dc.l	$04050700

Imp_Tab2	dc.l	$05050505
		dc.l	$05050505
		dc.l	$06060606

		dc.l	$05060707
		dc.l	$06060606
		dc.l	$07070606

		dc.l	$05060707
		dc.l	$07070707
		dc.l	$80808080

		dc.l	$05060780
		dc.l	$07078080
		dc.l	$80818181

		dc.l	$06070780
		dc.l	$07808181
		dc.l	$80818282

		dc.l	$06070780
		dc.l	$07818182
		dc.l	$80828383

		dc.l	$06070780
		dc.l	$07818182
		dc.l	$80828484

		dc.l	$06070780
		dc.l	$07818282
		dc.l	$80838485

		dc.l	$06070780
		dc.l	$07818283
		dc.l	$80838586
S_Imploder_END

