;______________________________________________________________________________
;
;	SYNCORE FOR JAZ
; 	This is the version of the new synth which is used as the default
;	synth for JAZ. Remember, the synth is not linked with JAZ, so changes
;	can be made and be loaded into JAZ.
;
;	There are comments next to those lables JAZ will be looking for
;
;*			COPYRIGHT 1995 ATARI CORP.			*
;*          UNATHORIZED REPRODUCTION, ADAPTATION, DISTRIBUTION,         *
;*          PERFORMANCE OR DISPLAY OF THIS COMPUTER PROGRAM OR          *
;*        THE ASSOCIATED AUDIOVISUAL WORK IS STRICTLY PROHIBITED.       *
;*                            ALL RIGHTS RESERVED.                      *
;
;	This code is the wrapping for the synth. It includes the voicetable,
;	circular buffering i2s_isr routines. It is the part that must be in
;	all synths. It houses the modules.	
;
;	Version:	1.1
;	Date:		12/08/95
;	
;______________________________________________________________________________
;		include "jaguar.inc"
;______________________________________________________________________________
		include "modules/synth.cnf"
;______________________________________________________________________________

REDBOOK		EQU		0

		
	xdef 	dbuf2p

;***	Begin XDEF section of symbols required by JAZ!

	XDEF	midi_bak		; required by JAZ
	XDEF	DSP_START		; required by JAZ
	XDEF	SYNTH_COPY		; required by JAZ
	XDEF	SHUTDOWN		; required by JAZ
	XDEF	SCOREP1			; required by JAZ
	XDEF	SCOREP2			; required by JAZ
	XDEF	PLISTP1			; required by JAZ
	XDEF	PLISTP2			; required by JAZ
	XDEF	MTIMEP1			; required by JAZ
	XDEF	MTIMEP2			; required by JAZ
	XDEF	DEF_PATCHES		; required by JAZ
	XDEF	DEF_N_PATCHES		; required by JAZ
	XDEF	DSP_IDLE		; required by JAZ
	XDEF	VOICE_TABLE		; required by JAZ
	XDEF	VOICE_BUFFER		; required by JAZ
	XDEF	REVERB_TABLE		; required by JAZ
	XDEF	PRIORITY_TABLE		; required by JAZ
	XDEF	MIDI_VOLUME

	XDEF	MDTAB_START		; required by JAZ
	XDEF	MDTAB_END		; required by JAZ
	XDEF	MDTAB_REVERB		; required by JAZ
	XDEF	VT_RETURN_LOC		; required by JAZ
	XDEF	VT_RET_VALUE		; required by JAZ


	XDEF	ENV_START		; required by JAZ
	XDEF	ENV_END			; required by JAZ

	XDEF	ENV_TEMP		; required by JAZ
	XDEF	ENV_TEMP_END		; required by JAZ

	XDEF	ATTN			; required by JAZ
	XDEF	DELAY			; required by JAZ
	XDEF	MIXER			; required by JAZ
	XDEF	REVERB			; required by JAZ
	XDEF	EFFECT_MODE		; required by JAZ

	XDEF	DIST			; required by JAZ

	XDEF	OSC_SAMPLER		; required by JAZ
	XDEF	OSC_SAMPLER_LOOP	; required by JAZ
	XDEF	OSC_NISAMPLER		; required by JAZ
	XDEF	OSC_FIXEDWAVE		; required by JAZ
	XDEF	OSC_FIXEDWAVE_LOOP	; required by JAZ
	XDEF	OSC_FM			; required by JAZ
	XDEF	OSC_FM_LOOP		; required by JAZ
	XDEF	OSC_POLYWAVE		; required by JAZ
	XDEF	OSC_NOISE		; required by JAZ

	XDEF	OSC_FX_PW		; required by JAZ
	XDEF	OSC_FX_PAN		; required by JAZ
	XDEF	OSC_FX_PITCH		; required by JAZ
	XDEF	OSC_FX_DIST		; required by JAZ
	XDEF	ENV_FX_PW		; required by JAZ
	XDEF	ENV_FX_PAN		; required by JAZ
	XDEF	ENV_FX_PITCH		; required by JAZ
	XDEF	OSC_FX_DIST		; required by JAZ
	XDEF	OSC_FX_VALUE		; required by JAZ

	XDEF	ENV_SLOT1		; required by JAZ
	XDEF	ENV_SLOT2		; required by JAZ
	XDEF	ENV_SLOT3		; required by JAZ

	XDEF	LOOPENV_SLOT1		; required by JAZ
	XDEF	LOOPENV_SLOT2		; required by JAZ
	XDEF	LOOPENV_SLOT3		; required by JAZ
	XDEF	LOOPENV_SKIP		; required by JAZ
	

	XDEF	LFO_1			; required by JAZ
	XDEF	LFO_2			; required by JAZ

	XDEF	DFT_FILTER		; required by JAZ
	XDEF	FILTER_2
	XDEF	FILTER_DEF_1		; required by JAZ
	XDEF	FILTER_DEF_2		; required by JAZ

;***	End XDEF section of symbols required by JAZ!


	XDEF	MDTAB_PWAVE
	XDEF	MDTAB_PWAVE2
	XDEF	MDTAB_SAMP
	XDEF	MDTAB_FSAMP
	XDEF	MDTAB_FM
	XDEF	MDTAB_FWAVE
	XDEF	MDTAB_PULSE
	XDEF 	cir_buff_loc
	
;______________________________________________________________________________
;
;			Code Starts Here
;______________________________________________________________________________
	.TEXT
.68000					; Load header
	
	.PHRASE
SYNTH_COPY:
	.PHRASE				; here we find the synth
	.dc.l	SYNTH_START
	.dc.l	SYNTH_END-SYNTH_START
	.PHRASE

;______________________________________________________________________________
;
;			SYNTH Starts Here
;______________________________________________________________________________

	.TEXT
	.DSP

; ------------------------------------------------
; Constants
; ------------------------------------------------
.if 0
PLIST_SIZE	EQU	21	; now defined in "synthlib.s"
NUM_VOICES	EQU	14	; - " -
.endif
;FMSK_VALUE	EQU	$000001ff		
AMASK_VALUE	EQU	$FFFFF000
;FMASK_VALUE	EQU	$00000FFF
AMSK_VALUE	EQU	$0007F000
LWORD_MASK	EQU	$0000FFFF
SURROUND_VOICE	EQU 	NUM_VOICES - 1


; ------------------------------------------------
; Registers
; ------------------------------------------------


R_FLAGS			REGEQU	R0		; PERM!
R_VOICE_ID		REGEQU	R1		; id = frequency + patch no.
R_PR_P			REGEQU	R2		; ptr to priority table
R_VT_CP			REGEQU	R3		; voice table pointer
R_MPAN_VOICE		REGEQU	R4		; voice number for note on pan code
R_SUR_VOICE		REGEQU	R4		; voice for surround sound

; Registers for MIDI Note On/Off code

R_PLIST_NUM		REGEQU	R9		; NOT only needed for note on
R_TYPE			REGEQU	R10		; Type of event 
R_MPITCH		REGEQU	R10		; Pitch register
R_MJUMP			REGEQU	R10		; to get back from pan routine
R_EVENT_P		REGEQU	R11		; Done with before A_FREQ_TAB
R_VOICE_FLAGS		REGEQU	R11		; voice flag pointer
R_MVOLUME		REGEQU	R11		; Volume register
R_NEW_VALUE		REGEQU	R11		; for changing pan
R_PLIST_SIZE		REGEQU	R12		; open for usage in event routines
R_FREQ			REGEQU	R12		; Frequency register
R_MPAN_LOC		REGEQU	R12		; Pan table location register
R_MPITCH_LOC		REGEQU	R12		; Pitch table location register
R_VT_DIR_P		REGEQU	R13		; PERM!
R_VT_IND_P		REGEQU	R14		; PERM!
R_MDTAB_P		REGEQU	R15		; PERM!
R_M_EVENT		REGEQU	R16		; holds the event to extract bits from

R_P_COPY		REGEQU	R18		; Pitch copy register
R_MPAN_VALUE		REGEQU	R18		; Pan value
R_TEMP2			REGEQU	R19
R_MPAN_SHIFT		REGEQU	R19		; Pan shift amount

R_TEMP1			REGEQU	R28
R_READ_COUNT		REGEQU	R28		; This is the i2s_isr sample counter								
						; for the circular buffer 
R_MDJUMP_P		REGEQU	R29		
R_VOICE_NUM		REGEQU  R30		; This is the current number for the
								; voice that we are synthesizing PERM!

R_WRITE_COUNT	REGEQU	R31			; This is the voicetable sample counter
							; for the circular buffer PERM!


; Alternate bank Register variables

A_PRIORITY_TABLE 	REGEQU	R0
A_EFFECTS		REGEQU	R1
A_MASK_VALUE		REGEQU	R5		; Variable masking stuff
A_FW_MASK		REGEQU	R4
A_LW_MASK		REGEQU	R3

A_LAST_INST_P		REGEQU	R23		; Last inst. we were at before isr
A_DFLAGS_D		REGEQU	R24		; DFLAGS DATA 
A_SAMPLE		REGEQU	R25		; Packed sample to put into DAC's
A_BUFFPTR		REGEQU	R26		; Alt. Bank circular buffer pointer #perm#
A_R_DAC			REGEQU	R27		; R_DAC location #perm#
A_READCOUNT		REGEQU	R28		; Alt. Bank c_buff write count #perm#
A_DFLAGS_P		REGEQU	R29		; DFLAGS location #perm#
A_TEMP1			REGEQU	R30		; trashed upon entry into i2s_isr
A_STACK_P		REGEQU	R31		; I2s_sir stack pointer #perm#
								; was called ( return loc. ) #perm#


	.phrase
	ORG	D_RAM
SYNTH_START::

	movei	#DSP_START,r0		; (interrupt 0	- DSP Control)
	jump	(r0)
	nop
	nop
	nop
	nop

;______________________________________________________________________________
; We put the stack here so that we do not waste
; the first 16 bytes

i2s_int_stack:
	movei	#i2s_isr,A_TEMP1		; (interrupt 1 - I2S)
	jump	(A_TEMP1)
	nop
	nop
	nop
	nop

midi_int_stack:
	movei	#midi_isr,A_TEMP1		; (interrupt 2 - MIDI)
	jump	(A_TEMP1)
	nop
	nop
	nop
	nop

DSP_START:
        movei   #i2s_int_stack,r31		; Set up stack
        moveta  r31,r31				; Set up stack in both 
						; banks just in case

;----------------- Switch Banks ---------------------------------------

        movei   #D_FLAGS,r1             ; load dsp flags to go to bank 1
        moveta  r1,r1                   ; in both banks
        load    (r1),r0
	bset    #14,r0                  ; Use bank 1
        bset    #5,r0                   ; enable I2S interrupt
	bset    #6,r0                   ; enable MIDI interrupt

	store   r0,(r1)                 ; save dsp flags
        nop                             ; NEEDS TWO NOPS TO PROTECT AGAINST
        nop				; BAD REG BANK SWITCH
 	nop

;----------------- Now in Secondary Bank -----------------------------

	movei	#cir_buff_loc, A_BUFFPTR	; Set up i2s_isr buffer ptr
	moveta	A_BUFFPTR, A_BUFFPTR	
	movei	#L_I2S, A_R_DAC			; Get dac locations
	moveta	A_R_DAC, A_R_DAC	
	moveq	#0, A_READCOUNT			; Put i2s READ at 0
;;	movei	#32, A_READCOUNT		; ****TEST****READ at 8
	moveta	A_READCOUNT,A_READCOUNT	
	movei	#D_FLAGS,A_DFLAGS_P		; Flags ptr
	moveta	A_DFLAGS_P,A_DFLAGS_P		
	movei	#AMASK_VALUE,A_MASK_VALUE	; Mask data variable
	moveta	A_MASK_VALUE,A_MASK_VALUE		
	movei	#AMSK_VALUE,A_FW_MASK		; Mask data variable
	moveta	A_FW_MASK,A_FW_MASK		
	movei	#LWORD_MASK,A_LW_MASK		; Mask data variable
	moveta	A_LW_MASK,A_LW_MASK		

	movei	#priority_table, A_PRIORITY_TABLE
	moveta	A_PRIORITY_TABLE, A_PRIORITY_TABLE
	movei	#EFFECT_MODE, A_EFFECTS
	moveta	A_EFFECTS, A_EFFECTS

	moveq	#0, R_WRITE_COUNT		; Start wr counter at 0


; Set up the modulo adders to handle tables that are 128 longs in length
; This is the size of the internal ROM_TABLES
	movei	#D_MOD,R_TEMP1		; MODPARM
	movei	#$FFFFFE00,R_TEMP2
	store	R_TEMP2,(R_TEMP1)

main_loop:
	moveq	#0,R_TEMP2
main_loop2:
	nop					; location for other routines
	addq	#1,R_TEMP2
	
	movei	#voice_table,R_VT_IND_P		; to use DSP
	
c_buff_loop:	
	movefa	A_READCOUNT, R_READ_COUNT	; get where i2s_isr is at
	sub	R_WRITE_COUNT, R_READ_COUNT	; and compare to us

	jr	PL, c1				; if neg add 31 to W_COUNT
	sharq	#2,R_READ_COUNT			; because if R_COUNT > W_COUNT 
	addq	#31,R_READ_COUNT		; We have to get abs dist. 
c1:
	moveq	#0,R_VOICE_NUM			; Reset voice num to 0 (##)
	cmpq	#8,R_READ_COUNT			; check for dist. of 8 samples
	jr	CS, main_loop2
	nop					; possibly move (##) to here

	movei	#DSP_IDLE,R_TEMP1
	store	R_TEMP2,(R_TEMP1)
	
parse_voice_table:
	load	(R_VT_IND_P),R_MDTAB_P
	move	R_VT_IND_P,R_VT_DIR_P
	load	(R_MDTAB_P),R_MDJUMP_P
	addq	#4,R_VT_DIR_P
	addq	#4,R_MDTAB_P
	load	(R_VT_DIR_P),R_FLAGS

	movefa	A_PRIORITY_TABLE, R_PR_P
	move	R_VOICE_NUM, R_TEMP1
	move	R_PR_P, R_SUR_VOICE
	shlq	#3, R_TEMP1
	moveq	#13, R_TEMP2
	add	R_TEMP1, R_PR_P
	shlq	#3, R_TEMP2
	add	R_TEMP2,R_SUR_VOICE			; Voice 13

   	load	(R_PR_P), R_TEMP2
	btst	#0, R_TEMP2			; voice stolen?
	jr	EQ, not_stolen
	nop
	bclr	#30, R_FLAGS			; turn it off
	bclr	#0, R_TEMP2
	store	R_TEMP2, (R_PR_P)
	jump	(R_MDJUMP_P)
	addq	#4,R_VT_DIR_P

not_stolen:
	btst	#2, R_TEMP2
	jr	EQ,no_off
	movefa	A_EFFECTS,R_TEMP1
	bclr	#31, R_FLAGS	
; TURN OFF SURROUND VOICE
	load	(R_TEMP1),R_TEMP1
	btst	#1,R_TEMP1			; surround on ?
	jr	EQ,no_surr
	shrq	#16,R_TEMP1
	btst	#15,R_TEMP1			; surround voice on?
	jr	NE,no_surr
	cmp	R_VOICE_NUM,R_TEMP1
	jr	NE,no_surr
	load	(R_SUR_VOICE),R_TEMP1
	bset	#2,R_TEMP1
	store	R_TEMP1,(R_SUR_VOICE)
; TURN OFF SURROUND CODE END
		
no_surr:
	jump	(R_MDJUMP_P)
	addq	#4,R_VT_DIR_P

no_off:
	btst	#1, R_TEMP2
	jump	EQ, (R_MDJUMP_P)
	addq	#4,R_VT_DIR_P

; note on code

m_note_on:
	bclr	#1, R_TEMP2
	bset	#3, R_TEMP2		; set bit again in case we stole this one
	store	R_TEMP2, (R_PR_P)
	addq	#4, R_PR_P
	load	(R_PR_P), R_M_EVENT
	move	R_M_EVENT, R_TEMP1
	shlq	#8, R_TEMP1			; mask out velocity & event bit
	shrq	#8, R_TEMP1
	store	R_TEMP1, (R_PR_P)

	moveq	#PLIST_SIZE, R_PLIST_SIZE	; Number of longs to copy
	shlq	#2, R_PLIST_SIZE

get_plist_loc:
	movei	#PLISTP1,R_TEMP1		; points at SCOREP
	load	(R_TEMP1),R_TEMP1		; grab location in RAM
	move	R_M_EVENT,R_PLIST_NUM		; get plist number from event
	shlq	#25,R_PLIST_NUM
	shrq	#25,R_PLIST_NUM		
	mult	R_PLIST_SIZE,R_PLIST_NUM	; Now have plist number	
	add	R_TEMP1,R_PLIST_NUM		; Now points to plist location
	move	R_VT_IND_P, R_VT_CP
	moveq	#PLIST_SIZE,R_TEMP1		; Number of longs to copy
copy_plist:
	load	(R_PLIST_NUM),R_TEMP2		; Get plist data
	or	R_TEMP2,R_TEMP2			; PROTECT AGAINST BUG
	store	R_TEMP2,(R_VT_CP)		; Store it in the voice table
	addq	#4,R_PLIST_NUM			; Move pointer along
	subq	#1,R_TEMP1			; Copy all of them	
	jr	NE,copy_plist
	addq	#4,R_VT_CP			; Move pointer along
	

; We now have the plist	copied into the voice table and we can mess with it
; do pitch
; do second pitch
; do velocity
; do pan
; do reverb

change_values:
	load	(R_VT_IND_P+1),R_FLAGS		; get flags
; THIS IS THE CODE FOR FIRING A SURROUND EFFECT
	movefa	A_EFFECTS,R_TEMP2
	load	(R_TEMP2),R_TEMP1
	btst	#1,R_TEMP1			; surround on ?
	jr	EQ, no_surround
	btst	#22,R_FLAGS			; surround patch ?
	jr	EQ,no_surround
	load	(R_SUR_VOICE),R_TEMP1
	btst	#3,R_TEMP1			; Voice 13 free?
	jr	NE,no_surround
	moveq	#11,R_TEMP1
	store	R_TEMP1,(R_SUR_VOICE)		; set Used+Note On+STEAL(!)
						; TRICK: Steal gives us a 8 samples
						; delay on voice 13!
	addq	#4,R_SUR_VOICE
	store	R_M_EVENT,(R_SUR_VOICE)		; store event
	move	R_VOICE_NUM,R_TEMP1
	shlq	#16,R_TEMP1
	bset	#1,R_TEMP1
	store	R_TEMP1,(R_TEMP2)

; SURROUND CODE END

no_surround:	
	bclr	#31, R_M_EVENT			; clear event bit
						; velocity in highest 7 bits
	move	R_M_EVENT,R_FREQ		; get frequency
	shlq	#8,R_FREQ			; prepare to align freq.
	shrq	#24,R_M_EVENT			; Velocity in A_M_EVENT
	shrq	#15,R_FREQ			; Frequency 

pitch1:	
	load	(R_VT_IND_P+3),R_MPITCH		; get pitch tuning
	sharq	#1,R_FLAGS
	jr	CC,pitch2
	nop
	btst	#31,R_MPITCH			; check for reverse sample
	jr	EQ,not_reverse
	mult	R_FREQ,R_MPITCH			; multiply tuning+frequency
	neg	R_MPITCH
not_reverse:
	sharq	#10,R_MPITCH			; shift to X.12
;;or R_MPITCH, R_MPITCH			; +++ HMK 7/16/95
	store	R_MPITCH,(R_VT_IND_P+3)
	
pitch2:	
	movei	#pitch_table,R_TEMP2		; Could be faster
	move	R_VOICE_NUM,R_TEMP1
	shlq	#3,R_TEMP1			; voice long aligned *2
	add	R_TEMP2,R_TEMP1			; points to pitch table
	store 	R_MPITCH,(R_TEMP1) 		; needed for pitch bend

	moveq	#0,R_MPITCH			; reset pitch in case there

	sharq	#1,R_FLAGS
	jr	CC,vel_fx_vol
	nop					; secondary pitch is 7.12
	load	(R_VT_IND_P+6),R_MPITCH		; get pitch tuning
	move	R_MPITCH,R_P_COPY		; copy of pitch
	bclr	#15,R_MPITCH			; 15 bits always pos
	shrq	#15,R_P_COPY			; other bits o pitch
	mult	R_FREQ,R_MPITCH			; multiply tuning+frequency
	mult	R_FREQ,R_P_COPY			; multiply tuning+frequency
	shrq	#10,R_MPITCH			; shift to X.12
	shlq	#5,R_P_COPY			; align upper 15 bits
	add	R_P_COPY,R_MPITCH		; get final pitch
;;or R_MPITCH, R_MPITCH			; +++ HMK 7/16/95
	store	R_MPITCH,(R_VT_IND_P+6)

vel_fx_vol:
	addq	#4,R_TEMP1			; point to next pitch table	
	store 	R_MPITCH,(R_TEMP1) 		; needed for pitch bend

	movei	#MIDI_VOLUME,R_TEMP2
	load	(R_VT_IND_P+20),R_MVOLUME
	load	(R_TEMP2),R_TEMP1
	load	(R_PR_P), R_TEMP2
	btst	#23, R_TEMP2			; is it a sound fx?
	jr	eq, .l1	
	nop
	shrq	#16, R_TEMP1			; get sound fx volume!!!
.l1:
	mult	R_MVOLUME,R_TEMP1		; affected vol in lower 16bits
	sharq	#1,R_FLAGS
	jr	CC,no_vel_vol
	shrq	#15,R_TEMP1
	mult	R_M_EVENT,R_TEMP1
	shrq	#7,R_TEMP1
	
no_vel_vol:
	move	R_TEMP1,R_MVOLUME
	shlq	#16,R_MVOLUME			; new max volume in upper 16
	or	R_TEMP1,R_MVOLUME		; put copy and new volume back
;;or R_MVOLUME, R_MVOLUME			; +++ HMK 7/16/95
	store	R_MVOLUME, (R_VT_IND_P+20)

vel_fx_pan:
	sharq	#1,R_FLAGS
	jr	CC,vel_fx_env2
	nop
	store	R_M_EVENT,(R_VT_IND_P+19)		; Put vel. in pan loc

vel_fx_env2:
	sharq	#1,R_FLAGS
	jr	CC,move_pan
	nop
	load	(R_VT_IND_P+12),R_TEMP1
	shrq	#15,R_TEMP1
	mult	R_M_EVENT,R_TEMP1
	shlq	#8,R_TEMP1
	store	R_TEMP1,(R_VT_IND_P+12)		; Put vel. in Env2 value loc

move_pan:	
	store	R_FLAGS,(R_VT_IND_P+1)		
	movei	#pan_table,R_MPAN_LOC
	movei	#move_reverb,R_MJUMP
	movei	#note_pan,R_M_EVENT
	load	(R_VT_IND_P+19),R_NEW_VALUE
	jump	(R_M_EVENT)
	nop
move_reverb:	
	movei	#reverb_table,R_MPAN_LOC
	load	(R_VT_IND_P+18),R_NEW_VALUE
	jump	(R_M_EVENT)
	addq	#reverb_return-move_reverb,R_MJUMP  ; point to reverb_return

reverb_return:
	moveq	#0,R_M_EVENT
;;or R_M_EVENT, R_M_EVENT 		; +++ HMK 7/16/95
	store	R_M_EVENT,(R_VT_IND_P+19)		; Put 0 in filter loc2
	store	R_M_EVENT,(R_VT_IND_P+18)		; Put 0 in filter loc1
	
end_note_on:
	load	(R_VT_IND_P),R_MDTAB_P
	load	(R_MDTAB_P),R_MDJUMP_P
 	addq	#4,R_MDTAB_P
	jump	(R_MDJUMP_P)
	nop

VT_RETURN_LOC:	
vt_return_loc:
	moveq	#PLIST_SIZE,R_TEMP1
	addq	#1,R_VOICE_NUM			; Move voice number along 

	shlq	#2,R_TEMP1
	add	R_TEMP1,R_VT_IND_P		; increase voice table loc.(%%)
	movei	#parse_voice_table, R_TEMP1
	jump	(R_TEMP1)
	nop					; possibly move (%%) to here

;	8/8/95 - we don't know why it works but it does....
note_pan:
	move	R_VOICE_NUM,R_MPAN_VOICE	; get voice number for pan
	rorq	#1, R_MPAN_VOICE
	moveq	#0,R_MPAN_SHIFT			; Clear pan shift
	shlq	#2,R_MPAN_VOICE			; word align
	jr	CS,even_pan			; if #0 is set voice was odd	
	add	R_MPAN_VOICE,R_MPAN_LOC		; point to correct location

	moveq	#16,R_MPAN_SHIFT		; take care of packing
even_pan:
	load	(R_MPAN_LOC),R_MPAN_VALUE
	sh	R_MPAN_SHIFT,R_MPAN_VALUE
	shlq	#16,R_MPAN_VALUE
	addq	#16,R_MPAN_SHIFT
	add	R_NEW_VALUE,R_MPAN_VALUE
	ror	R_MPAN_SHIFT,R_MPAN_VALUE

note_pan_end:
	jump	(R_MJUMP)
	store	R_MPAN_VALUE,(R_MPAN_LOC)


.if 0	; should work but does not - missing Paul's magic...
note_pan:
	move	R_VOICE_NUM,R_MPAN_VOICE	; get voice number for pan
	moveq	#0,R_MPAN_SHIFT			; Clear pan shift
	btst	#0,R_VOICE_NUM
	jr	EQ,even_pan			; if #0 is set voice was odd	
	bclr	#0, R_VOICE_NUM

	moveq	#16,R_MPAN_SHIFT		; take care of packing
even_pan:
	shlq	#1,R_MPAN_VOICE			; word align
	add	R_MPAN_VOICE,R_MPAN_LOC		; point to correct location
	load	(R_MPAN_LOC),R_MPAN_VALUE
	sh	R_MPAN_SHIFT,R_MPAN_VALUE
	shlq	#16,R_MPAN_VALUE
	addq	#16,R_MPAN_SHIFT
	add	R_NEW_VALUE,R_MPAN_VALUE
	ror	R_MPAN_SHIFT,R_MPAN_VALUE

note_pan_end:
	jump	(R_MJUMP)
	store	R_MPAN_VALUE,(R_MPAN_LOC)
.endif



;____________________start of I2S interrupt service routine___________________
;_____________________________________________________________________________


i2s_isr:
	load	(A_DFLAGS_P),A_DFLAGS_D		; Get flag data

	move	A_BUFFPTR, A_TEMP1	; Get buffer start location
	add	A_READCOUNT, A_TEMP1	; Add current read location

.if REDBOOK
	btst	#1,A_READCOUNT
	jr		NE,.1
	load	(A_TEMP1), A_SAMPLE	; Get the sample sitting there
	addq	#4,A_R_DAC			; Get Left DAC location
	shlq	#16,A_SAMPLE		; sign extend
	sharq	#17,A_SAMPLE		; and div by 2
	load	(A_R_DAC),R5		; get left CD data
	sharq	#17,R5				; and div by 2
	add		R5,A_SAMPLE			; mix
	store	A_SAMPLE, (A_R_DAC)	; Store it in the DAC's
	load	(A_TEMP1), A_SAMPLE	; Get the sample sitting there
	subq	#4,A_R_DAC			; Get Right DAC location
	sharq	#17,A_SAMPLE		; lower 16 bits = Left sample
	load	(A_R_DAC),R5		; get right CD data
	sharq	#17,R5				; and div by 2
	add		R5,A_SAMPLE			; mix
	store	A_SAMPLE, (A_R_DAC)	; upper 16 bits = Right sample
.1:
	addq	#2, A_READCOUNT		; Increase buffer location	
	bclr	#7, A_READCOUNT		; Clear bit modulo 32 long words
	movei	#$fffff000,R5		; restore R5 with $FFFFF000
.else
	addq	#4,A_R_DAC		; Get Left DAC location
	load	(A_TEMP1), A_SAMPLE	; Get the sample sitting there
	addq	#4, A_READCOUNT		; Increase buffer location
	store	A_SAMPLE, (A_R_DAC)	; Store it in the DAC's
	sharq	#16,A_SAMPLE		; lower 16 bits = Left sample
	subq	#4,A_R_DAC		; Get Right DAC location
	bclr	#7, A_READCOUNT		; Clear bit modulo 32 long words
	store	A_SAMPLE, (A_R_DAC)	; upper 16 bits = Right sample
.endif

	bclr	#3,A_DFLAGS_D			; clear IMASK
	load	(A_STACK_P),A_LAST_INST_P	; get last instruction address
	bset	#10,A_DFLAGS_D			; clear I2S interrupt
	addq	#2,A_LAST_INST_P		; point at next to be executed
	addq	#4,A_STACK_P			; update the stack pointer
	jump	(A_LAST_INST_P)			; and return
	store	A_DFLAGS_D,(A_DFLAGS_P)		; restore flags
	nop
	nop

;----------------- MIDI interrupt -------------------------------------------

midi_isr:
	.include	"modules/midi.das"
	
;----------------- Synth auto Shutdown --------------------------------------

SHUTDOWN:
	movei	#D_FLAGS,r0
	movei	#$3e00,r1		; clear pending bits
	store	r1,(r0)
	movei	#D_CTRL,r0
	moveq	#0,r1			; turn off
	store	r1,(r0)
	nop
	nop
	nop
	nop

;---------------- Tables and Buffers ----------------------------------------

	.phrase
VOICE_BUFFER:	
voice_buffer:	
		.dcb.l	NUM_VOICES*8,0		; must be in lower 4k RAM
sbuff_loc:
		.dcb.l	8,0	
VOICE_TABLE:
voice_table:
	.include "modules/vtable.dat"

;---------------- Unit Generators -------------------------------------------

.if	SWITCH_OSC_SAMPLER
	.include	"modules/osc1.das"		;interp. reverse sample player
.endif

.if	SWITCH_OSC_NISAMPLER
	.include	"modules/osc2.das"		;NON-int. sample player
.endif

.if	SWITCH_OSC_ROMWAVE
	.include	"modules/osc3.das"		;interpolating ROMwave player
.endif

.if	SWITCH_OSC_FM
	.include	"modules/osc4.das"		;2-op FM small
.endif

.if	SWITCH_OSC_POLY
	.include	"modules/osc5.das"		;Poly wave
.endif

.if	SWITCH_OSC_SMROMWAVE
	.include	"modules/osc6.das"		;int. ROMwave player small
.endif

.if	SWITCH_OSC_SMNIROMWAVE
	.include	"modules/osc7.das"		;NON-int. ROMwave player small
.endif

.if	SWITCH_NILFO
	.include	"modules/lfo1.das"		;NON-int. LFO
.endif

.if	SWITCH_LFO
	.include	"modules/lfo2.das"		;interpolating LFO
.endif

.if	SWITCH_ENV
	.include	"modules/env1.das"		;ADSR env
.endif

.if	SWITCH_LOOPENV
	.include	"modules/env2.das"		;Looping ADSR env
.endif

.if	SWITCH_FILTER1
	.include	"modules/filter1.das"		;IIR filter w/resonance	
.endif

.if	SWITCH_FILTER2
	.include	"modules/filter2.das"		;IIR filter w/resonance	
.endif

.if	1
	.include	"modules/atten1.das"		;attenuate and put into buffer
.endif

.if	SWITCH_DIST
	.include	"modules/dist_mod.das"		;Pulse width and dist fx
.endif

.if	SWITCH_PAN
	.include	"modules/pan_mod.das"		;osc and env fx pan
.endif

.if	SWITCH_PITCH
	.include	"modules/pitchmod.das"		;osc and env fx pitch
.endif

.if	1
	.include	"modules/mixer.das"		;Pan and mix voice buffer
.endif

.if	SWITCH_DELAY
	.include	"modules/delay.das"		;first delay 
.endif

.if	SWITCH_REVERB
	.include	"modules/reverb.das"		;then reverb always
.endif

DSP_IDLE:
			.dc.l	0
debug:						;end of synth code
			.dc.l	0	

.long
.rept	(($F1C600-debug)>>2)-1
			.dcb.l	1,0
.endr

cir_buff_loc:
			.dcb.l	32,0 

;---------------------- Should be at F1C180 = 4480 bytes --------------------

	.long

pan_table:		
			.dcb.l	((NUM_VOICES+1)/2),$003f003f

REVERB_TABLE:
reverb_table:
			.dcb.l	((NUM_VOICES+1)/2),$003f007f

pitch_table:	
			.dcb.l	(NUM_VOICES*2),$0

.long
FILTER_DEF_1:
FILTER_DEF_2:
			.include "modules/filttab.dat"

			.long
midi_bak:
			.dc.l	0
		 	.long
EFFECT_MODE:
			.dc.l	$ffff0000
		 	.long
midi_dat:
			.include "modules/midi.dat"

;---------------- Module pointer tables -------------------------------------

			.long
MDTAB_MIXER: 
		.dc.l	mixer
		.dc.l	main_loop
			.long
MDTAB_START::
MDTAB_REVERB:
		.dc.l	0
		.dc.l	0

		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0

		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0
		.dc.l	0

MDTAB_END:
VT_RET_VALUE:
vt_ret_value:
		.dc.l	vt_return_loc

;----------------------- Envelopes -------------------------------------
			.long
ENVELOPE_START::		

SYNTH_END::

dbuf2p:	
			.dc.l	0	; *** for debugging

;______________________________________________________________________________
	END
