*******************************************************
**       XFD external decruncher for XPK files       **
**        written and © 1994 by Georg Hörmann        **
*******************************************************

		OUTPUT	"LIBS:xfd/XPK"

		SECTION	XPK,CODE

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

; xfdForeman structure MUST be first thing in all external decrunchers

F_XPK		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_XPKpacked	;first slave

		dc.b	"$VER: XFD XPK decruncher/decryptor by Georg Hörmann",13,10,0
XPKlib		dc.b	"xpkmaster.library",0
		cnop	0,4

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

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

S_XPKpacked	dc.l	S_XPKcrypted	;next slave
		dc.w	1		;version
		dc.w	33		;master version
		dc.l	N_XPKpacked	;name
		dc.w	XFDPFF_DATA	;flags
		dc.w	0
		dc.l	RB_XPKpacked	;recog buffer
		dc.l	DB_XPKpacked	;decrunch buffer
		dc.l	0		;recog segment
		dc.l	0		;decrunch segment

N_XPKpacked	dc.b	'XPK Packed',0
		even

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

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

RB_XPKpacked	cmp.l	#$24+16,d0	;min. file length for header and data
		ble.s	.Exit
		cmp.l	#'XPKF',(a0)	;some more verification
		bne.s	.Exit
		btst	#1,$20(a0)	;password?
		bne.s	.Exit
		moveq	#1,d0
		rts

.Exit		moveq	#0,d0
		rts

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

;Decrunch buffer function: receives bufferinfo in a0

DB_XPKpacked	moveq	#0,d0

** combined decrunch/decrypt routine

DB_XPK		movem.l	d2-d7/a2-a6,-(a7)
		move.w	d0,d7		;password flag
		move.l	a0,a5

** open lib

		moveq	#0,d0
		lea	XPKlib(pc),a1
		move.l	4.w,a6
		jsr	-552(a6)
		move.w	#XFDERR_MISSINGRESOURCE,xfdbi_Error(a5)
		tst.l	d0
		beq	.Exit
		move.l	d0,a4

** allocate buffer

		move.l	xfdbi_SourceBuffer(a5),a2
		move.l	$c(a2),d0
		move.l	d0,xfdbi_TargetBufSaveLen(a5)
		add.l	#XPK_MARGIN,d0
		move.l	d0,xfdbi_TargetBufLen(a5)

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

** decrunch/decrypt

		clr.l	-(a7)
		tst.w	d7
		beq.s	.NoPW1
		move.l	xfdbi_Special(a5),-(a7)
		move.l	#XPK_Password,-(a7)
.NoPW1		move.l	xfdbi_TargetBufLen(a5),-(a7)
		move.l	#XPK_OutBufLen,-(a7)
		move.l	d0,-(a7)
		move.l	#XPK_OutBuf,-(a7)
		move.l	xfdbi_SourceBufLen(a5),-(a7)
		move.l	#XPK_InLen,-(a7)
		move.l	a2,-(a7)
		move.l	#XPK_InBuf,-(a7)
		move.l	a7,a0
		move.l	a4,a6
		jsr	_LVOXpkUnpack(a6)
		add.w	#9*4,a7
		tst.w	d7
		beq.s	.NoPW2
		addq.w	#2*4,a7
.NoPW2		tst.l	d0
		beq.s	.Ok

** error -> free buffer

		bsr.s	XPKtoXFDerror
		move.w	d0,xfdbi_Error(a5)

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

** success

.Ok		moveq	#1,d0

** close lib

.ExitLib	move.l	d0,-(a7)
		move.l	a4,a1
		move.l	4.w,a6
		jsr	-414(a6)
		move.l	(a7)+,d0

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

** some stuff to translate XPK errorcodes to XFD

XPKtoXFDerror	cmp.w	#-32,d0
		bge.s	.Ok
		moveq	#-1,d0
		rts
.Ok		not.w	d0
		move.b	.Table(pc,d0.w),d0
		ext.w	d0
		rts

.Table		dc.b	XFDERR_NOTSUPPORTED	;XPKERR_NOFUNC
		dc.b	XFDERR_NOTSUPPORTED	;XPKERR_NOFILES
		dc.b	XFDERR_NOTSUPPORTED	;XPKERR_IOERRIN
		dc.b	XFDERR_NOTSUPPORTED	;XPKERR_IOERROUT
		dc.b	XFDERR_CORRUPTEDDATA	;XPKERR_CHECKSUM
		dc.b	XFDERR_NOTSUPPORTED	;XPKERR_VERSION
		dc.b	XFDERR_NOMEMORY		;XPKERR_NOMEM
		dc.b	XFDERR_NOTSUPPORTED	;XPKERR_LIBINUSE
		dc.b	XFDERR_NOTSUPPORTED	;XPKERR_WRONGFORM
		dc.b	XFDERR_NOMEMORY		;XPKERR_SMALLBUF
		dc.b	XFDERR_NOTSUPPORTED	;XPKERR_LARGEBUF
		dc.b	XFDERR_NOTSUPPORTED	;XPKERR_WRONGMODE
		dc.b	XFDERR_WRONGPASSWORD	;XPKERR_NEEDPASSWD
		dc.b	XFDERR_CORRUPTEDDATA	;XPKERR_CORRUPTPKD
		dc.b	XFDERR_MISSINGRESOURCE	;XPKERR_MISSINGLIB
		dc.b	XFDERR_NOTSUPPORTED	;XPKERR_BADPARAMS
		dc.b	XFDERR_NOTSUPPORTED	;XPKERR_EXPANSION
		dc.b	XFDERR_NOTSUPPORTED	;XPKERR_NOMETHOD
		dc.b	XFDERR_NOTSUPPORTED	;XPKERR_ABORTED
		dc.b	XFDERR_CORRUPTEDDATA	;XPKERR_TRUNCATED
		dc.b	XFDERR_NOTSUPPORTED	;XPKERR_WRONGCPU
		dc.b	XFDERR_NOTSUPPORTED	;XPKERR_PACKED
		dc.b	XFDERR_NOTSUPPORTED	;XPKERR_NOTPACKED
		dc.b	XFDERR_NOTSUPPORTED	;XPKERR_FILEEXISTS
		dc.b	XFDERR_NOTSUPPORTED	;XPKERR_OLDMASTLIB
		dc.b	XFDERR_NOTSUPPORTED	;XPKERR_OLDSUBLIB
		dc.b	XFDERR_NOTSUPPORTED	;XPKERR_NOCRYPT
		dc.b	XFDERR_NOTSUPPORTED	;XPKERR_NOINFO
		dc.b	XFDERR_NOTSUPPORTED	;XPKERR_LOSSY
		dc.b	XFDERR_NOTSUPPORTED	;XPKERR_NOHARDWARE
		dc.b	XFDERR_NOTSUPPORTED	;XPKERR_BADHARDWARE
		dc.b	XFDERR_WRONGPASSWORD	;XPKERR_WRONGPW

		cnop	0,4

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

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

S_XPKcrypted	dc.l	0		;no more slaves
		dc.w	1		;version
		dc.w	33		;master version
		dc.l	N_XPKcrypted	;name
		dc.w	XFDPFF_DATA!XFDPFF_PASSWORD	;flags
		dc.w	0
		dc.l	RB_XPKcrypted	;recog buffer
		dc.l	DB_XPKcrypted	;decrunch buffer
		dc.l	0		;recog segment
		dc.l	0		;decrunch segment

N_XPKcrypted	dc.b	'XPK Crypted',0
		even

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

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

RB_XPKcrypted	cmp.l	#$24+16,d0	;min. file length for header and data
		ble.s	.Exit
		cmp.l	#'XPKF',(a0)	;some more verification
		bne.s	.Exit
		btst	#1,$20(a0)	;password?
		beq.s	.Exit
		moveq	#1,d0
		rts

.Exit		moveq	#0,d0
		rts

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

;Decrunch buffer function: receives bufferinfo in a0

DB_XPKcrypted	moveq	#1,d0
		bra	DB_XPK

		END
