*****************************************************************************
*   xfdmaster.library internal slaves not yet rewritten as C code
*
*   XFD library system for cruncher handling
*   Copyright (C) 1994-1998 by Georg Hörmann
*   Copyright (C) 1998 by Dirk Stöcker <soft@dstoecker.de>
*   Copyright (C) 2014 by Fredrik Wikström <fredrik@a500.org>
*
*   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
*****************************************************************************

		SECTION	xfdmaster,CODE

		INCDIR	"include/"
		INCLUDE "exec/memory.i"
		INCLUDE "dos/dos.i"
		INCLUDE	"dos/doshunks.i"
		INCLUDE "libraries/xfdmaster.i"
		INCLUDE	"lvo/exec_lib.i"
		INCLUDE	"lvo/dos_lib.i"
		INCLUDE	"lvo/xfdmaster_lib.i"

Xfd68KHeader
		dc.l	XFDF_ID
		dc.l	XfdFirstSlave-Xfd68KHeader
		dc.l	LinkerBrain-Xfd68KHeader

		; Diz linker is special
		dc.l	LB_AnalyseDiz-Xfd68KHeader
		dc.l	LB_UnlinkDiz-Xfd68KHeader
		dc.l	LB_NameDiz-Xfd68KHeader

LinkerBrain	;4ef9 Linker  20+12+64+16+16
		;hunk0 = linker

		DC.W	16-1
		DC.L	$000003e9,$00000005,$48e7fffe,$4eb90000
		DC.L	$00004cdf,$7fff4ef9,$00000000,$000003ec
		DC.L	$00000001,$deadbeef,$00000006,$00000001
		DC.L	$deadbeef,$00000010,$00000000,$000003f2
		DC.L	LB_Analyse4EF9-Xfd68KHeader
		DC.L	LB_Unlink4EF9-Xfd68KHeader
		DC.L	LB_Name4EF9-Xfd68KHeader

		;4eb9 Linker Type A  20+12+60+16+16
		;hunk0 = linker

		DC.W	15-1
		DC.L	$000003e9,$00000004,$4eb90000,$00004eb9
		DC.L	$00000000,$70004e75,$000003ec,$00000001
		DC.L	$deadbeef,$00000002,$00000001,$deadbeef
		DC.L	$00000008,$00000000,$000003f2
		DC.L	LB_Analyse4EF9-Xfd68KHeader	;same
		DC.L	LB_Unlink4EF9-Xfd68KHeader	;same
		DC.L	LB_Name4EB9-Xfd68KHeader

		;4eb9 Linker Type B  20+12+60+16+16
		;hunk0 = linker

		DC.W	15-1
		DC.L	$000003e9,$00000004,$4eb90000,$00004eb9
		DC.L	$00000000,$70004e75,$000003ec,$00000001
		DC.L	$deadbeef,$00000008,$00000001,$deadbeef
		DC.L	$00000002,$00000000,$000003f2
		DC.L	LB_Analyse4EF9-Xfd68KHeader	;same
		DC.L	LB_Unlink4EF9-Xfd68KHeader	;same
		DC.L	LB_Name4EB9-Xfd68KHeader

		;4eb9 Linker Type B  20+12+68+16+16
		;hunk0 = linker

		DC.W	17-1
		DC.L	$000003e9,$00000006,$4eb90000,$00004eb9
		DC.L	$00000000,$70004e75,$deadbeef,$deadbeef
		DC.L	$000003ec,$00000001,$deadbeef,$00000002
		DC.L	$00000001,$deadbeef,$00000008,$00000000
		DC.L	$000003f2
		DC.L	LB_Analyse4EF9-Xfd68KHeader	;same
		DC.L	LB_Unlink4EF9-Xfd68KHeader	;same
		DC.L	LB_Name4EB9-Xfd68KHeader

		; $4EB9 with register save  20+12+72+16+16
		DC.W	18-1
		DC.L	$000003E9,$00000007,$48E7FFFE,$4EB90000
		DC.L	$00004CD7,$7FFF4EB9,$00000000,$4CDF7FFF
		DC.L	$70004E75,$000003EC,$00000001,$deadbeef
		DC.L	$00000006,$00000001,$deadbeef,$00000010
		DC.L	$00000000,$000003F2
		DC.L	LB_Analyse4EF9-Xfd68KHeader
		DC.L	LB_Unlink4EF9-Xfd68KHeader
		DC.L	LB_Name4EB9-Xfd68KHeader

		;UFO Linker  20+20+$144+16+44+16
		;1. link immer nur 1 hunk, hunk0/1/3 = linker
		;pic link hat hunk3 weiter hinten, deshalb suchen

		DC.W	9-1
		DC.L	$000003e9,$0000002b,$4feffe08,$48e7fffe
		DC.L	$227afff2,$d3c9d3c9,$58892f49,$003c4cdf
		DC.L	$7fff4e75
		DC.L	LB_AnalyseUFO-Xfd68KHeader
		DC.L	LB_UnlinkUFO-Xfd68KHeader
		DC.L	LB_NameUFO-Xfd68KHeader

		;XLink 3.0 Linker  20+12+$c4+16+16
		;hunk0 = linker

		DC.W	16-1
		DC.L	$000003e9,$00000026,$487a006a,$48e7ffff
		DC.L	$207cffff,$fffc7200,$615c23c0,$0000008e
		DC.L	$323a0072,$615023c0,$00000092,$74024a02
		DC.L	$660c2f7a,$0062003c,$41fa0060,$60240c02
		DC.L	LB_AnalyseXLink-Xfd68KHeader
		DC.L	LB_Unlink4EF9-Xfd68KHeader	;same
		DC.L	LB_NameXLink-Xfd68KHeader

		;Glue 2.3 Linker  20+8+$fc+4+4+16
		;text typed before prg
		;hunk0 = linker + text

		DC.W	39-1
		DC.L	$000003e9,$deadbeef,$48e7fffc,$2c780004
		DC.L	$93c94eae,$feda2a40,$7a004aad,$00ac6612
		DC.L	$41ed005c,$4eaefe80,$41ed005c,$4eaefe8c
		DC.L	$2a0043fa,$006a7021,$4eaefdd8,$4a806740
		DC.L	$2c4043fa,$00662209,$243c0000,$03ed4eae
		DC.L	$ffe22c00,$67202206,$41fa009e,$26182408
		DC.L	$4eaeffd0,$2206243c,$00989680,$4eaeff34
		DC.L	$22064eae,$ffdc224e,$2c780004,$4eaefe62
		DC.L	$4a85670a,$224541ed,$005c4eae,$fe924cdf
		DC.L	$3fff2c7a,$ff70ddce,$ddce4eee
		DC.L	LB_AnalyseGlue-Xfd68KHeader
		DC.L	LB_UnlinkGlue-Xfd68KHeader
		DC.L	LB_NameGlue23-Xfd68KHeader

		;Glue 2.3 Linker  20+8+$c8+4+4+16
		;text typed after prg
		;hunk0 = linker + text

		DC.W	27-1
		DC.L	$000003e9,$deadbeef,$2c7afffa,$ddceddce
		DC.L	$4eae0004,$2f002c78,$000443fa,$00507021
		DC.L	$4eaefdd8,$4a806740,$2c4041fa,$004c2208
		DC.L	$243c0000,$03ed4eae,$ffe22c00,$67202206
		DC.L	$41fa0082,$26182408,$4eaeffd0,$2206243c
		DC.L	$00989680,$4eaeff34,$22064eae,$ffdc224e
		DC.L	$2c780004,$4eaefe62,$201f4e75
		DC.L	LB_AnalyseGlue-Xfd68KHeader
		DC.L	LB_UnlinkGlue-Xfd68KHeader
		DC.L	LB_NameGlue23-Xfd68KHeader

		;Glue 2.2 Linker  20+8+$ec+4+4+16
		;text typed before prg
		;hunk0 = linker + text

		DC.W	39-1
		DC.L	$000003e9,$deadbeef,$48e7fffc,$2c780004
		DC.L	$93c94eae,$feda2a40,$7a004aad,$00ac6612
		DC.L	$41ed005c,$4eaefe80,$41ed005c,$4eaefe8c
		DC.L	$2a0043fa,$00687021,$4eaefdd8,$4a80673e
		DC.L	$2c4043fa,$00642209,$243c0000,$03ed4eae
		DC.L	$ffe22c00,$671e2206,$41fa008e,$26182408
		DC.L	$4eaeffd0,$08390006,$00bfe001,$66f62206
		DC.L	$4eaeffdc,$224e2c78,$00044eae,$fe624a85
		DC.L	$670a2245,$41ed005c,$4eaefe92,$4cdf3fff
		DC.L	$2c7aff72,$ddceddce,$4eee0004
		DC.L	LB_AnalyseGlue-Xfd68KHeader
		DC.L	LB_UnlinkGlue-Xfd68KHeader
		DC.L	LB_NameGlue22-Xfd68KHeader

		;Glue 2.2 Linker  20+8+$bc+4+4+16
		;text typed after prg
		;hunk0 = linker + text

		DC.W	26-1
		DC.L	$000003e9,$deadbeef,$2c7afffa,$ddceddce
		DC.L	$4eae0004,$2f002c78,$000443fa,$004e7021
		DC.L	$4eaefdd8,$4a80673e,$2c4041fa,$004a2208
		DC.L	$243c0000,$03ed4eae,$ffe22c00,$671e2206
		DC.L	$41fa0076,$26182408,$4eaeffd0,$08390006
		DC.L	$00bfe001,$66f62206,$4eaeffdc,$224e2c78
		DC.L	$00044eae,$fe62201f
		DC.L	LB_AnalyseGlue-Xfd68KHeader
		DC.L	LB_UnlinkGlue-Xfd68KHeader
		DC.L	LB_NameGlue22-Xfd68KHeader

		;EXP 1.1 Text Linker	20+8+92

		DC.W	20-1
		DC.L	$000003E9,$deadbeef,$48E7FFFE,$4E7143FA
		DC.L	$00362C78,$00044EAE,$FE682C40,$4EAEFFC4
		DC.L	$22006718,$41FA0038,$2408263A,$0026D6BA
		DC.L	$00260683,$0000002C,$4EAEFFD0,$4CDF7FFF
		DC.L	$4EF90000,$0000646F,$732E6C69,$62726172
		DC.L	LB_AnalyseEXP11-Xfd68KHeader
		DC.L	LB_UnlinkEXP11-Xfd68KHeader
		DC.L	LB_NameEXP11-Xfd68KHeader

		; ETA 0.91 Text Linker	20+8+132

		DC.W	20-1
		DC.L	$000003E9,$deadbeef,$48E7FFFE,$41FAFFFA
		DC.L	$59882010,$E5885880,$43FA003A,$23400002
		DC.L	$2C780004,$43FA0038,$70004EAE,$FE682C40
		DC.L	$671E4EAE,$FFC42200,$41FA0049,$2408263A
		DC.L	$001A4EAE,$FFD02C78,$0004224E,$4EAEFE62
		DC.L	LB_AnalyseETA091-Xfd68KHeader
		DC.L	LB_UnlinkETA091-Xfd68KHeader
		DC.L	LB_NameETA091-Xfd68KHeader

		; ETA 0.99 Text Linker	20+8+136

		DC.W	20-1
		DC.L	$000003E9,$deadbeef,$48E7FFFE,$41FAFFFA
		DC.L	$59882010,$E5885880,$43FA003A,$23400002
		DC.L	$2C780004,$43FA003A,$70004EAE,$FE682C40
		DC.L	$671E4EAE,$FFC42200,$41FA004B,$2408263A
		DC.L	$001C4EAE,$FFD02C78,$0004224E,$4EAEFE62
		DC.L	LB_AnalyseETA099-Xfd68KHeader
		DC.L	LB_UnlinkETA099-Xfd68KHeader
		DC.L	LB_NameETA099-Xfd68KHeader

		; ETA 1.00 Text Linker	20+8+156

		DC.W	20-1
		DC.L	$000003E9,$deadbeef,$48E7FFFE,$41FAFFFA
		DC.L	$59882010,$E5885880,$43FA0056,$23400002
		DC.L	$203A0056,$538043FA,$007341FA,$00504A10
		DC.L	$67F81218,$D201B319,$51C8FFF4,$2C780004
		DC.L	$43FA003A,$70004EAE,$FE682C40,$671E4EAE
		DC.L	LB_AnalyseETA100-Xfd68KHeader
		DC.L	LB_UnlinkETA100-Xfd68KHeader
		DC.L	LB_NameETA100-Xfd68KHeader

		; FileShield

		DC.W	10-1
		DC.L	$000003E9,$00000003,$48790000,$00004E75
		DC.L	$4E754E75,$000003EC,$00000001,$00000001
		DC.L	$00000002,$00000000
		DC.L	LB_AnalyseFileShield-Xfd68KHeader
		DC.L	LB_UnlinkFileShield-Xfd68KHeader
		DC.L	LB_NameFileSh-Xfd68KHeader

		;ExeDescript 1.0 Linker   muß ganz geladen sein
		;last hunk = text

		DC.W	0
		DC.L	LB_AnalyseExeDes-Xfd68KHeader
		DC.L	LB_UnlinkExeDes-Xfd68KHeader
		DC.L	LB_NameExeDes-Xfd68KHeader

		DC.W	-1

LB_Name4EF9		DC.B	'4EF9 Linker',0
LB_Name4EB9		DC.B	'4EB9 Linker',0
LB_NameUFO		DC.B	'UFO Linker',0
LB_NameXLink	DC.B	'XLink Linker',0
LB_NameGlue23	DC.B	'Glue 2.3 Linker',0
LB_NameGlue22	DC.B	'Glue 2.2 Linker',0
LB_NameEXP11	DC.B	'EXP 1.1 Text Linker',0
LB_NameETA091	DC.B	'ETA 0.91 Text Linker',0
LB_NameETA099	DC.B	'ETA 0.99 Text Linker',0
LB_NameETA100	DC.B	'ETA 1.00 Text Linker',0
LB_NameExeDes	DC.B	'ExeDescript 1.0 Linker',0
LB_NameDiz		DC.B	'FileDescript Linker',0
LB_NameFileSh	DC.B	'FileShield Linker',0
		EVEN

LB_Analyse4EF9	move.l	-28(a1),d0
		move.l	-16(a1),d1
		cmp.l	d1,d0
		blt.b	.Ok
		exg	d1,d0
.Ok		move.l	d0,xfdli_Hunk1(a5)
		move.l	d1,xfdli_Hunk2(a5)
		sub.l	d0,d1
		beq.b	.Exit
		move.l	d1,xfdli_Amount1(a5)
		moveq	#1,d0
		rts

.Exit		moveq	#0,d0
		rts

LB_AnalyseUFO	moveq	#1,d0
		bsr	GetHunkX
		tst.w	d0
		beq.b	.Exit
		cmp.w	#$6028,8(a0)
		bne.b	.Exit
		moveq	#2,d0
		move.l	d0,xfdli_Hunk1(a5)
		moveq	#4,d0
		move.l	d0,xfdli_Hunk2(a5)
		moveq	#1,d0
		move.l	d0,xfdli_Amount1(a5)
		moveq	#1,d0
		rts

.Exit		moveq	#0,d0
		rts

LB_AnalyseXLink	moveq	#1,d0
		move.l	d0,xfdli_Hunk1(a5)
		moveq	#1,d1
		add.w	$dc-$48(a0),d1
		move.l	d1,xfdli_Amount1(a5)
		add.l	d0,d1
		move.l	d1,xfdli_Hunk2(a5)
		rts

LB_AnalyseETA091
		MOVEQ	#0,D0
		CMP.L	#'.91 ',112(A0)		* check version
		BEQ.B	LB_AnalyseGlue
		RTS

LB_AnalyseETA099
		MOVEQ	#0,D0
		CMP.L	#'.99 ',114(A0)		* check version
		BEQ.B	LB_AnalyseGlue
		RTS

LB_AnalyseETA100
		MOVEQ	#0,D0
		CMP.L	#'.00 ',142(A0)		* check version
		BEQ.B	LB_AnalyseGlue
		RTS

LB_AnalyseFileShield
LB_AnalyseEXP11
LB_AnalyseGlue	moveq	#0,d0
		move.l	d0,xfdli_Hunk1(a5)
		moveq	#1,d0
		move.l	d0,xfdli_Amount1(a5)
		move.l	d0,xfdli_Hunk2(a5)
		rts

LB_AnalyseExeDes
		move.l	xfdli_Buffer(a5),a0
		move.l	16(a0),d0
		sub.l	12(a0),d0
		move.l	d0,-(a7)
		bsr	GetHunkX		* this may cause enforcer hits!
		move.l	(a7)+,d1
		tst.w	d0
		beq.b	.Exit
		cmp.l	#$3eb,(a0)
		beq.b	.Exit
		cmp.l	#'FLID',8(a0)
		bne.b	.Exit
		clr.l	xfdli_Hunk1(a5)
		move.l	d1,xfdli_Amount1(a5)
		move.l	d1,xfdli_Hunk2(a5)
		moveq	#1,d0
		rts

.Exit		moveq	#0,d0
		rts

LB_AnalyseDiz	MOVE.L	A2,-(A7)
		MOVEQ	#0,D0
		MOVE.L	xfdli_Buffer(A5),A0
		MOVE.L	A0,A2
		ADD.L	xfdli_BufLen(A5),A2
		LEA	-16(A2),A2

		MOVE.L	#1,xfdli_Amount1(A5)	* the linker type
		LEA	DizStartTxt(PC),A1
.Loop1		TST.B	(A1)
		BEQ.B	.Ok1			* found an start text
		CMP.B	(A0)+,(A1)+
		BEQ.B	.Loop1

		MOVE.L	#2,xfdli_Amount1(A5)	* the linker type
		LEA	DizEndTxt(PC),A1
.Loop2		TST.B	(A1)
		BEQ.B	.Ok			* found an end text
		CMP.B	(A2)+,(A1)+
		BEQ.B	.Loop2
		BRA.B	.No
		LEA	DizEndTxt(PC),A1
.Ok1		CMP.B	#$0A,16(A2)	* check if file ends in end text
		BNE.B	.skip
		MOVE.B	-(A2),D1	* decrement A2
.skip		LEA	DizEndTxt(PC),A1
.Loop3		TST.B	(A1)
		BEQ.B	.No			* found an end text
		CMP.B	(A2)+,(A1)+
		BEQ.B	.Loop3

.Ok		MOVEQ	#1,D0
.No		MOVE.L	(A7)+,A2
		RTS

DizStartTxt	DC.B	'@BEGIN_FILE_ID.DIZ',0
DizEndTxt	DC.B	'@END_FILE_ID.DIZ',0
		EVEN

LB_UnlinkDiz	MOVEM.L	D2/A2-A4,-(A7)
		MOVEQ	#0,D0			* FALSE result value
		MOVE.W	#XFDERR_UNKNOWN,xfdli_Error(A0)
		MOVE.L	xfdli_Buffer(A0),A1
		MOVE.L	A1,A3
		ADD.L	xfdli_BufLen(A0),A3
		CMP.L	#1,xfdli_Amount1(A0)
		BNE.B	.endfile

		LEA	18(A1),A2
		MOVE.L	A2,xfdli_Save1(A0)
		LEA	DizEndTxt(PC),A4
.Loop0		CLR.W	D1
.Loop1		CMP.L	A3,A2
		BGE.W	.end
		MOVE.B	(A4,D1.W),D2
		BEQ.B	.foundS
		CMP.B	(A2)+,D2
		BNE.B	.Loop0
		ADDQ.W	#1,D1
		BRA.B	.Loop1
.foundS		MOVEQ	#18+16,D2	*strip a newline, when there is one
		CMP.B	#$0A,(A2)
		BNE.B	.skip
		ADDQ.L	#1,A2
		ADDQ.L	#1,D2
.skip		MOVE.L	A2,xfdli_Save2(A0)
		SUBA.L	A2,A3
		MOVE.L	A3,xfdli_SaveLen2(A0)
		BLE.W	.end
		SUBA.L	A1,A2
		SUBA.L	D2,A2
		MOVE.L	A2,xfdli_SaveLen1(A0)
		BRA.B	.ok

.endfile	MOVE.L	A1,xfdli_Save1(A0)
		MOVEA.L	A1,A2
		LEA	DizStartTxt(PC),A4
.Loop2		CLR.W	D1
.Loop3		CMP.L	A3,A1
		BGE.B	.end
		MOVE.B	(A4,D1.W),D2
		BEQ.B	.foundE
		CMP.B	(A1)+,D2
		BNE.B	.Loop2
		ADDQ.W	#1,D1
		BRA.B	.Loop3
.foundE		MOVE.L	A1,xfdli_Save2(A0)
		SUBA.L	A1,A3
		LEA	-16(A3),A3
		MOVE.L	A3,xfdli_SaveLen2(A0)
		LEA	-18(A1),A1
		SUBA.L	A2,A1
		MOVE.L	A1,xfdli_SaveLen1(A0)
		BEQ.B	.end
.ok		MOVE.L	xfdli_Save1(A0),D0
		BTST.B	#0,D0			* check for even address
		BEQ.B	.Part2
		MOVE.L	D0,A2
		MOVE.L	xfdli_SaveLen1(A0),D0	* copy one byte forward
		LEA	1(A2),A1
		MOVE.L	A1,xfdli_Save1(A0)
		ADD.L	D0,A2
		ADD.L	D0,A1
.Part1L		MOVE.B	-(A2),-(A1)
		SUBQ.L	#1,D0
		BNE.B	.Part1L
.Part2		MOVE.L	xfdli_Save2(A0),D0	* copy one byte backwards
		BTST.B	#0,D0
		BEQ.B	.EndEven
		MOVE.L	D0,A2
		MOVE.L	xfdli_SaveLen2(A0),D0
		LEA	-1(A2),A1
		MOVE.L	A1,xfdli_Save2(A0)
.Part2L		MOVE.B	(A2)+,(A1)+
		SUBQ.L	#1,D0
		BNE.B	.Part2L
.EndEven	MOVEQ	#1,D0
.end		MOVEM.L	(A7)+,D2/A2-A4
		RTS

LB_Unlink4EF9	movem.l	d2-d7/a2-a6,-(a7)
		move.l	a0,a5
		move.l	xfdli_Hunk1(a5),d0
		bsr	GetHunkX
		move.w	#XFDERR_BADHUNK,xfdli_Error(a5)
		tst.w	d0
		beq	.Exit
		move.l	a0,a2		;link1

		move.l	xfdli_Hunk2(a5),d0
		bsr	GetHunkX
		tst.w	d0
		beq	.Exit
		move.l	a0,a3		;link2

		move.l	xfdli_Buffer(a5),a0
		move.l	xfdli_Amount1(a5),d0
		addq.w	#8,a0
		move.l	d0,(a0)+
		clr.l	(a0)+
		move.l	d0,(a0)
		subq.l	#1,(a0)+
		addq.w	#4,a0		;skip #1

.CopyLen1	move.l	(a0)+,-8(a0)	;lens of link1
		subq.l	#1,d0
		bne.b	.CopyLen1

		move.l	xfdli_Amount2(a5),d7
		lsl.l	#2,d7
		sub.l	d7,a7		;save on stack

		move.l	d7,d0
.SaveLen2	move.l	-4(a0,d0.l),-4(a7,d0.l)
		subq.l	#4,d0
		bne.b	.SaveLen2

		subq.w	#4,a0		;target of link1

		move.l	a3,d0
		sub.l	a2,d0		;len of link1
.CopyHunks1	move.l	(a2)+,(a0)+
		subq.l	#4,d0
		bne.b	.CopyHunks1

		sub.l	xfdli_Buffer(a5),a0
		move.l	a0,xfdli_SaveLen1(a5)
		move.l	xfdli_Buffer(a5),xfdli_Save1(a5)

		move.l	a3,a0
		sub.l	d7,a0
		sub.w	#20,a0
		move.l	a0,xfdli_Save2(a5)

		move.l	xfdli_Buffer(a5),d0
		sub.l	a0,d0
		add.l	xfdli_BufLen(a5),d0
		move.l	d0,xfdli_SaveLen2(a5)

		move.l	#HUNK_HEADER,(a0)+
		clr.l	(a0)+
		move.l	xfdli_Amount2(a5),d0
		move.l	d0,(a0)+
		clr.l	(a0)+
		move.l	d0,(a0)
		subq.l	#1,(a0)+

.CopyLen2	move.l	(a7)+,(a0)+
		subq.l	#4,d7
		bne.b	.CopyLen2

		move.l	xfdli_Save1(a5),a0
		move.l	xfdli_SaveLen1(a5),d0
		move.l	xfdli_Hunk1(a5),d1
		neg.l	d1
		bsr	CorrectReloc
		tst.w	d0
		beq.b	.Exit

		move.l	xfdli_Save2(a5),a0
		move.l	xfdli_SaveLen2(a5),d0
		move.l	xfdli_Hunk2(a5),d1
		neg.l	d1
		bsr	CorrectReloc

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

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

		move.w	#XFDERR_BADHUNK,xfdli_Error(a5)

		move.l	xfdli_Buffer(a5),a0
		move.l	16(a0),d3
		moveq	#3,d2
.LookHunk3	cmp.l	d3,d2
		bgt	.Exit0
		move.l	d2,d0
		bsr	GetHunkX
		tst.w	d0
		beq	.Exit
		cmp.l	#$4fef01f4,8(a0)
		beq.b	.FoundHunk3
		addq.l	#1,d2
		bra.b	.LookHunk3

.FoundHunk3	addq.l	#1,d2
		cmp.l	d3,d2
		bgt	.Exit0
		move.l	xfdli_Hunk2(a5),d0
		move.l	d2,xfdli_Hunk2(a5)
		sub.l	d0,d2
		sub.l	d2,xfdli_Amount2(a5)

		move.l	xfdli_Hunk1(a5),d0
		bsr	GetHunkX
		tst.w	d0
		beq	.Exit
		move.l	a0,a2		;link1

		move.l	xfdli_Hunk2(a5),d0
		bsr	GetHunkX
		tst.w	d0
		beq	.Exit
		move.l	a0,a3		;link2

		move.l	xfdli_Hunk1(a5),d0
		add.l	xfdli_Amount1(a5),d0
		bsr	GetHunkX
		tst.w	d0
		beq	.Exit
		move.l	a0,a4		;ufo hunk #3

		move.l	xfdli_Buffer(a5),a0
		move.l	xfdli_Amount1(a5),d0
		addq.w	#8,a0
		move.l	d0,(a0)+
		clr.l	(a0)+
		move.l	d0,(a0)
		subq.l	#1,(a0)+
		addq.w	#8,a0		;skip #0 + #1

.CopyLen1	move.l	(a0)+,-12(a0)	;lens of link1
		subq.l	#1,d0
		bne.b	.CopyLen1

		move.l	xfdli_Amount2(a5),d7
		lsl.l	#2,d7
		sub.l	d7,a7		;save on stack

		move.l	d7,d0
.SaveLen2	move.l	(a0,d0.l),-4(a7,d0.l)	;skip #3
		subq.l	#4,d0
		bne.b	.SaveLen2

		subq.w	#8,a0		;target of link1

		move.l	a4,d0
		sub.l	a2,d0		;len of link1
.CopyHunks1	move.l	(a2)+,(a0)+
		subq.l	#4,d0
		bne.b	.CopyHunks1

		sub.l	xfdli_Buffer(a5),a0
		move.l	a0,xfdli_SaveLen1(a5)
		move.l	xfdli_Buffer(a5),xfdli_Save1(a5)

		move.l	a3,a0
		sub.l	d7,a0
		sub.w	#20,a0
		move.l	a0,xfdli_Save2(a5)

		move.l	xfdli_Buffer(a5),d0
		sub.l	a0,d0
		add.l	xfdli_BufLen(a5),d0
		move.l	d0,xfdli_SaveLen2(a5)

		move.l	#HUNK_HEADER,(a0)+
		clr.l	(a0)+
		move.l	xfdli_Amount2(a5),d0
		move.l	d0,(a0)+
		clr.l	(a0)+
		move.l	d0,(a0)
		subq.l	#1,(a0)+

.CopyLen2	move.l	(a7)+,(a0)+
		subq.l	#4,d7
		bne.b	.CopyLen2

		move.l	xfdli_Save1(a5),a0
		move.l	xfdli_SaveLen1(a5),d0
		move.l	xfdli_Hunk1(a5),d1
		neg.l	d1
		bsr	CorrectReloc
		tst.w	d0
		beq.b	.Exit

		move.l	xfdli_Save2(a5),a0
		move.l	xfdli_SaveLen2(a5),d0
		move.l	xfdli_Hunk2(a5),d1
		neg.l	d1
		bsr	CorrectReloc

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

.Exit0		moveq	#0,d0
		bra.b	.Exit

LB_UnlinkGlue	movem.l	d2-d7/a2-a6,-(a7)
		move.l	a0,a5
		move.l	xfdli_Hunk1(a5),d0
		bsr	GetHunkX
		move.w	#XFDERR_BADHUNK,xfdli_Error(a5)
		tst.w	d0
		beq	.Exit
		move.l	a0,a2		;link1

		move.l	xfdli_Hunk2(a5),d0
		bsr	GetHunkX
		tst.w	d0
		beq	.Exit
		move.l	a0,a3		;link2

		move.l	xfdli_Buffer(a5),a0
		add.w	#20+4,a0	;skip #1

		move.l	xfdli_Amount2(a5),d7
		lsl.l	#2,d7
		sub.l	d7,a7		;save on stack

		move.l	d7,d0
.SaveLen2	move.l	-4(a0,d0.l),-4(a7,d0.l)
		subq.l	#4,d0
		bne.b	.SaveLen2

		move.l	a2,a0
		cmp.w	#$ddce,$c(a0)	;typed after prg?
		bne.b	.Front
		move.w	#$c4,d0		;2.3
		cmp.w	#$0839,$4c(a0)
		bne.b	.GetText
		move.w	#$b8,d0		;2.2
		bra.b	.GetText
.Front		move.w	#$e8,d0		;2.2
		cmp.w	#$ddce,$94(a0)
		beq.b	.GetText
		move.w	#$f8,d0		;2.3
.GetText	add.w	d0,a0
		move.l	(a0)+,d0
		move.l	xfdli_Buffer(a5),a1

		move.l	d0,xfdli_SaveLen1(a5)
		move.l	a1,xfdli_Save1(a5)

.CopyText	move.b	(a0)+,(a1)+
		subq.l	#1,d0
		bne.b	.CopyText

		move.l	a3,a0
		sub.l	d7,a0
		sub.w	#20,a0
		move.l	a0,xfdli_Save2(a5)

		move.l	xfdli_Buffer(a5),d0
		sub.l	a0,d0
		add.l	xfdli_BufLen(a5),d0
		move.l	d0,xfdli_SaveLen2(a5)

		move.l	#HUNK_HEADER,(a0)+
		clr.l	(a0)+
		move.l	xfdli_Amount2(a5),d0
		move.l	d0,(a0)+
		clr.l	(a0)+
		move.l	d0,(a0)
		subq.l	#1,(a0)+

.CopyLen2	move.l	(a7)+,(a0)+
		subq.l	#4,d7
		bne.b	.CopyLen2

		move.l	xfdli_Save2(a5),a0
		move.l	xfdli_SaveLen2(a5),d0
		move.l	xfdli_Hunk2(a5),d1
		neg.l	d1
		bsr	CorrectReloc

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

LB_UnlinkFileShield
		MOVEM.L	A2/A3/A5,-(A7)
		MOVE.L	A0,A5
		MOVE.L	xfdli_Buffer(A5),A2
		MOVE.L	xfdli_Hunk2(A5),D0
		BSR.W	GetHunkX
		MOVE.W	#XFDERR_BADHUNK,xfdli_Error(a5)
		TST.W	D0
		BEQ.B	.Exit

		LEA	-40(A0),A1
		LEA	24(A2),A3
		
.Loop2		MOVE.L	-(A1),-(A0)
		CMP.L	A3,A1
		BGT.B	.Loop2

		MOVE.L	-(A1),D0	* skip first size
		MOVE.L	-(A1),D0
		SUBQ	#1,D0
		MOVE.L	D0,-(A0)
		MOVE.L	-(A1),-(A0)
		MOVE.L	-(A1),D0
		SUBQ	#1,D0
		MOVE.L	D0,-(A0)
		MOVE.L	-(A1),-(A0)
		MOVE.L	-(A1),-(A0)

		MOVE.L	D0,8(A2)
		LEA	16(A2),A1
		CLR.L	(A1)+
		MOVEQ	#2,D0
		MOVE.L	D0,(A1)+
		MOVE.L	#HUNK_CODE,(A1)+
		MOVE.L	D0,(A1)+
		MOVE.L	#$00004E75,(A1)+
		MOVE.L	#$4E754E75,(A1)+
		MOVE.L	#HUNK_END,(A1)+

		MOVE.L	xfdli_BufLen(A5),D0
		MOVEQ.L	#44,D1
		SUB.L	D1,D0
		MOVE.L	D0,xfdli_SaveLen2(A5)
		MOVE.L	D1,xfdli_SaveLen1(A5)
		MOVE.L	A2,xfdli_Save1(A5)
		MOVE.L	A0,xfdli_Save2(A5)

	*	MOVE.L	xfdli_Save2(A5),A0
	*	MOVE.L	xfdli_SaveLen2(A5),D0
		MOVE.L	xfdli_Hunk2(A5),D1
		NEG.L	D1
		BSR.W	CorrectReloc
		
.Exit		MOVEM.L	(A7)+,A2/A3/A5
		RTS

LB_UnlinkExeDes	move.l	a5,-(a7)
		move.l	a0,a5
		move.l	xfdli_Hunk2(a5),d0
		BSR.W	GetHunkX
		move.w	#XFDERR_BADHUNK,xfdli_Error(a5)
		tst.w	d0
		beq.b	.Exit
		move.l	a0,a1

		move.l	4(a0),d0
		lsl.l	#2,d0
		subq.l	#4,d0
		add.w	#$c,a0
		move.l	a0,xfdli_Save2(a5)
		add.l	d0,a0
.GetLen		tst.b	-(a0)
		bne.b	.SetLen
		subq.l	#1,d0
		bra.b	.GetLen
.SetLen		move.l	d0,xfdli_SaveLen2(a5)

		move.l	xfdli_Buffer(a5),a0
		moveq	#20,d1
		move.l	16(a0),d0
		sub.l	12(a0),d0
		lsl.l	#2,d0
		add.l	d0,d1
		add.l	d1,a0
.Copy		move.l	-(a0),4(a0)
		subq.l	#4,d1
		bne.b	.Copy

		addq.w	#4,a0
		subq.l	#1,8(a0)
		subq.l	#1,16(a0)
		move.l	a0,xfdli_Save1(a5)
		sub.l	a0,a1
		move.l	a1,xfdli_SaveLen1(a5)
		moveq	#1,d0

.Exit		move.l	(a7)+,a5
		rts

LB_UnlinkEXP11	MOVEM.L	D2-D3,-(A7)
		MOVE.W	#82,D2
		MOVE.W	#94,D3
		BSR.B	UnlinkText
		MOVEM.L	(A7)+,D2-D3
		RTS

LB_UnlinkETA091
		MOVEM.L	D2-D3,-(A7)
		MOVE.W	#90,D2
		MOVE.W	#131,D3
		BSR.B	UnlinkText
		MOVEM.L	(A7)+,D2-D3
		RTS

LB_UnlinkETA099
		MOVEM.L	D2-D3,-(A7)
		MOVE.W	#92,D2
		MOVE.W	#133,D3
		BSR.B	UnlinkText
		MOVEM.L	(A7)+,D2-D3
		RTS

LB_UnlinkETA100 MOVEM.L	D2-D3/A2/A5,-(A7)
		MOVE.L	A0,A5
		MOVE.L	xfdli_Hunk1(A5),D0
		BSR.W	GetHunkX
		MOVE.W	#XFDERR_BADHUNK,xfdli_Error(A5)
		TST.W	D0
		BEQ.B	.Exit
		LEA	120(A0),A2	* get size pointer
		LEA	155(A0),A1	* get data start
		MOVE.L	(A2)+,D0	* get decode text
		SUBQ.L	#1,D0
.Loop1		MOVEA.L	A2,A0		* decode with
.Loop2		TST.B	(A0)		* 'dos.library' text
		BEQ.B	.Loop1
		MOVE.B	(A0)+,D1
		ADD.B	D1,D1
		EOR.B	D1,(A1)+
		DBRA	D0,.Loop2
		MOVE.W	#120,D2
		MOVE.W	#155,D3
		MOVEA.L	A5,A0
		BSR.B	UnlinkText
.Exit		MOVEM.L	(A7)+,D2-D3/A2/A5
		RTS

		* destroys D2
UnlinkText	MOVEM.L	A3-A6,-(A7)
		MOVE.L	A0,A5
		MOVE.L	xfdli_Hunk1(A5),D0
		BSR.W	GetHunkX
		MOVE.W	#XFDERR_BADHUNK,xfdli_Error(A5)
		TST.W	D0
		BEQ.W	.Exit
		MOVEA.L	A0,A4				* start of Hunk0
		MOVE.L	4(A4),D0			* get hunk size
		ADDQ.L	#2,D0				* add the 2 header bytes
		LSL.L	#2,D0				* in byte
		SUB.L	D3,D0				* subtract start position
		MOVE.L	(A0,D2.W),D2			* size of Text-Data
		BNE.B	.IsNotZero			* fix zero length
		MOVEQ	#-1,D2				* set high value
.IsNotZero	CMP.L	D0,D2				* maximum size?
		BLS.B	.IsOk
		MOVE.L	D0,D2				* replace with maximum size
.IsOk		MOVE.L	D2,xfdli_SaveLen1(A5)
		LEA	(A0,D3.W),A6			* start of Text-Data
		MOVE.L	xfdli_Hunk2(A5),D0
		BSR.B	GetHunkX
		TST.W	D0
		BEQ.B	.Exit
		MOVE.L	A0,A3		* start of Code-Hunk
		MOVE.L	xfdli_Buffer(A5),A0
		MOVE.L	8(A0),D0	* number of hunks
		SUBQ.L	#1,D0		* we will remove first hunk
		MOVE.L	D0,D1		* store number of hunks
.CopyLoop	MOVE.L	-(A4),-(A7)	* copy hunk sizes to stack
		SUBQ.L	#1,D0
		BNE.B	.CopyLoop
		MOVE.L	A0,xfdli_Save1(A5)	* text starts at file start
		MOVE.L	A0,A1			* store buffer start
.CopyText	MOVE.B	(A6)+,(A0)+
		SUBQ.L	#1,D2
		BNE.B	.CopyText
		MOVE.L	D1,D0
		LSL.L	#2,D0
		NEG.L	D0
		LEA	-20(A3,D0.W),A3
		MOVEA.L	A3,A4			* store hunk start
		MOVE.L	A3,xfdli_Save2(A5)
		ADD.L	xfdli_BufLen(A5),A1
		SUBA.L	A3,A1			* file size
		MOVE.L	A1,D2			* store size
		MOVE.L	D2,xfdli_SaveLen2(A5)
		MOVE.L	#HUNK_HEADER,(A3)+	* header
		CLR.L	(A3)+			* zero field
		MOVE.L	D1,(A3)+		* numhunks
		CLR.L	(A3)+			* first hunk
		MOVE.L	D1,D0
		SUBQ.L	#1,D0
		MOVE.L	D0,(A3)+		* last hunk
.CopyLoop2	MOVE.L	(A7)+,(A3)+		* copy hunk sizes
		SUBQ.L	#1,D1
		BNE.B	.CopyLoop2

		MOVE.L	A4,A0
		MOVE.L	D2,D0
		MOVE.L	xfdli_Hunk1(A5),D1
		SUB.L	xfdli_Hunk2(A5),D1
		BSR.B	CorrectReloc
		MOVEQ	#1,D0
.Exit		MOVEM.L	(A7)+,A3-A6
		RTS

*************************************************************
*              Get begin of hunk #n of a file               *
*************************************************************
* a5: xfdli	a0: new pos                                 *
* d0: hunk #	d0: BOOL                                    *
*************************************************************

GetHunkX	MOVE.L	D1,-(A7)
		MOVE.L	xfdli_Buffer(A5),A0
		MOVE.L	D0,D1
		MOVE.L	xfdli_BufLen(A5),D0
		BSR	xfdGetHunk
		TST.L	D0
		BEQ.B	.End
		MOVE.L	D0,A0
		MOVEQ	#1,D0
.End		MOVE.L	(A7)+,D1
		RTS

*************************************************************
*                Correct reloc hunk numbers                 *
*************************************************************
* a0: buffer	d1: offset to add                           *
* d0: buflen                                                *
*************************************************************

CorrectReloc	lea	(a0,d0.l),a1
		move.l	8(a0),d0
		lsl.l	#2,d0
		lea	20(a0,d0.l),a0

.NextCorrect	cmp.l	a1,a0
		beq.b	.EndCorrect
		move.l	(a0)+,d0

		cmp.w	#$3ea,d0	;3e8,3e9,3ea
		ble.b	.SkipCode
		cmp.w	#$3eb,d0	;3eb
		bne.b	.NoBSS
		addq.w	#4,a0
		bra.b	.NextCorrect
.NoBSS		cmp.w	#$3ec,d0	;3ec
		beq.b	.CorrectReloc
		cmp.w	#$3f0,d0	;3f0
		beq.b	.SkipSymbol
		cmp.w	#$3f1,d0	;3f1
		beq.b	.SkipCode
		cmp.w	#$3f2,d0	;3f2
		beq.b	.NextCorrect
		moveq	#0,d0
		rts

.SkipCode	move.l	(a0)+,d0
		lsl.l	#2,d0
		add.l	d0,a0
		bra.b	.NextCorrect

.CorrectReloc	move.l	(a0)+,d0
		beq.b	.NextCorrect
		add.l	d1,(a0)
		lsl.l	#2,d0
		lea	4(a0,d0.l),a0
		bra.b	.CorrectReloc

.SkipSymbol	move.l	(a0)+,d0
		beq.b	.NextCorrect
		lsl.l	#2,d0
		lea	4(a0,d0.l),a0
		bra.b	.SkipSymbol

.EndCorrect	moveq	#1,d0
		rts

*************************************************************
*                 Change MemType of Hunks                   *
*************************************************************
* a0: first BPTR     d1: relmode                            *
* d0: number hunks                                          *
*************************************************************

xfdChangeHunkMemType
		movem.l	d2/d3/d7/a2/a3/a6,-(a7)
		cmp.w	#XFDREL_DEFAULT,d1
		beq.b	.Ok
		moveq	#2,d2
		cmp.w	#XFDREL_FORCECHIP,d1
		beq.b	.ChipFast
		moveq	#4,d2
		move.w	#XFDERR_BADRELMODE,d7
		cmp.w	#XFDREL_FORCEFAST,d1
		bne.b	.Exit
.ChipFast	move.l	4.w,a6
		move.w	d0,d3
		move.l	a0,a3
		moveq	#XFDERR_NOMEMORY,d7

.CheckNext	move.l	(a3),a2
		add.l	a2,a2
		add.l	a2,a2
		move.l	a2,a1
		jsr	_LVOTypeOfMem(a6)
		and.w	d2,d0
		bne.b	.GetNext

		move.l	-(a2),d0
		move.l	#$10001,d1
		or.w	d2,d1
		jsr	_LVOAllocMem(A6)
		tst.l	d0
		beq.b	.Exit
		move.l	d0,a0

		move.l	a2,a1
		move.l	(a1),d0
		move.l	d0,(a0)+
		move.l	4(a1),(a0)
		move.l	a0,a2
		move.l	a0,d1
		lsr.l	#2,d1
		move.l	d1,(a3)
		jsr	_LVOFreeMem(A6)

.GetNext	move.l	a2,a3
		subq.w	#1,d3
		bne.b	.CheckNext

.Ok		moveq	#XFDERR_OK,d7
.Exit		bsr	ClearCache
		moveq	#0,d0
		move.w	d7,d0
		movem.l	(a7)+,d2/d3/d7/a2/a3/a6
		rts

*************************************************************
*     Change MemType of Hunks and copy old contents         *
*************************************************************
* a0: first BPTR     d1: relmode                            *
* d0: number hunks                                          *
*************************************************************

xfdChangeHunkMemTypeCopy
		movem.l	d2/d3/d7/a2/a3/a6,-(a7)
		cmp.w	#XFDREL_DEFAULT,d1
		beq.b	.Ok
		moveq	#2,d2
		cmp.w	#XFDREL_FORCECHIP,d1
		beq.b	.ChipFast
		moveq	#4,d2
		move.w	#XFDERR_BADRELMODE,d7
		cmp.w	#XFDREL_FORCEFAST,d1
		bne.b	.Exit
.ChipFast	move.l	4.w,a6
		move.w	d0,d3
		move.l	a0,a3
		moveq	#XFDERR_NOMEMORY,d7

.CheckNext	move.l	(a3),a2
		add.l	a2,a2
		add.l	a2,a2
		move.l	a2,a1
		jsr	_LVOTypeOfMem(a6)
		and.w	d2,d0
		bne.b	.GetNext

		move.l	-(a2),d0
		move.l	#$10001,d1
		or.w	d2,d1
		jsr	_LVOAllocMem(A6)
		tst.l	d0
		beq.b	.Exit
		move.l	d0,a0

		move.l	a2,a1
		move.l	(a1),d0
		movem.l	d0/a0/a1,-(a7)
		exg	a0,a1
		jsr	_LVOCopyMemQuick(a6)
		movem.l	(a7)+,d0/a0/a1
		addq.w	#4,a0
		move.l	a0,a2
		move.l	a0,d1
		lsr.l	#2,d1
		move.l	d1,(a3)
		jsr	_LVOFreeMem(A6)

.GetNext	move.l	a2,a3
		subq.w	#1,d3
		bne.b	.CheckNext

.Ok		moveq	#XFDERR_OK,d7
.Exit		bsr.b	ClearCache
		moveq	#0,d0
		move.w	d7,d0
		movem.l	(a7)+,d2/d3/d7/a2/a3/a6
		rts

*************************************************************
*             Clear CPU Caches (Kick 1.2 komp.)             *
*************************************************************

ClearCache	movem.l	d0/d1/a0/a1/a6,-(a7)
		move.l	4.w,a6
		cmp.w	#36,20(a6)
		blt.b	.Kick13
		jsr	_LVOCacheClearU(a6)
.Kick13		movem.l	(a7)+,d0/d1/a0/a1/a6
		rts

*************************************************************************
*		 checksum CRC-16 calculation routine 			*
*									*
* This is made of reassembled code from PCompress2 and P-Reader.	*
* I optimized the code a lot and is real assembler now.	:-)		*
*									*
*	gets following parameters:					*
*		A0	buffer						*
*	        D0	buffersize					*
*	returns D0:	checksum (WORD)					*
*************************************************************************

GetCRC_A001	MOVEM.L	D2/D3,-(A7)
		LEA	-$200(A7),A7		* get work space

		MOVEQ	#0,D1
		ST	D1			* set $FF
.Loop1		MOVE.W	D1,D3
		MOVEQ	#7,D2
.Loop2		LSR.W	#1,D3
		BCC.B	.Loop2End		* is shifted bit 1 ?
		EORI.W	#$A001,D3
.Loop2End	DBRA	D2,.Loop2
		MOVE.W	D1,D2
		ASL.L	#1,D2
		MOVE.W	D3,(A7,D2.W)
		DBRA	D1,.Loop1

		MOVEQ	#0,D3
.SumLoop	MOVE.B	(A0)+,D1
		EOR.B	D1,D3
		MOVEQ	#0,D1
		MOVE.B	D3,D1
		ASL.W	#1,D1
		LSR.W	#8,D3
		MOVE.W	(A7,D1.W),D1
		EOR.W	D1,D3
		SUBQ.L	#1,D0
		BNE.B	.SumLoop
		LEA	$200(A7),A7		* free work space
		MOVE.L	D3,D0
		MOVEM.L	(A7)+,D2/D3
		RTS	

*************************************************************
*              Get begin of hunk #n of a file               *
*************************************************************
* A0: buffer						    *
* D0: buffer size					    *
* D1: hunk number	D0: Hunk start or 0                 *
*************************************************************

xfdGetHunk	MOVEM.L	A0/D1-D3,-(A7)
		SUB.L	#5*4,D0
		BLO.W	.Exit			* at least 20 Bytes!
		CMP.L	#HUNK_HEADER,(A0)+
		BNE.W	.Exit			* HUNK_HEADER ?
		TST.L	(A0)+
		BNE.W	.Exit			* must be empty
		MOVEQ	#1,D2
		ADD.W	8+2(A0),D2		* last hunk num ; only use 16 bit hunk numbers 21.08.2001
		SUB.W	4+2(a0),D2		* first hunk num --> number of real hunks
		LEA	12(A0),A0		* start of size field
		CMP.L	D1,D2			* not enough hunks
		BLE.W	.Exit
.NextSize	SUBQ.L	#4,D0			* enough size for entry
		BLO.W	.Exit
		MOVE.L	(A0)+,D3
		AND.L	#(3<<30),D3		* first 2 bits mean mem type follows as long
		CMP.L	#(3<<30),D3
		BNE.B	.nomemspec
		SUBQ.L	#4,D0			* enough size for mem entry
		BLO.B	.Exit
		ADDQ.L	#4,A0
.nomemspec	SUBQ.L	#1,D2
		BNE.B	.NextSize

.NextHunk	SUBQ.L	#4,D0
		BLO.B	.Exit
		MOVE.L	(A0)+,D2

		CMP.W	#HUNK_CODE,D2
		BEQ.B	.Code
		CMP.W	#HUNK_DATA,D2
		BNE.B	.NoCode
.Code		SUBQ.L	#1,D1			* test for hunk number
		BMI.B	.Ok
.Skip		SUBQ.L	#4,D0
		BLO.B	.Exit
		MOVE.L	(A0)+,D2
		LSL.L	#2,D2
		SUB.L	D2,D0
		BLO.B	.Exit
		ADD.L	D2,A0
		BRA.B	.NextHunk

.NoCode		CMP.W	#HUNK_BSS,D2
		BNE.B	.NoBSS
		SUBQ.L	#1,D1			* test for hunk number
		BMI.B	.Ok
		SUBQ.L	#4,D0
		BLO.B	.Exit
		ADDQ.W	#4,A0
		BRA.B	.NextHunk

.NoBSS		CMP.W	#HUNK_ABSRELOC32,D2
		BEQ.B	.NextReloc
		CMP.W	#HUNK_SYMBOL,D2
		BNE.B	.NoReloc
.NextReloc	SUBQ.L	#4,D0
		BLO.B	.Exit
		MOVE.L	(A0)+,D2
		BEQ.B	.NextHunk
		LSL.L	#2,D2
		ADDQ.L	#4,D2
		SUB.L	D2,D0
		BLO.B	.Exit
		LEA	(A0,D2.L),A0
		BRA.B	.NextReloc

.NoReloc	CMP.W	#HUNK_NAME,D2
		BEQ.B	.Skip
		CMP.W	#HUNK_DEBUG,D2
		BEQ.B	.Skip
		CMP.W	#HUNK_END,D2
		BEQ.B	.NextHunk

.Exit		MOVE.W	#4,A0	* results in A0 = 0
.Ok		SUBQ.W	#4,A0
		MOVE.L	A0,D0
		MOVEM.L	(A7)+,A0/D1-D3
		RTS

*************************************************************
*                 Get first hunk #n                         *
*************************************************************
* A0: buffer						    *
*************************************************************

xfdCodeBegin	moveq	#1,d0
		add.w	16+2(a0),d0		; only use 16 bit hunk numbers 21.08.2001
		sub.w	12+2(a0),d0
		lsl.l	#2,d0
		lea	28(a0,d0.l),a0
		RTS

*************************************************************
*                 Get first hunk #n                         *
*************************************************************
* A0: buffer						    *
* D0: buflen
*************************************************************

xfdCodeBeginRecog
		moveq	#0,D1
		BSR	xfdGetHunk
		TST.L	D0
		BEQ.B	.Exit
		MOVE.L	D0,A0
		ADDQ.L	#8,A0
.Exit		RTS

		INCDIR	"slaves/"
XfdFirstSlave
		INCLUDE	"CrunchMania.s"
		INCLUDE	"StoneCracker.s"
		INCLUDE	"ProPack.s"
		INCLUDE	"Imploder.s"
		INCLUDE	"PowerPacker.s"
		INCLUDE	"CFP.s"
		INCLUDE	"PKProt.s"
		INCLUDE	"PCompress2.s"
		INCLUDE	"ByteKiller.s"
*		INCLUDE	"XPK.s"
		INCLUDE	"TetraPack.s"
		INCLUDE	"DefJam.s"
		INCLUDE	"MasterCruncher.s"
		INCLUDE	"PackIt.s"
		INCLUDE	"TimeCruncher.s"
		INCLUDE	"DoubleAction.s"
		INCLUDE	"FreewaY.s"
		INCLUDE	"IAM.s"
		INCLUDE	"DragPack.s"
		INCLUDE	"TurtleSmasher.s"
		INCLUDE	"Titanics.s"
		INCLUDE	"Spike.s"
		INCLUDE	"TryIt.s"
		INCLUDE	"BytePacker.s"
		INCLUDE	"MaxPacker.s"
		INCLUDE	"FCG.s"
		INCLUDE	"SyncroPacker.s"
		INCLUDE	"TurboSqueezer.s"
		INCLUDE	"SoundPacker.s"
		INCLUDE	"Chryseis.s"
		INCLUDE	"GNU.s"
		INCLUDE	"Super.s"
		INCLUDE	"Ultimate.s"
		INCLUDE	"ISC.s"
*		INCLUDE	"MagneticFields.s"
XFD_LASTSLAVE	SET	1
		INCLUDE "SMF.s"

