;1990-05-29
; 01	data labels changed to offsets, (pc) accesses to (a4) changed
; 02	mt_data lea's to move.l mt_song(a4) changed
; 03+	all absolute data access changed to (a4)
; 04+	all branches extended to either .s or .L, MasterSeka opt O used
; 05+	illegal clr and .b access to hardware regs replaced
; 06+	some severe cases optimized
;1990-05-30
; 07+	data table initialized, stupid setfilt repaired
; 08+	interrupt wait inserted, shit twice wait repaired


; @ includes colortest speed monitor marked @

; ONLY FOR EXAMPLEPLAYER!!!
songabs = $90000

start:	lea	mt_initdata(pc),a4	; this region may be obtained
					;  via ALLOCMEM
	move.l	#songabs,mt_song(a4)	; set module address
	bsr.s	timerinit
	bsr.L	mt_init

loop:
	cmpi.b	#200,$dff006
	bne.s	loop
	move.w	#$000f,$dff180		; @ color
	bsr.L	mt_music
	move.w	#0,$dff180		; @ color
lolo:	cmpi.b	#201,$dff006
	blo.s	lolo
	btst	#7,$bfe001
	bne.s	nores
	bsr.L	mt_init
nores:	btst	#6,$bfe001
	bne.s	loop
	bsr.L	mt_end
	bsr.L	timerexit
	rts




skip = 8				; # lines delay for DMAoff

;------------   Init timerA of CIAB (l6int) AMICOM 1988-01-26
; this routine does NOT work along with high-level AmigaDOS
;  applications. (Use cia.resource instead)

timerinit:				
	movem.l	d1/a0-a1,-(a7)		;
	lea	timer_iv_data(pc),a1	; maybe you'll find a better
	move.l	a4,(a1)			;  solution (ex: use addr 0!)
	lea	timeroldIena(pc),a1	;
	move.w	$dff01c,(a1)+		;
	move.b	$bfde00,(a1)+		; save old cr

; find divide value of cia timer 1989-08-19 by AMICOM

	and.b	#$fe,$bfde00		; stop timerA  CIAB
	bsr.s	timeriwait		; delay for slow cia...
	bset	#4,$bfde00		; force load
	bsr.s	timeriwait		; delay for slow cia...
	move.b	$bfd500,(a1)+		; get high
	move.b	$bfd400,(a1)+		; low byte

	move.b	#$01,$bfdd00		; disable ciab timerA int
	lea	timerl6handler(pc),a0	;
	lea	timeroldl6int(pc),a1	;
	move.l	$78.w,(a1)		;
	tst.b	$bfdd00			; clr all requests
	move.w	#$2000,$dff09c		;
	move.l	a0,$78.w		;
					
	move.w	#skip*455/10,d1		; 227.5 cycles/line div by 5
	and.b	#$c0,$bfde00		; ciab timerA init
	or.b	#$08,$bfde00		; one shot mode
	move.b	d1,$bfd400		; low byte
	lsr.w	#8,d1			;
	move.b	d1,$bfd500		; high byte (starts timer!)
	and.b	#$fe,$bfde00		; stop it!
	move.b	#$81,$bfdd00		; allow timerA int
	move.w	#$a000,$dff09a		; allow l6 (ciab) int
	movem.l	(a7)+,d1/a0-a1		;
timeriwait:				
	rts				;
					
					
timerexit:				
	movem.l	d0/a0,-(a7)		;
	move.w	#$2000,$dff09a		; disable l6/ciab int
	move.b	#$01,$bfdd00		; disable ciab timerA int
	and.b	#$fe,$bfde00		; stop timera 
	tst.b	$bfdd00			; clr all requests
	move.w	#$2000,$dff09c		;
	move.l	timeroldl6int(pc),$78.w	; restore
	lea	timeroldcr(pc),a0	;
	move.b	2(a0),$bfd400		; restore old counter
	move.b	1(a0),$bfd500		; starts timer
	and.b	#$fe,$bfde00		; stop it!
	move.b	(a0),d0			;
	and.b	#$0f,d0			; only timerA bits
	or.b	d0,$bfde00		; restore cont reg
	move.w	timeroldIena(pc),d0	;
	and.w	#$2000,d0		; mask l6 status
	lsl.w	#2,d0			; to set/clr
	or.w	#$2000,d0		; only this one
	move.w	d0,$dff09a		; set/clr
	move.b	#$81,$bfdd00		; allow int on cia
	movem.l	(a7)+,d0/a0		;
	rts				;
					
timer_iv_data:  dc.l    0       ; base for routine
timeroldl6int:	dc.l	0	; old l6 auto-vector
timeroldIena:	dc.w	0	; old status of INTENA
timeroldcr:	dc.b	0	; old status of contr reg
timerolddiv:	dc.b	0,0	; old divide counter value
even


***********************************************************************
***   Mega fast playroutine for the Spreadpoint SoundTracker V2.5   ***
***                                                                 ***
***  Based on the playroutine by Mahoney & Kaktus, Hallonsoft 1989  ***
***  Tidied-up, de-lamed, sped up and changed to interrupt wait     ***
***                             by                                  ***
***            A M I C O M  of  SPREADPOINT in May 1990             ***
***********************************************************************


mt_init:
	movem.l	d0-d7/a0-a6,-(a7)
	moveq	#mt_enddata/4-3,d0
	lea	8(a4),a0

mt_i_2:
	clr.l	(a0)+
	dbf	d0,mt_i_2
	move.w	#$0001,20+mt_voice1(a4)
	move.w	#$0002,20+mt_voice2(a4)
	move.w	#$0004,20+mt_voice3(a4)
	move.w	#$0008,20+mt_voice4(a4)
	move.l	mt_song(a4),a0
	move.l	a0,a1
	add.l	#$3b8,a1
	moveq	#$7f,d0
	moveq	#0,d1
mt_loop:move.l	d1,d2
	subq.w	#1,d0
mt_lop2:move.b	(a1)+,d1
	cmp.b	d2,d1
	bgt.s	mt_loop
	dbf	d0,mt_lop2
	addq.b	#1,d2

	lea	mt_samplestarts(a4),a1
	asl.l	#8,d2
	asl.l	#2,d2
	add.l	#$43c,d2
	add.l	a0,d2
	move.l	d2,a2
	moveq	#$1e,d0
mt_lop3:clr.l	(a2)
	move.l	a2,(a1)+
	moveq	#0,d1
	move.w	42(a0),d1
	add.l	d1,d1
	add.l	d1,a2
	add.l	#$1e,a0
	dbf	d0,mt_lop3

;	or.b	#$2,$bfe001		; nonsense
	move.b	#$6,mt_speed(a4)
	moveq	#0,d0
	move.w	d0,$dff0a8		; was clr
	move.w	d0,$dff0b8
	move.w	d0,$dff0c8
	move.w	d0,$dff0d8
	clr.b	mt_songpos(a4)
	clr.b	mt_counter(a4)
	clr.w	mt_pattpos(a4)
	movem.l	(a7)+,d0-d7/a0-a6
	rts

mt_end:	
	move.l	d0,-(a7)
	moveq	#0,d0
	move.w	d0,$dff0a8		; was clr
	move.w	d0,$dff0b8
	move.w	d0,$dff0c8
	move.w	d0,$dff0d8
	move.w	#$000f,$dff096
	move.l	(a7)+,d0
	rts

mt_music:
	movem.l	d0-d4/a0-a3/a5-a6,-(a7)
	bsr.s	mt_music_2
	movem.l	(a7)+,d0-d4/a0-a3/a5-a6
	rts

mt_music_2:
	move.l	mt_song(a4),a0
	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.L	mt_getnew

mt_nonew:
	lea	mt_voice1(a4),a6
	lea	$dff0a0,a5
	bsr.L	mt_checkcom
	lea	mt_voice2(a4),a6
	add.w	#$10,a5			; next audio ch
	bsr.L	mt_checkcom
	lea	mt_voice3(a4),a6
	add.w	#$10,a5			; next audio ch
	bsr.L	mt_checkcom
	lea	mt_voice4(a4),a6
	add.w	#$10,a5			; next audio ch
	bsr.L	mt_checkcom
	bra.L	mt_endr

mt_arpeggio:
	moveq	#0,d0
	move.b	mt_counter(a4),d0
	divs	#$3,d0
	swap	d0
	tst.w	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:add.w	d0,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	mt_song(a4),a0
	move.l	a0,a3
	move.l	a0,a2
	add.l	#$c,a3
	add.l	#$3b8,a2
	add.l	#$43c,a0

	moveq	#0,d0
	move.l	d0,d1
	move.b	mt_songpos(a4),d0
	move.b	(a2,d0.w),d1
	asl.l	#8,d1
	asl.l	#2,d1
	add.w	mt_pattpos(a4),d1
	clr.w	mt_dmacon(a4)

	lea	$dff0a0,a5
	lea	mt_voice1(a4),a6
	bsr.s	mt_playvoice
	lea	$dff0b0,a5
	lea	mt_voice2(a4),a6
	bsr.s	mt_playvoice
	lea	$dff0c0,a5
	lea	mt_voice3(a4),a6
	bsr.s	mt_playvoice
	lea	$dff0d0,a5
	lea	mt_voice4(a4),a6
	bsr.s	mt_playvoice
	bra.L	mt_setdma

mt_playvoice:
	move.l	(a0,d1.l),(a6)
	addq.l	#4,d1
	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		; had a tst.b d2 following
	beq.s	mt_setregs
	moveq	#0,d3
	lea	mt_samplestarts(a4),a1
	move.l	d2,d4
	subq.l	#$1,d2
	asl.l	#2,d2
	mulu	#$1e,d4
	move.l	(a1,d2.l),$4(a6)
	move.w	(a3,d4.l),$8(a6)
	move.w	$2(a3,d4.l),$12(a6)
	move.w	$4(a3,d4.l),d3	; had a tst.w d3 following
	beq.s	mt_noloop
	move.l	$4(a6),d2
	add.w	d3,d3
	add.l	d3,d2
	move.l	d2,$a(a6)
	move.w	$4(a3,d4.l),d0
	add.w	$6(a3,d4.l),d0
	move.w	d0,8(a6)
	move.w	$6(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,$a(a6)
	move.w	$6(a3,d4.l),$e(a6)
	move.w	$12(a6),$8(a5)
mt_setregs:
	move.w	(a6),d0
	and.w	#$fff,d0
	beq.L	mt_checkcom2
	move.b	$2(a6),d0
	and.b	#$F,d0
	cmp.b	#$3,d0
	bne.s	mt_setperiod
	bsr.L	mt_setmyport
	bra.L	mt_checkcom2
mt_setperiod:
	move.w	(a6),$10(a6)
	and.w	#$fff,$10(a6)
	move.w	$14(a6),d0
;	move.w	d0,$dff096		; nonsense
	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	$14(a6),d0
	or.w	d0,mt_dmacon(a4)
	bra.L	mt_checkcom2

mt_setdma:
	move.w	mt_dmacon(a4),$dff096	;
	or.b	#1,$bfde00		; start ciab timerA
	rts

timerl6handler:					
	move.w	#$0f0f,$dff180			;@color
	movem.l	d0-d7/a0-a6,-(a7)		; all registers...
	move.l	timer_iv_data(pc),a4		; well ahem...
	bsr.s	mt_waitcont			; do delayed routine
	tst.b	$bfdd00				; clr cia int req
	move.w	#$2000,$dff09c			; clr int req
	movem.l	(a7)+,d0-d7/a0-a6		;
	move.w	#$0000,$dff180			;@color
	rte					;

mt_waitcont:
	move.w	mt_dmacon(a4),d0
	or.w	#$8000,d0
	move.w	d0,$dff096

	lea	$dff0d0,a2
	lea	mt_voice4(a4),a6
	moveq	#$10,d2
	moveq	#1,d1
	moveq	#3,d0
mt_voiceloop:
	move.l	10(a6),(a2);			$dff0d0
	cmp.w	14(a6),d1
	bne.s	mt_nextvoice
	move.w	d1,4(a2);			$dff0d4 ,len
mt_nextvoice:
	sub.w	#mt_voice2-mt_voice1,a6
	sub.l	d2,a2;				#$10
	dbf	d0,mt_voiceloop

	add.w	#$10,mt_pattpos(a4)
	cmp.w	#$400,mt_pattpos(a4)
	bne.s	mt_endr
mt_nex:	clr.w	mt_pattpos(a4)
	clr.b	mt_break(a4)
	addq.b	#1,mt_songpos(a4)
	and.b	#$7f,mt_songpos(a4)
	move.b	mt_songpos(a4),d1
	move.l	mt_song(a4),a1
	cmp.b	$3b6(a1),d1
	bne.s	mt_endr
	clr.b	mt_songpos(a4)
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),a1		; was a4
	lsr.w	#$2,d0
	and.w	#$1f,d0
	moveq	#0,d2
	move.b	(a1,d0.w),d2		; was a4
	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)
	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		; had a tst.b d0 following
	beq.L	mt_arpeggio
	cmp.b	#$1,d0
	beq.s	mt_portup
	cmp.b	#$2,d0
	beq.L	mt_portdown
	cmp.b	#$3,d0
	beq.L	mt_myport
	cmp.b	#$4,d0
	beq.L	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		; had a tst.b d0 following
	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
	beq.s	mt_filtoff
	or.b	#2,$bfe001
	rts
mt_filtoff:
	and.b	#$fd,$bfe001
	rts

mt_pattbreak:
	not.b	mt_break(a4)
	rts
mt_posjmp:
	move.b	$3(a6),d0
	subq.b	#$1,d0
	move.b	d0,mt_songpos(a4)
	not.b	mt_break(a4)
	rts
mt_setvol:
	cmp.b	#$40,$3(a6)
	ble.s	mt_vol4
	move.b	#$40,$3(a6)
mt_vol4:moveq	#0,d0
	move.b	$3(a6),d0
	move.w	d0,$8(a5)	; was move.b
	rts
mt_setspeed:
	move.b	$3(a6),d0
	and.w	#$1f,d0
	beq.s	mt_rts2
	clr.b	mt_counter(a4)
	move.b	d0,mt_speed(a4)
mt_rts2: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,$0000,$0000

mt_song:	equ	4
mt_speed:	equ	8
mt_songpos:	equ	9
mt_pattpos:	equ	10
mt_counter:	equ	12

mt_break:	equ	13
mt_dmacon:	equ	14
mt_samplestarts:equ	16	; len = 124
mt_voice1:	equ	140	; len = 28
mt_voice2:	equ	168
mt_voice3:	equ	196
mt_voice4:	equ	224
mt_enddata:	equ	252

;---------------------------   END OF MTP   ------------------------------


;***   This part belongs to the exampleplayer and can be removed
;***   if not used. The space must then be ALLOCATEd

mt_initdata:
	dc.l	0
	dc.l	0
	dc.b	$6
	dc.b	$0
	dc.w	$0
	dc.b	$0

	dc.b	$0
	dc.w	$0
	blk.l	$1f,0
	blk.w	10,0
	dc.w	$1
	blk.w	3,0
	blk.w	10,0
	dc.w	$2
	blk.w	3,0
	blk.w	10,0
	dc.w	$4
	blk.w	3,0
	blk.w	10,0
	dc.w	$8
	blk.w	3,0
