*  Dieses Modul stellt eine universelle interruptgesteuerte
*  Sample-Play-Routine fr alle STs zur Verfgung:
*
*  Data = play_sam( Startadresse, Endadresse, Hertz, Hold, DMA );
*
*  Parameterbergabe in Purbo-C-Manier (A0,A1,D0,D1,D2).
*  Aufruf normal im USER-Mode.
*  Endadresse muá direkt HINTER die Sampledaten zeigen
*  (Konvention wie FRAME-Adressen beim STE/TT-DMA-Sound).
*  Sound abschalten mit Endadresse == Startadresse und Hold == 0.
*  Dabei muá die angegebene Adresse auch tatschlich mit der
*  ursprnglich zum Spielen des betreffenden Samples angegebenen
*  Startadresse bereinstimmen, sonst passiert nichts!
*  Bevor man das DMA-Flag setzt, sollte man sicherstellen
*  (Cookie-Abfrage), daá DMA-Sound berhaupt mglich ist!
*  In D0.W wird eine Kennung fr die Frequenzeinstellung
*  zurckgegeben (kann ignoriert oder dazu benutzt werden, um
*  nachtrglich die Frequenz whrend des Spielens zu verndern).
*
*  Es muá PCTOSLIB.LIB mit gelinkt werden.

	import	Super, Xbtimer
	export	play_sam

	text
	super				; privileg. Befehle erlauben

play_sam:
	movem.l	d0-d2/a0-a1,-(a7)	; Register retten
	clr.l	d0
	lea	volt,a1			; Adresse der Pegelwerte
	bclr	d0,(a1)			; Flag Tabelle initialisieren
	beq	start			; ok
	subq.b	#1,d0			; Lnge der Tabelle (-1) = 255
	lea	tabelle,a0		; Adresse der Soundbytes
	clr.b	-2(a0)			; conterm not saved
loop:	move.b	#$8,(a0)		; Umwandeln
	move.b	#$9,4(a0)		; der
	move.b	#$A,8(a0)		; Pegelwerte
	move	(a1)+,d1
	move	d1,d2
	and	#15,d2
	move.b	d2,10(a0)		; in auszugebende
	lsr	#4,d1
	move	d1,d2
	and	#15,d2
	move.b	d2,6(a0)		; Lautstrken
	lsr	#4,d1
	move.b	d1,2(a0)		; fr den Soundchip
	lea	16(a0),a0		; immer 16 Bytes
	dbra	d0,loop 		; loopen

start:	sub.l	a0,a0
	jsr	Super
	move.l	d0,a0

	lea	sam_data,a1
	move.l	12(a7),d1		; Frame Base Address
	move.l	16(a7),d2		; Frame End Address

	tst	10(a7)			; DMA-Sound ?
	bne	dma			; aber ja doch!

	cmp.l	d2,d1
	bne	doit
	cmp.l	8(a1),d1
	bne	done
doit:	clr.b	$FFFFFA19.w		; Timer A Stop
	move.l	d1,(a1)+		; Frame Address Counter
	move.l	d2,(a1)+		; Frame End Address
	move.l	d1,(a1)+		; Frame Base Address
	move.w	6(a7),(a1)+		; Frame Hold
	tas	(a1)+			; conterm saved
	bne	go_on
	move.b	$484.w,(a1)		; save conterm
	and.b	#%11111010,$484.w	; Klick/Bell aus !
go_on:	move.b	#64,$FFFFFA17.w		; AEOI
	move.l	#$07007F00,$FFFF8800.w	; Soundchip-Init

	jsr	Super

	lea	play_s(pc),a0		; Interrupt Player
	move.l	#1228800,d2		; Frequenz
	divu.w	2(a7),d2		; in
	addq.w	#1,d2			; Teiler
	lsr.w	#1,d2			; umrechnen (runden)
	move.l	d2,(a7)			; Data und merken
	moveq.l	#1,d1			; Control
	clr	d0			; Timer A
	jsr	Xbtimer			; starten bitte...
	bra	raus

dma:	cmp.l	d2,d1
	bne	dostop
	cmp.l	-4(a1),d1
	bne	done
dostop:	clr	$FFFF8900.w		; DMA-Sound Stop
	cmp.l	d2,d1
	beq	done
	move.l	d1,-(a1)
	move.b	d1,$FFFF8907.w
	lsr.l	#8,d1
	move.b	d1,$FFFF8905.w
	lsr.l	#8,d1
	move.b	d1,$FFFF8903.w
	bclr	#0,d2			; force even address!
	move.b	d2,$FFFF8913.w
	lsr.l	#8,d2
	move.b	d2,$FFFF8911.w
	lsr.l	#8,d2
	move.b	d2,$FFFF890F.w
	move.l	#10000,a1
	move	#$80,d0			; Mono, 6258 Hz
	cmp.l	(a7),a1
	bgt	setmod
	add.l	a1,a1
	addq	#1,d0			;	12517 Hz
	cmp.l	(a7),a1
	bgt	setmod
	add.l	a1,a1
	addq	#1,d0			;	25033 Hz
	cmp.l	(a7),a1
	bgt	setmod
	addq	#1,d0			;	50066 Hz
setmod:	move.w	d0,$FFFF8920.w		; Sound Mode Control
	move.l	d0,(a7)			; und merken
	move.l	4(a7),d0		; Frame Hold
	add	d0,d0
	addq	#1,d0
	move.w	d0,$FFFF8900.w		; Sound DMA Control

done:	jsr	Super
raus:	movem.l	(a7)+,d0-d2/a0-a1	; Register holen
	rts				; und zurck

* Interrupt Player

	dc.l	'XBRA', 'SMPL', imret
play_s:	movem.l	d0/a0-a1,-(a7)		; Register retten
	lea	sam_data,a0		; Adresse der Sampledaten
	move.l	(a0)+,a1 		; Aktuelle Sampleadresse
	cmp.l	(a0),a1			; Endadresse erreicht ?
	bcc	test			; ja --> Hold-Test
	move.w	#128,d0			; offset
	add.b	(a1)+,d0		; Datenbyte plus offset
	move.l	a1,-(a0) 		; Nchste Sampleadresse
	lsl.w	#4,d0
	lea	16(a0,d0.w),a0
	move.l	(a0)+,$FFFF8800.w	; beep Kanal 1
	move.l	(a0)+,$FFFF8800.w	; beep Kanal 2
	move.l	(a0)+,$FFFF8800.w	; beep Kanal 3
ende:	movem.l	(a7)+,d0/a0-a1		; Register holen
imret:	rte				; und zurck

test:	move.w	8(a0),d0
	beq	stop			; kein Hold --> AUS
	move.l	4(a0),-4(a0)		; Play it again, Sam...
	bra	ende
stop:	clr.b	$FFFFFA19.w		; Timer A Stop
	and.b	#%11111010,$484.w	; Klick/Bell ausblenden
	move.b	11(a0),d0		; saved conterm
	and.b	#%00000101,d0		; nur Klick/Bell
	or.b	d0,$484.w		; einblenden
	clr.b	10(a0)			; conterm not saved
	bra	ende

	data

volt:	dc.w	$0100, $0200, $0210, $0310, $0410, $0510, $0600, $0610
	dc.w	$0630, $0710, $0720, $0731, $0741, $0810, $0820, $0831
	dc.w	$0841, $0900, $0910, $0930, $0940, $0950, $0951, $0953
	dc.w	$0962, $0963, $0A10, $0A30, $0A31, $0A50, $0A52, $0A53
	dc.w	$0A62, $0A70, $0A72, $0B10, $0B30, $0B31, $0B41, $0B51
	dc.w	$0B53, $0B62, $0B63, $0B72, $0B74, $0B80, $0B81, $0B83
	dc.w	$0B84, $0B85, $0B91, $0B93, $0B94, $0C20, $0C21, $0C41
	dc.w	$0C51, $0C53, $0C62, $0C70, $0C72, $0C74, $0C75, $0C82
	dc.w	$0C84, $0C85, $0C90, $0C92, $0C94, $0C95, $0C96, $0C97
	dc.w	$0C97, $0CA0, $0CA3, $0D20, $0D31, $0D50, $0D52, $0D61
	dc.w	$0D70, $0D72, $0D74, $0D75, $0D82, $0D84, $0D90, $0D91
	dc.w	$0D94, $0D95, $0D96, $0D97, $0DA0, $0DA0, $0DA3, $0DA5
	dc.w	$0DA6, $0DA7, $0DA8, $0DA8, $0DA8, $0DB1, $0DB4, $0DB6
	dc.w	$0DB7, $0DB7, $0DB8, $0DB8, $0DB9, $0DB9, $0DB9, $0DBA
	dc.w	$0DBA, $0DBA, $0DBA, $0DBA, $0DC2, $0DC5, $0DC6, $0E00
	dc.w	$0E31, $0E52, $0E62, $0E72, $0E75, $0E81, $0E85, $0E90
	dc.w	$0E93, $0E96, $0E97, $0E98, $0E98, $0EA2, $0EA6, $0EA7
	dc.w	$0EA8, $0EA9, $0EA9, $0EA9, $0EB3, $0EB7, $0EB8, $0EB9
	dc.w	$0EB9, $0EBA, $0EBA, $0EBA, $0EBA, $0EC0, $0EC0, $0EC0
	dc.w	$0EC7, $0EC7, $0EC8, $0EC8, $0EC9, $0ECA, $0ECA, $0ECA
	dc.w	$0ECA, $0ECB, $0ECB, $0ECB, $0ED0, $0ED0, $0ED0, $0ED7
	dc.w	$0ED7, $0ED7, $0ED9, $0ED9, $0ED9, $0EDA, $0EDA, $0EDA
	dc.w	$0EDB, $0EDB, $0EDB, $0F00, $0F00, $0F00, $0F70, $0F70
	dc.w	$0F90, $0F90, $0F90, $0FA0, $0FA0, $0FA9, $0FB0, $0FB0
	dc.w	$0FB0, $0FBA, $0FBA, $0FC0, $0FC0, $0FC9, $0FC9, $0FCA
	dc.w	$0FCA, $0FCA, $0FCB, $0FCB, $0FCB, $0FCC, $0FCC, $0FCC
	dc.w	$0FD0, $0FD0, $0FD0, $0FD0, $0FD0, $0FD0, $0FD0, $0FDB
	dc.w	$0FDB, $0FDB, $0FDB, $0FDB, $0FDB, $0FDB, $0FDC, $0FDC
	dc.w	$0FDC, $0FDC, $0FDC, $0FDC, $0FDD, $0FDD, $0FDD, $0FDD
	dc.w	$0FDD, $0FDD, $0FE0, $0FE0, $0FE0, $0FE0, $0FE0, $0FE0
	dc.w	$0FE0, $0FE0, $0FE0, $0FEC, $0FEC, $0FEC, $0FEC, $0FEC
	dc.w	$0FEC, $0FED, $0FED, $0FED, $0FED, $0FED, $0FED, $0FED

	bss

	ds.l	1		; DMA Base Address
sam_data:
	ds.l	1		; Frame Address Counter
	ds.l	1		; Frame End Address
	ds.l	1		; Frame Base Address
	ds.w	1		; Frame Hold
	ds.b	1		; conterm saved
	ds.b	1		; saved conterm
tabelle:
	ds.l	1024
