;Audio hardware offsets
ac_ptr	EQU	$00
ac_len	EQU	$04
ac_per	EQU	$06
ac_vol	EQU	$08
ac_end	EQU	$0C

		SECTION	"text",CODE

		XREF	_period1,_period2,_slen,_sample
		XDEF	_play,_endplay

;**************************************************************************
;*
;*		8 CHANNEL PLAY ROUTINE
;*
;**************************************************************************

; This code does the magic 8 channel thing (mixing).
MAGIC_8TRK	MACRO
		swap	d6
		swap	d7
		move.b	0(a3,d6.w),d0
		add.b	0(a4,d7.w),d0
		move.b	d0,(a1)+
		swap	d6
		swap	d7
		add.l	d1,d6
		add.l	d2,d7
		ENDM

_IntHandler8:	movem.l	d2/d5-d7/a2-a5,-(sp)
		lea	DB,a6
; ================ 8 channel handling (buffer swap) ======
		not.b	whichbuff-DB(a6)	;swap buffer
		bne.s	usebuff1
		move.l	a1,$a0(a0)
		move.w	#100,$a4(a0)
		bra.s	buffset
usebuff1	lea	200(a1),a1
		move.l	a1,$a0(a0)
		move.w	#100,$a4(a0)
buffset		move.w	#1<<7,$9c(a0)
		move.w	#64,$a8(a0)
; ============== fill buffers ============
startfillb	lea	track0hw-DB(a6),a2
;calculate channel A period
		move.l	#3719168,d7	;227 * 16384
		move.w	ac_per(a2),d6
		beq.s	setpzero0
		move.l	d7,d2
		divu 	d6,d2
		moveq	#0,d1
		move.w	d2,d1
		add.l	d1,d1
		add.l	d1,d1
;get channel A addresses
		move.l	ac_end(a2),a5
		move.l	(a2),d0
		beq.s	setpzero0
chA_dfnd	move.l	d0,a3	;a3 = start address, a5 = end address
;calc bytes before end
		mulu	#200<<3,d2
		clr.w	d2
		swap	d2
; d2 = # of bytes/fill
		add.l	a3,d2	;d2 = end position after this fill
		sub.l	a5,d2	;subtract sample end
		bmi.s	norestart0
		clr.l	(a2)
setpzero0	lea	zerodata-DB(a6),a3
		moveq	#0,d1
norestart0
;channel B period
		move.w	SIZE4TRKHW+ac_per(a2),d6
		beq.s	setpzero0b
		divu	d6,d7
		moveq	#0,d2
		move.w	d7,d2
		add.l	d2,d2
		add.l	d2,d2
;channel B addresses
		move.l	SIZE4TRKHW+ac_end(a2),a5
		move.l	SIZE4TRKHW(a2),d0
		beq.s	setpzero0b
		move.l	d0,a4
		mulu	#200<<3,d7
		clr.w	d7
		swap	d7
		add.l	a4,d7
		sub.l	a5,d7
		bmi.s	norestart0b
		clr.l	SIZE4TRKHW(a2)
setpzero0b	lea	zerodata-DB(a6),a4
		moveq	#0,d2
norestart0b	moveq	#0,d6
		moveq	#0,d7
		moveq	#9,d5
do8trkmagic
		MAGIC_8TRK	;20 times..
		MAGIC_8TRK
		MAGIC_8TRK
		MAGIC_8TRK
		MAGIC_8TRK
		MAGIC_8TRK
		MAGIC_8TRK
		MAGIC_8TRK
		MAGIC_8TRK
		MAGIC_8TRK
		MAGIC_8TRK
		MAGIC_8TRK
		MAGIC_8TRK
		MAGIC_8TRK
		MAGIC_8TRK
		MAGIC_8TRK
		MAGIC_8TRK
		MAGIC_8TRK
		MAGIC_8TRK
		MAGIC_8TRK

		dbf	d5,do8trkmagic	;do until cnt zero
end8trkmagic	clr.w	d6
		clr.w	d7
		swap	d6
		swap	d7
		add.l	d6,(a2)
		add.l	d7,SIZE4TRKHW(a2)
		movem.l	(sp)+,d2/d5-d7/a2-a5
		rts

playsound	;plays the notes (normally this would happen within the
		;			interrupt)
		lea	track0hw,a0	;pointer to "pseudo"-hardware
		move.w	_period1,ac_per(a0)
		move.l	_sample,d0
		move.l	d0,ac_ptr(a0)
		add.l	_slen,d0
		move.l	d0,ac_end(a0)
		; and the other channel
		lea	track4hw,a0
		move.w	_period2,ac_per(a0)
		move.l	_sample+4,d0
		move.l	d0,ac_ptr(a0)
		add.l	_slen+4,d0
		move.l	d0,ac_end(a0)
		rts

_play:		bsr.w	_InitPlayer8
		tst.l	d0
		bne.s	x_play
		bsr.s	playsound
		bsr.s	_Start8Play
x_play:		rts

_endplay	bra.w	_RemPlayer8


_Wait1line:	move.l	d0,-(sp)
		moveq	#$79,d0
wl0:		move.b	$dff007,d1
wl1:		cmp.b	$dff007,d1
		beq.s	wl1
		dbf	d0,wl0
		move.l	(sp)+,d0
		rts

_Start8Play:	;d0 = pstate
		lea	_audiobuff,a0
		move.w	#200-1,d1
clrbuffloop:	clr.w	(a0)+		;clear track buffers
		dbf	d1,clrbuffloop
		lea	$dff000,a0
		move.w	#100,$a4(a0)	;set audio buffer sizes (100 words)
		move.w	#227,$a6(a0)
		move.l	#_audiobuff,$a0(a0)
		move.w	#64,$a8(a0)
		clr.b	whichbuff-DB(a6)
		movea.l	4,a1
		move.w	#$4000,$9a(a0)
		addq.b	#1,$126(a1)
		lea	track0hw-DB(a6),a1
		clr.l	(a1)
		clr.w	ac_per(a1)
		move.w	#$0001,$dff096	;audio DMA off
		bsr.w	_Wait1line	;wait until all stopped
		st	play8-DB(a6)
		move.w	#$8080,$9a(a0)
		move.w	#$8001,$96(a0)	;DMA audio channel 1 ON
		movea.l	4,a1
		subq.b	#1,$126(a1)
		bge.s	x8play
		move.w	#$c000,$9a(a0)
x8play		rts

_End8Play:	tst.b	play8
		beq.s	noend8play
		move.w	#1<<7,$dff09a
		move.w	#$F,$dff096
		clr.b	play8
noend8play	rts

_Rem8chan:	move.l	a6,-(sp)
		lea	DB,a6
		move.b	eightrkon-DB(a6),d0
		beq.s	no8init
		clr.b	eightrkon-DB(a6)
		move.w	#1<<7,$dff09a
		moveq	#7,d0
		move.l	prevaud-DB(a6),d0
		beq.s	no8init
		move.l	d0,a1
		move.l	4,a6
		jsr	-$a2(a6)
no8init		move.l	(sp)+,a6
		rts

; *************************************************************************
; InitPlayer8() -- allocate interrupt, audio, serial port etc...
; *************************************************************************
_InitPlayer8:	bsr.s	_AudioInit
		tst.l	d0
		bne.s	IP_error
		rts
IP_error	bsr.s	_RemPlayer8
		moveq	#-1,d0
		rts

; *************************************************************************
; RemPlayer8() -- free interrupt, audio, serial port etc..
; *************************************************************************
_RemPlayer8:	bsr	_End8Play
;		vvvvvvvvvvvvvvvv  to _AudioRem
; *************************************************************************
_AudioRem:	movem.l	a5-a6,-(sp)
		lea	DB,a5
		bsr.w	_Rem8chan
		movea.l	4,a6
		tst.b	audiodevopen-DB(a5)
		beq.s	rem2
		clr.b	audiodevopen-DB(a5)
		move.w	#$000f,$dff096	;stop audio DMA
;	+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ close audio.device
		lea	allocreq-DB(a5),a1
		jsr	-$1c2(a6)	;CloseDevice()
rem2:		moveq	#0,d0
		move.b	sigbitnum-DB(a5),d0
		bmi.s	rem3
;	+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ free signal bit
		jsr	-$150(a6)	;FreeSignal()
		st	sigbitnum-DB(a5)
rem3:		movem.l	(sp)+,a5-a6
		rts

_AudioInit:	movem.l	a4/a6/d2-d3,-(sp)
		lea	DB,a4
		movea.l	4,a6
		moveq	#0,d2
;	+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ alloc signal bit
		moveq	#1,d2
		moveq	#-1,d0
		jsr	-$14a(a6)	;AllocSignal()
		tst.b	d0
		bmi.w	initerr
		move.b	d0,sigbitnum-DB(a4)
;	+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ prepare IORequest
		lea	allocport-DB(a4),a1
		move.b	d0,15(a1)	;set mp_SigBit
		move.l	a1,-(sp)
		suba.l	a1,a1
		jsr	-$126(a6)	;FindTask(0)
		move.l	(sp)+,a1
		move.l	d0,16(a1)	;set mp_SigTask
		lea	reqlist-DB(a4),a0
		move.l	a0,(a0)		;NEWLIST begins...
		addq.l	#4,(a0)
		clr.l	4(a0)
		move.l	a0,8(a0)	;NEWLIST ends...
;	+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ open audio.device
		moveq	#2,d2
		lea	allocreq-DB(a4),a1
		lea	audiodevname-DB(a4),a0
		moveq	#0,d0
		moveq	#0,d1
		jsr	-$1bc(a6)	;OpenDevice()
		tst.b	d0
		bne.w	initerr
		st.b	audiodevopen-DB(a4)
		move.w	#1<<7,$dff09a	;Init 8 channel stuff
		moveq	#7,d0		;Audio channel 0 interrupt
		lea	audiointerrupt-DB(a4),a1
		jsr	-$a2(a6)	;SetIntVector()
		move.l	d0,prevaud-DB(a4)
		st	eightrkon-DB(a4)
		moveq	#0,d0
initret:	movem.l	(sp)+,a4/a6/d2-d3
		rts
initerr:	move.l	d2,d0
		bra.s	initret

		DATA
DB:		;Data base pointer
sigbitnum	dc.b	-1
audiodevopen	dc.b	0
allocm		dc.b	$F,0
allocport	dc.l	0,0	;succ, pred
		dc.b	4,0	;NT_MSGPORT
		dc.l	0	;name
		dc.b	0,0	;flags = PA_SIGNAL
		dc.l	0	;task
reqlist		dc.l	0,0,0	;list head, tail and tailpred
		dc.b	5,0
allocreq	dc.l	0,0
		dc.b	0,127	;NT_UNKNOWN, use maximum priority (127)
		dc.l	0,allocport	;name, replyport
		dc.w	68		;length
		dc.l	0	;io_Device
		dc.l	0	;io_Unit
		dc.w	0	;io_Command
		dc.b	0,0	;io_Flags, io_Error
		dc.w	0	;ioa_AllocKey
		dc.l	allocm	;ioa_Data
		dc.l	1	;ioa_Length
		dc.w	0,0,0	;ioa_Period, Volume, Cycles
		dc.w	0,0,0,0,0,0,0,0,0,0	;ioa_WriteMsg
audiodevname	dc.b	'audio.device',0
		even

zerodata	dc.w	0
whichbuff	dc.w	0

track0hw	dc.l	0,0,tmpvol,0
track4hw	dc.l	0,0,tmpvol,0
SIZE4TRKHW	equ	16

tmpvol		dc.b	0,0,0,0

audintname	dc.b	'AM/FM AudioInterrupt example',0
		even
audiointerrupt	dc.w	0,0,0,0,0
		dc.l	audintname,_audiobuff,_IntHandler8
prevaud		dc.l	0
play8		dc.b	0
eightrkon	dc.b	0
		
		EVEN

per0	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
	dc.w	214,202,190,180,170,160,151,143,135,127,120,113
	dc.w	214,202,190,180,170,160,151,143,135,127,120,113
	dc.w	214,202,190,180,170,160,151,143,135,127,120,113

	IFND	__G2
		section "datachip",bss,chip ;for A68k
	ENDC
	IFD	__G2
		section "datachip",bss_c ;this is for Devpac 2
	ENDC

_audiobuff:	ds.w	100*2		;two 200-byte buffers
		END
