; vidclin.s
; Channel handler code for 8-bit signed linear

	AREA |VIDC$$Data|, DATA
	EXPORT vidclin_extended_header_template

vidclin_extended_header_template
	DCD extended_voice_header


	AREA |VIDC$$Code|, CODE, READONLY

; SWI
XSound_Configure	EQU 0x60140

; Only the extended voice header stuff is used,
; the rest is there to make it much easier to reference offsets

vidc_descriptor
th_slot			DCD 0
sys_slot		DCD 0
data_start		DCD 0
data_end		DCD 0
log_table		DCD 0
lin_to_log		DCD 0

extended_voice_header
raw_fill		B	fill_code
raw_update		B	update_code
raw_gate_on		B	gate_on
raw_gate_off		B	gate_off_code
raw_instantiate		B	instantiate_stack
raw_free		B	free_stack
raw_rtn			LDMFD	r13!, {pc}
raw_name_offset		DCD	voice_name - extended_voice_header
gate_on			ADR	r0, vidc_descriptor
branch_to_gate_on	B	gate_on_code
instantiate_stack	STMFD	r13!, {r0-r5}
instantiate_addr	ADR	r5, vidc_descriptor
branch_to_instantiate	B	instantiate_code
free_stack		STR	r13, poll_word
free_rtn		LDMFD	r13!, {pc}

poll_word		DCD 0
voice_name		DCD 0
			DCD 0
			DCD 0

; Useful offsets
SCCB_amplitude		EQU 0
SCCB_phaseacc_pitch	EQU 4
SCCB_current_place	EQU 8
SCCB_sample_end		EQU 12
SCCB_log_table		EQU 16
SCCB_lin_to_log		EQU 20
SCCB_poll_word		EQU 24

ChanHandler_fill	EQU 0
ChanHandler_overrun	EQU 4
ChanHandler_lintolog	EQU 8
ChanHandler_logscale	EQU 12


; r5 points to vidc_descriptor
instantiate_code
	MOV	r0, #0
	MOV	r1, #0
	MOV	r2, #0
	MOV	r3, #0
	MOV	r4, #0
	SWI	XSound_Configure
	LDR	r0, [r3, #ChanHandler_logscale]
	STR	r0, [r5, #(log_table - vidc_descriptor)]
	LDR	r0, [r3, #ChanHandler_lintolog]
	STR	r0, [r5, #(lin_to_log - vidc_descriptor)]
	LDMFD	r13!, {r0-r5, pc}
gate_on_code
	; Read data from sample handle and store in SCCB
	ADD	r1, r0, #(poll_word - vidc_descriptor)
	STR	r1, [r9, #SCCB_poll_word]
	ADD	r0, r0, #(data_start - vidc_descriptor)
	LDMIA	r0, {r1-r4}
	ADD	r0, r9, #SCCB_current_place
	STMIA	r0, {r1-r4}
update_code
	; Half pitch phase increment
	LDR	r0, [r9, #SCCB_phaseacc_pitch]
	MOV	r1, r0, LSR #16
	MOV	r0, r0, LSL #16
	MOV	r0, r0, LSR #17
	ORR	r0, r0, r1, LSL #16
	STR	r0, [r9, #SCCB_phaseacc_pitch]
fill_code
	; Read registers from SCCB
	; r0 = amplitude etc
	; r1 = Phase accumulator pitch
	; r2 => Current place in sample
	; r3 => End of sample
	; r4 => Volume log table
	; r6 => Linear to log table
	LDMIA	r9, {r0-r4, r6}
	; Convert r0 to attenuation factor
	AND	r0, r0, #&7F
	LDRB	r0, [r4, r0, LSL #1]
	MOV	r0, r0, LSR #1
	RSB	r0, r0, #&7F
fill_loop
	ADDS	r1, r1, r1, LSL #16
	ADDCS	r2, r2, #&100
	; Will next fill be beyond sample?
	ADD	r5, r2, r1, LSR #24
	CMP	r5, r3
	BGE	end_of_sample
	LDRB	r5, [r2, r1, LSR #24]
	; Convert to log
	LDRB	r5, [r6, r5, LSL #5]
	; Attenuate
	SUBS	r5, r5, r0
	MOVMI	r5, #0
	STRB	r5, [r12], r11
	ADDS	r1, r1, r1, LSL #16
	ADDCS	r2, r2, #&100
	; Will next fill be beyond sample?
	ADD	r5, r2, r1, LSR #24
	CMP	r5, r3
	BGE	end_of_sample
	LDRB	r5, [r2, r1, LSR #24]
	; Convert to log
	LDRB	r5, [r6, r5, LSL #5]
	; Attenuate
	SUBS	r5, r5, r0
	MOVMI	r5, #0
	STRB	r5, [r12], r11
	ADDS	r1, r1, r1, LSL #16
	ADDCS	r2, r2, #&100
	; Will next fill be beyond sample?
	ADD	r5, r2, r1, LSR #24
	CMP	r5, r3
	BGE	end_of_sample
	LDRB	r5, [r2, r1, LSR #24]
	; Convert to log
	LDRB	r5, [r6, r5, LSL #5]
	; Attenuate
	SUBS	r5, r5, r0
	MOVMI	r5, #0
	STRB	r5, [r12], r11
	ADDS	r1, r1, r1, LSL #16
	ADDCS	r2, r2, #&100
	; Will next fill be beyond sample?
	ADD	r5, r2, r1, LSR #24
	CMP	r5, r3
	BGE	end_of_sample
	LDRB	r5, [r2, r1, LSR #24]
	; Convert to log
	LDRB	r5, [r6, r5, LSL #5]
	; Attenuate
	SUBS	r5, r5, r0
	MOVMI	r5, #0
	STRB	r5, [r12], r11
	CMP	r12, r10
	BLT	fill_loop
	; Update SCCB and return Active
	STMIB	r9, {r1, r2}
	MOV	r0, #8
	LDMFD	r13!, {pc}
gate_off_code
	MOV	r0, #1
	B	flush
end_of_sample
	MOV	r0, #2
flush
	LDR	r3, [r9, #SCCB_sample_end]
	STR	r3, [r9, #SCCB_current_place]
	MOV	r5, #0
flush_loop
	STRB	r5, [r12], r11
	STRB	r5, [r12], r11
	STRB	r5, [r12], r11
	STRB	r5, [r12], r11
	CMP	r12, r10
	BLT	flush_loop
	MVN	r0, #0
	LDR	r1, [r9, #SCCB_poll_word]
	STR	r0, [r1]
	LDMFD	r13!, {pc}

	END
