;*******************************
;*** NOISETRACKER COMPRESSED ***
;*** REPLAYROUTINE 1.3 D     ***
;*** IMPROVED ON 15/03/91    ***
;*** BY ANTICHRIST OF UFO    ***
;*******************************

; This routine is fully pc-relative.
; Don't change anything in mt_vars
; ('coz the offsets below won't fit anymore!).

; Include your PACKED module at mt_data (still the same!)
; To init, jump to Offset 0
; »» Load your start position to d0.l ««
; To play, jump to Offset 4
; To stop, jump to Offset 8

; !!!!
	XDEF	_pack_init,_pack_music,_pack_end
	XREF	_adr_data
; !!!!



mt_speed	=0
mt_songpos	=1
mt_pattpos	=2
mt_counter	=4
mt_break	=5
mt_dmacon	=6
mt_samplestarts =8
mt_voice1	=132
mt_voice2	=166
mt_voice3	=200
mt_voice4	=234

_pack_init:
; !!!!
	movem.l	d0-d7/a0-a6,-(a7)
; !!!!
	move.l	d0,-(sp)
	lea	mt_vars(pc),a4
	move.l	_adr_data,a0
	move.l	a0,a1
	lea	$176(a1),a1
	moveq	#$7f,d0
	moveq	#0,d1
	moveq	#0,d2

.seek	move.b	(a1)+,d1
	cmp.b	d1,d2
	bge.s	.nohi
	move.b	d1,d2
.nohi	dbf	d0,.seek

	move.l	_adr_data,(a0)
	lea	$1f6(a0),a0
	lea	mt_patterns(pc),a1
	move.w	#$5041,d0
	move.w	#$5454,d1
.getPatt
	cmp.w	(a0)+,d0
	bne.s	.getPatt
	cmp.w	(a0)+,d1
	bne.s	.getPatt
	move.l	a0,(a1)+
	dbf	d2,.getPatt

	lea	mt_samplestarts(a4),a1
	move.l	_adr_data,a2
	move.l	a2,d2
	moveq	#31-1,d1
mt_lop3:
	move.l	(a2),d0
	add.l	d2,d0
	move.l	d0,(a1)+
	lea	12(a2),a2
	dbf	d1,mt_lop3

	move.l	(sp)+,d0
	moveq	#0,d0			;insert this line, if you don't
	bsr	setChannel		;want to start your song at any 
					;other position than 0
	bset	#1,$bfe001
	move.b	#6,mt_speed(a4)
	clr.w	$dff0a8
	clr.w	$dff0b8
	clr.w	$dff0c8
	clr.w	$dff0d8
	clr.b	mt_counter(a4)
	clr.w	mt_pattpos(a4)

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

_pack_end:
	clr.w	$dff0a8
	clr.w	$dff0b8
	clr.w	$dff0c8
	clr.w	$dff0d8
	move.w	#$f,$dff096
	rts
_pack_music:
; !!!!
	movem.l	d0-d7/a0-a6,-(a7)
; !!!!
	bsr	mt_music
; !!!!
	movem.l	(a7)+,d0-d7/a0-a6
; !!!!
	rts

mt_music:
	lea	mt_vars(pc),a4
	addq.b	#1,mt_counter(a4)
	move.b	mt_counter(a4),D0
	cmp.b	mt_speed(a4),D0
	blt.s	mt_nonew
	clr.b	mt_counter(a4)
	bra	mt_getnew

mt_nonew:
	lea	mt_voice1(a4),a6
	lea	$dff0a0,a5
	bsr	mt_checkcom
	lea	mt_voice2(a4),a6
	lea	$10(a5),a5
	bsr	mt_checkcom
	lea	mt_voice3(a4),a6
	lea	$10(a5),a5
	bsr	mt_checkcom
	lea	mt_voice4(a4),a6
	lea	$10(a5),a5
	bsr	mt_checkcom
	bra	mt_endr

mt_arpeggio:
	moveq	#0,d0
	move.b	mt_counter(a4),d0
	divs	#3,d0
	swap	d0
	cmp.w	#0,d0
	beq.s	mt_arp2
	cmp.w	#2,d0
	beq.s	mt_arp1

	moveq	#0,d0
	move.b	3(a6),d0
	lsr.b	#4,d0
	bra.s	mt_arp3
mt_arp1:
	moveq	#0,d0
	move.b	$3(a6),d0
	and.b	#$f,d0
	bra.s	mt_arp3
mt_arp2:
	move.w	$10(a6),d2
	bra.s	mt_arp4
mt_arp3:
	asl.w	#1,d0
	moveq	#0,d1
	move.w	$10(a6),d1
	lea	mt_periods(pc),a0
	moveq	#$24,d7
mt_arploop:
	move.w	(a0,d0.w),d2
	cmp.w	(a0),d1
	bge.s	mt_arp4
	addq.l	#2,a0
	dbf	d7,mt_arploop
	rts
mt_arp4:move.w	d2,$6(a5)
	rts

mt_getnew:
	move.l	_adr_data,a3
	clr.w	mt_dmacon(a4)
	lea	$dff0a0,a5
	lea	mt_voice1(a4),a6
	bsr.s	mt_playvoice
	lea	$10(a5),a5
	lea	mt_voice2(a4),a6
	bsr.s	mt_playvoice
	lea	$10(a5),a5
	lea	mt_voice3(a4),a6
	bsr.s	mt_playvoice
	lea	$10(a5),a5
	lea	mt_voice4(a4),a6
	bsr.s	mt_playvoice
	bra	mt_setdma

mt_playvoice:
	tst.w	32(a6)
	beq.s	.nodelay
	subq.w	#1,32(a6)
	bra.s	.morevoice
.nodelay
	move.l	28(a6),a0
	moveq	#0,d2
	move.b	(a0),d2
	cmpi.b	#$ff,d2
	bne.s	.nocrunch
	move.b	1(a0),33(a6)
	addq.l	#2,28(a6)
	clr.l	(a6)
	bra.s	mt_playvoice
.nocrunch
	move.b	d2,d0
	andi.b	#$3f,d2
	beq.s	.noset
	lsl.w	#1,d2
	lea	mt_periods(pc),a1
	move.w	-2(a1,d2.w),d2
.noset	btst	#7,d0
	beq.s	.nohisamp
	bset	#12,d2
.nohisamp
	move.w	d2,(a6)
	move.b	1(a0),2(a6)
	clr.b	3(a6)
	btst	#6,d0
	bne.s	.nocom
	move.b	2(a0),3(a6)
	addq.l	#1,28(a6)
.nocom	addq.l	#2,28(a6)
.morevoice
	moveq	#0,d2
	move.b	2(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.s	mt_setregs
	lea	mt_samplestarts(a4),a1
	subq.l	#1,d2
	move.l	d2,d4
	mulu	#12,d4				
	asl.l	#2,d2				
	move.l	(a1,d2.l),4(a6)			
	move.w	4(a3,d4.l),8(a6)		
	move.w	6(a3,d4.l),18(a6)		
	moveq	#0,d3
	move.w	8(a3,d4.l),d3
	tst.w	d3
	beq.s	mt_noloop
	move.l	4(a6),d2
	lsl.l	#1,d3
	add.l	d3,d2
	move.l	d2,$a(a6)
	move.w	8(a3,d4.l),d0
	add.w	10(a3,d4.l),d0
	move.w	d0,8(a6)
	move.w	10(a3,d4.l),$e(a6)
	move.w	$12(a6),$8(a5)
	bra.s	mt_setregs
mt_noloop:
	move.l	4(a6),d2
	add.l	d3,d2
	move.l	d2,10(a6)
	move.w	10(a3,d4.l),14(a6)
	move.w	18(a6),8(a5)
mt_setregs:
	move.w	(a6),d0
	andi.w	#$fff,d0
	beq	mt_checkcom2
	move.b	2(a6),d0
	and.b	#$F,d0
	cmp.b	#$3,d0
	bne.s	mt_setperiod
	bsr	mt_setmyport
	bra	mt_checkcom2

mt_setperiod:
	move.w	(a6),$10(a6)
	and.w	#$fff,$10(a6)
	move.w	$14(a6),d0
	move.w	d0,$dff096
	clr.b	$1b(a6)

	move.l	4(a6),(a5)
	move.w	8(a6),4(a5)
	move.w	$10(a6),d0
	and.w	#$fff,d0
	move.w	d0,$6(a5)
	move.w	20(a6),d0
	or.w	d0,mt_dmacon(a4)
	bra	mt_checkcom2

mt_setdma:
	move.w	#300,d0
mt_wait:dbf	d0,mt_wait
	move.w	mt_dmacon(a4),d0
	or.w	#$8000,d0
	move.w	d0,$dff096
	move.w	#300,d0
mt_wai2:dbf	d0,mt_wai2

	lea	$dff000,a5
	lea	mt_voice4(a4),a6
	move.l	$a(a6),$d0(a5)
	move.w	$e(a6),$d4(a5)
	lea	mt_voice3(a4),a6
	move.l	$a(a6),$c0(a5)
	move.w	$e(a6),$c4(a5)
	lea	mt_voice2(a4),a6
	move.l	$a(a6),$b0(a5)
	move.w	$e(a6),$b4(a5)
	lea	mt_voice1(a4),a6
	move.l	$a(a6),$a0(a5)
	move.w	$e(a6),$a4(a5)
	addq.b	#1,mt_pattpos+1(a4)
	cmpi.b	#64,mt_pattpos+1(a4)
	bne.s	mt_endr
mt_nex:	clr.b	mt_pattpos+1(a4)
	clr.b	mt_break(a4)
	addq.b	#1,mt_songpos(a4)
	andi.b	#$7f,mt_songpos(a4)
	move.l	a0,-(a7)
	move.l	_adr_data,a0
	move.b	mt_songpos(a4),d1
	cmp.b	$174(a0),d1		
	bne.s	.not
	move.b	$175(a0),mt_songpos(a4)	
.not	moveq	#0,d0
	movem.l	(a7)+,a0
	move.b	mt_songpos(a4),d0
	bsr	setChannel
mt_endr:
	tst.b	mt_break(a4)
	bne.s	mt_nex
	rts

mt_setmyport:
	move.w	(a6),d2
	and.w	#$fff,d2
	move.w	d2,$18(a6)
	move.w	$10(a6),d0
	clr.b	$16(a6)
	cmp.w	d0,d2
	beq.s	mt_clrport
	bge.s	mt_rt
	move.b	#$1,$16(a6)
	rts
mt_clrport:
	clr.w	$18(a6)
mt_rt:	rts

mt_myport:
	move.b	3(a6),d0
	beq.s	mt_myslide
	move.b	d0,$17(a6)
	clr.b	3(a6)
mt_myslide:
	tst.w	$18(a6)
	beq.s	mt_rt
	moveq	#0,d0
	move.b	$17(a6),d0
	tst.b	$16(a6)
	bne.s	mt_mysub
	add.w	d0,$10(a6)
	move.w	$18(a6),d0
	cmp.w	$10(a6),d0
	bgt.s	mt_myok
	move.w	$18(a6),$10(a6)
	clr.w	$18(a6)
mt_myok:move.w	$10(a6),$6(a5)
	rts
mt_mysub:
	sub.w	d0,$10(a6)
	move.w	$18(a6),d0
	cmp.w	$10(a6),d0
	blt.s	mt_myok
	move.w	$18(a6),$10(a6)
	clr.w	$18(a6)
	move.w	$10(a6),$6(a5)
	rts

mt_vib:	move.b	3(a6),d0
	beq.s	mt_vi
	move.b	d0,$1a(a6)

mt_vi:	move.b	$1b(a6),d0
	lea	mt_sin(pc),a4
	lsr.w	#$2,d0
	and.w	#$1f,d0
	moveq	#0,d2
	move.b	(a4,d0.w),d2
	move.b	$1a(a6),d0
	and.w	#$f,d0
	mulu	d0,d2
	lsr.w	#$6,d2
	move.w	$10(a6),d0
	tst.b	$1b(a6)
	bmi.s	mt_vibmin
	add.w	d2,d0
	bra.s	mt_vib2
mt_vibmin:
	sub.w	d2,d0
mt_vib2:move.w	d0,$6(a5)
	move.b	$1a(a6),d0
	lsr.w	#$2,d0
	and.w	#$3c,d0
	add.b	d0,$1b(a6)
	lea	mt_vars(pc),a4
	rts

mt_nop:	move.w	$10(a6),$6(a5)
	rts

mt_checkcom:
	move.w	2(a6),d0
	and.w	#$fff,d0
	beq.s	mt_nop
	move.b	2(a6),d0
	and.b	#$f,d0
	tst.b	d0
	beq	mt_arpeggio
	cmp.b	#$1,d0
	beq.s	mt_portup
	cmp.b	#$2,d0
	beq	mt_portdown
	cmp.b	#$3,d0
	beq	mt_myport
	cmp.b	#$4,d0
	beq	mt_vib
	move.w	$10(a6),$6(a5)
	cmp.b	#$a,d0
	beq.s	mt_volslide
	rts

mt_volslide:
	moveq	#0,d0
	move.b	$3(a6),d0
	lsr.b	#4,d0
	tst.b	d0
	beq.s	mt_voldown
	add.w	d0,$12(a6)
	cmp.w	#$40,$12(a6)
	bmi.s	mt_vol2
	move.w	#$40,$12(a6)
mt_vol2:move.w	$12(a6),$8(a5)
	rts

mt_voldown:
	moveq	#0,d0
	move.b	$3(a6),d0
	and.b	#$f,d0
	sub.w	d0,$12(a6)
	bpl.s	mt_vol3
	clr.w	$12(a6)
mt_vol3:move.w	$12(a6),$8(a5)
	rts

mt_portup:
	moveq	#0,d0
	move.b	3(a6),d0
	sub.w	d0,$10(a6)
	move.w	$10(a6),d0
	and.w	#$fff,d0
	cmp.w	#$71,d0
	bpl.s	mt_por2
	and.w	#$f000,$10(a6)
	or.w	#$71,$10(a6)
mt_por2:move.w	$10(a6),d0
	and.w	#$fff,d0
	move.w	d0,$6(a5)
	rts

mt_portdown:
	clr.w	d0
	move.b	$3(a6),d0
	add.w	d0,$10(a6)
	move.w	$10(a6),d0
	and.w	#$fff,d0
	cmp.w	#$358,d0
	bmi.s	mt_por3
	and.w	#$f000,$10(a6)
	or.w	#$358,$10(a6)
mt_por3:move.w	$10(a6),d0
	and.w	#$fff,d0
	move.w	d0,$6(a5)
	rts

mt_checkcom2:
	move.b	2(a6),d0
	and.b	#$f,d0
	cmp.b	#$e,d0
	beq.s	mt_setfilt
	cmp.b	#$d,d0
	beq.s	mt_pattbreak
	cmp.b	#$b,d0
	beq.s	mt_posjmp
	cmp.b	#$c,d0
	beq.s	mt_setvol
	cmp.b	#$f,d0
	beq.s	mt_setspeed
	rts

mt_setfilt:
	move.b	$3(a6),d0
	and.b	#$1,d0
	asl.b	#$1,d0
	and.b	#$fd,$bfe001
	or.b	d0,$bfe001
	rts
mt_posjmp:
	move.b	3(a6),d0
	subq.b	#1,d0
	move.b	d0,mt_songpos(a4)
mt_pattbreak:
	not.b	mt_break(a4)
	rts
mt_setvol:
	cmp.b	#$40,$3(a6)
	ble.s	mt_vol4
	move.b	#$40,$3(a6)
mt_vol4:
	move.b	$3(a6),$8(a5)
	rts

mt_setspeed:
	cmp.b	#$1f,$3(a6)
	ble.s	mt_sets
	move.b	#$1f,$3(a6)
mt_sets:
	move.b	$3(a6),d0
	beq.s	mt_rts2
	move.b	d0,mt_speed(a4)
	clr.b	mt_counter(a4)
mt_rts2:
	rts

setChannel:
	move.l	_adr_data,a0
	lea	mt_vars(pc),a4
	cmp.b	$174(a0),d0
	blt.s	.valid
	moveq	#0,d0
.valid	move.b	d0,mt_songpos(a4)
	lea	$176(a0),a0
	move.b	(a0,d0.w),d0
	lsl.l	#2,d0
	lea	mt_voice1(a4),a1
	lea	mt_patterns(pc),a0
	move.l	(a0,d0.w),a0
	move.l	a0,d2
	move.l	d2,d0
	addq.l	#6,d0
	moveq	#3,d1
	bra.s	.dochan
.setchannel
	lea	34(a1),a1
	moveq	#0,d0
	move.w	(a0)+,d0
	add.l	d2,d0
.dochan
	move.l	d0,28(a1)
	clr.w	32(a1)
	dbf	d1,.setchannel
	rts

mt_sin:
 DC.b $00,$18,$31,$4a,$61,$78,$8d,$a1,$b4,$c5,$d4,$e0,$eb,$f4,$fa,$fd
 DC.b $ff,$fd,$fa,$f4,$eb,$e0,$d4,$c5,$b4,$a1,$8d,$78,$61,$4a,$31,$18

mt_periods:
 DC.w $0358,$0328,$02fa,$02d0,$02a6,$0280,$025c,$023a,$021a,$01fc,$01e0
 DC.w $01c5,$01ac,$0194,$017d,$0168,$0153,$0140,$012e,$011d,$010d,$00fe
 DC.w $00f0,$00e2,$00d6,$00ca,$00be,$00b4,$00aa,$00a0,$0097,$008f,$0087
 DC.w $007f,$0078,$0071

mt_patterns:
	dcb.l	64
mt_vars:			;*** DON'T CHANGE ANYTHING BELOW ***
	DC.b	6
	DC.b	0
	DC.w	0
	DC.b	0
	DC.b	0
	DC.w	0
;mt_samplestarts
	dcb.L	$1f

;mt_voice1
	dcb.w	10
	DC.w	1
	dcb.w	3
	dc.l	0		
	dc.w	0		

;mt_voice2
	dcb.w	10
	DC.w	2
	dcb.w	3
	dc.l	0
	dc.w	0
	
;mt_voice3
	dcb.w	10
	DC.w	4
	dcb.w	3
	dc.l	0
	dc.w	0
	
;mt_voice4
	dcb.w	10
	DC.w	8
	dcb.w	3
	dc.l	0
	dc.w	0

;atdp Coke's Touchdown !




