; =========================================================
; CSX.S: This is a 68K program to "fetch" csx audio from
; the "Cartridge" between addresses AUDFILE and AUDFILEx.
; It monitors the DSP buffer and keeps it full.
; =========================================================
; Copyright, 1995 Atari Corporation.
; Written for Atari by Highlight Software Solutions.
; =========================================================
; The initial code was taken from the sample simple.s.



	.include	'jaguar.inc'

	.extern		DSPSTART
	.extern		DSPEND
	.extern		DSP_START

	.extern		SHUTDOWN
	.extern		TMR1_ISR

; CSX Specific external references
; --------------------------------
	.extern		CSXIN_START
	.extern		CSXIN_HEAD
	.extern		CSXIN_TAIL
	.extern		CSXSETCHAN
	.extern		CSX68_1
	.extern		CSX68_2
	.extern		CSX68_3
	.extern		CSX68_4
	.extern		AUDFILE
	.extern		AUDFILEx
	AUDBUFSIZE 	.EQU	1024		; Size in 16 bit words of csxb
						; input buffer.
	AUDBUFWSIZE  	.EQU	64		; buffer write size, it must
						; evenly go into AUDBUFSIZE.


	HIBIT		equ		$80000000

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; This section was taken from simple.s demo software
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	move.l	#$00070007,D_END	; Set GOOD mode
	move.l	#$1ffffc,sp		; Set 68000 stack pointer to end of DRAM.

; At this point we assume that the DSP is turned off!
; First we copy the Jerry code into Jerry
; for bigger blocks you would use the Blitter, for it is SO MUCH faster
; than this copy loop (but for blitting you have to make sure that the
; transfered block will be at a phrase boundary)

	move.l	#D_RAM,a1
	move.l	#DSPSTART,a0
	move.l	a0,d0
	move.l	#DSPEND,d1
	sub.l	d0,d1
	asr.l	#2,d1
translop:
	move.l	(a0)+,(a1)+
	dbra	d1,translop

; Make sure the DACs are silent!

	move.l	#0,R_DAC
	move.l	#0,L_DAC

; Set up the I2S mode and clock
	move.l	#19,SCLK
	move.l	#$15,SMODE

; Enable sound (mute bit)

	move.w	#$100,JOYSTICK


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; End of section taken from simple.s demo software
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; ---------------------------------------------------
; load initial buffer of audio before turning on DSP
; ---------------------------------------------------

asetup:
	move.l	#(AUDBUFSIZE-AUDBUFWSIZE),d2	; Fill buffer to maximum allowed
	move.l	#CSXIN_START, a1
	move.l	a1, a3
	add.l	#AUDBUFSIZE, a3		    	; twice for byte addresses
	add.l	#AUDBUFSIZE, a3			; a3 is end of buffer
	move.l	#AUDFILE, a2
aloop:
	move.w	(a2), d0  			; load data into next spot
	move.w	d0, (a1)
	add.l	#2,a1
	add.l	#2, a2
	sub.l	#1, d2
	bne	aloop 				; loop until done
	nop
	move.l	#CSXIN_HEAD,a4
f1:
	move.l	a1,(a4)				; save new head ptr

	;move.l	#$43434343, a1                  ; non-zero is mono
	move.l	#0, a1				; zero is stereo
	move.l	a1,CSXSETCHAN			; initialize mono/stereo(0)

; -----------------------------------------------------------------
; Now that buffer is pre-loaded, turn on the DSP
; -----------------------------------------------------------------
	move.l	#DSP_START,D_PC	; Set up D_PC

	move.l	#$1,D_CTRL	; Start DSP

; DEBUG ONLY
;jmp	aloopdone	; uncomment this for few pass DSP Debugging only.

; -----------------------------------------------------------------
; check whether there is room, and if so move in more audio
; stop if done with AUDFILE audio
; -----------------------------------------------------------------
; Register Rules from here on in the file.
; a2,a3 needs to remain throughout, others are reset each pass
; -----------------------------------------------------------------
	nop
	move.l	#0, d5			; use to count writes

acont:
	move.l	d5, d0
	sub.l	#5, d0
	bne	skipdb
	nop
dbug1:
	nop
	nop
skipdb:
	move.l	#CSXIN_HEAD, a4
	move.l	(a4),d0
	move.l	#CSXIN_TAIL, a4
	move.l	(a4),a5
	sub.l	a5, d0			; head - tail
	blt	aminus			; head less than tail

	; head is greater or equal to tail
	beq.w	acont			; if equal then no room to write
	move.l	#(AUDBUFSIZE - AUDBUFWSIZE),a5
	add.l	#(AUDBUFSIZE - AUDBUFWSIZE),a5
	sub.l	a5,d0
	beq	acont			; equal, no room to write
	bgt	acont			; (head-tail) > (remaining space), no room
	jmp	aloopwrite
aminus:
	add.l	#AUDBUFWSIZE,d0
	add.l	#AUDBUFWSIZE,d0
	bge	acont			; not enough room to write
	jmp	aloopwrite		; else, enough room, write
	nop

; if there is room, then write audio here
aloopwrite:
	add.l	#1, d5 					; debug counter
	move.l	#AUDBUFWSIZE,d2				; Write 64 at a time
	move.l	#CSXIN_HEAD, a4
	move.l	(a4),a1
aloop1:
	move.w	(a2), d0
	move.w	d0, (a1)
	add.l	#2,a1
	add.l	#2, a2
	sub.l	#1, d2
	bne	aloop1
aloop1x:
	nop

	; increment head flag
	move.l	a1,d0
	sub.l	a3,d0
	blt	aloop2			; we do not need to wrap around
	nop
	move.l	#CSXIN_START, d0
	move.l 	#CSXIN_HEAD, a1
	move.l	d0, (a1)		; wrap around head pointer
	jmp	aloop3
	nop
aloop2:
	; no wrap around is needed
	move.l	#CSXIN_HEAD, a4
	move.l	a1, (a4)		; no wrap around, update pointer

aloop3:
	; done with this write, see if we have reached end of audiofile
	move.l	#AUDFILEx, d0
	sub.l	a2, d0
	bgt    acont			; still more to play
	nop
	jmp 	aloopdone


; -----------------------------------------------------------------------
; FOR NOW, when we are done, jump to illegal to allow debugging
; -----------------------------------------------------------------------
aloopdone:
; Disable sound (mute bit)

	move.w	#$000,JOYSTICK

	nop
	illegal
; -----------------------------------------------------------------------
; The following section was taken from the simple.s sample program.
; -----------------------------------------------------------------------
; THIS IS NEW MAGIC TO CAUSE THE DSP TO STOP
; AT THE NEXT SAMPLE INTERRUPT

	move.l	#SHUTDOWN,d0
	and.l	#$ffff,d0
	or.l	#$981d0000,d0
	move.l	d0,$f1b010

	illegal

; ************************ END OF MAIN CODE ***********************

