;		AT LAST SOMEONE DID A CHANGE ON IT!
;
;		    AMICOM - THE HARDWARE WIZARD
;
;			     PRESENTS
;
;		AMICOM'S FAST SOUNDTRACKER PLAYER 34
;
;			  DONE IN 8-1989
;		    BY THE POWER OF SPREADPOINT
;
;--------------------------------------------------------

;@ test version showing speedtest


; V35 AMICOM 1989-11-29 = some minor changes
;  regs in soundinit/soundoff saved
;  illegal clr in soundoff replaced
;  status of l6int in INTENA saved/restored
; V36 AMICOM 1989-12-21 = minor change
; re-init didn't always work
; had change position of soundoff call
; V37 AMICOM 1990-03-02
; freed a5 for use in re-entrant progs



start:;	EXAMPLEPLAYER
	lea	song,a0			; replace with move [allocated
					; base in chip memory],a0
	lea	songptr(pc),a1
	move.l	a0,(a1)			; tell player where song is
	bsr.s	timerinit		; init timer stuff
	bsr.L	soundinit		; init and set position to start
loop:
	cmpi.b	#200,$dff006		; stupid, but ok for this example
	bne.s	loop
	move.w	#$000f,$dff180		;@color
	bsr.L	soundplay
	move.w	#0,$dff180		;@color / don't use clr!
lolo:	cmpi.b	#201,$dff006		; yes, this must be done!
	blo.s	lolo
	btst	#7,$bfe001		; restart sound on fire
	bne.s	nores
	bsr.L	soundinit
nores:	btst	#6,$bfe001
	bne.s	loop
	bsr.L	soundoff		; sound off, before timeroff!
	bsr.L	timerexit		; timer off
	rts


**********************************************************************
*** Mega fast playroutine for the Spreadpoint SoundTracker V2.3-2.5 **
****  ^  gröl!! (comment from Depeche)				    **
**************** Based on the playroutine from TJC *******************
*********** Improved and omptimized by Unknown of D.O.C **************
***   shortened, sped up & made work on all 680X0 by Power Point    **
***     Finally repaired, pipelined and interrupt wait added by	    **
***			     A M I C O M			    **
**********************************************************************

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	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				;
					
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

soundinit:				
	movem.l	d0-d7/a0-a6,-(a7)	;
	bsr.s	soundoff		
	lea	soundcounter(pc),a0	;
	clr.b	(a0)			; ensure re-init works ok
	move.l	songptr(pc),a0		
	add.w	#$3b8,a0		
	moveq	#$7f,d0			
	moveq	#$00,d1			
					
soundinit1:				
	move.l	d1,d2			
	subq.w	#1,d0			
					
soundinit2:				
	move.b	(a0)+,d1		
	cmp.b	d2,d1			
	bgt.s	soundinit1		
	dbra	d0,soundinit2		
	addq.b	#1,d2			
					
soundinit3:				
	move.l	songptr(pc),a0		
	add.w	#42,a0			
	lea	soundsample1(pc),a1	
	move.l	a1,a3			
	moveq	#10,d3			
	asl.l	d3,d2			
	lea	$438-42(a0),a4		
	add.l	d2,a4			
	moveq	#30,d0			
	moveq	#$1e,d2			
					
soundinit4:				
	move.l	a4,(a3)+		
	moveq	#$00,d1			
	move.w	(a0),d1			
	add.l	d1,d1			
	add.l	d1,a4			
	add.w	d2,a0			
	dbra	d0,soundinit4		

	moveq	#30,d0			
					
soundclear:				
	move.l	(a1)+,a0		; soundsamples
	clr.l	(a0)			
	dbra	d0,soundclear		

	lea	soundregdata1(pc),a0	
	moveq	#31,d0			; 8 words, 4 ch

soundclear2:				
	move.w	#-1,(a0)+		; clr register buffer
	dbf	d0,soundclear2		

	bsr.L	soundsixinit 		; start & do 4 channels
	movem.l	(a7)+,d0-d7/a0-a6	
	rts				

soundoff:				
	movem.l	a0/a1,-(a7)		; used regs
	lea	$dff0a8,a0		
	move.w	#0,(a0)			; $dff0a8, don't use clr!
	move.w	#0,$10(a0)		; $dff0b8
	move.w	#0,$20(a0)		; $dff0c8
	move.w	#0,$30(a0)		; $dff0d8
	move.w	#$000f,$96-$a8(a0)	; $dff096
	lea	soundpartnrplay(pc),a0	
	clr.l	(a0)			; clr ok here!
	lea	soundpartnote(pc),a0	
	clr.l	(a0)			
	lea	soundpartpoint(pc),a0	
	clr.l	(a0)			

	lea	soundmaxpart+1(pc),a0	
	move.l	songptr(pc),a1		
	move.b	$3b6(a1),(a0)		
	movem.l	(a7)+,a0/a1		
	rts				


soundplay:
	lea	soundcounter(pc),a0
	addq.b	#1,(a0)
	move.b	soundcoolcounter(pc),d0
soundcool:
	cmp.b	(a0),d0
	bne.s	soundnotsix
	clr.b	(a0)
	bra	soundrout2

soundnotsix:
	lea	soundaud1temp(pc),a6
	lea	$dff0a0,a2
	moveq	#3,d7
soundnotsixloop:
	tst.b	3(a6)
	beq.s	soundnotarprout
soundarprout:
	move.b	2(a6),d0
	and.b	#$0f,d0
	beq	soundarpegrt
	subq.b	#1,d0;			1 ?
	beq.s	soundportup
	subq.b	#1,d0;			2 ?
	beq.s	soundportdwn
	subq.b	#8,d0;			$a ?
	beq.s	soundvolslide
soundnotarprout:
	add.w	#soundaudtemplen+0,a6	;'+0' for idiot-SEKA
	add.w	#$10,a2
	dbra	d7,soundnotsixloop

soundnotsix2:
	lea	soundctrl0(pc),a4	; channel counter
	tst.w	(a4)			;
	beq.s	soundnotsix2_x		;
	subq.w	#1,(a4)			;

	movem.l	soundtmpdat(pc),d1/a0/a3/a2/a6	; get local parameters
						; a2= soundregdata1
						; a6= soundaud1temp
	bsr	soundplayit
	add.w	#$10,a2	;		$dff0b0...
	add.w	#soundaudtemplen+0,a6
	lea	soundtmpdat(pc),a4
	movem.l	d1/a0/a3/a2/a6,(a4)	;

soundnotsix2_x:
	rts


soundportup:
	moveq	#$00,d0
	move.b	3(a6),d0
	sub.w	d0,22(a6)
	moveq	#124,d0		; min. period
	cmp.w	22(a6),d0	; val <124 will cause distortion!
	blo.s	soundok1
	move.w	d0,22(a6)
soundok1:
	move.w	22(a6),6(a2)
	bra.s	soundnotarprout

soundportdwn:
	moveq	#$00,d0
	move.b	3(a6),d0
	add.w	d0,22(a6)
	move.w	#1336,d0
	cmp.w	22(a6),d0
	bhi.s	soundok2
	move.w	d0,22(a6)
soundok2:
	move.w	22(a6),6(a2)
	bra.s	soundnotarprout

soundvolslide:
	moveq	#0,d0
	move.b	3(a6),d0
	move.w	d0,d1
	lsr.b	#4,d0
	beq.s	soundvoldwn
	add.w	d0,18(a6)
	moveq	#64,d0
	cmp.w	18(a6),d0
	bhs.s	soundok3
	move.w	d0,18(a6)
soundok3:
	move.w	18(a6),8(a2)
	bra.L	soundnotarprout
soundvoldwn:
	and.b	#$0f,d1
	sub.w	d1,18(a6)
	bpl.s	soundok4
	clr.w	18(a6)
soundok4:
	move.w	18(a6),8(a2)
	bra	soundnotarprout

soundarpegrt:
	move.b	soundcounter(pc),d0
	subq.b	#1,d0;				1 ?
	beq.s	soundloop2
	subq.b	#1,d0;				2 ?
	beq.s	soundloop3
	subq.b	#1,d0;				3 ?
	beq.s	soundloop4
	subq.b	#1,d0;				4 ?
	beq.s	soundloop2
	subq.b	#1,d0;				5 ?
	beq.s	soundloop3
	bra	soundnotarprout

soundloop2:
	moveq	#$00,d0
	move.b	3(a6),d0
	lsr.b	#4,d0
	bra.s	soundcont
soundloop3:
	moveq	#$00,d0
	move.b	3(a6),d0
	and.b	#$0f,d0
	bra.s	soundcont
soundloop4:
	move.w	16(a6),d2
	bra.s	soundendpart
soundcont:
	add.w	d0,d0
	moveq	#$00,d1
	move.w	16(a6),d1
	lea	soundarpeggio(pc),a0
soundloop5:
	move.w	(a0,d0),d2
	cmp.w	(a0)+,d1
	bne.s	soundloop5
soundendpart:
	move.w	d2,6(a2)
	bra	soundnotarprout

soundrout2:
soundcopyparam:				
	lea	soundregdata1(pc),a4	;
	lea	$dff0a0,a2		;
	moveq	#3,d1			; 4 channels
	moveq	#-1,d6			; to clear
					
soundcopyp_2:				
	move.l	(a4)+,d0		;
	bmi.s	soundnotnewptr		;
	move.l	d6,-4(a4)		; clear it
	move.l	d0,(a2)			; ptr
					
soundnotnewptr:				
	addq.l	#4,a2			; next reg

	move.w	(a4)+,d0		;
	bmi.s	soundnotnewlen		;
	move.w	d6,-2(a4)		; clear it
	move.w	d0,(a2)			; len
					
soundnotnewlen:				
	addq.l	#2,a2			; next reg
				
	move.w	(a4)+,d0		;
	bmi.s	soundnotnewper		;
	move.w	d6,-2(a4)		; clear it
	move.w	d0,(a2)			; per
					
soundnotnewper:				
	addq.l	#2,a2			; next reg
	move.w	(a4)+,d0		;
	bmi.s	soundnotnewvol		;
	move.w	d6,-2(a4)		;
	move.w	d0,(a2)			; vol
					
soundnotnewvol:				
	addq.l	#6,a4			; next data set
	addq.l	#8,a2			; next reg. set
					
	dbf	d1,soundcopyp_2		;

	move.w	sounddmacon(pc),$dff096	;

	or.b	#1,$bfde00		; start ciab timerA
	rts				;
					
timerl6handler:				
	move.w	#$0f0f,$dff180			;@color
	movem.l	d0/d1/d6/d7/a0/a2-a6,-(a7)	; used registers only!
	bsr.s	soundwaitcont			; do delayed routine
	tst.b	$bfdd00				; clr cia int req
	move.w	#$2000,$dff09c			; clr int req
	movem.l	(a7)+,d0/d1/d6/d7/a0/a2-a6	;
	move.w	#$0000,$dff180			;@color
	rte					;
					
soundwaitcont:
	move.w	#$8000,d0
	or.w	sounddmacon(pc),d0

	lea	$dff0d0,a2
	move.w	d0,$96-$d0(a2);			$dff096
	lea	soundaud4temp(pc),a6
	moveq	#$10,d6
	moveq	#1,d1
	moveq	#3,d7
soundvoiceloop:
	cmp.w	14(a6),d1
	bne.s	soundnextvoice
	move.l	10(a6),(a2);			$dff0d0
	move.w	d1,4(a2);			$dff0d4 ,len
soundnextvoice:
	sub.w	#soundaudtemplen+0,a6
	sub.l	d6,a2;				#$10
	dbra	d7,soundvoiceloop
	lea	soundpartnote(pc),a0
	move.l	(a0),d0
	add.l	d6,d0;				#$10
	move.l	d0,(a0);			soundpartnote
	cmp.l	#$400,d0
	bne.s	soundstop
soundhigher:
	clr.l	(a0);				soundpartnote
	lea	soundpartnrplay(pc),a3
	addq.l	#1,(a3);			soundpartnrplay
	moveq	#$00,d0
	move.w	soundmaxpart(pc),d0
	move.l	(a3),d1;			soundpartnrplay
	cmp.l	d0,d1
	bne.s	soundstop
	clr.l	(a3);				soundpartnrplay

soundstop:
	lea	soundstatus(pc),a4
	tst.w	(a4)
	beq.s	soundstop2
	clr.w	(a4)
	bra.s	soundhigher
soundstop2:

soundsixinit:
	move.l	songptr(pc),a0
	add.w	#$43c,a0
	lea	$c-$43c(a0),a3
	lea	$3b8-$43c(a0),a4
	move.l	soundpartnrplay(pc),d0
	moveq	#$00,d1
	move.b	(a4,d0),d1
	moveq	#10,d6
	asl.l	d6,d1
	add.l	soundpartnote(pc),d1
	lea	soundpartpoint(pc),a4
	move.l	d1,(a4)
	lea	sounddmacon(pc),a4
	clr.w	(a4)
	lea	soundregdata1(pc),a2	; dff0a0
	lea	soundaud1temp(pc),a6
	lea	soundtmpdat(pc),a4
	movem.l	d1/a0/a3/a2/a6,(a4)	; store local data
	lea	soundctrl0(pc),a4	;  for playit
	move.w	#4,(a4)			; 4 channels to do
	rts


soundplayit:
	move.l	(a0,d1),(a6)
	addq.l	#4,d1
	moveq	#$00,d2
	move.b	2(a6),d2
	lsr.b	#4,d2
	beq.s	soundnosamplechange

	lea	soundsamples(pc),a1
	move.l	d2,d4
	add.w	d2,d2
	lsl.w	#5,d4;
	sub.w	d2,d4;		=	mulu	#$1e,d4
	add.w	d2,d2
	moveq	#$00,d3
	move.l	(a1,d2),4(a6)
	move.w	(a3,d4),8(a6)
	move.w	2(a3,d4),18(a6)
	move.w	4(a3,d4),d3
	beq.s	sounddisplace
	move.l	4(a6),d2
	add.l	d3,d2
	move.l	d2,4(a6)
	move.l	d2,10(a6)
	move.w	6(a3,d4),8(a6)
	move.w	6(a3,d4),14(a6)
	move.w	18(a6),8(a2)
	bra.s	soundnosamplechange

sounddisplace:
	move.l	4(a6),d2
;	add.l	d3,d2;			What the hell? (Power Point)
	move.l	d2,10(a6)
	move.w	6(a3,d4),14(a6)
	move.w	18(a6),8(a2)
soundnosamplechange:
	tst.w	(a6)
	beq.s	soundretrout
	move.w	(a6),16(a6)
	move.l	4(a6),(a2)
	move.w	8(a6),4(a2)
	move.w	(a6),6(a2)
	lea	sounddmacon(pc),a4
	move.w	20(a6),d0
	or.w	d0,(a4)

soundretrout:
	tst.w	(a6)
	beq.s	soundnonewper
	move.w	(a6),22(a6)

soundnonewper:
	lea	soundstatus(pc),a4
	move.b	2(a6),d0
	and.b	#$0f,d0
	sub.b	#11,d0;			11 ?
	beq.s	soundposjmp
	subq.b	#1,d0;			12 ?
	beq.s	soundsetvol
	subq.b	#1,d0;			13 ?
	beq.s	soundbreak
	subq.b	#1,d0;			14 ?
	beq.s	soundsetfil
	subq.b	#1,d0;			15 ?
	beq.s	soundsetspeed
	rts

soundposjmp:
	not.w	(a4);			soundstatus
	moveq	#$00,d0
	move.b	3(a6),d0
	subq.b	#1,d0
	lea	soundpartnrplay(pc),a4
	move.l	d0,(a4)
	rts

soundsetvol:
	moveq	#0,d0
	move.b	3(a6),d0
	move.w	d0,8(a2)
	rts

soundbreak:
	not.w	(a4);			soundstatus
	rts

soundsetfil:
	lea	$bfe001,a4
	move.b	3(a6),d0
	btst	#0,3(a6)
	bne.s	filteron
filteroff:
	bclr	#1,(a4)
	rts
filteron:
	bset	#1,(a4)
	rts

soundsetspeed:
	move.b	3(a6),d0
	and.b	#$0f,d0
	beq.s	soundback
;	lea	soundcounter(pc),a4 ;	what !!? (AMICOM)
;	clr.b	(a4) ;			
	lea	soundcoolcounter(pc),a4
	move.b	d0,(a4)
soundback:
	rts

soundaud1temp:
			blk.w	10,0
			dc.w	$0001
			blk.w	2,0
soundaud2temp:
			blk.w	10,0
			dc.w	$0002
			blk.w	2,0
soundaud3temp:
			blk.w	10,0
			dc.w	$0004
			blk.w	2,0
soundaud4temp:
			blk.w	10,0
			dc.w	$0008
			blk.w	2,0
soundaudtemplen=soundaud2temp-soundaud1temp

soundpartnote:		dc.l	0
soundpartnrplay:	dc.l	0
soundpartpoint:		dc.l	0
soundsamples:		dc.l	0
soundsample1:		blk.l	31,0
soundmaxpart:		dc.w	$0000
sounddmacon:		dc.w	$0000
soundstatus:		dc.w	$0000

soundregdata1:		blk.w	8,-1	; dff0a0
			blk.w	8,-1
			blk.w	8,-1
soundregdata4:		blk.w	8,-1	; dff0d0

soundctrl0:		dc.w	0	; no channel to treat now
soundtmpdat:		blk.l	5,0
songptr:		dc.l	0	; pointer to song data
					; must be set by main prog!
soundcounter:		dc.b	0
soundcoolcounter:	dc.b	6

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

;----------------------------------------------------------

; copy this data to CHIP memory or place it into
; a DATA:CHIP hunk section

song:
;blk.w	97552/2,0
