;*********************************
;* Jungle Jag - JagCode 500 Game *
;*********************************
;
; by Cedric Bourse, (a.k.a Orion_) [2007]
;
; http://onorisoft.info/
;
; This Source Code is licensed under the term of the following Creative Commons License:
; http://creativecommons.org/licenses/by-nc/3.0/
;
; You are free:
;  * to Share : to copy, distribute and transmit the work
;  * to Remix : to adapt the work
;
; Under the following conditions:
;  * Attribution. You must attribute the work in the manner specified by the author or licensor (but not in any way that suggests that they endorse you or your use of the work).
;  * Noncommercial. You may not use this work for commercial purposes.
;  * For any reuse or distribution, you must make clear to others the license terms of this work. The best way to do this is with a link to this web page.
;  * Any of the above conditions can be waived if you get permission from the copyright holder.
;  * Nothing in this license impairs or restricts the author's moral rights.
;

;***************************
;* DSP Part of the program *
;***************************
; Here are all the DSP code and data to be loaded in DSP Cache !

	.68000
	.text

	.long
DSPCode:
	.DSP
	.org     D_RAM

;*****************
;- Main DSP Code -
;*****************

; DSP Interupts

	movei		#dsp_main,r0	; start DSP main program
	jump		(r0)
	nop
	nop
	nop
	nop
dsp_int_1:
;	storew		r0,(r2)		; DBUG
	movei		#i2s_int,r24	; Our Audio Interrupt
	jump		(r24)
	nop
	nop
	nop
	nop
dsp_int_2:				; <------ Interrupt vide (on valide juste l'interrupt et on ce barre)
	load		(r28),r29	; D_FLAGS
	bclr		#3,r29		; clear IMASK
	load		(r31),r30
	bset		#11,r29		; IRQ 2 clear
	addq		#2,r30
	addq		#4,r31		; correct the Stack
	jump		(r30)		; jump back to the code
	store		r29,(r28)	; D_FLAGS
dsp_int_3:
	load		(r28),r29	; D_FLAGS
	bclr		#3,r29		; clear IMASK
	load		(r31),r30
	bset		#12,r29		; IRQ 3 clear
	addq		#2,r30
	addq		#4,r31		; correct the Stack
	jump		(r30)		; jump back to the code
	store		r29,(r28)	; D_FLAGS
dsp_int_4:
	load		(r28),r29	; D_FLAGS
	bclr		#3,r29		; clear IMASK
	load		(r31),r30
	bset		#13,r29		; IRQ 4 clear
	addq		#2,r30
	addq		#4,r31		; correct the Stack
	jump		(r30)		; jump back to the code
	store		r29,(r28)	; D_FLAGS
dsp_int_5:
	load		(r28),r29	; D_FLAGS
	bclr		#3,r29		; clear IMASK
	load		(r31),r30
	bset		#17,r29		; IRQ 5 clear
	addq		#2,r30
	addq		#4,r31		; correct the Stack
	jump		(r30)		; jump back to the code
	store		r29,(r28)	; D_FLAGS

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


;----------------------------
;- DSP Audio Initialisation -
;----------------------------

dsp_main:
	movei	#D_FLAGS,r28
	load	(r28),r29
	bset	#3,r29		; IMASK
	bclr	#14,r29		; register bank selection (bank 0)
	store	r29,(r28)

; Stack Pointer
	movei	#D_RAM+$1F00,r31	; set the stack at the end of the DSP Ram - 256
	moveta	r31,r31			; in both bank

; Init audio
	movei	#SCLK,r13
	movei	#SMODE,r9
	movei	#18,r0		; SCLK
	movei	#%010101,r1	; SMODE

	; n = (830968,75/(2*freq))-1 = 18 for 22050hz
	; f = 830968,75/(2*(n+1))

	store	r0,(r13)	; 18 -> SCLK
	store	r1,(r9)		; 010101 -> SMODE (activate sound ...)


;	movei	#BG,r2		; DBUG !
;	moveq	#0,r1
;	movei	#$F800,r0


	load	(r28),r29
	bset	#5,r29		; IRQ 1 enable, I2S Interrupt
	store	r29,(r28)

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

	movei	#dsp_loop,r20
	nop
dsp_loop:
	jump	T,(r20)		; do nothing loop (just keep DSP alive ^^)
	nop

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


;-------------------
;- Audio Interrupt -
;-------------------

i2s_int:
	load	(r28),r29	; D_FLAGS
	bclr	#3,r29		; clear IMASK
	load	(r31),r30
	bset	#10,r29		; IRQ 1 clear

;-----
; Channels Manager

	movei	#Channel1_ptr,r14
	moveq	#1,r25
	store	r25,(r14+16)	; Lock ChannelAccess

	movei	#L_I2S,r26	; left channel
	movei	#R_I2S,r27	; right channel
	movei	#128,r25	; Signed
	move	r25,r21		; Channel 1 Sample !
	move	r25,r22		; Channel 2 Sample !
	move	r25,r23		; Channel 3 Sample !
	move	r25,r24		; Channel 4 Sample !

	load	(r14),r15	; Channel 1 Sample Pointer
	or	r15,r15
	jr	EQ,.playCh1	; Don't play if pointer null !
	nop

	loadb	(r15),r21	; Load Sample
	load	(r14+1),r16	; Load Length
	addq	#1,r15		; Pointer++
	subq	#1,r16		; Length--
	jr	NE,.nupC1	; If end of the sample (length = 0)
	nop
	load	(r14+2),r15	; Load Original Info (for looping, or stopping -> 0)
	load	(r14+3),r16
.nupC1:	store	r15,(r14)	; Store info back
	store	r16,(r14+1)

.playCh1:

	load	(r14+4),r15	; Channel 2 Sample Pointer
	or	r15,r15
	jr	EQ,.playCh2	; Don't play if pointer null !
	nop

	loadb	(r15),r22	; Load Sample
	load	(r14+5),r16	; Load Length
	addq	#1,r15		; Pointer++
	subq	#1,r16		; Length--
	jr	NE,.nupC2	; If end of the sample (length = 0)
	nop
	load	(r14+6),r15	; Load Original Info (for looping, or stopping -> 0)
	load	(r14+7),r16
.nupC2:	store	r15,(r14+4)	; Store info back
	store	r16,(r14+5)

.playCh2:

	load	(r14+8),r15	; Channel 3 Sample Pointer
	or	r15,r15
	jr	EQ,.playCh3	; Don't play if pointer null !
	nop

	loadb	(r15),r23	; Load Sample
	load	(r14+9),r16	; Load Length
	addq	#1,r15		; Pointer++
	subq	#1,r16		; Length--
	jr	NE,.nupC3	; If end of the sample (length = 0)
	nop
	load	(r14+10),r15	; Load Original Info (for looping, or stopping -> 0)
	load	(r14+11),r16
.nupC3:	store	r15,(r14+8)	; Store info back
	store	r16,(r14+9)

.playCh3:

	load	(r14+12),r15	; Channel 4 Sample Pointer
	or	r15,r15
	jr	EQ,.playCh4	; Don't play if pointer null !
	nop

	loadb	(r15),r24	; Load Sample
	load	(r14+13),r16	; Load Length
	addq	#1,r15		; Pointer++
	subq	#1,r16		; Length--
	jr	NE,.nupC4	; If end of the sample (length = 0)
	nop
	load	(r14+14),r15	; Load Original Info (for looping, or stopping -> 0)
	load	(r14+15),r16
.nupC4:	store	r15,(r14+12)	; Store info back
	store	r16,(r14+13)

.playCh4:

;********--------

	add	r21,r22		; Add the 4 Channels
	add	r23,r24
	add	r22,r24

	shrq	#2,r24		; 4 Channels -> /4
	sub	r25,r24		; Signed
	shlq	#8,r24		; 8bits -> 16bits

	store	r24,(r26)	; send the sample to the left channel
	store	r24,(r27)	; send the sample to the right channel

	moveq	#0,r25
	store	r25,(r14+16)	; UnLock ChannelAccess

;-----

	addq	#2,r30
	addq	#4,r31		; correct the Stack
	store	r29,(r28)	; D_FLAGS
	jump	(r30)		; jump back to the code
;	storew	r1,(r2)		; DBUG
	nop

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

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

	StopDSP

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

; Datas

	.long
Channel1_ptr:	dc.l	0	; Pointer to the current sample position
Channel1_len:	dc.l	0	; Length to be played until the end
Channel1_optr:	dc.l	0	; Pointer to the beginning of the sample (0 if no sample loop)
Channel1_olen:	dc.l	0	; Length of the sample

Channel2_ptr:	dc.l	0
Channel2_len:	dc.l	0
Channel2_optr:	dc.l	0
Channel2_olen:	dc.l	0

Channel3_ptr:	dc.l	0
Channel3_len:	dc.l	0
Channel3_optr:	dc.l	0
Channel3_olen:	dc.l	0

Channel4_ptr:	dc.l	0
Channel4_len:	dc.l	0
Channel4_optr:	dc.l	0
Channel4_olen:	dc.l	0

ChannelAccess:	dc.l	0

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

	.68000
DSPEnd:
	.print "[DSP code size: ",/u (DSPEnd-DSPCode),"] [DSP Free Memory: ",/u (8192-(DSPEnd-DSPCode)),"]"
