* Programmheader
*
*	Name:		ISC
*	Author:		SDI
*	Distribution:	PD
*	Description:	XFD external decruncher for recognising ISC
*	Compileropts:	-
*	Linkeropts:	-
*
* 1.0   31.05.98 : first version

**************
*
* As there is no way to determine the file size before uncrunching, this
* external always uses double input size as decrunch buffer. Source files
* larger than this cannot be decrunched, but should not crash the file, as
* for every write the current buffer state is checked.
*
************** 


		INCLUDE	"AINCLUDE:IncDirs.i"
		INCLUDE	"lvo.i"

		INCLUDE	"libraries/xfdmaster.i"
		INCLUDE "exec/memory.i"

		* head function for tests
*		INCLUDE	"xfdExeHead.a"

ForeMan		MOVEQ	#-1,D0
		RTS

		DC.L	XFDF_ID
		DC.W	1,0
		DC.L	0,0,Slave1

		DC.B	"$VER: ISC 1.0 (31.05.1998) by SDI",0
N_ISCPass1	DC.B	'ISC1.5 Normal    (Pass1)',0
N_ISCPass2	DC.B	'ISC1.5 Comparer  (Pass2)',0
N_ISCPass3	DC.B	'ISC1.5 Bitstream (Pass3)',0
		EVEN

Slave1		DC.L	Slave2		;no more slaves
		DC.W	2		;version
		DC.W	36		;master version
		DC.L	N_ISCPass1	;name
		DC.W	XFDPFF_ADDR	;flags
		DC.W	0
		DC.L	RB_Pass1	;recog buffer
		DC.L	DB_Pass1	;decrunch buffer
		DC.L	0		;recog segment
		DC.L	0		;decrunch segment
		DC.W	0,0
		DC.L	$104		;MinBufSize

Slave2		DC.L	Slave3		;no more slaves
		DC.W	2		;version
		DC.W	36		;master version
		DC.L	N_ISCPass2	;name
		DC.W	XFDPFF_ADDR	;flags
		DC.W	0
		DC.L	RB_Pass2	;recog buffer
		DC.L	DB_Pass2	;decrunch buffer
		DC.L	0		;recog segment
		DC.L	0		;decrunch segment
		DC.W	0,0
		DC.L	$198		;MinBufSize

Slave3		DC.L	0		;no more slaves
		DC.W	2		;version
		DC.W	36		;master version
		DC.L	N_ISCPass3	;name
		DC.W	XFDPFF_ADDR	;flags
		DC.W	0
		DC.L	RB_Pass3	;recog buffer
		DC.L	DB_Pass3	;decrunch buffer
		DC.L	0		;recog segment
		DC.L	0		;decrunch segment
		DC.W	0,0
		DC.L	$104		;MinBufSize

*************************************************************************
*	Recog buffer function: receives buffer + length in A0/D0	*
*************************************************************************

RB_Pass1	MOVEQ	#0,D0			; False

		CMP.L	#$000003F3,(A0)
		BNE.B	.No
		CMP.L	#$4FF90000,$2C(A0)
		BNE.B	.No
		CMP.L	#$B7C866FA,$78(A0)
		BNE.B	.No
		CMP.L	#$13C000DF,$8C(A0)
		BNE.B	.No
		CMP.L	#$0008D7C1,$A0(A0)
		BNE.B	.No
		CMP.L	#$D60251C8,$F0(A0)
		BNE.B	.No
		MOVEQ	#1,D0			; True
.No		RTS

RB_Pass2	MOVEQ	#0,D0			; False

		CMP.L	#$000003F3,(A0)
		BNE.B	.No
		CMP.L	#$4EF90000,$64(A0)
		BNE.B	.No
		CMP.L	#$2323B7C8,$78(A0)
		BNE.B	.No
		CMP.L	#$00C80880,$8C(A0)
		BNE.B	.No
		CMP.L	#$60027202,$DC(A0)
		BNE.B	.No
		CMP.L	#$72036002,$F0(A0)
		BNE.B	.No
		MOVEQ	#1,D0			; True
.No		RTS

RB_Pass3	MOVEQ	#0,D0			; False

		CMP.L	#$000003F3,(A0)
		BNE.B	.No
		CMP.L	#$51C9FFFC,$78(A0)
		BNE.B	.No
		CMP.L	#$DBC0D3C0,$B4(A0)
		BNE.B	.No
		CMP.L	#$660E13C0,$C8(A0)
		BNE.B	.No
		CMP.L	#$B0341000,$DC(A0)
		BNE.B	.No
		CMP.L	#$65DED035,$E0(A0)
		BNE.B	.No
		MOVEQ	#1,D0			; True
.No		RTS

*************************************************************************
*	Decrunch buffer function: receives xfdbiBufferInfo in A0	*
*************************************************************************

DB_Pass1	MOVE.L	D2,-(A7)
		MOVEQ	#1,D2
		BSR.B	DB_ISC
		MOVE.L	(A7)+,D2
		RTS
		
DB_Pass2	MOVE.L	D2,-(A7)
		MOVEQ	#2,D2
		BSR.B	DB_ISC
		MOVE.L	(A7)+,D2
		RTS

DB_Pass3	MOVE.L	D2,-(A7)
		MOVEQ	#3,D2
		BSR.B	DB_ISC
		MOVE.L	(A7)+,D2
		RTS

DB_ISC		MOVEM.L	D3-D7/A2-A6,-(A7)
		MOVE.L	A0,A5

		MOVEA.L	xfdbi_SourceBufLen(A5),D0
		LSL.L	#1,D0				* double input buf
		MOVE.L	D0,xfdbi_TargetBufLen(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)
		BEQ.B	.NoMem

		MOVEA.L	xfdbi_SourceBuffer(A5),A0
		MOVEA.L	D0,A2				* destination
		MOVEA.L	A2,A4				* testpointer
		ADDA.L	xfdbi_TargetBufLen(A5),A4

		SUBQ.L	#1,D2		* Pass1 ?
		BNE.B	.doP2
		MOVE.L	$22(A0),xfdbi_DecrAddress(A5)
		MOVE.L	$88(A0),xfdbi_JmpAddress(A5)
		LEA	$104(A0),A1
		BSR.B	DecrunchPass1
		BRA.B	.ok

.doP2		SUBQ.L	#1,D2		* Pass2 ?
		BNE.B	.doP3
		MOVE.L	$22(A0),xfdbi_DecrAddress(A5)
		MOVE.L	$11A(A0),xfdbi_JmpAddress(A5)
		LEA	$198(A0),A1
		BSR.W	DecrunchPass2
		BRA.B	.ok

.doP3					* Pass3
		MOVE.L	$28(A0),xfdbi_DecrAddress(A5)
		MOVE.L	$100(A0),xfdbi_JmpAddress(A5)
		LEA	$104(A0),A1
		MOVE.L	$14(A0),D2
		LSL.L	#2,D2
		ADD.L	A0,D2
		SUB.L	#$205,D0			* buffer end ptr
		BSR.W	DecrunchPass3
		
.ok		TST.L	D0
		BEQ.B	.NoMem
		CLR.W	xfdbi_Error(A5)
		MOVE.L	D0,xfdbi_TargetBufSaveLen(A5)
		MOVEQ	#1,D0
.NoMem		MOVEM.L	(A7)+,D3-D7/A2-A6
		RTS

*************************************************************************
*	decrunch routine - copied from file (a bit modified)		*
*************************************************************************

* A4 - destination end (for test)
* A2 - destination
* A1 - source
* uses D0,D1,D2,D3,D6,A1,A2,A3

DecrunchPass1	CLR.L	D0
		CLR.L	D1
		MOVE.B	(A1)+,D0
		BNE.B	.Pass1_01
.ok		SUBA.L	xfdbi_TargetBuffer(A5),A2
		MOVE.L	A2,D0
		RTS

.DecrErr	CLR.L	D0
		RTS

.Pass1_01	MOVE.B	D0,D1
		ANDI.B	#$001F,D0
		ANDI.B	#-$0020,D1
		LSR.B	#4,D1
		LEA	.Pass1_02(PC),A3
		ADDA.L	D1,A3
		JSR	(A3)
		BRA.B	DecrunchPass1
.Pass1_02	BRA.B	.Pass1_06
		BRA.B	.Pass1_14
		BRA.B	.Pass1_10
		BRA.B	.Pass1_11
		BRA.B	.Pass1_04
		BRA.B	.Pass1_03
		BRA.B	.Pass1_15
		CLR.B	D1
		BRA.B	.Pass1_05
.Pass1_03	LSL.W	#8,D0
		MOVE.B	(A1)+,D0
.Pass1_04	MOVE.B	(A1)+,D1
.Pass1_05	CMP.L	A2,A4		* buffer overflow ?
		BEQ.B	.DecrErr
		MOVE.B	D1,(A2)+
		DBRA	D0,.Pass1_05
		RTS	
.Pass1_06	MOVE.B	(A1)+,D1
.Pass1_07	CLR.L	D6
.Pass1_08	CMP.L	A2,A4		* buffer overflow ?
		BEQ.B	.DecrErr
		MOVE.B	(A1,D6.W),(A2)+
		ADDQ.B	#1,D6
		CMP.B	D6,D0
		BNE.B	.Pass1_08
		DBRA	D1,.Pass1_07
.Pass1_09	MOVE.B	(A1)+,D0
		SUBQ.B	#1,D6
		BNE.B	.Pass1_09
		RTS	
.Pass1_10	MOVE.B	#1,D2
		BRA.B	.Pass1_12
.Pass1_11	MOVE.B	(A1)+,D2
.Pass1_12	MOVE.B	(A1)+,D3
.Pass1_13	CMP.L	A2,A4		* buffer overflow ?
		BEQ.B	.DecrErr
		MOVE.B	D3,(A2)+
		ADD.B	D2,D3
		DBRA	D0,.Pass1_13
		RTS	
.Pass1_14	LSL.W	#8,D0
		MOVE.B	(A1)+,D0
.Pass1_15	CMP.L	A2,A4		* buffer overflow ?
		BEQ.B	.DecrErr
		MOVE.B	(A1)+,(A2)+
		DBRA	D0,.Pass1_15
		RTS

*************************************************************************
*	decrunch routine - copied from file (a bit modified)		*
*************************************************************************

* A4 - destination end (for test)
* A2 - destination
* A1 - source
* uses D0,D1,D2,D6,D7,A0,A1,A2,A3

DecrunchPass2	LEA	.Pass2_07(PC),A3
		CLR.L	D6
		CLR.L	D7
.Pass2_01	CLR.L	D0
		CLR.L	D1
		BSR.W	.Pass2_26
		BCLR	#3,D0
		BNE.B	.Pass2_06
		BCLR	#2,D0
		BNE.B	.Pass2_02
		BSR.B	.Pass2_16
		CLR.L	D1
		TST.W	D0
		BNE.W	.Pass2_33

		SUBA.L	xfdbi_TargetBuffer(A5),A2
		MOVE.L	A2,D0
		RTS

.DecrErr	CLR.L	D0
		RTS

.Pass2_02	MOVE.W	D0,D1
.Pass2_03	BSR.W	.Pass2_24
		CMP.L	A2,A4		* buffer overflow ?
		BEQ.B	.DecrErr
		MOVE.B	D0,(A2)+
		DBRA	D1,.Pass2_03
		BRA.B	.Pass2_01
.Pass2_04	LSL.W	#8,D0
		BSR.B	.Pass2_24
.Pass2_05	ADDQ.W	#4,D0
		BRA.B	.Pass2_02
.Pass2_06	MOVE.B	D0,D1
		BSR.W	.Pass2_26
		LSL.B	#1,D1
		JMP	(A3,D1.W)
.Pass2_07	BRA.B	.Pass2_05
		BRA.B	.Pass2_04
		BRA.B	.Pass2_23
		BRA.B	.Pass2_10
		BRA.B	.Pass2_20
		BRA.B	.Pass2_21
		BRA.B	.Pass2_22
		BCLR	#3,D0
		BEQ.B	.Pass2_08
		MOVEQ	#1,D1
		BRA.B	.Pass2_09
.Pass2_08	MOVEQ	#2,D1
.Pass2_09	BSR.B	.Pass2_16
		BRA.B	.Pass2_19
.Pass2_10	BCLR	#3,D0
		BEQ.B	.Pass2_13
		BCLR	#2,D0
		BEQ.B	.Pass2_11
		MOVEQ	#3,D1
		BRA.B	.Pass2_12
.Pass2_11	MOVEQ	#2,D1
.Pass2_12	BSR.B	.Pass2_14
		BRA.B	.Pass2_19
.Pass2_13	BCLR	#2,D0
		BNE.B	.Pass2_18
		BSR.B	.Pass2_16
		BRA.B	.Pass2_29
.Pass2_14	LSL.W	#8,D0
.Pass2_15	BSR.B	.Pass2_24
.Pass2_16	LSL.L	#8,D0
		BSR.B	.Pass2_24
		RTS	
.Pass2_18	BSR.B	.Pass2_16
		ADDI.W	#$0800,D0
		MOVEQ	#1,D1
.Pass2_19	BRA.B	.Pass2_33
.Pass2_20	MOVE.B	D0,D1
		BSR.B	.Pass2_15
		BRA.B	.Pass2_32
.Pass2_21	BSR.B	.Pass2_16
		BRA.B	.Pass2_30
.Pass2_22	MOVE.B	D0,D1
		BSR.B	.Pass2_24
		BRA.B	.Pass2_32
.Pass2_23	BRA.B	.Pass2_28
.Pass2_24	TST.B	D7
		BNE.B	.Pass2_25
		MOVE.B	(A1)+,D0
		RTS	
.Pass2_25	MOVE.B	D6,D0
		LSL.B	#4,D0
		MOVE.B	(A1)+,D6
		MOVE.B	D6,D5
		LSR.B	#4,D5
		OR.B	D5,D0
		ANDI.B	#$000F,D6
		RTS	
.Pass2_26	TST.B	D7
		BNE.B	.Pass2_27
		MOVEQ	#1,D7
		MOVE.B	(A1)+,D6
		MOVE.B	D6,D0
		ANDI.B	#$000F,D6
		LSR.B	#4,D0
		RTS	
.Pass2_27	CLR.L	D7
		MOVE.B	D6,D0
		RTS	
.Pass2_28	BSR.B	.Pass2_14
		BCLR	#$0013,D0
		BEQ.B	.Pass2_30
.Pass2_29	MOVE.L	D0,D2
		BSR.B	.Pass2_15
		BRA.B	.Pass2_31
.Pass2_30	MOVE.L	D0,D2
		CLR.L	D0
		BSR.B	.Pass2_24
.Pass2_31	MOVE.W	D0,D1
		MOVE.L	D2,D0
.Pass2_32	ADDQ.L	#1,D1
.Pass2_33	MOVEA.L	A2,A0
		SUBA.L	D0,A0
		ADDQ.W	#1,D1
.Pass2_34	CMP.L	A2,A4		* buffer overflow ?
		BEQ.W	.DecrErr
		MOVE.B	(A0)+,(A2)+
		DBRA	D1,.Pass2_34
		BRA.W	.Pass2_01

*************************************************************************
*	decrunch routine - copied from file (a bit modified)		*
*************************************************************************

* A4 - destination end (for test)
* A2 - destination
* A1 - source
* D2 - source buffer end
* uses D0,D1.W,D2,D4.B,A0,A1,A2,A3

DecrunchPass3	MOVEQ	#$E,D0
		MOVE.B	#$80,D4
		LEA	$100(A1),A6
		MOVEA.L	A6,A0
		ADDA.L	D0,A0
		MOVE.L	A0,A3
		ADDA.L	D0,A3
.Pass3_01	CLR.L	D0
		MOVE.W	#$00FF,D1
.Pass3_02	ADDQ.B	#1,D1
		LSL.B	#1,D4
		BNE.B	.Pass3_04
		MOVE.B	(A3)+,D4
		BNE.B	.Pass3_03
		CMPA.L	D2,A3		* reached end
		BCC.B	.ok
.Pass3_03	ROXL.B	#1,D4
.Pass3_04	ROXL.B	#1,D0
		CMP.B	(A6,D1.W),D0
		BCS.B	.Pass3_02
		ADD.B	(A0,D1.W),D0
		CMP.L	A2,A4		* buffer overflow ?
		BEQ.B	.DecrErr
		MOVE.B	(A1,D0.W),(A2)+
		BRA.B	.Pass3_01

.DecrErr	CLR.L	D0
		RTS

.ok		SUBA.L	xfdbi_TargetBuffer(A5),A2
		MOVE.L	A2,D0
		RTS

		END
