*****************************************************************************
*   $Id: DragPack.a,v 1.2 2005/06/23 14:39:16 stoecker Exp $
*   DragPack 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_Drag252Data	dc.l	S_Drag252-Xfd68KHeader
		dc.w	2
		dc.w	39
		dc.l	N_Drag252Data-Xfd68KHeader
		dc.w	XFDPFF_DATA|XFDPFF_USERTARGET|XFDPFF_RECOGLEN
		dc.w	0
		dc.l	RB_Drag252Data-Xfd68KHeader
		dc.l	DB_Drag252Data-Xfd68KHeader
		dc.l	SD_Drag252Data-Xfd68KHeader
		dc.l	VD_Drag252Data-Xfd68KHeader
		dc.w	XFDID_DragPack252Data
		dc.w	0
		dc.l	2+32

N_Drag252Data	dc.b	'DragPack 2.52 Data',0
		even

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

RB_Drag252Data	MOVEQ	#0,D0
		CMP.W	#'BH',(A0)
		BNE.B	.Exit
		MOVE.L	12(A0),D1
		AND.L	#$F0F0F0F0,D1
		BNE.B	.Exit
		MOVE.L	16(A0),D1
		AND.L	#$F0F0F0F0,D1
		BNE.B	.Exit
		MOVE.L	2(A0),D0
		AND.L	#$00FFFFFF,D0
		MOVE.L	D0,xfdrr_MinTargetLen(A1)
		MOVE.L	D0,xfdrr_FinalTargetLen(A1)
		MOVE.L	6(A0),xfdrr_MinSourceLen(A1)
		MOVEQ	#1,D0
.Exit		RTS

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

SD_Drag252Data	moveq	#0,d0
		cmp.w	#'BH',(a0)
		BNE.B	.Exit
		MOVEQ	#1,D0
.Exit		rts

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

VD_Drag252Data	move.l	12(a0),d0
		and.l	#$f0f0f0f0,d0
		bne.s	.Exit
		move.l	16(a0),d0
		and.l	#$f0f0f0f0,d0
		bne.s	.Exit
		move.l	6(a0),d1
		cmp.l	d0,d1		;crlen > buflen ??
		bgt.s	.Exit
		move.l	2(a0),d0
		and.l	#$00ffffff,d0
		sub.l	6(a0),d0	;cr > uncr ??
		bmi.s	.Exit
		move.l	d1,d0
		rts

.Exit		moveq	#0,d0
		rts

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

DB_Drag252Data	movem.l	d2-d7/a2-a6,-(a7)
		move.l	a0,a5
		move.l	xfdbi_SourceBuffer(a5),a3
		MOVE.L	xfdbi_UserTargetBuf(A5),A1
		move.l	a1,a4
		add.l	xfdbi_TargetBufSaveLen(a5),a1

		subq.w	#4,a7

		moveq	#0,d0
		move.b	10(a3),d0
		move.w	d0,(a7)
		moveq	#2,d1
		lsl.w	d0,d1
		subq.w	#1,d1
		move.w	d1,2(a7)

		moveq	#0,d6
		move.b	11(a3),d6
		moveq	#2,d7
		lsl.w	d6,d7
		subq.w	#1,d7
		
		moveq	#0,d5
		move.b	2(a3),d5
		moveq	#2,d0
		lsl.w	d5,d0
		lea	12(a3),a2

		lea	-32(a7),a7
		move.l	a7,a3

		move.l	a3,a6
		clr.w	(a6)+
		subq.w	#1,d0
		move.l	a2,a0

		moveq	#0,d1
.Prep		move.b	(a0)+,d2
		addq.b	#1,d2
		moveq	#1,d3
		lsl.l	d2,d3
		move.w	d3,(a6)
		add.w	d1,(a6)+
		add.w	d3,d1
		subq.w	#1,d0
		bne.s	.Prep

		move.l	xfdbi_SourceBuffer(a5),a0
		add.l	6(a0),a0

		lea	32(a7),a6
		bsr	D_Drag252

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

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

S_Drag252
		IFND	XFD_LASTSLAVE
		dc.l	S_Drag_END-Xfd68KHeader
		ELSE
		dc.l	0
		ENDIF
		dc.w	2
		dc.w	39
		dc.l	N_Drag252-Xfd68KHeader
		dc.w	XFDPFF_RELOC!XFDPFF_RELMODE
		dc.w	0
		dc.l	RB_Drag252-Xfd68KHeader
		dc.l	DB_Drag252-Xfd68KHeader
		dc.l	RS_Drag252-Xfd68KHeader
		dc.l	DS_Drag252-Xfd68KHeader
		dc.w	XFDID_DragPack252
		dc.w	0
		dc.l	$172+$22+4

N_Drag252	dc.b	'DragPack 2.52',0
		even

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

RB_Drag252	cmp.l	#$487a0046,$20(a0)
		bne.s	.Exit
		cmp.l	#$49faffee,$28(a0)
		bne.s	.Exit
		cmp.l	#$24482248,$36(a0)
		bne.s	.Exit
		moveq	#1,d0
		rts

.Exit		moveq	#0,d0
		rts

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

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

		lea	$34(a3),a2
		add.w	(a2),a2		;now data
		move.l	$40(a3),d2	;new len
		move.l	$46(a3),d3	;crunched len
		move.w	$3c(a3),d4	;data offset

		moveq	#0,d5
		move.b	$a3(a3),d5	;offset mirror

		move.l	$52(a3),d0
		move.l	d0,xfdbi_TargetBufSaveLen(a5)
		move.l	d0,xfdbi_TargetBufLen(a5)

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

		move.l	d0,a1
		move.l	#$3f3,(a1)+		
		move.l	a2,a0

		move.l	a1,a4
		sub.w	d4,a1
		add.l	d2,a1
		move.l	a1,d7		;laenge jetzt

		move.l	d7,-(a7)

		moveq	#0,d6
		move.b	$79(a3),d6
		move.w	$80(a3),d7
		
		subq.w	#4,a7
		clr.l	(a7)
		move.b	$a9(a3),1(a7)
		move.w	$b0(a3),2(a7)
		move.l	a7,a6

		moveq	#0,d0
		move.b	$93(a3),d0
		lea	(a2,d5.w),a3	;mirror
		move.w	d0,d5

		add.l	d3,a0
		bsr	D_Drag252
		addq.w	#4,a7

		move.l	(a7)+,d7
		bsr.b	.Correct
		tst.l	d0
		bne.s	.Exit

		move.l	xfdbi_TargetBuffer(a5),a1
		move.l	xfdbi_TargetBufLen(a5),d0
		move.l	4.w,a6
		jsr	-210(a6)
		moveq	#0,d0
		move.w	#XFDERR_CORRUPTEDDATA,xfdbi_Error(a5)

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

.Correct	move.l	xfdbi_TargetBuffer(a5),a0
		move.l	8(a0),d0
		lsl.l	#2,d0
		lea	20(a0,d0.l),a0
		
.Next		move.w	(a0)+,d2
		lea	.HunkTab(pc),a1
		cmp.b	(a1)+,d2
		beq.s	.Code
		cmp.b	(a1)+,d2
		beq.s	.Code
		cmp.b	(a1)+,d2
		beq.s	.BSS
		cmp.b	(a1)+,d2
		beq.s	.Reloc
		cmp.b	(a1)+,d2
		beq.s	.Symbol
		cmp.b	(a1)+,d2
		beq.s	.End
		moveq	#0,d0
		rts

.End		move.l	#$3f2,d0
		cmp.l	d7,a0
		beq.s	.End1
		bsr.s	.CopyWord
		subq.w	#2,a0
		move.l	d0,(a0)+
		bra.s	.Next
.End1		move.l	d0,-2(a0)
		moveq	#1,d0
		rts

.BSS		bsr.s	.CopyWord
		subq.w	#2,a0
		move.l	#$3eb,(a0)+
		addq.w	#4,a0
		bra.s	.Next

.Code		bsr.s	.CopyWord
		subq.w	#2,a0
		move.l	#$3e9,(a0)+
		move.l	(a0)+,d0
		lsl.l	#2,d0
		add.l	d0,a0
		bra.s	.Next
		
.Reloc		bsr.s	.CopyWord
		subq.w	#2,a0
		move.l	#$3ec,(a0)+
		moveq	#0,d2
.Reloc3		move.l	(a0)+,d0		;amount
		beq.s	.Next
		moveq	#0,d1
		move.w	(a0),d2
		bsr.s	.CopyWord
		move.l	d2,(a0)+		;hunknum
.Reloc2		move.w	(a0),d2
		add.l	d2,d1
		bsr.s	.CopyWord
		move.l	d1,(a0)+
		subq.l	#1,d0
		bne.s	.Reloc2		
		bra.s	.Reloc3

.CopyWord	move.l	d7,a2
.CopyWord1	move.w	-(a2),2(a2)
		cmp.l	a2,a0
		bne.s	.CopyWord1	
		addq.l	#2,d7
		rts

.Symbol		bsr.s	.CopyWord
		subq.w	#2,a0
		move.l	#$3f0,(a0)+
.Symbol1	move.l	(a0)+,d0
		beq	.Next
		lsl.l	#2,d0
		lea	4(a0,d0.l),a0
		bra.s	.Symbol1		

.HunkTab	dc.b	$e9
		dc.b	$ea
		dc.b	$eb
		dc.b	$ec
		dc.b	$f0
		dc.b	$f2

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

RS_Drag252	add.l	a0,a0
		add.l	a0,a0
		cmp.l	#$152+$22+8,-4(a0)
		blt.s	.Exit

		cmp.l	#$487a0046,$4(a0)
		bne.s	.Exit
		cmp.l	#$49faffee,$c(a0)
		bne.s	.Exit
		cmp.l	#$24482248,$1a(a0)
		bne.s	.Exit
		moveq	#1,d0
		rts

.Exit		moveq	#0,d0
		rts

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

DS_Drag252	movem.l	d2-d7/a2-a6,-(a7)
		move.l	xfdm_DosBase(a6),-(a7)

		move.l	a0,a5
		move.l	xfdsi_SegList(a5),a3
		clr.l	xfdsi_SegList(a5)
		add.l	a3,a3
		add.l	a3,a3

		lea	$34-$1c(a3),a0
		add.w	(a0),a0		;now data
		move.l	$40-$1c(a3),d2	;new len
		move.l	$46-$1c(a3),d3	;crunched len
		move.w	$3c-$1c(a3),d4	;data offset
		moveq	#0,d5
		move.b	$a3-$1c(a3),d5	;offset mirror

		move.l	a0,a1
		move.l	a0,a2
		lea	(a0,d4.w),a4
		add.l	d2,a1
		add.l	d3,a0
		ext.l	d4
		sub.l	d4,d2
		movem.l	d2/a3,-(a7)

		moveq	#0,d6
		move.b	$79-$1c(a3),d6
		move.w	$80-$1c(a3),d7
		
		clr.l	-(a7)
		move.b	$a9-$1c(a3),1(a7)
		move.w	$b0-$1c(a3),2(a7)
		move.l	a7,a6

		moveq	#0,d0
		move.b	$93-$1c(a3),d0
		lea	(a2,d5.w),a3	;mirror
		move.w	d0,d5

		bsr	D_Drag252
		addq.w	#4,a7

		movem.l	(a7)+,d0/a3
		move.l	a4,a0
		lea	xfdsi_SegList(a5),a1
		move.w	xfdsi_RelMode(a5),d1
		bsr.b	Drag_Relocate
		moveq	#0,d1
		move.w	d0,xfdsi_Error(a5)
		bne.s	.FreeSeg
		moveq	#1,d1

.FreeSeg	move.l	d1,-(a7)
		move.l	a3,d1
		lsr.l	#2,d1
		move.l	4(a7),a6
		jsr	-156(a6)
		move.l	(a7)+,d0

		addq.w	#4,a7
		movem.l	(a7)+,d2-d7/a2-a6
		rts

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

Drag_Relocate	movem.l	d2-d7/a2-a6,-(a7)
		clr.l	(a1)
		movem.l	d0/d1/a0/a1,-(a7)
		movem.l	(a7)+,d0/d6/a2/a4
		lea	(a2,d0.l),a5

		move.l	4(a2),d2
		add.w	#16,a2

		move.l	4.w,a6
		move.l	a4,a3

.AllocNext	cmp.w	#XFDREL_DEFAULT,d6
		beq.s	.AllocDefault
		move.l	#$10003,d1
		cmp.w	#XFDREL_FORCECHIP,d6
		beq.s	.AllocChipFast
		move.l	#$10005,d1
		cmp.w	#XFDREL_FORCEFAST,d6
		beq.s	.AllocChipFast
		move.w	#XFDERR_BADRELMODE,d7
		bra	.MemError
.AllocDefault	moveq	#1,d1
		swap	d1
		move.w	(a2),d1
		rol.w	#3,d1
		and.w	#$0006,d1
		or.w	#$0001,d1
.AllocChipFast	move.l	(a2)+,d0
		addq.l	#2,d0
		lsl.l	#2,d0
		move.l	d0,-(a7)
		jsr	-198(a6)
		move.l	(a7)+,d1
		moveq	#XFDERR_NOMEMORY,d7
		tst.l	d0
		beq	.MemError
		move.l	d0,a0
		move.l	d1,(a0)+
		move.l	a0,d0
		lsr.l	#2,d0
		move.l	d0,(a3)
		move.l	a0,a3
		subq.l	#1,d2
		bne.s	.AllocNext

		moveq	#-1,d2	;hunk num

.ReloNext	cmp.l	a5,a2
		beq	.Exit
		move.w	(a2)+,d0
		cmp.b	#$eb,d0		;bss
		bcs.s	.ReloCode
		beq.s	.ReloBSS
		cmp.b	#$ec,d0		;reloc32
		beq.s	.ReloReloc
		cmp.b	#$f0,d0		;symbol
		beq.s	.JumpSymbol
		cmp.b	#$f2,d0		;end
		beq.s	.ReloNext
		move.w	#XFDERR_UNSUPPORTEDHUNK,d7
		bra.s	.MemError

.JumpSymbol	move.l	(a2)+,d0
		beq.s	.ReloNext
		lsl.l	#2,d0
		lea	4(a2,d0.l),a2
		bra.s	.JumpSymbol

.ReloCode	addq.l	#1,d2
		move.l	d2,d1
		bsr.s	.GetHunk
		move.l	(a2)+,d0
		beq.s	.ReloNext
.ReloCodeCopy	move.l	(a2)+,(a1)+
		subq.l	#1,d0
		bne.s	.ReloCodeCopy
		bra.s	.ReloNext

.ReloBSS	addq.l	#1,d2
		addq.w	#4,a2
		bra.s	.ReloNext

.ReloReloc	move.l	d2,d1
		bsr.s	.GetHunk
		move.l	a1,a3
.ReloRelocHunk	move.l	(a2)+,d0	;amount
		beq.s	.ReloNext
		move.w	(a2)+,d1	;hunk
		bsr.s	.GetHunk
		move.l	a1,d4
		moveq	#0,d3
		moveq	#0,d1
.ReloRelocNext	move.w	(a2)+,d1
		add.l	d1,d3
		add.l	d4,(a3,d3.l)
		subq.l	#1,d0
		bne.s	.ReloRelocNext
		bra.s	.ReloRelocHunk

.GetHunk	move.l	a4,a1
.GetHunkNext	move.l	(a1),a1
		add.l	a1,a1
		add.l	a1,a1
		subq.w	#1,d1
		bge.s	.GetHunkNext
		addq.w	#4,a1
		rts

.MemError	move.l	(a4),d2
		clr.l	(a4)
		move.l	4.w,a6
.FreeNext	lsl.l	#2,d2
		beq.s	.Error
		move.l	d2,a1
		move.l	(a1),d2
		move.l	-(a1),d0
		jsr	-210(a6)
		bra.s	.FreeNext

.Exit		moveq	#XFDERR_OK,d7

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

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

D_Drag252	bra.s	.Decr5

.Decr4		add.w	d2,d2
		bne.s	.Decr6
.Decr5		move.w	-(a0),d2
		move.b	#$10,ccr
		addx.w	d2,d2
.Decr6		bcs.s	.Decr9

		moveq	#0,d3
.Decr7		move.w	d6,d1
		bsr.s	.Decr1
		add.l	d0,d3
		cmp.w	d7,d0
		beq.s	.Decr7
.Decr8		moveq	#7,d1
		bsr.s	.Decr2
		move.b	d0,-(a1)
		cmp.l	a4,a1
		dbeq	d3,.Decr8
		cmp.w	#-1,d3
		bne.s	.Exit

.Decr9		move.w	d5,d1
		bsr.s	.Decr1
		move.b	(a2,d0.w),d1
		move.w	d0,d3
		bsr.s	.Decr1
		add.w	d3,d3
		add.w	(a3,d3.w),d0
		moveq	#0,d3
		move.w	d0,d4
.Decr10		move.w	(a6),d1
		bsr.s	.Decr1
		add.l	d0,d3
		cmp.w	2(a6),d0
		beq.s	.Decr10
		addq.l	#1,d3
.Decr11		move.b	(a1,d4.w),-(a1)
		cmp.l	a4,a1
		dbeq	d3,.Decr11
		cmp.w	#-1,d3
		beq.s	.Decr4
.Exit		rts

.Decr1		moveq	#0,d0
.Decr2		add.w	d2,d2
		bne.s	.Decr3
		move.w	-(a0),d2
		move.b	#$10,ccr
		addx.w	d2,d2
.Decr3		addx.w	d0,d0
		subq.b	#1,d1
		bge.s	.Decr2
		rts

S_Drag_END

