	Section	Demo,Code_C

	Opt	C-,O+,w-


headspeed	= 3	
time		= 716*headspeed
load		= 14			; trap number to nondos load
	
Start:	
	move.l	$80,a0
	move.l	a0,volumespace	
	add.l	#$18000,a0
	move.l	a0,my_mem

	lea	loadtracks(pc),a0
	move.l	a0,$80+(4*load)

	lea	$dff000,a5		; hardware base address

	Move.w	$1c(a5),OldInt		; Save Old Interupts
	Move.w	$02(a5),OldDma		; Save Old DMA

	Move.w	#$7fff,$9a(a5)		; Clear DMA
	Move.w	#$7fff,$96(a5)		; Clear Interupts
	Move.w	#$7fff,$9c(a5)		; Clear Interupt Requests
	
	Move.l	$6c.w,OldV3		; save level 3 int

	Move.l	#my_level3,$6c.w		; put new copper interupt
	Move.l	#my_copper,$80(a5) 	; Address of copper 1

	Move.w	#$e010,$9a(a5)		; Start interupts
	Move.w	#$83df,$96(a5)		; Start DMA
	Move.w	#1,$88(a5)		; Strobe for copper start

	MOVE.L	#1773447,D7 ; PAL
	move.l	d7,timervalue	
	divu	#125,D7 		; Default to normal 50 Hz timer
	move.w	d7,ciatime
	move.l	$78,old
	move.l	#l6int,$78
	move.b	#$7f,$bfdd00
	move.b	#%00010001,$bfde00	; cra
	move.b	#%10000001,$bfdd00	; icr
	move.b	ciatime+0,$bfd400
	move.b	ciatime+1,$bfd500

	move.l	#main_screen,iff
	bsr	show_iff

	bsr	loadmodule
	add.l	#20,diskptr

	bsr	mt_init
	st	mt_enable

	move.l	mt_data1,d0
	move.l	mt_data2,d1
	move.l	d0,mt_data2
	move.l	d1,mt_data1

next_module:

	bsr	loadmodule
	add.l	#20,diskptr

.wait	btst	#10,$dff016
	bne	.ok
	
	bsr	mt_music
	
.ok

	btst	#6,$bfe001
	beq	quit
	cmp.w	#-1,songended
	bne	.wait

	sf	mt_enable
	bsr	mt_end
	bsr	mt_init
	st	mt_enable

	move.l	mt_data1,d0
	move.l	mt_data2,d1
	move.l	d0,mt_data2
	move.l	d1,mt_data1

	move.l	diskptr,a6
	cmp.l	#-1,(a6)
	bne	next_module

	move.l	#diskmap,diskptr
	bra	next_module
	
quit:
	lea	$dff000,a5		; hardware base address
	move.l	#0,$80(a5)		; blank copper list
	move.l	#0,$84(a5)		; if gfx lib not open (slayer boot)
	move.w	#0,$180(a5)		; bgc to black
	
	Move.l	OldV3,$6c.w		; restore old l3
	
	bsr	mt_end
	move.l	old,$78

	Lea	GfxLib,a1		; Pointer to Library Text
	move.l	4.w,a6
	jsr	-132(a6)			; forbid
	Move.l	4.w,a6			; Exec
	Moveq.l	#0,d0			; Clear D0
	Jsr	-$228(a6)		; Open Library
	cmp.l	#0,d0
	beq	no_gfx_lib		; if gfx lib not open dont restore copper lib (slayer boot)
	
	Move.l	d0,a1			
	Move.l	$26(a1),$80(a5)		; restore copper 1
	Move.l	$32(a1),$84(a5)		; restore copper 2
no_gfx_lib:

	Move.w	OldInt,d0		; start old interupts
	Or.w	#$8000,d0
	Move.w	d0,$9a(a5)
	Move.w	OldDma,d0		; start old DMA
	Or.w	#$8000,d0
	Move.w	d0,$96(a5)
	Move.b	#$9b,$bfed01		; Start Timers
	Move.l	4.w,a6			; Close Gfx lib
	Jsr	-$19e(a6)
	move.l	4.w,a6
	jsr	-138(a6)			; permit

	move.w	#0,$bfec00		; clear kbd

	Moveq.l	#0,d0			; No errors
	Rts				; Exit


my_level3:
	Movem.l	d0-d7/a0-a6,-(a7)		; New copper
	Move.w	#$10,$dff09c		; Serviced Interupt

Exit:	Movem.l	(a7)+,d0-d7/a0-a6
	Rte				; Return from Interupt

	*********

l6int:	move.w	#$2000,$dff09c
	tst.b	$bfdd00

	move.w	ciatime,ciatime2
	not.w	ciatime2
	move.b	ciatime2+1,$bfe400
	move.b	ciatime2+0,$bfe500

	bsr	mt_music

	rte

RealTempo	dc.w	125
TimerValue	dc.l 	0
ciatime:		dc.l	0
old:		dc.l	0


n_note		EQU	0  ; W
n_cmd		EQU	2  ; W
n_cmdlo		EQU	3  ; B
n_start		EQU	4  ; L
n_length		EQU	8  ; W
n_loopstart	EQU	10 ; L
n_replen		EQU	14 ; W
n_period		EQU	16 ; W
n_finetune	EQU	18 ; B
n_volume		EQU	19 ; B
n_dmabit		EQU	20 ; W
n_toneportdirec	EQU	22 ; B
n_toneportspeed	EQU	23 ; B
n_wantedperiod	EQU	24 ; W
n_vibratocmd	EQU	26 ; B
n_vibratopos	EQU	27 ; B
n_tremolocmd	EQU	28 ; B
n_tremolopos	EQU	29 ; B
n_wavecontrol	EQU	30 ; B
n_glissfunk	EQU	31 ; B
n_sampleoffset	EQU	32 ; B
n_pattpos	EQU	33 ; B
n_loopcount	EQU	34 ; B
n_funkoffset	EQU	35 ; B
n_wavestart	EQU	36 ; L
n_reallength	EQU	40 ; W

mt_init	move.w	#0,songended
	move.l	mt_data1,A0
	MOVE.L	A0,mt_SongDataPtr
	MOVE.L	A0,A1
	LEA	952(A1),A1
	MOVEQ	#127,D0
	MOVEQ	#0,D1
mtloop	MOVE.L	D1,D2
	SUBQ.W	#1,D0
mtloop2	MOVE.B	(A1)+,D1
	CMP.B	D2,D1
	BGT.S	mtloop
	DBRA	D0,mtloop2
	ADDQ.B	#1,D2
			
	LEA	mt_SampleStarts(PC),A1
	ASL.L	#8,D2
	ASL.L	#2,D2
	ADD.L	#1084,D2
	ADD.L	A0,D2
	MOVE.L	D2,A2
	MOVEQ	#30,D0
mtloop3	CLR.L	(A2)
	MOVE.L	A2,(A1)+
	MOVEQ	#0,D1
	MOVE.W	42(A0),D1
	ASL.L	#1,D1
	ADD.L	D1,A2
	ADD.L	#30,A0
	DBRA	D0,mtloop3

	OR.B	#2,$BFE001
	MOVE.B	#6,mt_speed
	CLR.B	mt_counter
	CLR.B	mt_SongPos
	CLR.W	mt_PatternPos
mt_end	SF	mt_Enable
	LEA	$DFF000,A0
	CLR.W	$A8(A0)
	CLR.W	$B8(A0)
	CLR.W	$C8(A0)
	CLR.W	$D8(A0)
	MOVE.W	#$F,$DFF096
	RTS

mt_music
	MOVEM.L	D0-D4/A0-A6,-(SP)
	TST.B	mt_Enable
	BEQ	mt_exit
	ADDQ.B	#1,mt_counter
	MOVE.B	mt_counter(PC),D0
	CMP.B	mt_speed(PC),D0
	BLO.S	mt_NoNewNote
	CLR.B	mt_counter
	TST.B	mt_PattDelTime2
	BEQ.S	mt_GetNewNote
	BSR.S	mt_NoNewAllChannels
	BRA	mt_dskip

mt_NoNewNote
	BSR.S	mt_NoNewAllChannels
	BRA	mt_NoNewPosYet

mt_NoNewAllChannels
	LEA	$DFF0A0,A5
	LEA	mt_chan1temp(PC),A6
	BSR	mt_CheckEfx
	LEA	$DFF0B0,A5
	LEA	mt_chan2temp(PC),A6
	BSR	mt_CheckEfx
	LEA	$DFF0C0,A5
	LEA	mt_chan3temp(PC),A6
	BSR	mt_CheckEfx
	LEA	$DFF0D0,A5
	LEA	mt_chan4temp(PC),A6
	BRA	mt_CheckEfx

mt_GetNewNote
	MOVE.L	mt_SongDataPtr(PC),A0
	LEA	12(A0),A3
	LEA	952(A0),A2	;pattpo
	LEA	1084(A0),A0	;patterndata
	MOVEQ	#0,D0
	MOVEQ	#0,D1
	MOVE.B	mt_SongPos(PC),D0
	MOVE.B	(A2,D0.W),D1
	ASL.L	#8,D1
	ASL.L	#2,D1
	ADD.W	mt_PatternPos(PC),D1
	CLR.W	mt_DMACONtemp

	LEA	$DFF0A0,A5
	LEA	mt_chan1temp(PC),A6
	BSR.S	mt_PlayVoice
	LEA	$DFF0B0,A5
	LEA	mt_chan2temp(PC),A6
	BSR.S	mt_PlayVoice
	LEA	$DFF0C0,A5
	LEA	mt_chan3temp(PC),A6
	BSR.S	mt_PlayVoice
	LEA	$DFF0D0,A5
	LEA	mt_chan4temp(PC),A6
	BSR.S	mt_PlayVoice
	BRA	mt_SetDMA

mt_PlayVoice
	TST.L	(A6)
	BNE.S	mt_plvskip
	BSR	mt_PerNop
mt_plvskip
	MOVE.L	(A0,D1.L),(A6)
	ADDQ.L	#4,D1
	MOVEQ	#0,D2
	MOVE.B	n_cmd(A6),D2
	AND.B	#$F0,D2
	LSR.B	#4,D2
	MOVE.B	(A6),D0
	AND.B	#$F0,D0
	OR.B	D0,D2
	TST.B	D2
	BEQ	mt_SetRegs
	MOVEQ	#0,D3
	LEA	mt_SampleStarts(PC),A1
	MOVE	D2,D4
	SUBQ.L	#1,D2
	ASL.L	#2,D2
	MULU	#30,D4
	MOVE.L	(A1,D2.L),n_start(A6)
	MOVE.W	(A3,D4.L),n_length(A6)
	MOVE.W	(A3,D4.L),n_reallength(A6)
	MOVE.B	2(A3,D4.L),n_finetune(A6)
	MOVE.B	3(A3,D4.L),n_volume(A6)
	MOVE.W	4(A3,D4.L),D3 ; Get repeat
	TST.W	D3
	BEQ.S	mt_NoLoop
	MOVE.L	n_start(A6),D2	; Get start
	ASL.W	#1,D3
	ADD.L	D3,D2		; Add repeat
	MOVE.L	D2,n_loopstart(A6)
	MOVE.L	D2,n_wavestart(A6)
	MOVE.W	4(A3,D4.L),D0	; Get repeat
	ADD.W	6(A3,D4.L),D0	; Add replen
	MOVE.W	D0,n_length(A6)
	MOVE.W	6(A3,D4.L),n_replen(A6)	; Save replen
	MOVEQ	#0,D0
	MOVE.B	n_volume(A6),D0
	MOVE.W	D0,8(A5)	; Set volume
	BRA.S	mt_SetRegs

mt_NoLoop
	MOVE.L	n_start(A6),D2
	ADD.L	D3,D2
	MOVE.L	D2,n_loopstart(A6)
	MOVE.L	D2,n_wavestart(A6)
	MOVE.W	6(A3,D4.L),n_replen(A6)	; Save replen
	MOVEQ	#0,D0
	MOVE.B	n_volume(A6),D0
	MOVE.W	D0,8(A5)	; Set volume
mt_SetRegs
	MOVE.W	(A6),D0
	AND.W	#$0FFF,D0
	BEQ	mt_CheckMoreEfx	; If no note
	MOVE.W	2(A6),D0
	AND.W	#$0FF0,D0
	CMP.W	#$0E50,D0
	BEQ.S	mt_DoSetFineTune
	MOVE.B	2(A6),D0
	AND.B	#$0F,D0
	CMP.B	#3,D0	; TonePortamento
	BEQ.S	mt_ChkTonePorta
	CMP.B	#5,D0
	BEQ.S	mt_ChkTonePorta
	CMP.B	#9,D0	; Sample Offset
	BNE.S	mt_SetPeriod
	BSR	mt_CheckMoreEfx
	BRA.S	mt_SetPeriod

mt_DoSetFineTune
	BSR	mt_SetFineTune
	BRA.S	mt_SetPeriod

mt_ChkTonePorta
	BSR	mt_SetTonePorta
	BRA	mt_CheckMoreEfx

mt_SetPeriod
	MOVEM.L	D0-D1/A0-A1,-(SP)
	MOVE.W	(A6),D1
	AND.W	#$0FFF,D1
	LEA	mt_PeriodTable(PC),A1
	MOVEQ	#0,D0
	MOVEQ	#36,D2
mt_ftuloop
	CMP.W	(A1,D0.W),D1
	BHS.S	mt_ftufound
	ADDQ.L	#2,D0
	DBRA	D2,mt_ftuloop
mt_ftufound
	MOVEQ	#0,D1
	MOVE.B	n_finetune(A6),D1
	MULU	#36*2,D1
	ADD.L	D1,A1
	MOVE.W	(A1,D0.W),n_period(A6)
	MOVEM.L	(SP)+,D0-D1/A0-A1

	MOVE.W	2(A6),D0
	AND.W	#$0FF0,D0
	CMP.W	#$0ED0,D0 ; Notedelay
	BEQ	mt_CheckMoreEfx

	MOVE.W	n_dmabit(A6),$DFF096
	BTST	#2,n_wavecontrol(A6)
	BNE.S	mt_vibnoc
	CLR.B	n_vibratopos(A6)
mt_vibnoc
	BTST	#6,n_wavecontrol(A6)
	BNE.S	mt_trenoc
	CLR.B	n_tremolopos(A6)
mt_trenoc
	MOVE.L	n_start(A6),(A5)	; Set start
	MOVE.W	n_length(A6),4(A5)	; Set length
	MOVE.W	n_period(A6),D0
	MOVE.W	D0,6(A5)		; Set period
	MOVE.W	n_dmabit(A6),D0
	OR.W	D0,mt_DMACONtemp
	BRA	mt_CheckMoreEfx
 
mt_SetDMA
	MOVE.W	#300,D0
mt_WaitDMA
	DBRA	D0,mt_WaitDMA
	MOVE.W	mt_DMACONtemp(PC),D0
	OR.W	#$8000,D0
	MOVE.W	D0,$DFF096
	MOVE.W	#300,D0
mt_WaitDMA2
	DBRA	D0,mt_WaitDMA2

	LEA	$DFF000,A5
	LEA	mt_chan4temp(PC),A6
	MOVE.L	n_loopstart(A6),$D0(A5)
	MOVE.W	n_replen(A6),$D4(A5)
	LEA	mt_chan3temp(PC),A6
	MOVE.L	n_loopstart(A6),$C0(A5)
	MOVE.W	n_replen(A6),$C4(A5)
	LEA	mt_chan2temp(PC),A6
	MOVE.L	n_loopstart(A6),$B0(A5)
	MOVE.W	n_replen(A6),$B4(A5)
	LEA	mt_chan1temp(PC),A6
	MOVE.L	n_loopstart(A6),$A0(A5)
	MOVE.W	n_replen(A6),$A4(A5)

mt_dskip
	ADD.W	#16,mt_PatternPos
	MOVE.B	mt_PattDelTime,D0
	BEQ.S	mt_dskc
	MOVE.B	D0,mt_PattDelTime2
	CLR.B	mt_PattDelTime
mt_dskc	TST.B	mt_PattDelTime2
	BEQ.S	mt_dska
	SUBQ.B	#1,mt_PattDelTime2
	BEQ.S	mt_dska
	SUB.W	#16,mt_PatternPos
mt_dska	TST.B	mt_PBreakFlag
	BEQ.S	mt_nnpysk
	SF	mt_PBreakFlag
	MOVEQ	#0,D0
	MOVE.B	mt_PBreakPos(PC),D0
	CLR.B	mt_PBreakPos
	LSL.W	#4,D0
	MOVE.W	D0,mt_PatternPos
mt_nnpysk
	CMP.W	#1024,mt_PatternPos
	BLO.S	mt_NoNewPosYet
mt_NextPosition	
	MOVEQ	#0,D0
	MOVE.B	mt_PBreakPos(PC),D0
	LSL.W	#4,D0
	MOVE.W	D0,mt_PatternPos
	CLR.B	mt_PBreakPos
	CLR.B	mt_PosJumpFlag
	ADDQ.B	#1,mt_SongPos
	AND.B	#$7F,mt_SongPos
	MOVE.B	mt_SongPos(PC),D1
	MOVE.L	mt_SongDataPtr(PC),A0
	CMP.B	950(A0),D1
	BLO.S	mt_NoNewPosYet
	CLR.B	mt_SongPos
	move.w	#-1,songended
mt_NoNewPosYet	
	TST.B	mt_PosJumpFlag
	BNE.S	mt_NextPosition
mt_exit	MOVEM.L	(SP)+,D0-D4/A0-A6
	RTS

mt_CheckEfx
	BSR	mt_UpdateFunk
	MOVE.W	n_cmd(A6),D0
	AND.W	#$0FFF,D0
	BEQ.S	mt_PerNop
	MOVE.B	n_cmd(A6),D0
	AND.B	#$0F,D0
	BEQ.S	mt_Arpeggio
	CMP.B	#1,D0
	BEQ	mt_PortaUp
	CMP.B	#2,D0
	BEQ	mt_PortaDown
	CMP.B	#3,D0
	BEQ	mt_TonePortamento
	CMP.B	#4,D0
	BEQ	mt_Vibrato
	CMP.B	#5,D0
	BEQ	mt_TonePlusVolSlide
	CMP.B	#6,D0
	BEQ	mt_VibratoPlusVolSlide
	CMP.B	#$E,D0
	BEQ	mt_E_Commands
SetBack	MOVE.W	n_period(A6),6(A5)
	CMP.B	#7,D0
	BEQ	mt_Tremolo
	CMP.B	#$A,D0
	BEQ	mt_VolumeSlide
mt_Return
	RTS

mt_PerNop
	MOVE.W	n_period(A6),6(A5)
	RTS

mt_Arpeggio
	MOVEQ	#0,D0
	MOVE.B	mt_counter(PC),D0
	DIVS	#3,D0
	SWAP	D0
	CMP.W	#0,D0
	BEQ.S	mt_Arpeggio2
	CMP.W	#2,D0
	BEQ.S	mt_Arpeggio1
	MOVEQ	#0,D0
	MOVE.B	n_cmdlo(A6),D0
	LSR.B	#4,D0
	BRA.S	mt_Arpeggio3

mt_Arpeggio1
	MOVEQ	#0,D0
	MOVE.B	n_cmdlo(A6),D0
	AND.B	#15,D0
	BRA.S	mt_Arpeggio3

mt_Arpeggio2
	MOVE.W	n_period(A6),D2
	BRA.S	mt_Arpeggio4

mt_Arpeggio3
	ASL.W	#1,D0
	MOVEQ	#0,D1
	MOVE.B	n_finetune(A6),D1
	MULU	#36*2,D1
	LEA	mt_PeriodTable(PC),A0
	ADD.L	D1,A0
	MOVEQ	#0,D1
	MOVE.W	n_period(A6),D1
	MOVEQ	#36,D3
mt_arploop
	MOVE.W	(A0,D0.W),D2
	CMP.W	(A0),D1
	BHS.S	mt_Arpeggio4
	ADDQ.L	#2,A0
	DBRA	D3,mt_arploop
	RTS

mt_Arpeggio4
	MOVE.W	D2,6(A5)
	RTS

mt_FinePortaUp
	TST.B	mt_counter
	BNE.S	mt_Return
	MOVE.B	#$0F,mt_LowMask
mt_PortaUp
	MOVEQ	#0,D0
	MOVE.B	n_cmdlo(A6),D0
	AND.B	mt_LowMask(PC),D0
	MOVE.B	#$FF,mt_LowMask
	SUB.W	D0,n_period(A6)
	MOVE.W	n_period(A6),D0
	AND.W	#$0FFF,D0
	CMP.W	#113,D0
	BPL.S	mt_PortaUskip
	AND.W	#$F000,n_period(A6)
	OR.W	#113,n_period(A6)
mt_PortaUskip
	MOVE.W	n_period(A6),D0
	AND.W	#$0FFF,D0
	MOVE.W	D0,6(A5)
	RTS	
 
mt_FinePortaDown
	TST.B	mt_counter
	BNE	mt_Return
	MOVE.B	#$0F,mt_LowMask
mt_PortaDown
	CLR.W	D0
	MOVE.B	n_cmdlo(A6),D0
	AND.B	mt_LowMask(PC),D0
	MOVE.B	#$FF,mt_LowMask
	ADD.W	D0,n_period(A6)
	MOVE.W	n_period(A6),D0
	AND.W	#$0FFF,D0
	CMP.W	#856,D0
	BMI.S	mt_PortaDskip
	AND.W	#$F000,n_period(A6)
	OR.W	#856,n_period(A6)
mt_PortaDskip
	MOVE.W	n_period(A6),D0
	AND.W	#$0FFF,D0
	MOVE.W	D0,6(A5)
	RTS

mt_SetTonePorta
	MOVE.L	A0,-(SP)
	MOVE.W	(A6),D2
	AND.W	#$0FFF,D2
	MOVEQ	#0,D0
	MOVE.B	n_finetune(A6),D0
	MULU	#37*2,D0
	LEA	mt_PeriodTable(PC),A0
	ADD.L	D0,A0
	MOVEQ	#0,D0
mt_StpLoop
	CMP.W	(A0,D0.W),D2
	BHS.S	mt_StpFound
	ADDQ.W	#2,D0
	CMP.W	#37*2,D0
	BLO.S	mt_StpLoop
	MOVEQ	#35*2,D0
mt_StpFound
	MOVE.B	n_finetune(A6),D2
	AND.B	#8,D2
	BEQ.S	mt_StpGoss
	TST.W	D0
	BEQ.S	mt_StpGoss
	SUBQ.W	#2,D0
mt_StpGoss
	MOVE.W	(A0,D0.W),D2
	MOVE.L	(SP)+,A0
	MOVE.W	D2,n_wantedperiod(A6)
	MOVE.W	n_period(A6),D0
	CLR.B	n_toneportdirec(A6)
	CMP.W	D0,D2
	BEQ.S	mt_ClearTonePorta
	BGE	mt_Return
	MOVE.B	#1,n_toneportdirec(A6)
	RTS

mt_ClearTonePorta
	CLR.W	n_wantedperiod(A6)
	RTS

mt_TonePortamento
	MOVE.B	n_cmdlo(A6),D0
	BEQ.S	mt_TonePortNoChange
	MOVE.B	D0,n_toneportspeed(A6)
	CLR.B	n_cmdlo(A6)
mt_TonePortNoChange
	TST.W	n_wantedperiod(A6)
	BEQ	mt_Return
	MOVEQ	#0,D0
	MOVE.B	n_toneportspeed(A6),D0
	TST.B	n_toneportdirec(A6)
	BNE.S	mt_TonePortaUp
mt_TonePortaDown
	ADD.W	D0,n_period(A6)
	MOVE.W	n_wantedperiod(A6),D0
	CMP.W	n_period(A6),D0
	BGT.S	mt_TonePortaSetPer
	MOVE.W	n_wantedperiod(A6),n_period(A6)
	CLR.W	n_wantedperiod(A6)
	BRA.S	mt_TonePortaSetPer

mt_TonePortaUp
	SUB.W	D0,n_period(A6)
	MOVE.W	n_wantedperiod(A6),D0
	CMP.W	n_period(A6),D0
	BLT.S	mt_TonePortaSetPer
	MOVE.W	n_wantedperiod(A6),n_period(A6)
	CLR.W	n_wantedperiod(A6)

mt_TonePortaSetPer
	MOVE.W	n_period(A6),D2
	MOVE.B	n_glissfunk(A6),D0
	AND.B	#$0F,D0
	BEQ.S	mt_GlissSkip
	MOVEQ	#0,D0
	MOVE.B	n_finetune(A6),D0
	MULU	#36*2,D0
	LEA	mt_PeriodTable(PC),A0
	ADD.L	D0,A0
	MOVEQ	#0,D0
mt_GlissLoop
	CMP.W	(A0,D0.W),D2
	BHS.S	mt_GlissFound
	ADDQ.W	#2,D0
	CMP.W	#36*2,D0
	BLO.S	mt_GlissLoop
	MOVEQ	#35*2,D0
mt_GlissFound
	MOVE.W	(A0,D0.W),D2
mt_GlissSkip
	MOVE.W	D2,6(A5) ; Set period
	RTS

mt_Vibrato
	MOVE.B	n_cmdlo(A6),D0
	BEQ.S	mt_Vibrato2
	MOVE.B	n_vibratocmd(A6),D2
	AND.B	#$0F,D0
	BEQ.S	mt_vibskip
	AND.B	#$F0,D2
	OR.B	D0,D2
mt_vibskip
	MOVE.B	n_cmdlo(A6),D0
	AND.B	#$F0,D0
	BEQ.S	mt_vibskip2
	AND.B	#$0F,D2
	OR.B	D0,D2
mt_vibskip2
	MOVE.B	D2,n_vibratocmd(A6)
mt_Vibrato2
	MOVE.B	n_vibratopos(A6),D0
	LEA	mt_VibratoTable(PC),A4
	LSR.W	#2,D0
	AND.W	#$001F,D0
	MOVEQ	#0,D2
	MOVE.B	n_wavecontrol(A6),D2
	AND.B	#$03,D2
	BEQ.S	mt_vib_sine
	LSL.B	#3,D0
	CMP.B	#1,D2
	BEQ.S	mt_vib_rampdown
	MOVE.B	#255,D2
	BRA.S	mt_vib_set
mt_vib_rampdown
	TST.B	n_vibratopos(A6)
	BPL.S	mt_vib_rampdown2
	MOVE.B	#255,D2
	SUB.B	D0,D2
	BRA.S	mt_vib_set
mt_vib_rampdown2
	MOVE.B	D0,D2
	BRA.S	mt_vib_set
mt_vib_sine
	MOVE.B	(A4,D0.W),D2
mt_vib_set
	MOVE.B	n_vibratocmd(A6),D0
	AND.W	#15,D0
	MULU	D0,D2
	LSR.W	#7,D2
	MOVE.W	n_period(A6),D0
	TST.B	n_vibratopos(A6)
	BMI.S	mt_VibratoNeg
	ADD.W	D2,D0
	BRA.S	mt_Vibrato3
mt_VibratoNeg
	SUB.W	D2,D0
mt_Vibrato3
	MOVE.W	D0,6(A5)
	MOVE.B	n_vibratocmd(A6),D0
	LSR.W	#2,D0
	AND.W	#$003C,D0
	ADD.B	D0,n_vibratopos(A6)
	RTS

mt_TonePlusVolSlide
	BSR	mt_TonePortNoChange
	BRA	mt_VolumeSlide

mt_VibratoPlusVolSlide
	BSR.S	mt_Vibrato2
	BRA	mt_VolumeSlide

mt_Tremolo
	MOVE.B	n_cmdlo(A6),D0
	BEQ.S	mt_Tremolo2
	MOVE.B	n_tremolocmd(A6),D2
	AND.B	#$0F,D0
	BEQ.S	mt_treskip
	AND.B	#$F0,D2
	OR.B	D0,D2
mt_treskip
	MOVE.B	n_cmdlo(A6),D0
	AND.B	#$F0,D0
	BEQ.S	mt_treskip2
	AND.B	#$0F,D2
	OR.B	D0,D2
mt_treskip2
	MOVE.B	D2,n_tremolocmd(A6)
mt_Tremolo2
	MOVE.B	n_tremolopos(A6),D0
	LEA	mt_VibratoTable(PC),A4
	LSR.W	#2,D0
	AND.W	#$001F,D0
	MOVEQ	#0,D2
	MOVE.B	n_wavecontrol(A6),D2
	LSR.B	#4,D2
	AND.B	#$03,D2
	BEQ.S	mt_tre_sine
	LSL.B	#3,D0
	CMP.B	#1,D2
	BEQ.S	mt_tre_rampdown
	MOVE.B	#255,D2
	BRA.S	mt_tre_set
mt_tre_rampdown
	TST.B	n_vibratopos(A6)
	BPL.S	mt_tre_rampdown2
	MOVE.B	#255,D2
	SUB.B	D0,D2
	BRA.S	mt_tre_set
mt_tre_rampdown2
	MOVE.B	D0,D2
	BRA.S	mt_tre_set
mt_tre_sine
	MOVE.B	(A4,D0.W),D2
mt_tre_set
	MOVE.B	n_tremolocmd(A6),D0
	AND.W	#15,D0
	MULU	D0,D2
	LSR.W	#6,D2
	MOVEQ	#0,D0
	MOVE.B	n_volume(A6),D0
	TST.B	n_tremolopos(A6)
	BMI.S	mt_TremoloNeg
	ADD.W	D2,D0
	BRA.S	mt_Tremolo3
mt_TremoloNeg
	SUB.W	D2,D0
mt_Tremolo3
	BPL.S	mt_TremoloSkip
	CLR.W	D0
mt_TremoloSkip
	CMP.W	#$40,D0
	BLS.S	mt_TremoloOk
	MOVE.W	#$40,D0
mt_TremoloOk
	MOVE.W	D0,8(A5)
	MOVE.B	n_tremolocmd(A6),D0
	LSR.W	#2,D0
	AND.W	#$003C,D0
	ADD.B	D0,n_tremolopos(A6)
	RTS

mt_SampleOffset
	MOVEQ	#0,D0
	MOVE.B	n_cmdlo(A6),D0
	BEQ.S	mt_sononew
	MOVE.B	D0,n_sampleoffset(A6)
mt_sononew
	MOVE.B	n_sampleoffset(A6),D0
	LSL.W	#7,D0
	CMP.W	n_length(A6),D0
	BGE.S	mt_sofskip
	SUB.W	D0,n_length(A6)
	LSL.W	#1,D0
	ADD.L	D0,n_start(A6)
	RTS
mt_sofskip
	MOVE.W	#$0001,n_length(A6)
	RTS

mt_VolumeSlide
	MOVEQ	#0,D0
	MOVE.B	n_cmdlo(A6),D0
	LSR.B	#4,D0
	TST.B	D0
	BEQ.S	mt_VolSlideDown
mt_VolSlideUp
	ADD.B	D0,n_volume(A6)
	CMP.B	#$40,n_volume(A6)
	BMI.S	mt_vsuskip
	MOVE.B	#$40,n_volume(A6)
mt_vsuskip
	MOVE.B	n_volume(A6),D0
	MOVE.W	D0,8(A5)
	RTS

mt_VolSlideDown
	MOVEQ	#0,D0
	MOVE.B	n_cmdlo(A6),D0
	AND.B	#$0F,D0
mt_VolSlideDown2
	SUB.B	D0,n_volume(A6)
	BPL.S	mt_vsdskip
	CLR.B	n_volume(A6)
mt_vsdskip
	MOVE.B	n_volume(A6),D0
	MOVE.W	D0,8(A5)
	RTS

mt_PositionJump
	MOVE.B	n_cmdlo(A6),D0
	SUBQ.B	#1,D0
	MOVE.B	D0,mt_SongPos
mt_pj2	CLR.B	mt_PBreakPos
	ST 	mt_PosJumpFlag
	RTS

mt_VolumeChange
	MOVEQ	#0,D0
	MOVE.B	n_cmdlo(A6),D0
	CMP.B	#$40,D0
	BLS.S	mt_VolumeOk
	MOVEQ	#$40,D0
mt_VolumeOk
	MOVE.B	D0,n_volume(A6)
	MOVE.W	D0,8(A5)
	RTS

mt_PatternBreak
	MOVEQ	#0,D0
	MOVE.B	n_cmdlo(A6),D0
	MOVE.L	D0,D2
	LSR.B	#4,D0
	MULU	#10,D0
	AND.B	#$0F,D2
	ADD.B	D2,D0
	CMP.B	#63,D0
	BHI.S	mt_pj2
	MOVE.B	D0,mt_PBreakPos
	ST	mt_PosJumpFlag
	RTS

mt_SetSpeed
	MOVEQ	#0,D0
	MOVE.B	3(A6),D0
	BEQ	mt_end
	CMP.B	#32,D0
	BHS	SetTempo
	CLR.B	mt_counter
	MOVE.B	D0,mt_speed
	RTS

SetTempo:
	CMP.W	#32,D0
	BHS.S	setemsk
	MOVEQ	#32,D0
setemsk	MOVE.W	D0,RealTempo
	MOVE.L	TimerValue(PC),D2
	DIVU	D0,D2
	move.w	d2,ciatime
	
	RTS

mt_CheckMoreEfx
	BSR	mt_UpdateFunk
	MOVE.B	2(A6),D0
	AND.B	#$0F,D0
	CMP.B	#$9,D0
	BEQ	mt_SampleOffset
	CMP.B	#$B,D0
	BEQ	mt_PositionJump
	CMP.B	#$D,D0
	BEQ	mt_PatternBreak
	CMP.B	#$E,D0
	BEQ.S	mt_E_Commands
	CMP.B	#$F,D0
	BEQ	mt_SetSpeed
	CMP.B	#$C,D0
	BEQ	mt_VolumeChange
	BRA	mt_PerNop

mt_E_Commands
	MOVE.B	n_cmdlo(A6),D0
	AND.B	#$F0,D0
	LSR.B	#4,D0
	BEQ.S	mt_FilterOnOff
	CMP.B	#1,D0
	BEQ	mt_FinePortaUp
	CMP.B	#2,D0
	BEQ	mt_FinePortaDown
	CMP.B	#3,D0
	BEQ.S	mt_SetGlissControl
	CMP.B	#4,D0
	BEQ	mt_SetVibratoControl
	CMP.B	#5,D0
	BEQ	mt_SetFineTune
	CMP.B	#6,D0
	BEQ	mt_JumpLoop
	CMP.B	#7,D0
	BEQ	mt_SetTremoloControl
	CMP.B	#9,D0
	BEQ	mt_RetrigNote
	CMP.B	#$A,D0
	BEQ	mt_VolumeFineUp
	CMP.B	#$B,D0
	BEQ	mt_VolumeFineDown
	CMP.B	#$C,D0
	BEQ	mt_NoteCut
	CMP.B	#$D,D0
	BEQ	mt_NoteDelay
	CMP.B	#$E,D0
	BEQ	mt_PatternDelay
	CMP.B	#$F,D0
	BEQ	mt_FunkIt
	RTS

mt_FilterOnOff
	MOVE.B	n_cmdlo(A6),D0
	AND.B	#1,D0
	ASL.B	#1,D0
	AND.B	#$FD,$BFE001
	OR.B	D0,$BFE001
	RTS	

mt_SetGlissControl
	MOVE.B	n_cmdlo(A6),D0
	AND.B	#$0F,D0
	AND.B	#$F0,n_glissfunk(A6)
	OR.B	D0,n_glissfunk(A6)
	RTS

mt_SetVibratoControl
	MOVE.B	n_cmdlo(A6),D0
	AND.B	#$0F,D0
	AND.B	#$F0,n_wavecontrol(A6)
	OR.B	D0,n_wavecontrol(A6)
	RTS

mt_SetFineTune
	MOVE.B	n_cmdlo(A6),D0
	AND.B	#$0F,D0
	MOVE.B	D0,n_finetune(A6)
	RTS

mt_JumpLoop
	TST.B	mt_counter
	BNE	mt_Return
	MOVE.B	n_cmdlo(A6),D0
	AND.B	#$0F,D0
	BEQ.S	mt_SetLoop
	TST.B	n_loopcount(A6)
	BEQ.S	mt_jumpcnt
	SUBQ.B	#1,n_loopcount(A6)
	BEQ	mt_Return
mt_jmploop	MOVE.B	n_pattpos(A6),mt_PBreakPos
	ST	mt_PBreakFlag
	RTS

mt_jumpcnt
	MOVE.B	D0,n_loopcount(A6)
	BRA.S	mt_jmploop

mt_SetLoop
	MOVE.W	mt_PatternPos(PC),D0
	LSR.W	#4,D0
	MOVE.B	D0,n_pattpos(A6)
	RTS

mt_SetTremoloControl
	MOVE.B	n_cmdlo(A6),D0
	AND.B	#$0F,D0
	LSL.B	#4,D0
	AND.B	#$0F,n_wavecontrol(A6)
	OR.B	D0,n_wavecontrol(A6)
	RTS

mt_RetrigNote
	MOVE.L	D1,-(SP)
	MOVEQ	#0,D0
	MOVE.B	n_cmdlo(A6),D0
	AND.B	#$0F,D0
	BEQ.S	mt_rtnend
	MOVEQ	#0,D1
	MOVE.B	mt_counter(PC),D1
	BNE.S	mt_rtnskp
	MOVE.W	(A6),D1
	AND.W	#$0FFF,D1
	BNE.S	mt_rtnend
	MOVEQ	#0,D1
	MOVE.B	mt_counter(PC),D1
mt_rtnskp
	DIVU	D0,D1
	SWAP	D1
	TST.W	D1
	BNE.S	mt_rtnend
mt_DoRetrig
	MOVE.W	n_dmabit(A6),$DFF096	; Channel DMA off
	MOVE.L	n_start(A6),(A5)	; Set sampledata pointer
	MOVE.W	n_length(A6),4(A5)	; Set length
	MOVE.W	#300,D0
mt_rtnloop1
	DBRA	D0,mt_rtnloop1
	MOVE.W	n_dmabit(A6),D0
	BSET	#15,D0
	MOVE.W	D0,$DFF096
	MOVE.W	#300,D0
mt_rtnloop2
	DBRA	D0,mt_rtnloop2
	MOVE.L	n_loopstart(A6),(A5)
	MOVE.L	n_replen(A6),4(A5)
mt_rtnend
	MOVE.L	(SP)+,D1
	RTS

mt_VolumeFineUp
	TST.B	mt_counter
	BNE	mt_Return
	MOVEQ	#0,D0
	MOVE.B	n_cmdlo(A6),D0
	AND.B	#$F,D0
	BRA	mt_VolSlideUp

mt_VolumeFineDown
	TST.B	mt_counter
	BNE	mt_Return
	MOVEQ	#0,D0
	MOVE.B	n_cmdlo(A6),D0
	AND.B	#$0F,D0
	BRA	mt_VolSlideDown2

mt_NoteCut
	MOVEQ	#0,D0
	MOVE.B	n_cmdlo(A6),D0
	AND.B	#$0F,D0
	CMP.B	mt_counter(PC),D0
	BNE	mt_Return
	CLR.B	n_volume(A6)
	MOVE.W	#0,8(A5)
	RTS

mt_NoteDelay
	MOVEQ	#0,D0
	MOVE.B	n_cmdlo(A6),D0
	AND.B	#$0F,D0
	CMP.B	mt_Counter,D0
	BNE	mt_Return
	MOVE.W	(A6),D0
	BEQ	mt_Return
	MOVE.L	D1,-(SP)
	BRA	mt_DoRetrig

mt_PatternDelay
	TST.B	mt_counter
	BNE	mt_Return
	MOVEQ	#0,D0
	MOVE.B	n_cmdlo(A6),D0
	AND.B	#$0F,D0
	TST.B	mt_PattDelTime2
	BNE	mt_Return
	ADDQ.B	#1,D0
	MOVE.B	D0,mt_PattDelTime
	RTS

mt_FunkIt
	TST.B	mt_counter
	BNE	mt_Return
	MOVE.B	n_cmdlo(A6),D0
	AND.B	#$0F,D0
	LSL.B	#4,D0
	AND.B	#$0F,n_glissfunk(A6)
	OR.B	D0,n_glissfunk(A6)
	TST.B	D0
	BEQ	mt_Return
mt_UpdateFunk
	MOVEM.L	A0/D1,-(SP)
	MOVEQ	#0,D0
	MOVE.B	n_glissfunk(A6),D0
	LSR.B	#4,D0
	BEQ.S	mt_funkend
	LEA	mt_FunkTable(PC),A0
	MOVE.B	(A0,D0.W),D0
	ADD.B	D0,n_funkoffset(A6)
	BTST	#7,n_funkoffset(A6)
	BEQ.S	mt_funkend
	CLR.B	n_funkoffset(A6)

	MOVE.L	n_loopstart(A6),D0
	MOVEQ	#0,D1
	MOVE.W	n_replen(A6),D1
	ADD.L	D1,D0
	ADD.L	D1,D0
	MOVE.L	n_wavestart(A6),A0
	ADDQ.L	#1,A0
	CMP.L	D0,A0
	BLO.S	mt_funkok
	MOVE.L	n_loopstart(A6),A0
mt_funkok
	MOVE.L	A0,n_wavestart(A6)
	MOVEQ	#-1,D0
	SUB.B	(A0),D0
	MOVE.B	D0,(A0)
mt_funkend
	MOVEM.L	(SP)+,A0/D1
	RTS


mt_FunkTable dc.b 0,5,6,7,8,10,11,13,16,19,22,26,32,43,64,128

mt_VibratoTable	
	dc.b   0, 24, 49, 74, 97,120,141,161
	dc.b 180,197,212,224,235,244,250,253
	dc.b 255,253,250,244,235,224,212,197
	dc.b 180,161,141,120, 97, 74, 49, 24

mt_PeriodTable
; Tuning 0, Normal
	dc.w	856,808,762,720,678,640,604,570,538,508,480,453
	dc.w	428,404,381,360,339,320,302,285,269,254,240,226
	dc.w	214,202,190,180,170,160,151,143,135,127,120,113
; Tuning 1
	dc.w	850,802,757,715,674,637,601,567,535,505,477,450
	dc.w	425,401,379,357,337,318,300,284,268,253,239,225
	dc.w	213,201,189,179,169,159,150,142,134,126,119,113
; Tuning 2
	dc.w	844,796,752,709,670,632,597,563,532,502,474,447
	dc.w	422,398,376,355,335,316,298,282,266,251,237,224
	dc.w	211,199,188,177,167,158,149,141,133,125,118,112
; Tuning 3
	dc.w	838,791,746,704,665,628,592,559,528,498,470,444
	dc.w	419,395,373,352,332,314,296,280,264,249,235,222
	dc.w	209,198,187,176,166,157,148,140,132,125,118,111
; Tuning 4
	dc.w	832,785,741,699,660,623,588,555,524,495,467,441
	dc.w	416,392,370,350,330,312,294,278,262,247,233,220
	dc.w	208,196,185,175,165,156,147,139,131,124,117,110
; Tuning 5
	dc.w	826,779,736,694,655,619,584,551,520,491,463,437
	dc.w	413,390,368,347,328,309,292,276,260,245,232,219
	dc.w	206,195,184,174,164,155,146,138,130,123,116,109
; Tuning 6
	dc.w	820,774,730,689,651,614,580,547,516,487,460,434
	dc.w	410,387,365,345,325,307,290,274,258,244,230,217
	dc.w	205,193,183,172,163,154,145,137,129,122,115,109
; Tuning 7
	dc.w	814,768,725,684,646,610,575,543,513,484,457,431
	dc.w	407,384,363,342,323,305,288,272,256,242,228,216
	dc.w	204,192,181,171,161,152,144,136,128,121,114,108
; Tuning -8
	dc.w	907,856,808,762,720,678,640,604,570,538,508,480
	dc.w	453,428,404,381,360,339,320,302,285,269,254,240
	dc.w	226,214,202,190,180,170,160,151,143,135,127,120
; Tuning -7
	dc.w	900,850,802,757,715,675,636,601,567,535,505,477
	dc.w	450,425,401,379,357,337,318,300,284,268,253,238
	dc.w	225,212,200,189,179,169,159,150,142,134,126,119
; Tuning -6
	dc.w	894,844,796,752,709,670,632,597,563,532,502,474
	dc.w	447,422,398,376,355,335,316,298,282,266,251,237
	dc.w	223,211,199,188,177,167,158,149,141,133,125,118
; Tuning -5
	dc.w	887,838,791,746,704,665,628,592,559,528,498,470
	dc.w	444,419,395,373,352,332,314,296,280,264,249,235
	dc.w	222,209,198,187,176,166,157,148,140,132,125,118
; Tuning -4
	dc.w	881,832,785,741,699,660,623,588,555,524,494,467
	dc.w	441,416,392,370,350,330,312,294,278,262,247,233
	dc.w	220,208,196,185,175,165,156,147,139,131,123,117
; Tuning -3
	dc.w	875,826,779,736,694,655,619,584,551,520,491,463
	dc.w	437,413,390,368,347,328,309,292,276,260,245,232
	dc.w	219,206,195,184,174,164,155,146,138,130,123,116
; Tuning -2
	dc.w	868,820,774,730,689,651,614,580,547,516,487,460
	dc.w	434,410,387,365,345,325,307,290,274,258,244,230
	dc.w	217,205,193,183,172,163,154,145,137,129,122,115
; Tuning -1
	dc.w	862,814,768,725,684,646,610,575,543,513,484,457
	dc.w	431,407,384,363,342,323,305,288,272,256,242,228
	dc.w	216,203,192,181,171,161,152,144,136,128,121,114

mt_chan1temp	dc.l	0,0,0,0,0,$00010000,0,  0,0,0,0
mt_chan2temp	dc.l	0,0,0,0,0,$00020000,0,  0,0,0,0
mt_chan3temp	dc.l	0,0,0,0,0,$00040000,0,  0,0,0,0
mt_chan4temp	dc.l	0,0,0,0,0,$00080000,0,  0,0,0,0

mt_SampleStarts	dc.l	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
		dc.l	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

mt_SongDataPtr	dc.l 0
mt_speed	dc.b 6
mt_counter	dc.b 0
mt_SongPos	dc.b 0
mt_PBreakPos	dc.b 0
mt_PosJumpFlag	dc.b 0
mt_PBreakFlag	dc.b 0
mt_LowMask	dc.b 0
mt_PattDelTime	dc.b 0
mt_PattDelTime2	dc.b 0
mt_Enable	dc.b 0
mt_PatternPos	dc.w 0
mt_DMACONtemp	dc.w 0
ciatime2:	dc.l	0

;/* End of File */



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


***------------------------------------------------------------------------
*** 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 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:
	move.w	d1,$dff180

	cmp.l	a5,a1
	ble.L	.DecrEnd			;a1=a5: fertig (a1<a5: eigentlich Fehler)

	bsr.s	.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:
	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


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

search_for_disk:
	move.l	d0,looklabel

sfd_loop:
	move.b	#0,drive
	move.l	#1,d7		; check drive for ready
	trap	#load
	cmp.l	looklabel,d0
	beq	found_disk

	move.b	#1,drive
	move.l	#1,d7		; check drive for ready
	trap	#load
	cmp.l	looklabel,d0
	beq	found_disk

	move.b	#2,drive
	move.l	#1,d7		; check drive for ready
	trap	#load
	cmp.l	looklabel,d0
	beq	found_disk

	move.b	#3,drive
	move.l	#1,d7		; check drive for ready
	trap	#load
	cmp.l	looklabel,d0
	beq	found_disk

	;bsr	show_insert_pic
	
	bra	sfd_loop	


found_disk:
	clr.l	d0
	rts

	
get_volume_name:
	move.l	#0,label
	lea	$bfd000,a5
	move.b	#$ff,$100(a5)	; deselect all drives
	bsr	mini_pause
	bclr	#7,$100(a5)	; motor on
	bsr	mini_pause
	move.b	drive,d6
	add.b	#3,d6
	bclr	d6,$100(a5)	; select drive
	bsr	mini_pause
	
	move.w	#600/headspeed,d7
.volloop
	bsr	mspause
	btst	#5,$1001(a5)	; drive ready 
	beq	.is_ready
	dbf	d7,.volloop
.not_ready
	move.b	#$ff,$100(a5)	; deselect all drives
	bsr	mini_pause

	move.b	#$ff,d0
	move.b	drive,d6
	add.b	#3,d6
	bchg	d6,d0
	move.b	d0,$100(a5)	; select drive
	bsr	mini_pause

	move.b	#$ff,$100(a5)	; deselect all drives
	bsr	mini_pause
	
	move.l	#-1,d0
	rte

.is_ready
	move.l	volumespace,a0	; load address
	move.l	#$000000,d0	; disk address (as trackdisk.device)
	move.l	#$400,d1		; length
	move.l	#0,d7		; mfm load
	trap	#load
	move.l	14(a0),label
	move.l	14(a0),d0
	rte

loadtracks:
	cmp.l	#1,d7
	beq	get_volume_name

	movem.l	d0-d7/a1-a6,-(sp)

	move.l	a0,loadaddress
	move.l	d0,diskaddress
	move.l	d1,loadlength
	
	lsr.l	#7,d1
	lsr.l	#2,d1		; div by 512

	divu	#11,d1		; number of tracks
	and.l	#$ffff,d1
	add.w	#1,d1
	cmp.l	#$2c00,loadlength
	blt	.short_load
	add.w	#1,d1
.short_load
	
	lsr.l	#7,d0		
	lsr.l	#2,d0		; div by 512	
	divu	#11,d0
	and.l	#$ffff,d0

	move.w	d0,temp
	
				; d0=track
				; d1=number of tracks
		

	lea	workspace,a4	; workspace
	lea	$bfd000,a5	; base address of cia
	lea	$dff000,a6	; base address of hardware
	move.l	#$55555555,d7	; data mask - for mfm decoding

	move.b	$1f01(a5),d6
	and.b	#%11000000,d6
	or.b	#%00001000,d6
	move.b	d6,$1f01(a5)
	move.b	#%00000010,$1d01(a5)
	move.b	#(time&$ff),$1601(a5)
	move.b	#(time>>8),$1701(a5)

	move.w	#$98d0,d5	; disk length
	move.w	#$4489,a1	; disk sync
	bsr	load2
	
	clr.l	d2
	move.w	temp,d2		; track number
	move.l	loadaddress,a0
	move.l	diskaddress,d0
	move.l	loadlength,d1
	
	mulu	#11,d2
	asl.l	#7,d2
	asl.l	#2,d2
	
	sub.l	d2,d0
	add.l	d0,a0		; a0 = data start address

	movem.l	(sp)+,d0-d7/a1-a6	
	rte

load2:	subq.w	#1,d1
	bmi	mini_pause
	bsr	find_track

read_tracks
	bsr.w	readdata

	move.l	a4,a2
	moveq	#10,d6

find_sync
	cmp.w	(a2)+,a1
	bne.b	find_sync

	cmp.w	(a2),a1
	bne.b	double_sync

	add.l	#2,a2

double_sync
	move.l	(a2),d3
	move.l	4(a2),d4
	and.w	d7,d3
	and.w	d7,d4
	lsl.w	#1,d3
	or.w	d4,d3
	asr.w	#8,d3
	move.l	a0,a3
	lsl.w	#8,d3
	lsl.w	#1,d3
	add.w	d3,a3
	lea	$38(a2),a2

	moveq	#127,d2

decode_mfm	
	move.l	$200(a2),d3
	move.l	(a2)+,d4
	and.l	d7,d3
	and.l	d7,d4
	lsl.l	#1,d4
	or.l	d3,d4
	move.l	d4,(a3)+
	dbf	d2,decode_mfm
	dbf	d6,find_sync

	lea	$1600(a0),a0
	add.b	#1,d0
	bsr	mspause
	bsr.b	flip_side
	bsr	mspause
	dbf	d1,read_tracks

finished_blocks:

	move.b	#$ff,$100(a5)	; deselect all drives
	bsr.b	mini_pause	

	move.b	#$ff,d0
	move.b	drive,d6
	add.b	#3,d6
	bchg	d6,d0
	move.b	d0,$100(a5)	; select drive
	bsr	mini_pause
	
	move.b	#$ff,$100(a5)	; deselect all drives
mini_pause:
	rts	

find_track
	move.b	#$ff,$100(a5)	; deselect all drives
	bsr.b	mini_pause
	
	bclr	#7,$100(a5)	; motor on
	bsr.b	mini_pause	
	
	move.b	drive,d6
	add.b	#3,d6
	bclr	d6,$100(a5)	; select drive 0
	bsr.b	mini_pause
	bsr.b	drive_ready

	bset	#1,$100(a5)	; direction towards outside

	; look for track 0

track_0:
	btst	#4,$1001(a5)	; check for track 0	
	beq.b	side0
	bsr.b	step_heads
	bra.b	track_0

flip_side:
	bchg	#2,$100(a5)	; change side 
	btst	#0,d0
	bne.b	mini_pause

centre:	bclr	#1,$100(a5)	; direction towards centre

step_heads:
	bclr	#0,$100(a5)	; pulse step low
	bsr.b	mini_pause
	bset	#0,$100(a5)	; pulse step high	
	bsr	mspause		; milisecond pause
	rts

side0:	bset	#2,$100(a5)	; side 0
	move.w	d0,d2
	lsr.b	#1,d2
	bcc.b	side1

	bclr	#2,$100(a5)	; side 1

side1:	subq.b	#1,d2
	bmi	mini_pause
	
find_centre:
	bsr.b	centre
	dbf	d2,find_centre
	rts

drive_ready:
	btst	#5,$1001(a5)	; drive ready 
	bne.b	drive_ready
	rts


readdata:
	move.w	#$8500,$9e(a6)	; set bits 8,10 = disk data clock rate 1=fast 
				; word sync to sync ($4489)	
	move.w	a1,$7e(a6)	; set sync to $4489
	bsr	drive_ready

	move.w	#$4000,$24(a6)	; disk length (write disk to ram)
	move.l	a4,$20(a6)	; disk pointer
	move.w	d5,$24(a6)	; disk length($18d0 + set)
	move.w	d5,$24(a6)	; disk length again - must be twice(!!)

	move.w	#2,$9c(a6)	; int req - clear disk blk finished

waitblk:	move.w	$1e(a6),d2	; irq bits read - 
	btst	#1,d2		; disk blk finished
	beq	waitblk
	
	rts

mspause:
	lea	$bfd000,a5	; base address of cia

	move.b	$1f01(a5),d6
	and.b	#%11000000,d6
	or.b	#%00001000,d6
	move.b	d6,$1f01(a5)
	move.b	#%00000010,$1d01(a5)
	move.b	#(time&$ff),$1601(a5)
	move.b	#(time>>8),$1701(a5)

busy_wait:
	btst.b	#1,$1d01(a5)
	beq	busy_wait

	rts

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

loadmodule:	
	move.l	diskptr,a6

	move.l	00(a6),d0
	bsr	search_for_disk

.reloadfile
	move.l	my_mem,a0	; load address
	move.l	04(a6),d0	; disk address
	move.l	08(a6),d1	; length
	move.l	#0,d7		; mfm load
	trap	#load

	movem.l	d1-d7/a0-a6,-(a7)
	
	move.l	08(a6),d1
	lsr.l	#2,d1
	sub.l	#1,d1
	move.l	#0,d0
.loop	move.l	(a0)+,d2
	eor.l	d2,d0
	sub.l	#1,d1
	bpl.s	.loop

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

	cmp.l	16(a6),d0	; checksum
	bne	.reloadfile
	

	move.l	mt_data1,a1
	bsr	NormalDecrunch

	rts

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

show_iff:
	move.w	#$0200,iff_res+2
	
	move.l	iff,a0
	cmp.l	#"FORM",(a0)
	bne	not_iff

	move.l	iff,a0
	move.l	#"BMHD",d0
	bsr	findhunk
	cmp.l	#-1,a0
	beq	not_iff
	
	move.w	08(a0),iff_width
	move.w	10(a0),iff_height
	move.b	16(a0),iff_depth
	move.b	18(a0),iff_compression

	move.w	iff_width,d0
	lsr.w	#3,d0
	move.w	iff_height,d1
	mulu	d0,d1
	move.l	d1,iff_bmpsize
	move.b	iff_depth,d0
	mulu	d0,d1
	move.l	iff_maxsize,d0
	cmp.l	d1,d0
	blt	not_iff	

	move.l	iff,a0
	move.l	#"CMAP",d0
	bsr	findhunk
	cmp.l	#-1,a0
	beq	not_iff
	bsr	decode_iff_cmap	
	
	move.l	iff,a0
	move.l	#"BODY",d0

	lea	screen1,a3

	bsr	findhunk
	cmp.l	#-1,a0
	beq	not_iff
	bsr	iff_body

	lea	iff_cmap,a0
	lea	cmap+2,a1
	move.w	iff_colours,d0
	sub.w	#1,d0
.cmaploop
	move.w	(a0)+,(a1)
	add.l	#4,a1
	dbf	d0,.cmaploop

	move.l	#screen1,d0
	move.l	iff_bmpsize,d1
	
	move.w	d0,bitplane0_lo
	swap	d0
	move.w	d0,bitplane0_hi
	swap	d0
	add.l	d1,d0
	move.w	d0,bitplane1_lo
	swap	d0
	move.w	d0,bitplane1_hi
	swap	d0
	add.l	d1,d0
	move.w	d0,bitplane2_lo
	swap	d0
	move.w	d0,bitplane2_hi
	swap	d0
	add.l	d1,d0
	move.w	d0,bitplane3_lo
	swap	d0
	move.w	d0,bitplane3_hi
	swap	d0
	add.l	d1,d0
	move.w	d0,bitplane4_lo
	swap	d0
	move.w	d0,bitplane4_hi

	moveq	#0,d0
	move.b	iff_depth,d0
	asl.w	#8,d0
	asl.w	#4,d0
	or.w	#$0200,d0
	move.w	d0,iff_res+2

	rts

not_iff:
	move.w	#$fff,$dff180

	rts

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

decode_iff_cmap:
	
	move.l	4(a0),d0
	divu	#3,d0
	move.w	d0,iff_colours

	sub.w	#1,d0
	add.l	#8,a0
	lea	iff_cmap,a1
cmap_loop:		
	moveq	#0,d2
	
	moveq	#0,d1
	move.b	0(a0),d1
	asl.w	#4,d1
	or.w	d1,d2	
	moveq	#0,d1
	move.b	1(a0),d1
	or.w	d1,d2	
	moveq	#0,d1
	move.b	2(a0),d1
	lsr.w	#4,d1
	or.w	d1,d2	

	move.w	d2,(a1)+			; store cmap
	add.l	#3,a0			; next colour
	dbf	d0,cmap_loop	

	rts

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

iff_body:
	moveq	#0,d7
	moveq	#0,d6
	moveq	#0,d5
	move.w	iff_width,d5
	lsr.w	#3,d5

	move.l	a3,a2
	
	lea	8(a0),a1
	add.l	4(a0),a1
	add.l	#8,a0	
	cmp.b	#1,iff_compression
	beq	do_byterun1
	
.err	move.w	$dff006,$dff180
	bra	.err

do_byterun1:
	moveq	#0,d0
	move.b	(a0)+,d0

	cmp.b	#128,d0
	beq	iff_body_end			; 128=nop

	bclr	#7,d0
	beq	iff_not_byterun
	
	moveq	#0,d1
	move.b	(a0)+,d1

	move.w	#128,d2
	sub.w	d0,d2
	move.w	d2,d0
	add.w	d0,d7
	add.w	#1,d7
iff_byterun1
	move.b	d1,(a2)+	
	dbf	d0,iff_byterun1
	bra	iff_body_end
	
iff_not_byterun
	add.w	d0,d7
	add.w	#1,d7
iff_not_byterun2
	move.b	(a0)+,(a2)+	
	dbf	d0,iff_not_byterun2
iff_body_end	
	cmp.w	d5,d7
	bne	.no_end
	
	move.w	#0,d7
	move.l	a3,a2
	move.l	iff_bmpsize,d0
	add.w	#1,d6
	move.l	d6,d1
	mulu	d1,d0
	add.l	d0,a2
	moveq	#0,d0
	move.b	iff_depth,d0
	cmp.w	d6,d0
	bne	.no_end

	moveq	#0,d6
	moveq	#0,d0
	move.w	iff_width,d0
	lsr.w	#3,d0
	add.l	d0,a3
	move.l	a3,a2	

.no_end
	cmp.l	a1,a0
	blt	do_byterun1	
.br1fin	
	rts
	
	*************************************************************
	
findhunk:
	lea	8(a0),a1
	add.l	4(a0),a1
.findloop
	cmp.l	a1,a0
	bge	.cantfind
	add.l	#2,a0
	move.l	(a0),d1
	cmp.l	d0,d1
	bne	.findloop
	rts
.cantfind	
	move.l	#-1,a0
	rts

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

	
my_copper:	
iff_res:		dc.w	$100,$1200	; 4 bp - lo res
		dc.w	$104,$a		; bp control reg
		dc.w	$108,0		; bp modulo - odd
		dc.w	$10a,0		; bp modulo - even
		dc.w	$180,0		; colour 0 to black
		dc.w	$102,0
		
		dc.w	$08e,$2c81	; bp window start left
		dc.w	$090,$2cc1	; bp window bot right
		dc.w	$94,$d0		; bp stop horz
		dc.w	$92,$38

		dc.w	$120,0,$122,0
		dc.w	$124,0,$126,0
		dc.w	$128,0,$12a,0
		dc.w	$12c,0,$12e,0
		dc.w	$130,0,$132,0
		dc.w	$134,0,$136,0
		dc.w	$138,0,$13a,0
		dc.w	$13c,0,$13e,0
		
		dc.w	  $e0
bitplane0_hi:	dc.w	0,$e2
bitplane0_lo:	dc.w	0,$e4
bitplane1_hi:	dc.w	0,$e6
bitplane1_lo:	dc.w	0,$e8
bitplane2_hi:	dc.w	0,$ea
bitplane2_lo:	dc.w	0,$ec
bitplane3_hi:	dc.w	0,$ee
bitplane3_lo:	dc.w	0,$f0
bitplane4_hi:	dc.w	0,$f2
bitplane4_lo:	dc.w	0
	
cmap:		dc.w	$180,$000
		dc.w	$182,$000
		dc.w	$184,$000
		dc.w	$186,$000
		dc.w	$188,$000
		dc.w	$18a,$000
		dc.w	$18c,$000
		dc.w	$18e,$000
		dc.w	$190,$000
		dc.w	$192,$000
		dc.w	$194,$000
		dc.w	$196,$000
		dc.w	$198,$000
		dc.w	$19a,$000
		dc.w	$19c,$000
		dc.w	$19e,$000
		dc.w	$1a0,$000
		dc.w	$1a2,$000
		dc.w	$1a4,$000
		dc.w	$1a6,$000
		dc.w	$1a8,$000
		dc.w	$1aa,$000
		dc.w	$1ac,$000
		dc.w	$1ae,$000
		dc.w	$1b0,$000
		dc.w	$1b2,$000
		dc.w	$1b4,$000
		dc.w	$1b6,$000
		dc.w	$1b8,$000
		dc.w	$1ba,$000
		dc.w	$1bc,$000
		dc.w	$1be,$000
				
		dc.w	$ffe1,$fffe	; end of ntsc screen
		dc.w	$3001,$ff00	; end of pal screen
		dc.w	$9c,$8010	; irq set bits - restart copper
		dc.w	$ffff,$fffe	; end of copper list

oldint:		dc.l	0
olddma:		dc.l	0
oldv3:		dc.l	0
gfxlib:		dc.b	"graphics.library",0

diskptr:		dc.l	diskmap
 
diskmap:	dc.l	"TWAR",$00400,99754,0,$64E50037
	dc.l	"TWAR",$18A00,112604,0,$F3997123
	dc.l	"TWAR",$34200,90644,0,$E7B6FA2A
	dc.l	"TWAR",$4A600,90226,0,$515E2C85
	dc.l	"TWAR",$60800,111710,0,$E0C89426
	dc.l	"TWAR",$7BE00,98280,0,$D7A7C441
	dc.l	"TWAR",$93E00,107450,0,$4758AF44
	dc.l	-1


	section	mods,bss_c

mod_data1:	ds.l	36250
mod_data2:	ds.l	36250
workspace:	ds.l	$c80		; dma for loader
screen1:		ds.l 	10*256*5

	section	temp,data
	
my_mem:		dc.l	0
mt_data1:	dc.l	mod_data1
mt_data2:	dc.l	mod_data2
songended:	dc.l	0

volumespace:	dc.l	0
drive:		dc.w	0
temp:		dc.l	0
label:		dc.l	0
looklabel:	dc.l	0
loadaddress:	dc.l	0
diskaddress:	dc.l	0
loadlength:	dc.l	0
	
iff_width:	dc.w	0		; width in pixels
iff_height:	dc.w	0		; height in pixels
iff_bmpsize:	dc.l	0		; bitmap size
iff_depth:	dc.b	0		; no. of bitplanes
iff_compression:	dc.b	0		; compresstion type (0=bitmap, 1=byterun1)
iff_colours:	dc.w	0		; no., of colours
iff_maxsize:	dc.l	40*256*5		; max size allowed for iff pic
iff_cmap:	dcb.w	32,0		; buffers for colourmap
iff:		dc.l	0		; ptr to iff pic

main_screen:	incbin	"dh1:techno/main.iff"

	end

