
	section	ddp,code_c

doio     = -456

boot:	dc.b	"DOS",0
	dc.l	0
	dc.l	880
go:	bra.s	go2
	dc.b	"TK01"
go2:
	movem.l	d0-d7/a0-a6,-(a7)

	move.w	#0,d7

claim:	move.l	4,a6
	move.l	#320*1000,d0
	move.l	#$10001,d1
	jsr	-198(a6)			; alloc
	move.l	d0,$80
	add.l	#1,d7
	cmp.l	#50,d7
	beq	halfmeg
	cmp.l	#$80000,d0
	blt	claim

	movem.l	(a7)+,d0-d7/a0-a6

	move.w	#2,28(a1)		; 28 = command
	move.l	#$10000,36(a1)		; 36 = length
	move.l	#$30000,40(a1)		; 40 = data
	move.l	#$c0000,44(a1)		; 44 = disk address
	jsr	doio(a6)

	move.w	#$7fff,$dff096
	move.w	#$7fff,$dff09a

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

	move.w	#$fff,d0
.loop1	cmp.b	#$2c,$dff006
	bne	.loop1
.loop2	cmp.b	#$40,$dff006
	bne	.loop2
.loop3	cmp.b	#$1c,$dff006
	bne	.loop3

	move.w	d0,$dff180

.loop4	cmp.b	#$3c,$dff006
	bne	.loop4

	sub.w	#$111,d0
	bpl	.loop1	

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

	move.l	$80,d0
	and.l	#$fff80000,d0
	move.l	d0,$80
	add.l	#250*1000,d0
	move.l	d0,$84

	move.l	$80,d2
	add.l	#$80000,d2

	move.l	#$30000,a0
	move.l	6(a0),d1
	add.l	d0,d1			; calc end
	cmp.l	d2,d1
	bge	Error
		
	move.l	$84,a1
	bsr	NormalDecrunch

	move.l	$84,a0
	lea	start(pc),a1
	move.l	a1,$88
	trap	#2

start:	move.l	$80,d2
	add.l	#$80000,d2
	move.l	d2,a7

	jmp	(a0)	
	
Error:
halfmeg:
	move.w	$dff006,$dff180
	bra	halfmeg

	********************************
	
***------------------------------------------------------------------------
*** This is the ultimate Data-Decrunch-Routine
*** for Crunch-Mania V1.4
*** (c) 1991 by FRESH THRASH of CERBERUS, all rights reserved
*** You may use this piece of code as long as you don't claim that
*** you have written it. In any case the author (me) has to be
*** mentioned someplace in your proggy.
*** Note: Source- and Destinationaddresses have to be always even Addresses
***------------------------------------------------------------------------
*** Here is the Format of the Header:
*** Type  Offset  Contents                   Function
*** LONG  0       "CrM!"                     to recongnize crunched files
*** WORD  4       Minimum Security Distance  to savely decrunch data when
***					     Source and Dest is in the same
***					     Memoryblock
*** LONG  6       Original Len               Datalen before packing
*** LONG  10 ($a) Crunched Len               Datalen after packing without
***					     Header
***------------------------------------------------------------------------
** Jump here to decrunch some data with overlap check
** You need some Memory directly in front of the Destination Area
** which has to be as large as the MinSecDist
** Load the Regs with:
** a0: Adr of Source (with Header)	** a1: Adr of Dest
**---------------------------------------------------------------
OverlapDecrunch:
	movem.l	d0-d7/a0-a6,-(sp)
	cmp.l	#"CrM!",(a0)+
	bne.s	.NotCrunched
	moveq	#0,d0
	move.w	(a0)+,d0	;MinSecDist
	move.l	(a0)+,d1	;DestLen
	move.l	(a0)+,d2	;SrcLen
	lea	0(a0,d0.l),a2
	cmp.l	a1,a2
	ble.s	.NoCopy
	move.l	a0,a2
	move.l	a1,a0
	sub.l	d0,a0		;MinSecDist abziehen
	move.l	a0,a3
	move.l	d2,d7
	lsr.l	#2,d7		;Longs
.CopyLoop:
	move.l	(a2)+,(a3)+
	subq.l	#1,d7
	bne.s	.CopyLoop
	move.l	(a2)+,(a3)+	;in case of ...
.NoCopy:
	move.l	a0,a2
	bsr.s	FastDecruncher
.NotCrunched:
	movem.l	(sp)+,d0-d7/a0-a6
	rts
**-----------------------------------------------------------
** Jump here to decrunch some data without any overlap checks
** The Regs have to loaded with:
** a0: Adr of Source (with Header)
** a1: Adr of Dest
**-----------------------------------------------------------
NormalDecrunch:
	movem.l	d0-d7/a0-a6,-(sp)
	cmp.l	#"CrM!",(a0)+
	bne.s	.NotCrunched
	tst.w	(a0)+		;skip MinSecDist
	move.l	(a0)+,d1	;OrgLen
	move.l	(a0)+,d2	;CrLen
	move.l	a0,a2
	bsr.s	FastDecruncher
.NotCrunched:
	movem.l	(sp)+,d0-d7/a0-a6
	rts
**-------------------------------------------------------------------
** This is the pure Decrunch-Routine
** The Registers have to be loaded with the following values:
** a1: Adr of Destination (normal)	** a2: Adr of Source (packed)
** d1: Len of Destination		** d2: Len of Source
**-------------------------------------------------------------------
FastDecruncher:
	move.l	a1,a5			;Decrunched Anfang (hier Ende des Decrunchens)
	add.l	d1,a1
	add.l	d2,a2
	move.w	-(a2),d0		;Anz Bits in letztem Wort
	move.l	-(a2),d6		;1.LW
	moveq	#16,d7			;Anz Bits
	sub.w	d0,d7			;Anz Bits, die rotiert werden müssen
	lsr.l	d7,d6			;1.Bits an Anfang bringen
	move.w	d0,d7			;Anz Bits, die noch im Wort sind
	moveq	#16,d3
	moveq	#0,d4
.DecrLoop:
	cmp.l	a5,a1
	ble	.DecrEnd			;a1=a5: fertig (a1<a5: eigentlich Fehler)

	bsr.w	.BitTest
	bcc.s	.InsertSeq		;1.Bit 0: Sequenz
	moveq	#0,d4
** einzelne Bytes einfügen **
.InsertBytes:
	moveq	#8,d1
	bsr.w	.GetBits
	move.b	d0,-(a1)
	dbf	d4,.InsertBytes
	bra.s	.DecrLoop
*------------
.SpecialInsert:
	moveq	#14,d4
	moveq	#5,d1
	bsr.s	.BitTest
	bcs.s	.IB1
	moveq	#14,d1
.IB1:	bsr.s	.GetBits
	add.w	d0,d4
	bra.s	.InsertBytes
*------------
.InsertSeq:
** Anzahl der gleichen Bits holen **
	bsr.s	.BitTest
	bcs.s	.AB1
	moveq	#1,d1			;Maske: 0 (1 AB)
	moveq	#1,d4			;normal: Summe 1
	bra.s	.ABGet
.AB1:
	bsr.s	.BitTest
	bcs.s	.AB2
	moveq	#2,d1			;Maske: 01 (2 ABs)
	moveq	#3,d4			;ab hier: Summe mindestens 3
	bra.s	.ABGet
.AB2:
	bsr.s	.BitTest
	bcs.s	.AB3
	moveq	#4,d1			;Maske: 011 (4 ABs)
	moveq	#7,d4			;hier: Summe 11
	bra.s	.ABGet
.AB3:
	moveq	#8,d1			;Maske: 111 (8 ABs)
	moveq	#$17,d4			;hier: Summe 11
.ABGet:
	bsr.s	.GetBits
	add.w	d0,d4			;d0: Länge der Sequenz - 1
	cmp.w	#22,d4
	beq.s	.SpecialInsert
	blt.s	.Cont
	subq.w	#1,d4
.Cont:
** SequenzAnbstand holen **
	bsr.s	.BitTest
	bcs.s	.DB1
	moveq	#9,d1			;Maske: 0 (9 DBs)
	moveq	#$20,d2
	bra.s	.DBGet
.DB1:
	bsr.s	.BitTest
	bcs.s	.DB2
	moveq	#5,d1			;Maske: 01 (5 DBs)
	moveq	#0,d2
	bra.s	.DBGet
.DB2:
	moveq	#14,d1			;Maske: 11 (12 DBs)
	move.w	#$220,d2
.DBGet:
	
	;move.w	d4,$dff180
	
	bsr.s	.GetBits
	add.w	d2,d0
	lea	0(a1,d0.w),a3		;a3 auf Anf zu kopierender Seq setzten
.InsSeqLoop:
	move.b	-(a3),-(a1)		;Byte kopieren
	dbf	d4,.InsSeqLoop

	bra.w	.DecrLoop
*------------
.BitTest:
	subq.w	#1,d7
	bne.s	.BTNoLoop
	moveq	#16,d7			;hier kein add notwendig: d7 vorher 0
	move.w	d6,d0
	lsr.l	#1,d6			;Bit rausschieben und Flags setzen
	swap	d6			;ror.l	#16,d6
	move.w	-(a2),d6		;nächstes Wort holen
	swap	d6			;rol.l	#16,d6
	lsr.w	#1,d0			;Bit rausschieben und Flags setzen
	rts
.BTNoLoop:
	lsr.l	#1,d6			;Bit rausschieben und Flags setzen
	rts
*----------
.GetBits:				;d1:AnzBits->d0:Bits
	move.w	d6,d0			;d6:Akt Wort
	lsr.l	d1,d6			;nächste Bits nach vorne bringen
	sub.w	d1,d7			;d7:Anz Bits, die noch im Wort sind
	bgt.s	.GBNoLoop
;	add.w	#16,d7			;BitCounter korrigieren
	add.w	d3,d7			;BitCounter korrigieren
	ror.l	d7,d6			;restliche Bits re rausschieben
	move.w	-(a2),d6		;nächstes Wort holen
	rol.l	d7,d6			;und zurückrotieren
.GBNoLoop:
	add.w	d1,d1			;*2 (in Tab sind Ws)
	and.w	.AndData-2(pc,d1.w),d0	;unerwünschte Bits rausschmeißen
	rts
*----------
.AndData:
	dc.w	%1,%11,%111,%1111,%11111,%111111,%1111111
	dc.w	%11111111,%111111111,%1111111111
	dc.w	%11111111111,%111111111111
	dc.w	%1111111111111,%11111111111111
*-----------
.DecrEnd:
	rts		;a5: Start of decrunched Data
	

	dcb.b	2000,0


