
;/*
; * StarTrekker v1.3a (8-Voices <Realtime Sample-mixing> Module replayer)
; * By Björn Wesen / Exolon of FairLight
; *
; *	Björn Wesen
; *	Roslins v.20A
; *	S-217 55 Malmö
; *	SWEDEN
; *
; * USE ON 8-CHANNEL STARTREKKER MODULES ONLY!
; * (SEKA SOURCE)
; *
; */
	section	play8,code_c

	lea	st_mod,a0		;module
	bsr	st_init

loop1:	lea	$dff004,a0
waitvb:	move.l	(a0),d0
	lsr.l	#8,d0
	and.w	#$1ff,d0
	cmp.w	#301,d0			;wait for vbl line 301!
	bne.s	waitvb

	bsr	st_play			;play music

	btst	#6,$bfe001		;wait for mouse
	bne.s	loop1

	bsr	st_end			;music off
gpc:	rts

*** setup music ***

st_init:
	lea	st_mdl(pc),a1		;save module-address
	move.l	a0,(a1)
	move.l	a0,a1
	lea	$3b8(a1),a1
	moveq	#$7f,d0
	moveq	#0,d1
st_lp1:	move.l	d1,d2
	subq.w	#1,d0
st_lp2:	move.b	(a1)+,d1
	cmp.b	d2,d1			;get highest pattern
	bgt.s	st_lp1
	dbf	d0,st_lp2
	addq.b	#1,d2

	lea	st_ins(pc),a1		;instrument-list => a1
	moveq	#10,d3
	lsl.l	d3,d2
	move.l	d2,a2
	lea	$43c(a2),a2
	add.l	a0,a2			;sample-offset => a2
	moveq	#$1e,d0			;init 31 instruments
st_lp3:	clr.l	(a2)
	move.l	a2,(a1)+		;pointer => liste
	moveq	#0,d1
	move.w	42(a0),d1
	add.l	d1,d1
	add.l	d1,a2
	lea	$1e(a0),a0
	dbf	d0,st_lp3

	move.l	st_mdl(pc),a0
	lea	$3b8(a0),a0
	moveq	#0,d1
	move.b	(a0),d1			;get first pattern
	moveq	#10,d0
	lsl.l	d0,d1
	lea	$42c-$3b8(a0),a0
	add.l	a0,d1
	lea	st_evn(pc),a0
	move.l	d1,(a0)+
	add.l	#$400,d1
	move.l	d1,(a0)

	bset	#1,$bfe001		;filter off

	lea	st_ctr(pc),a0
	move.w	#6,(a0)+		;set speed
	clr.w	(a0)+
	clr.w	(a0)+
	move.w	#313,(a0)		;set buffer 2

	lea	st_dat(pc),a0
	move.w	#$37+(313*2),d0
st_cl1:	clr.l	(a0)+			;clear buffer
	dbf	d0,st_cl1

	lea	st_smp(pc),a1
	lea	st_dat(pc),a0
	moveq	#7,d0
st_lp4:	move.l	a0,(a1)+		;clear now-played instr.
	lea	$1c(a0),a0
	dbf	d0,st_lp4

	lea	$dff000,a6
	move.w	#15,$96(a6)		;stop audio-dma
	lea	st_ch1(pc),a0
	move.l	a0,$a0(a6)		;init audio-dma
	lea	313*2(a0),a0
	move.l	a0,$b0(a6)
	lea	313*2(a0),a0
	move.l	a0,$c0(a6)
	lea	313*2(a0),a0
	move.l	a0,$d0(a6)
	move.w	#313,d0			;length 313 sample-bytes
	move.w	d0,$a4(a6)
	move.w	d0,$b4(a6)
	move.w	d0,$c4(a6)
	move.w	d0,$d4(a6)
	move.w	#$e3,d0			;play one sample per line
	move.w	d0,$a6(a6)
	move.w	d0,$b6(a6)
	move.w	d0,$c6(a6)
	move.w	d0,$d6(a6)
	moveq	#$40,d0			;volumen 64
	move.w	d0,$a8(a6)
	move.w	d0,$b8(a6)
	move.w	d0,$c8(a6)
	move.w	d0,$d8(a6)
	move.w	#$800f,$96(a6)		;start dma
	rts

*** end music ***

st_end:	lea	$dff000,a6
	move.w	#$f,$96(a6)			;stop dma
	clr.w	$a8(a6)				;set vol to 0
	clr.w	$b8(a6)
	clr.w	$c8(a6)
	clr.w	$d8(a6)
	bclr	#1,$bfe001			;filter off
	rts

*** play music ***

st_play:
	lea	st_chg(pc),a2
	eor.w	#313,(a2)			;change between buffer
	move.w	(a2),d0

	lea	st_ctr(pc),a2
	tst.b	(a2)				;new note ?
	bne.s	st_l07
	movem.l	d0-a6,-(a7)
	bsr.s	st_gt2				; => get data
	movem.l	(a7)+,d0-a6

st_l07:	subq.b	#1,(a2)
	lea	st_smp(pc),a2
	movem.l	(a2)+,a3/a4
	lea	st_ch1(pc),a5
	add.w	d0,a5
	bsr	st_mix				;mix channel 1 & 2
	movem.l	(a2)+,a3/a4
	lea	st_ch2(pc),a5
	add.w	d0,a5
	bsr	st_mix				;mix channel 3 & 4
	movem.l	(a2)+,a3/a4
	lea	st_ch3(pc),a5
	add.w	d0,a5
	bsr	st_mix				;mix channel 5 & 6
	movem.l	(a2)+,a3/a4
	lea	st_ch4(pc),a5
	add.w	d0,a5
	bsr	st_mix				;mix channel 7 & 8
	rts

st_gt2:	move.l	a2,-(a7)
	move.b	1(a2),(a2)			;set speed
	moveq	#16,d0
	lea	st_evn(pc),a0
	add.l	d0,(a0)+			;point to next note
	add.l	d0,(a0)+
	lea	st_ins(pc),a0
	move.l	st_mdl(pc),a1
	lea	$2a(a1),a1
	lea	st_dat(pc),a3
	lea	st_smp(pc),a5
	move.l	st_evn(pc),a2			;even pattern
	bsr.s	st_set
	move.l	st_odd(pc),a2			;odd pattern
	bsr.s	st_set

	lea	st_nte(pc),a0
	lea	st_pos(pc),a1
	move.w	(a1),d0				;add pattern-pos
	addq.w	#1,(a0)
	cmp.w	#$40,(a0)
	bne.s	st_ed2
	addq.w	#1,d0
st_nxt:	clr.w	(a0)
	move.l	st_mdl(pc),a0
	addq.b	#1,d0				;remove bug
	cmp.b	$3b6(a0),d0			;end of song ?
	blt.s	st_l14
	move.b	$3b7(a0),d0			;ja, restart !
	addq.w	#1,d0
st_l14:	lea	$3b8(a0),a0
	subq.w	#1,d0
	move.w	d0,(a1)
	moveq	#0,d1
	move.b	(a0,d0.w),d1
	moveq	#10,d0
	lsl.l	d0,d1
	lea	$42c-$3b8(a0),a0
	add.l	a0,d1
	lea	st_evn(pc),a0
	move.l	d1,(a0)+
	add.l	#$400,d1
	move.l	d1,(a0)
st_ed2:	move.l	(a7)+,a0
	rts

st_set:	lea	$dff0a9,a6
	moveq	#3,d7
st_lp5:	moveq	#0,d0
	moveq	#0,d1
	move.b	2(a2),d0			;get command
	and.b	#15,d0
	cmp.b	#15,d0				;speed ?
	bne.s	st_l08
	lea	st_spd(pc),a4
	move.b	3(a2),(a4)
st_l08:	cmp.b	#12,d0				;get vol
	bne.s	st_l09
	move.b	3(a2),(a6)
	st 	d1
st_l09:	move.w	(a2),d0
	and.w	#$fff,d0
	beq.s	st_l13				;new note ?
	tst.b	d1
	bne.s	st_l10
	move.b	#$40,(a6)
st_l10:	move.l	a3,(a5)
	move.l	#$38c000,d1			;get sample-speed
	divu	d0,d1
	swap	d1
	clr.w	d1
	swap	d1
	add.l	d1,d1
	add.l	d1,d1
	move.l	d1,8(a3)
	moveq	#0,d0
	move.b	2(a2),d0
	lsr.b	#4,d0
	btst	#7,(a2)
	beq.s	st_l11				;instrument 16...31 ?
	add.b	#$10,d0
st_l11:	move.w	d0,d1
	beq.s	st_l13
	subq.w	#1,d1
	add.w	d0,d0
	add.w	d0,d0
	move.l	-4(a0,d0.w),(a3)		;set sample-address
	mulu	#$1e,d1
	move.w	(a1,d1.w),d0
	add.l	d0,d0
	move.l	d0,4(a3)			;set sample-length
	tst.w	4(a1,d1.w)
	beq.s	st_l12				;loop ?
	move.l	(a3),12(a3)			; => set loop
	moveq	#0,d0
	move.w	4(a1,d1.w),d0
	add.l	d0,d0
	add.l	d0,12(a3)
	move.w	6(a1,d1.w),d0			;set loop-length
	add.l	d0,d0
	move.l	d0,16(a3)
	bra.s	st_l13
st_l12:	clr.l	12(a3)				;clear loop
	clr.l	16(a3)
	clr.l	20(a3)
st_l13:	addq.w	#4,a2				;set pointer to next
	lea	28(a3),a3			;channel
	addq.w	#4,a5
	lea	16(a6),a6
	dbf	d7,st_lp5
	rts

st_mix:	movem.l	d0-d7/a0-a6,-(a7)
	move.l	8(a3),d0			;get sample-position
	move.l	8(a4),d1
	lsr.l	#3,d0
	lsr.l	#3,d1
	muls	#313,d0
	muls	#313,d1
	lsl.l	#3,d0
	lsl.l	#3,d1
	swap	d0
	swap	d1
	ext.l	d0
	ext.l	d1
	move.l	4(a3),d2
	move.l	4(a4),d3
	tst.l	8(a3)
	bpl.s	st_l01
	exg	d0,d2
st_l01:	tst.l	8(a4)
	bpl.s	st_l02
	exg	d1,d3
st_l02:	cmp.l	d2,d0				;end of sample a ?
	blt.s	st_l04
	tst.l	12(a3)
	beq.s	st_l03
	move.l	12(a3),(a3)			;set loop
	move.l	$10(a3),4(a3)
	bra.s	st_l04

st_l03:	clr.l	(a3)				;clear loop
	clr.l	4(a3)
	clr.l	8(a3)
st_l04:	cmp.l	d3,d1				;end of sample b ?
	blt.s	st_l06
	tst.l	12(a4)
	beq.s	st_l05
	move.l	12(a4),(a4)			;set loop
	move.l	$10(a4),4(a4)
	bra.s	st_l06

st_l05:	clr.l	(a4)				;clear loop
	clr.l	4(a4)
	clr.l	8(a4)
st_l06:	move.l	(a3),a0				;sample/speed => a0/d2
	move.l	8(a3),d2
	move.l	(a4),a1				;sample/speed => a1/d3
	move.l	8(a4),d3
	moveq	#0,d0				;start-offsets 0
	move.l	d0,d1

	rept	313				;mix 313 sample-bytes
	move.b	(a0,d0.w),d4			;get sample-byte a
	ext.w	d4
	move.b	(a1,d1.w),d5			;get sample-byte b
	ext.w	d5
	add.w	d5,d4				; & mix them
	lsr.w	#1,d4
	swap	d0
	add.l	d2,d0				;increase pointer to next
	swap	d1
	add.l	d3,d1				;sample-byte
	swap	d0
	move.b	d4,(a5)+
	swap	d1
	endr
	
	ext.l	d0
	ext.l	d1
	add.l	d0,a0				;get new sample-address
	add.l	d1,a1
	move.l	a0,(a3)
	move.l	a1,(a4)
	sub.l	d0,4(a3)
	sub.l	d1,4(a4)
	movem.l	(a7)+,d0-d7/a0-a6
	rts

st_mdl: dc.l	0			;module
st_ins: ds.l	31			;intrument-list
st_ctr: dc.b	0			;speed-counter
st_spd: dc.b	6			;speed
st_pos: dc.w	0			;song-pos
st_nte: dc.w	0			;note-pos
st_chg: dc.w	313			;buffer-change
st_evn: dc.l	0			;even pattern
st_odd: dc.l	0			;odd pattern
st_smp: ds.l	8			;now-played samples
st_dat: ds.b	224			;now-played sample-data
st_ch1: ds.w	313			;channel mix-buffer
st_ch2: ds.w	313
st_ch3: ds.w	313
st_ch4: ds.w	313
st_mod:	incbin  'startrekker/modules/st8.chords'
