;****** thxplay.library/thxInit ******************************************
;
;   NAME
;       thxInit -- initialise player and module.
;
;   SYNOPSIS
;       error = thxInit(module)
;       D0              A0
;
;       ULONG thxInit(APTR);
;
;       error := thxInit(module)
;
;   FUNCTION
;       Initialises  the  player (if needed) and initializes the module. You
;       may  also  call  thxInit(NIL)  to  initialise the player but not the
;       module.  Does not start to play the module until you call thxPlay().
;       You  must  call  this each time you want to play a different module.
;       The allocations made for the player are made only the first time you
;       call  thxInit(), no matter how many modules you want. If allocations
;       fail, they will be automatically freed.
;
;   INPUTS
;       module - pointer to a THX module or NIL
;
;   RESULT
;       error - zero means all went OK, any other value means failure.
;
;   NOTE
;       In  the  library  version of this interface, thxInit() and thxFree()
;       use  a task ownership system - to begin with, nobody 'owns' THX. The
;       first  task  to  call  thxInit() will then 'own' THX, and successive
;       calls  to  thxInit()  and thxFree() will only succeed for this task.
;       When  this  task calls thxFree(), the owner goes back to nobody, and
;       now other tasks are free to use THX.
;
;       This  is the only arbitration used by the interface. All other calls
;       may  be called from any task at all. Please respect this arbitration
;       mechanism and avoid calling other THX functions unless thxInit() has
;       succeeded  for  you. You must call thxFree() from the same task that
;       called thxInit().
;
;   SEE ALSO
;       thxFree(), thxPlay()
;
;****************************************************************************
;
;
	cnop	0,4
	xdef	thxInit__i
thxInit__i
	ifnd	_LIBRARY_
	move.l	4(sp),a0
	endc

	movem.l	d2-d7/a2-a6,-(sp)
	lea	mod(pc),a1
	move.l	a0,(a1)			; store moduleptr

	lea	mod_OK(pc),a0
	clr.b	(a0)			; mod is NOT ok until we say so
	lea	song(pc),a0
	clr.w	(a0)			; set current subsong to 0

; allocate player memory/allocate channels and such
	move.b	init_OK(pc),d0
	bne.s	.setmod			; skip if already done
	moveq	#0,d0
	moveq	#0,d1
	sub.l	a0,a0			; auto-allocate public mem (fast)
	sub.l	a1,a1			; auto-allocate chip mem
	bsr	THX+thxInitPlayer
	tst.l	d0
	bne	.fail
	lea	init_OK(pc),a0
	st.b	(a0)

; initialise module (must be before initCIA)
.setmod	move.l	mod(pc),d0
	beq.s	.nomod
	move.l	d0,a0
	bsr	THX+thxInitModule
	moveq	#0,d0		; start with main song
	moveq	#1,d1		; don't play immediately
	bsr	THX+thxInitSubSong


; try to allocate CIA interrupt
.nomod	move.b	cia_OK(pc),d0
	bne.s	.done			; skip if already installed
	lea	intcode(pc),a0
	moveq	#0,d0
	bsr	THX+thxInitCIA		; install intcode
	tst.l	d0
	bne.s	.nocia
	lea	cia_OK(pc),a0
	st.b	(a0)
	bra.s	.done

; if CIA allocation failed, try to allocate VERTB interrupt
.nocia	move.b	vb_OK(pc),d0
	bne.s	.done			; skip is already installed
	move.l	4.w,a6
	lea	int(pc),a1
	moveq	#INTB_VERTB,d0
	jsr	_LVOAddIntServer(a6)	; install intcode
	lea	vb_OK(pc),a0
	st.b	(a0)

.done	move.l	mod(pc),d0	; if module is not-null, initialise it _again_
	beq.s	.exit		; this time _after_ interrupt is installed
	move.l	d0,a0
	bsr	THX+thxInitModule
	moveq	#0,d0		; start with main song
	moveq	#1,d1		; don't play immediately
	bsr	THX+thxInitSubSong
	bsr	THX+thxStopSong	; reset timer, audiochannels
	lea	mod_OK(pc),a0
	st.b	(a0)
	moveq	#0,d0
	bra.s	.exit

.fail	bsr.s	thxFree			; on failure, free everything
	moveq	#-1,d0			; return failure
.exit	movem.l	(sp)+,d2-d7/a2-a6
	rts




;****** thxplay.library/thxFree ******************************************
;
;   NAME
;       thxFree -- free resources held by player.
;
;   SYNOPSIS
;       void thxFree()
;
;       void thxFree(void);
;
;       thxFree()
;
;   FUNCTION
;       Stops any THX module playing and frees resources used by the player.
;       You can call this whether thxInit() suceeded or not.
;
;   SEE ALSO
;       thxInit()
;
;****************************************************************************
;
;
	cnop	0,4
	xdef	thxFree
thxFree	movem.l	d2-d7/a2-a6,-(sp)
	bsr	thxStop			; stop play

	move.b	cia_OK(pc),d0
	beq.s	.nocia
	bsr	THX+thxKillCIA		; remove CIA int if running
	
.nocia	move.b	vb_OK(pc),d0
	beq.s	.novb
	move.l	4.w,a6
	lea	int(pc),a1
	moveq	#INTB_VERTB,d0
	jsr	_LVORemIntServer(a6)	; remove VB int if running

.novb	move.b	init_OK(pc),d0
	beq.s	.noinit
	bsr	THX+thxKillPlayer	; free player resources

.noinit	lea	cia_OK(pc),a2
	clr.l	(a2)			; clear cia_OK, vb_OK, init_OK & mod_OK
	movem.l	(sp)+,d2-d7/a2-a6
	rts




; VARIABLES
mod	dc.l	0	; APTR the current module

cia_OK	dc.b	0	; BOOL int routine is CIA, and is init'd and running
vb_OK	dc.b	0	; BOOL int routine is VBI, and is init'd and running
init_OK	dc.b	0	; BOOL initialisation (memory, etc) is done
mod_OK	dc.b	0	; BOOL module is initialised, play can commence
