#dontinclude

; this library is for the hypithetical 2x76489an chips
; on my bread board
; Sept 15th 2024
; SMDReloaded'24



function	init_sn76489	init_sn76489_slot
rem	init_sn76489( mpislot.b )
rem	sets up sound board and silence code
rem	
rem	

def	init_sn76489_slot	byte


; frequency table

sn76489freq

	fcb	139,59	;2c	24
	fcb	133,56	;2c#	25
	fcb	131,53	;2d	26
	fcb	131,50	;2d#	27
	fcb	134,47	;2e	28
	fcb	139,44	;2f	29
	fcb	131,42	;2f#	30
	fcb	141,39	;2g	31
	fcb	137,37	;2g#	32
	fcb	136,35	;2a	33
	fcb	143,63	;2a#	34
	fcb	132,63	;2b
	fcb	139,59	;2c	24
	fcb	133,56	;2c#	25
	fcb	131,53	;2d	26
	fcb	131,50	;2d#	27
	fcb	134,47	;2e	28
	fcb	139,44	;2f	29
	fcb	131,42	;2f#	30
	fcb	141,39	;2g	31
	fcb	137,37	;2g#	32
	fcb	136,35	;2a	33
	fcb	143,63	;2a#	34
	fcb	132,63	;2b
	fcb	139,59	;3c
	fcb	133,56	;3c#
	fcb	131,53	;3d
	fcb	131,50	;3d#
	fcb	134,47	;3e
	fcb	139,44	;3f
	fcb	131,42	;3f#
	fcb	141,39	;3g
	fcb	137,37	;3g#
	fcb	136,35	;3a
	fcb	136,33	;3a#
	fcb	138,31	;3a
	fcb	141,29
	fcb	130,28
	fcb	137,26
	fcb	129,25
	fcb	139,23
	fcb	133,22
	fcb	129,21
	fcb	142,19
	fcb	140,18
	fcb	140,17
	fcb	140,16
	fcb	141,15
	fcb	142,14
	fcb	129,14
	fcb	132,13
	fcb	136,12
	fcb	141,11
	fcb	130,11
	fcb	136,10
	fcb	143,9
	fcb	134,9
	fcb	142,8
	fcb	134,8
	fcb	142,7
	fcb	135,7
	fcb	128,7
	fcb	138,6
	fcb	132,6
	fcb	142,5
	fcb	137,5
	fcb	132,5
	fcb	143,4
	fcb	139,4
	fcb	135,4
	fcb	131,4
	fcb	143,3
	fcb	139,3
	fcb	136,3
	fcb	133,3
	fcb	130,3
	fcb	143,2
	fcb	140,2
	fcb	138,2
	fcb	135,2
	fcb	133,2
	fcb	131,2
	fcb	129,2
	fcb	143,1
	fcb	141,1
	fcb	140,1
	fcb	138,1
	fcb	137,1
	fcb	135,1
	fcb	134,1
	fcb	133,1
	fcb	131,1
	fcb	130,1
	fcb	129,1
	fcb	128,1
	fcb	143,0	;8b	107

; speed table
sn76489_speedtbl
	fcb	0,0
	fcb	0,1
	fcb	1,1
	fcb	1,2
	fcb	2,2
	fcb	3,3
	fcb	4,4
	fcb	5,5
	fcb	6,6
	fcb	7,7
	fcb	8,8
	fcb	9,9
	fcb	10,10
	fcb	11,11



def	bootslot	byte	;has boot and boot on scs
def	mpislot	byte	;has boot and sound on scs

init_sn76489
	lda	$ff7f
	sta	bootslot
	anda	#240
	adda	init_sn76489_slot	;slot for 76489an's
	sta	mpislot

; basic setup end
	orcc	#$50	;kill interupts
	ldx	$010d
	stx	interupt

	ldx	#sn76489play
	stx	$010d
; mpi setup
	lda	mpislot
	sta	$ff7f	;set

; kill sounds on both chips
	lda	#159
	sta	$ff54	;channel 0 sound off
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	lda	#191
	sta	$ff54	;channel 1 sound off
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	lda	#223
	sta	$ff54	;channel 2 sound off
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	lda	#255
	sta	$ff54	;channel 3 sound off
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop	
; enable tv need to call if disrupted
	lda	$ff23
	ora	#8
	sta	$ff23
	lda	$ff03
	ora	#8
	sta	$ff03
	lda	$ff01
	ora	#8
	eora	#8
	sta	$ff01

	lda	bootslot
	sta	$ff7f	;set



; ok set starting vars loud
	lda	#144
	sta	sn76489_chan1
	lda	#176
	sta	sn76489_chan2
	lda	#208
	sta	sn76489_chan3
	lda	#240
	sta	sn76489_chan4




;test sound drop off
	lda	#0	;dead in  the water
	sta	sn76489_play	;not playing

	lda	#14
	sta	sn76489_vol0
	sta	sn76489_vol1
	sta	sn76489_vol2	
	sta	sn76489_vol3
	sta	sn76489_vol4
	sta	sn76489_vol5
	sta	sn76489_vol6
	sta	sn76489_vol7

	lda	#0
	sta	sn76489_cnt0
	sta	sn76489_cnt1
	sta	sn76489_cnt2	
	sta	sn76489_cnt3
	sta	sn76489_cnt4
	sta	sn76489_cnt5
	sta	sn76489_cnt6
	sta	sn76489_cnt7


	lda	#0
	sta	sn76489_len0
	sta	sn76489_len1
	sta	sn76489_len2	
	sta	sn76489_len3
	sta	sn76489_len4
	sta	sn76489_len5
	sta	sn76489_len6
	sta	sn76489_len7

	clr	sn76489_delta1
	clr	sn76489_delta2
	clr	sn76489_delta3


	andcc	#$ef
	rts
;**********
; the music player
; interrupt driven

def	interupt	word

def	sn76489_play	byte
def	sn76489_speed	byte

def	sn76489_pos	word
def	sn76489_rpt	word
def	sn76489_start	word

def	sn76489_delta1	byte
def	sn76489_delta2	byte
def	sn76489_delta3	byte

def	sn76489_vol0	byte	;chip 1
def	sn76489_vol1	byte
def	sn76489_vol2	byte	
def	sn76489_vol3	byte
def	sn76489_vol4	byte	;chip 2
def	sn76489_vol5	byte
def	sn76489_vol6	byte
def	sn76489_vol7	byte

def	sn76489_cnt0	byte
def	sn76489_cnt1	byte
def	sn76489_cnt2	byte
def	sn76489_cnt3	byte
def	sn76489_cnt4	byte
def	sn76489_cnt5	byte
def	sn76489_cnt6	byte
def	sn76489_cnt7	byte

def	sn76489_len0	byte
def	sn76489_len1	byte
def	sn76489_len2	byte
def	sn76489_len3	byte
def	sn76489_len4	byte
def	sn76489_len5	byte
def	sn76489_len6	byte
def	sn76489_len7	byte

def	sn76489_chan1	byte	;144
def	sn76489_chan2	byte	;176
def	sn76489_chan3	byte	;208
def	sn76489_chan4	byte	;240


sn76489play
	lda	mpislot
	sta	$ff7f
;	jsr	sn76489_silence

;check play
	if	b,sn76489_play!#0
	jsr	sn76489_musicplay
	endif


	lda	bootslot
	sta	$ff7f
	lda	$ff02
	rti
;	lda	$ff02
;	jmp	[interupt]

;**************************music play
sn76489_musicplay
	if	b,sn76489_delta1=#0
	jsr	sn76489_readyplay
	else
	ldb	sn76489_delta1
	subb	#1
	stb	sn76489_delta1
	endif
	rts

;**********************************************************************************************************play routine
sn76489_readyplay
	inc	sn76489_delta2	;second counter
	if	b,sn76489_delta2>#1
	clr	sn76489_delta2
	endif
	ldx	#sn76489_speedtbl
	lda	sn76489_speed
	ldb	#2
	mul
	abx
	ldb	sn76489_delta2
	lda	b,x
	sta	sn76489_delta1

;play speed resolved

	jsr	sn76489_silence

;nope check delta3
	lda	sn76489_delta3
	beq	sn76489_dplay
	dec	sn76489_delta3
	rts	;not ready

sn76489_dplay

	ldx	sn76489_pos
	stx	$400

sn76489_process

	ldb	,x+	;controller
	lda	,x+	;data
	cmpb	#12	;its a repeat looper locater
	lbeq	sn76489_repeatset	;new delta counter
	cmpb	#13	;delay
	lbeq	sn76489_setdelay	;new wait
	cmpb	#21
	lbeq	sn76489_resetsng
	cmpb	#14
	lbeq	sn76489_setchan0
	cmpb	#15
	lbeq	sn76489_setchan1
	cmpb	#16
	lbeq	sn76489_setchan2
	cmpb	#17
	lbeq	sn76489_setchan4
	cmpb	#18
	lbeq	sn76489_setchan5
	cmpb	#19
	lbeq	sn76489_setchan6	;snare
	cmpb	#20
	lbeq	sn76489_setchan7	;snare

	lbra	sn76489_process

sn76489_setdelay

	stx	sn76489_pos	;stx spos
	sta	sn76489_delta3
	rts	;done




; repeat locator
sn76489_repeatset
	stx	sn76489_rpt	;song repeater set
	lbra	sn76489_process


; reset
sn76489_resetsng
	ldx	sn76489_rpt
	stx	sn76489_pos
	if	b,sn76489_play=#1
	clra
	sta	sn76489_play	;play only once
	endif
	rts

;**********************************************************************************************************************
sn76489_setchan0
; first byte=note
; second byte =length

	ldy	#sn76489freq
	lda	,x+	;note

	suba	#24	;calibration adjustment will be needed
	ldb	#2
	mul
	leay	d,y

; sound chip 1 ff48
	lda	,y
	adda	#0	;add channel in
	sta	$ff44	;chip 1 channel 0
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	lda	1,y
	sta	$ff44	;data byte
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	lda	#159	;chan 0
	suba	#15	;volume setting
	sta	$ff44	;note on

	lda	,x+	;length
	lsra
	sta	sn76489_len0
	sta	sn76489_cnt0
	lda	#0
	sta	sn76489_vol0

	lbra	sn76489_process


sn76489_setchan1

; first byte=note
; second byte =length

	ldy	#sn76489freq
	lda	,x+	;note

	suba	#24	;calibration adjustment will be needed
	ldb	#2
	mul
	leay	d,y

; sound chip 1 ff48
	lda	,y
	adda	#32	;add channel in 1
	sta	$ff44	;chip 1 channel 1
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	lda	1,y
	sta	$ff44	;data byte
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	lda	#191	;chan 1
	suba	#15	;volume setting
	sta	$ff44	;note on

	lda	,x+	;length
	lsra
	sta	sn76489_len1
	sta	sn76489_cnt1
	lda	#0
	sta	sn76489_vol1

	lbra	sn76489_process








sn76489_setchan2


; first byte=note
; second byte =length

	ldy	#sn76489freq
	lda	,x+	;note

	suba	#24	;calibration adjustment will be needed
	ldb	#2
	mul
	leay	d,y

; sound chip 1 ff48
	lda	,y
	adda	#64	;add channel in 2
	sta	$ff44	;chip 1 channel 2
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	lda	1,y
	sta	$ff44	;data byte
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	lda	#223	;chan 2
	suba	#15	;volume setting
	sta	$ff44	;note on

	lda	,x+	;length
	lsra
	sta	sn76489_len2
	sta	sn76489_cnt2
	lda	#0
	sta	sn76489_vol2

	lbra	sn76489_process




sn76489_setchan3
; first byte=note
; second byte =length

	ldy	#sn76489freq
	lda	,x+	;note

	suba	#24	;calibration adjustment will be needed
	ldb	#2
	mul
	leay	d,y

; sound chip 2 ff57
	lda	,y
	adda	#0	;add channel in
	sta	$ff57	;chip 2 channel 0
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	lda	1,y
	sta	$ff57	;data byte
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	lda	#159	;chan 0
	suba	#15	;volume setting
	sta	$ff57	;note on

	lda	,x+	;length
	lsra
	sta	sn76489_len4
	sta	sn76489_cnt4
	lda	#0
	sta	sn76489_vol4

	lbra	sn76489_process


sn76489_setchan4

; first byte=note
; second byte =length

	ldy	#sn76489freq
	lda	,x+	;note

	suba	#24	;calibration adjustment will be needed
	ldb	#2
	mul
	leay	d,y

; sound chip 2 ff57
	lda	,y
	adda	#32	;add channel in
	sta	$ff57	;chip 2 channel 0
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	lda	1,y
	sta	$ff57	;data byte
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	lda	#191	;chan 1
	suba	#15	;volume setting
	sta	$ff57	;note on

	lda	,x+	;length
	lsra
	sta	sn76489_len5
	sta	sn76489_cnt5
	lda	#0
	sta	sn76489_vol5

	lbra	sn76489_process






sn76489_setchan5
	ldd	,x++
	lbra	sn76489_process


sn76489_setchan6
;	ldd	,x++
	lbra	sn76489_process

sn76489_setchan7
;	ldd	,x++
	lbra	sn76489_process







;*****volume controller
sn76489_silence


; chip 1 $ff48

	clrb

sn76489_silen1

	ldx	#sn76489_vol0
	leax	b,x
	lda	8,x	;delay counter
	bne	sn76489_silen2
	lda	16,x	;length
	sta	8,x
; lower the volume
	lda	0,x
	cmpa	#15
	bhs	sn76489_silen2
	inc	,x
sn76489_silen2
	lda	8,x
	beq	sn76489_silen3
	dec	8,x
sn76489_silen3
	lda	24,x	;chan
	adda	,x
	sta	$ff44	;may change
	nop
	nop
	nop
	nop
	incb
	cmpb	#4
	blo	sn76489_silen1

; chip 1 $ff57

	clrb

sn76489_silen11

	ldx	#sn76489_vol4
	leax	b,x
	lda	8,x	;delay counter
	bne	sn76489_silen22
	lda	16,x	;length
	sta	8,x
; lower the volume
	lda	,x
	cmpa	#15
	bhs	sn76489_silen22
	inc	,x
sn76489_silen22
	lda	8,x
	beq	sn76489_silen33
	dec	8,x
sn76489_silen33
	lda	24,x	;chan
	adda	,x
	sta	$ff57	;may change
	nop
	nop
	nop
	nop
	incb
	cmpb	#4
	blo	sn76489_silen11

	rts

endfunction





;*****************************************************************************************************************************************************************
function	sn_playmusic	sn76489_plays,sn76489_speed,sn76489_start
rem	sn_playmusic( play.b , speed.b , address.w )
rem	
rem	
rem	


def	sn76489_plays	byte
ref	sn76489_speed	byte
ref	sn76489_pos	word
ref	sn76489_rpt	word
ref	sn76489_start	word

; make sure settings are good
sn_playmusic
	clr	sn76489_delta1
	clr	sn76489_delta2

	ldd	sn76489_start
	std	sn76489_rpt
	std	sn76489_pos
	lda	sn76489_plays
	sta	sn76489_play
	rts

endfunction





;********************************************************************************************************************************************************************************
function	snd_outline
rem	snd_outline()
rem	setsup snd line from sound source to tv
rem	
rem	

snd_outline
; enable tv need to call if disrupted
	lda	$ff23
	ora	#8
	sta	$ff23
	lda	$ff03
	ora	#8
	sta	$ff03
	lda	$ff01
	ora	#8
	eora	#8
	sta	$ff01
	rts
endfunction
