; include file

#dontinclude


function	init_sidmml
rem	init_sidmml()
rem	
rem	
rem	setup sid music macro for assembly using irq


init_sidmml_playspeed
	fcb	0,0
	fcb	0,1
	fcb	1,1
	fcb	1,2
	fcb	2,2
	fcb	2,3
	fcb	3,3
	fcb	3,4
	fcb	4,4
	fcb	5,5
	fcb	6,6
	fcb	7,7
	fcb	8,8
	fcb	9,9
	fcb	10,10
	fcb	11,11
	fcb	12,12
	fcb	13,13
	fcb	14,14
	fcb	15,15
	fcb	16,16
	fcb	17,17
	fcb	18,18
	fcb	19,19
	fcb	20,20

init_sidmml_tones
	fdb	274,291,308,326,346,366,388,411,435,461,489,518	;oct 0
	fdb	549,581,616,652,691,732,776,822,871,923,978,1036	;oct 1
	fdb	1097,1163,1232,1305,1383,1465,1552,1644,1742,1845,1955,2071	;oct 2
	fdb	2195,2325,2463,2610,2765,2930,3104,3288,3484,3691,3910,4143	;oct 3
	fdb	4389,4650,4927,5220,5530,5859,6207,6577,6968,7382,7821,8286	;oct 4
	fdb	8779,9301,9854,10440,11060,11718,12415,13153,13935,14764,15642,16572	;oct 5
	fdb	17557,18601,19709,20897,22121,23436,24830,26306,27871,29528,31234,33144	;oct 6
	fdb	35115,37203,39415,41759,44242,46873,49660,52613,55741,59056,62567,65535	;oct 7 tone b7 out of range

init_sidmml_lentable
	fcb	248,248,248
	fcb	249,249,249
	fcb	250,250,250,250,250
	fcb	251,251,251,251,251		;16

	fcb	252,252,252,252,252,252,252,252
	fcb	252,252,252,252,252,252,252,252	;16

	fcb	253,253,253,253,253,253,253,253
	fcb	253,253,253,253,253,253,253,253
	fcb	253,253,253,253,253,253,253,253
	fcb	253,253,253,253,253,253,253,253	;32

	fcb	254,254,254,254,254,254,254,254
	fcb	254,254,254,254,254,254,254,254
	fcb	254,254,254,254,254,254,254,254
	fcb	254,254,254,254,254,254,254,254	;32

init_sidmml_notetable
	fcb	9,11,0,2,4,5,7,9



init_sidmml_speedtable
	fcb	250,251,252,253

def	sid_slot	byte
def	sid_slot1	byte
def	boot_slot	byte

def	sid_delta1	byte
def	sid_oct1	byte
def	sid_len1	byte
def	sid_vol	byte
def	sid_ins1	byte
def	sid_spd1	byte
def	sid_pulse1	word

def	sid_p_address1	word
def	sid_s_address1	word
def	sid_r_address1	word
def	sid_playback1	byte

def	sid_gate1	byte
def	sid_com1	byte
def	sid_playcnt1	byte
def	sid_delay1	byte
def	sid_loop1	byte
def	sid_sharp	byte




def	sid_delta2	byte
def	sid_oct2	byte
def	sid_len2	byte
def	sid_ins2	byte
def	sid_spd2	byte
def	sid_pulse2	word

def	sid_p_address2	word
def	sid_s_address2	word
def	sid_r_address2	word
def	sid_playback2	byte

def	sid_gate2	byte
def	sid_com2	byte
def	sid_playcnt2	byte
def	sid_delay2	byte
def	sid_loop2	byte

def	sid_delta3	byte
def	sid_oct3	byte
def	sid_len3	byte
def	sid_ins3	byte
def	sid_spd3	byte
def	sid_pulse3	word

def	sid_p_address3	word
def	sid_s_address3	word
def	sid_r_address3	word
def	sid_playback3	byte

def	sid_gate3	byte
def	sid_com3	byte
def	sid_playcnt3	byte
def	sid_delay3	byte
def	sid_loop3	byte


;****************************************************************************************************************
init_sidmml
	orcc	#$50	;kill interupt

	lda	$ff7f	;slot
	anda	#240
	sta	boot_slot	;boot slot

	lsra
	lsra
	lsra
	lsra
	anda	#12
	adda	boot_slot
	sta	sid_slot
	adda	#1
	sta	sid_slot1

	lda	$ff7f
	sta	boot_slot	;fixed

; lets get some settings ready
	lda	sid_slot
	sta	$ff7f
;settings here
	lda	#15
	sta	$ff58	;master volume 15 max

; set all pulse widths to square
	ldd	#2048
	sta	$ff43
	stb	$ff42
	ldd	#2048
	sta	$ff4a
	stb	$ff49
	ldd	#2048
	sta	$ff51
	stb	$ff50


	ldx	#init_sidmml_player_irq
	stx	$010d
	lda	boot_slot
	sta	$ff7f

	clr	sid_playback1	;not playing
	clr	sid_playback2	;not playing
	clr	sid_playback3	;not playing

	andcc	#$ef	;interrupt back on

	lda	#2
	sta	sid_oct1	;starting octave
	lda	#4
	sta	sid_len1	;starting note sizes
	clr	sid_gate1
	clr	sid_delay1
	clr	sid_delta1
	clr	sid_spd1


	lda	#2
	sta	sid_oct2	;starting octave
	lda	#4
	sta	sid_len2	;starting note sizes
	clr	sid_gate2
	clr	sid_delay2
	clr	sid_delta2
	clr	sid_spd2

	lda	#2
	sta	sid_oct3	;starting octave
	lda	#4
	sta	sid_len3	;starting note sizes
	clr	sid_gate3
	clr	sid_delay3
	clr	sid_delta3
	clr	sid_spd3


	rts



;****************************************************************************************************************************************
;****************** sid player version 1.5 by smdreloaded


init_sidmml_player_irq


; we are set for sid programming


; update system clock
	ldd	$112	;sys clock
	addd	#1
	std	$112

	lda	sid_slot
	sta	$ff7f	;mpi slot 1 of 0-3

; gate1 check
	com	sid_com1
	bmi	not_comgate1
	if	x,#1=sid_gate1
	lda	sid_gate1
	anda	#254
	sta	sid_gate1
	sta	$ff44
	endif
not_comgate1

; gate2 check
	com	sid_com2
	bmi	not_comgate2
	if	x,#1=sid_gate2
	lda	sid_gate2
	anda	#254
	sta	sid_gate2
	sta	$ff4b
	endif
not_comgate2

; gate3 check
	com	sid_com3
	bmi	not_comgate3
	if	x,#1=sid_gate3
	lda	sid_gate3
	anda	#254
	sta	sid_gate3
	sta	$ff52
	endif
not_comgate3


;player 1
	if	b,sid_playback1!#0
	if	b,sid_playcnt1>#0
	dec	sid_playcnt1
	else
	jsr	sid_playmml1	;jump to update
	endif
	endif
;player 2
	if	b,sid_playback2!#0
	if	b,sid_playcnt2>#0
	dec	sid_playcnt2
	else
	jsr	sid_playmml2	;jump to update
	endif
	endif
;player3
	if	b,sid_playback3!#0
	if	b,sid_playcnt3>#0
	dec	sid_playcnt3
	else
	jsr	sid_playmml3	;jump to update
	endif
	endif

	lda	boot_slot
	sta	$ff7f	;mpi slot 1 of 0-3
	lda	$ff02	;ack irq
	rti
; return to code



sid_playmml1

; sort out play speed
	ldx	#init_sidmml_playspeed
	ldb	#2
	lda	sid_spd1
	mul
	addb	sid_delta1
	leax	d,x

	lda	,x
	sta	sid_playcnt1
	inc	sid_delta1
	if	b,sid_delta1>#1
	clr	sid_delta1
	endif

	lda	sid_delay1
	beq	sid_playmusic_deltagood1
	dec	sid_delay1
	rts	;no play yet

sid_playmusic_deltagood1
	ldx	sid_p_address1	;song pos

sid_play_process1
	ldu	#init_sidmml_tones
	ldy	#init_sidmml_notetable

;note process
	lda	0,x
	lbeq	sid_play_done1


;octave change
	if	b,(0,x)=#79	;octave
	lda	1,x
	suba	#48
	sta	sid_oct1
	leax	2,x
	lbra	sid_play_process1
	endif

;volume change 0-9
	if	b,(0,x)=#86	b,(2,x)>#64	;0-9 range
	lda	1,x
	suba	#48
	sta	sid_vol
	sta	$ff58	;volume reg
	leax	2,x
	lbra	sid_play_process1
	endif
;volume change 10-15
	if	b,(0,x)=#86	b,(1,x)=#49	b,(2,x)<#54
	lda	2,x
	suba	#48
	adda	#10
	sta	sid_vol
	sta	$ff58	;volume reg
	leax	3,x
	lbra	sid_play_process1
	endif


;length change
	if	b,(0,x)=#76	;length change
	jsr	sid_change_len
	sta	sid_len1
	lbra	sid_play_process1
	endif

;pause len
	if	b,(0,x)=#80	;length change
	jsr	sid_change_len
	sta	sid_delay1
	stx	sid_p_address1
	rts

	endif

;tempo  change
	if	b,(0,x)=#84	;tempo change
	lda	1,x
	suba	#48
	sta	sid_spd1
	leax	2,x
	lbra	sid_play_process1
	endif

;instrument change
	if	b,(0,x)=#73
	lda	1,x
	suba	#48
	sta	sid_ins1	;save instrument
	lsla
	lsla
	lsla
	lsla
	adda	#1
	sta	sid_gate1
	leax	2,x
	lbra	sid_play_process1
	endif


;play note
	if	b,(0,x)=>#65	b,(0,x)=<#71
; sharp or not?
	clr	sid_sharp
	if	b,(1,x)=#35
	lda	#1
	sta	sid_sharp
	endif
;flat or not
	if	b,(1,x)=#45	b,(0,x)!#67
	lda	#255	;-1
	sta	sid_sharp
	endif

	ldb	#24	;12 word values
	lda	sid_oct1
	mul
	leau	d,u
	ldb	0,x
	subb	#65
	lda	b,y
	adda	sid_sharp
	ldb	#2
	mul
	leau	d,u
	lda	0,u
	ldb	1,u
	sta	$ff41	;frequency
	stb	$ff40
	ldy	#init_sidmml_lentable
	ldb	sid_len1
	lda	b,y	;length
	sta	$ff46	;sus release
	lda	#$0c
	sta	$ff45	;attack/delay
	lda	sid_gate1
	anda	#254
	adda	#1
	sta	sid_gate1
	sta	$ff44	;note away
	clr	sid_com1

	if	b,sid_sharp!#0
	leax	1,x
	endif

	leax	1,x
	lda	sid_len1
	sta	sid_delay1
	stx	sid_p_address1
	rts
	endif

;not found
	leax	1,x
	
	lbra	sid_play_process1
;****************************************************************************************************************************************************


sid_play_done1
	if	b,sid_loop1=#1
	ldd	sid_r_address1
	std	sid_p_address1
	rts
	else
	ldd	sid_s_address1
	std	sid_p_address1
	clr	sid_playback1
	rts
	endif
	rts



;************************************************change length jsr
;***********************************************returns value on a
sid_change_len

	if	b,(1,x)=#49	b,(2,x)=#48	;p10
	lda	#2
	leax	3,x
	rts
	endif


	if	b,(1,x)=#49	b,(2,x)=#46	;1 yes dot
	lda	#47
	leax	3,x
	rts
	endif
	if	b,(1,x)=#49	b,(2,x)!#46	b,(2,x)!#54	;1 no dot and not 16
	lda	#31
	leax	2,x
	rts
	endif

	if	b,(1,x)=#50	b,(2,x)=#46	;2 yes dot
	lda	#23
	leax	3,x
	rts
	endif
	if	b,(1,x)=#50	b,(2,x)!#46	;2 no dot
	lda	#15
	leax	2,x
	rts
	endif

	if	b,(1,x)=#51	b,(2,x)=#46	;3 yes dot
	lda	#17
	leax	3,x
	rts
	endif
	if	b,(1,x)=#51	b,(2,x)!#46	b,(2,x)!#50	;3 no dot and not 32
	lda	#11
	leax	2,x
	rts
	endif

	if	b,(1,x)=#52	b,(2,x)=#46	;4 yes dot
	lda	#11
	leax	3,x
	rts
	endif
	if	b,(1,x)=#52	b,(2,x)!#46	;4 no dot
	lda	#7
	leax	2,x
	rts
	endif

	if	b,(1,x)=#56	b,(2,x)=#46	;8 yes dot
	lda	#5
	leax	3,x
	rts
	endif
	if	b,(1,x)=#56	b,(2,x)!#46	;8 no dot
	lda	#3
	leax	2,x
	rts
	endif

; l16
	if	b,(1,x)=#49	b,(2,x)=#54
	lda	#1
	leax	3,x
	rts
	endif

; l32
	if	b,(1,x)=#51	b,(2,x)=#50
	lda	#0
	leax	3,x
	rts
	endif

;fucked up string
	leax	1,x
	clra
	rts








sid_playmml2

; sort out play speed
	ldx	#init_sidmml_playspeed
	ldb	#2
	lda	sid_spd2
	mul
	addb	sid_delta2
	leax	d,x

	lda	,x
	sta	sid_playcnt2
	inc	sid_delta2
	if	b,sid_delta2>#1
	clr	sid_delta2
	endif

	lda	sid_delay2
	beq	sid_playmusic_deltagood2
	dec	sid_delay2
	rts	;no play yet

sid_playmusic_deltagood2
	ldx	sid_p_address2	;song pos

sid_play_process2
	ldu	#init_sidmml_tones
	ldy	#init_sidmml_notetable

;note process
	lda	0,x
	lbeq	sid_play_done2


;octave change
	if	b,(0,x)=#79	;octave
	lda	1,x
	suba	#48

	sta	sid_oct2
	leax	2,x
	lbra	sid_play_process2
	endif

;length change
	if	b,(0,x)=#76	;length change
	jsr	sid_change_len
	sta	sid_len2
	lbra	sid_play_process2
	endif

;pause len
	if	b,(0,x)=#80	;length change
	jsr	sid_change_len
	sta	sid_delay2
	stx	sid_p_address2
	rts

	endif

;tempo  change
	if	b,(0,x)=#84	;tempo change
	lda	1,x
	suba	#48
	sta	sid_spd2
	leax	2,x
	lbra	sid_play_process2
	endif

;instrument change
	if	b,(0,x)=#73
	lda	1,x
	suba	#48
	sta	sid_ins2	;save instrument
	lsla
	lsla
	lsla
	lsla
	adda	#1
	sta	sid_gate2
	leax	2,x
	lbra	sid_play_process2
	endif

;volume change 0-9
	if	b,(0,x)=#86	b,(2,x)>#64	;0-9 range
	lda	1,x
	suba	#48
	sta	sid_vol
	sta	$ff58	;volume reg
	leax	2,x
	lbra	sid_play_process1
	endif
;volume change 10-15
	if	b,(0,x)=#86	b,(1,x)=#49	b,(2,x)<#54
	lda	2,x
	suba	#48
	adda	#10
	sta	sid_vol
	sta	$ff58	;volume reg
	leax	3,x
	lbra	sid_play_process1
	endif



;play note
	if	b,(0,x)=>#65	b,(0,x)=<#71
; sharp or not?
	clr	sid_sharp
	if	b,(1,x)=#35
	lda	#1
	sta	sid_sharp
	endif
;flat or not
	if	b,(1,x)=#45	b,(0,x)!#67
	lda	#255	;-1
	sta	sid_sharp
	endif

	ldb	#24	;12 word values
	lda	sid_oct2
	mul
	leau	d,u
	ldb	0,x
	subb	#65
	lda	b,y
	adda	sid_sharp
	ldb	#2
	mul
	leau	d,u
	lda	0,u
	ldb	1,u
	sta	$ff48	;frequency
	stb	$ff47
	ldy	#init_sidmml_lentable
	ldb	sid_len2
	lda	b,y	;length
	sta	$ff4d	;sus release
	lda	#$0c
	sta	$ff4c	;attack/delay
	lda	sid_gate2
	anda	#254
	adda	#1
	sta	sid_gate2
	sta	$ff4b	;note away
	clr	sid_com2

	if	b,sid_sharp!#0
	leax	1,x
	endif

	leax	1,x
	lda	sid_len2
	sta	sid_delay2
	stx	sid_p_address2
	rts
	endif

;not found
	leax	1,x
	
	lbra	sid_play_process2
;****************************************************************************************************************************************************


sid_play_done2
	if	b,sid_loop2=#1
	ldd	sid_r_address2
	std	sid_p_address2
	rts
	else
	ldd	sid_s_address2
	std	sid_p_address2
	clr	sid_playback2
	rts
	endif
	rts











sid_playmml3

; sort out play speed
	ldx	#init_sidmml_playspeed
	ldb	#2
	lda	sid_spd3
	mul
	addb	sid_delta3
	leax	d,x

	lda	,x
	sta	sid_playcnt3
	inc	sid_delta3
	if	b,sid_delta3>#1
	clr	sid_delta3
	endif

	lda	sid_delay3
	beq	sid_playmusic_deltagood3
	dec	sid_delay3
	rts	;no play yet

sid_playmusic_deltagood3
	ldx	sid_p_address3	;song pos

sid_play_process3
	ldu	#init_sidmml_tones
	ldy	#init_sidmml_notetable

;note process
	lda	0,x
	lbeq	sid_play_done3


;octave change
	if	b,(0,x)=#79	;octave
	lda	1,x
	suba	#48

	sta	sid_oct3
	leax	2,x
	lbra	sid_play_process3
	endif

;length change
	if	b,(0,x)=#76	;length change
	jsr	sid_change_len
	sta	sid_len3
	lbra	sid_play_process3
	endif

;pause len
	if	b,(0,x)=#80	;length change
	jsr	sid_change_len
	sta	sid_delay3
	stx	sid_p_address3
	rts

	endif

;tempo  change
	if	b,(0,x)=#84	;tempo change
	lda	1,x
	suba	#48
	sta	sid_spd3
	leax	2,x
	lbra	sid_play_process3
	endif

;instrument change
	if	b,(0,x)=#73
	lda	1,x
	suba	#48
	sta	sid_ins3	;save instrument
	lsla
	lsla
	lsla
	lsla
	adda	#1
	sta	sid_gate3
	leax	2,x
	lbra	sid_play_process3
	endif

;volume change 0-9
	if	b,(0,x)=#86	b,(2,x)>#64	;0-9 range
	lda	1,x
	suba	#48
	sta	sid_vol
	sta	$ff58	;volume reg
	leax	2,x
	lbra	sid_play_process3
	endif
;volume change 10-15
	if	b,(0,x)=#86	b,(1,x)=#49	b,(2,x)<#54
	lda	2,x
	suba	#48
	adda	#10
	sta	sid_vol
	sta	$ff58	;volume reg
	leax	3,x
	lbra	sid_play_process3
	endif

;play note
	if	b,(0,x)=>#65	b,(0,x)=<#71
; sharp or not?
	clr	sid_sharp
	if	b,(1,x)=#35
	lda	#1
	sta	sid_sharp
	endif
;flat or not
	if	b,(1,x)=#45	b,(0,x)!#67
	lda	#255	;-1
	sta	sid_sharp
	endif

	ldb	#24	;12 word values
	lda	sid_oct3
	mul
	leau	d,u
	ldb	0,x
	subb	#65
	lda	b,y
	adda	sid_sharp
	ldb	#2
	mul
	leau	d,u
	lda	0,u
	ldb	1,u
	sta	$ff4f	;frequency
	stb	$ff4e
	ldy	#init_sidmml_lentable
	ldb	sid_len3
	lda	b,y	;length
	sta	$ff54	;sus release
	lda	#$0c
	sta	$ff53	;attack/delay
	lda	sid_gate3
	anda	#254
	adda	#1
	sta	sid_gate3
	sta	$ff52	;note away
	clr	sid_com3

	if	b,sid_sharp!#0
	leax	1,x
	endif

	leax	1,x
	lda	sid_len3
	sta	sid_delay3
	stx	sid_p_address3
	rts
	endif

;not found
	leax	1,x
	
	lbra	sid_play_process3
;****************************************************************************************************************************************************


sid_play_done3
	if	b,sid_loop3=#1
	ldd	sid_r_address3
	std	sid_p_address3
	rts
	else
	ldd	sid_s_address3
	std	sid_p_address3
	clr	sid_playback3
	rts
	endif
	rts







endfunction




function	playsid_mml	playsid_mml_chan,playsid_mml_ins,playsid_mml_play,playsid_mml_spd,playsid_mml_addr
rem	playsid_mml( channel.b , instrument.b , playback.b , speed.b , address.w )
rem	
rem	
rem	plays back mml over selected channel
def	playsid_mml_chan	byte
def	playsid_mml_ins	byte
def	playsid_mml_play	byte
def	playsid_mml_spd	byte
def	playsid_mml_addr	word


playsid_mml

	if	b,playsid_mml_chan=#1
	ldd	playsid_mml_addr
	std	sid_p_address1
	std	sid_s_address1
	std	sid_r_address1

	clr	sid_playcnt1
	clr	sid_delta1
	lda	playsid_mml_spd
	sta	sid_spd1	;speed setup


;setup instrument
	lda	playsid_mml_ins
	lsla
	lsla
	lsla
	lsla
	adda	#1
	sta	sid_gate1	;setup instrument


;last
	if	b,playsid_mml_play<#2
	clr	sid_loop1
	else
	lda	#1
	sta	sid_loop1
	endif

	if	b,playsid_mml_play!#0
	lda	#1
	sta	sid_playback1
	endif

	rts
	endif
;*************************************************************************************

	if	b,playsid_mml_chan=#2
	ldd	playsid_mml_addr
	std	sid_p_address2
	std	sid_s_address2
	std	sid_r_address2

	clr	sid_playcnt2
	clr	sid_delta2
	lda	playsid_mml_spd
	sta	sid_spd2	;speed setup


;setup instrument
	lda	playsid_mml_ins
	lsla
	lsla
	lsla
	lsla
	adda	#1
	sta	sid_gate2	;setup instrument


;last
	if	b,playsid_mml_play<#2
	clr	sid_loop2
	else
	lda	#1
	sta	sid_loop2
	endif

	if	b,playsid_mml_play!#0
	lda	#1
	sta	sid_playback2
	endif

	rts
	endif



;*************************************************************************************

	if	b,playsid_mml_chan=#3
	ldd	playsid_mml_addr
	std	sid_p_address3
	std	sid_s_address3
	std	sid_r_address3

	clr	sid_playcnt3
	clr	sid_delta3
	lda	playsid_mml_spd
	sta	sid_spd3	;speed setup


;setup instrument
	lda	playsid_mml_ins
	lsla
	lsla
	lsla
	lsla
	adda	#1
	sta	sid_gate3	;setup instrument


;last
	if	b,playsid_mml_play<#2
	clr	sid_loop3
	else
	lda	#1
	sta	sid_loop3
	endif

	if	b,playsid_mml_play!#0
	lda	#1
	sta	sid_playback3
	endif

	rts
	endif




endfunction

