;-------T-------T-------T-------T-------T-------T-------T-------T-------T-------T-------T----x
;Labels (16)    Instructions (48)                               Comments (30++)
;              $VER: EagleRave 1.2
;	    Started: 980321
;	   Location: Waratah.au, Malmö.se
; 	 Last drunk: 6 weeks ago
;	Last stoned: 3 weeks ago (M)
;	       Mood: Homesick
;     Todays wishes: 1> LAG 2> Return to Sweden
;           Changed: 980322, 980323, 980324, 980413, 980414, 980415, 980416
;	    Changed: 980818, 980819, 980827

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*	                                               ... 	*
*	::::::.::::::. :::::::.   .::  ::::::. .::::.  ::: 	*
*	.::.::'.::..:: .::..::' ...`::..::..'' .::.    `'  	*
*	:::    :::: ::::::: `::.::::::'::::.::.::::::' ::: 	*
*	..................................................	*
*                                                               *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

; Captain's log...
;
; 980321:2115	(001) Started this source today. Added some macros and stuff from SpaceScope+.
;		Now it will display an about requester when loaded from Eagleplayer.
; 980322:0420	(002) Added/inserted some routines for the message handling, but haven't
;		tried to assemble it yet.
; 980322:2357	(002) Now I have a simple engine which will wait until Eagleplayer wants it
;		to exit, whereupon it will exit and free everything. Seems to work fine.
; 980323:0334	(003) Included some routines from DeliRave and adapted them to this source.
;		They try to load the eaglerave config, if this cannot be done it will pop up
;		a filerequester asking for the location of the RaveScope. This works, I don't
;		know if the config-reading routine works since I haven't made a config yet.
; 980323:0413	(004) Added some more routines from DeliRave, to find/execute the RaveScope.
;		Works, it seems. Now I only need to make the RaveScope 'accept' this engine.
; 980324:0459	(004) Inserted some other routines that deal with updating the channel structs,
;		and tried to convert them to use Eagleplayer's format. Got confused. Inserted
;		the routines to open/close the timer.device while I were at it, don't know
;		if I'll need it.
; 980413:1954	(042) Scrapped most of this source. I'm going to change everything now to use
;		the hostfunctions.
; 980414:0023	(042) This works again now. Now let's try to get the display working...
; 980416:0311	(043) I inserted a routine by Buggs to obtain the sample position, length
;		and volume, and got it to work. But all channels do not seem to be displayed,
;		and EaglePlayer will crash when it tries to load a new module (I think it did
;		this before, then I got rid of it, and now it's back).
; 980416:0332	(043) Hmm.. I made some change, in er_ProcMsg I think, and now it won't work
;		at all. Eagleplayer will lock up completely, and the Ravescope never starts.
; 980416:1720	(043) This disappeared when I removed the temporary routine to tell the
;		RaveScope that the player is active, as I have now made it believe (in debug
;		mode) that it is always active. I had forgotten to check all eagle channels,
;		this was why the scope did not look correct (it only read 1 channel). And I
;		may have done some more change, at the moment Eagleplayer does not crash
;		anymore when changing modules.
; 980416:2136	(044) Those strange crashes are now gone it seems. I added a routine to always
;		output the exact name of the eagleplayer-message, and noticed that stopint/
;		startint was sent whenever the music stopped/started, so I made eaglerave send
;		appropriate messages to the RaveScope. This works, the only thing that remains
;		is to get the state when starting up (and no such message has been recieved).
;		Also I have problems with Buggs routine to check the sample pointers, they will
;		be zero way too often. Especially when there's only a loop running...
; 980418:1822	(045) Found a few bugs in the Update-channels routine. The most serious being
;		me forgetting to increment the pointer to buggs period storage for each channel.
;		This was what caused the channels to be blacked out! Also corrected minor bug
;		in that routine (only clearing the sample-length word-wise). And in the update
;		channel routine I would clear the flag that indicated that the structure was
;		being updated, could cause incorrect behaviour sometimes.
; 980819:1600	(050) Yesterday I changed this routine to call _rh_PlyActive whenever eagleplayer
;		started to play. Now I have changed the er_FindPort("Eagleplayer") routine to
;		Forbid() before the FindPort() and only Permit() again if the port could not be
;		found.
; 980827:2041	(054) To support the SaveConfig message, and a variable config-path, I made a
;		routine called er_GetCfgName. It will create the full pathname to the config
;		by looking at the config-path in the eagleplayer data structure. If not present,
;		the current directory will be used. When the saveconfig message comes from eagle,
;		I'll update this path and send a RMSG_SAVECONFIG message to the RaveScope, which
;		will then save its config.
; 980922:0007	(065) *** Released version 1.2 on Aminet with this source (065).

		IFD	_PHXASS_
		MACHINE	68020
		ENDC

*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
*
*		Includes &c

		SECTION EngineCode,Code

		INCDIR	include:
		INCLUDE	exec/exec_lib.i
		INCLUDE	exec/exec.i
		INCLUDE	exec/tasks.i
		INCLUDE	devices/timer_lib.i
		INCLUDE	devices/timer.i
		INCLUDE	dos/dos_lib.i
		INCLUDE	dos/dos.i
		INCLUDE	dos/dostags.i
		INCLUDE graphics/graphics_lib.i
		INCLUDE	graphics/gfx.i
		INCLUDE	hardware/intbits.i
		INCLUDE	intuition/intuition_lib.i
		INCLUDE	intuition/intuition.i
		INCLUDE	libraries/gadtools_lib.i
		INCLUDE	libraries/gadtools.i
		INCLUDE	libraries/reqtools.i
		INCLUDE	libraries/reqtools_lib.i
		INCDIR	""
		INCLUDE	eagleplayer/EaglePlayer.i
		INCLUDE	eagleplayer/EagleplayerEngine.i
		INCLUDE	include/monoscope.i
		INCLUDE	include/ravescope.i
		INCLUDE	include/eaglerave.i

		XREF	_rh_InitHost				* Init this host
		XREF	_rh_FreeHost				* Free everything done in InitHost
		XREF	_rh_AllocSig				* Allocate a signal
		XREF	_rh_FreeSig				* Free a signal
		XREF	_rh_AddSig				* Add sig (d0) to the signalmask
		XREF	_rh_RemSig				* Remove sig (d0) from the sigmask
		XREF	_rh_ProcMsgs				* Process msgs from Rave
		XREF	_rh_SignalRave				* PutMsg Rave & wait IF WE HAVE IT
		XREF	_rh_TellRave				* PutMsg Rave IF WE HAVE IT
		XREF	_rh_PlyActive				* Tell Rave we're playing
		XREF	_rh_UpdateChans				* Update the channel structures
		XREF	_rh_OpenLibs				* Open dos, intuition and reqtools.library
		XREF	_rh_CloseLibs				* Close dos, intuition and reqtools.library

*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
*
*		Constants

NO:		EQU	0
YES:		EQU	1
MYDEBUG:	EQU	NO
DEBTIME:	EQU	0
er_RELEASE:	EQU	YES
er_VERSION:	EQU	102

*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
*
*		Macros


PUSH:		MACRO
		IFC	"\1","ALL"
		movem.l	d0-a6,-(sp)
		ELSE	
		movem.l	\1,-(sp)
		ENDC
		ENDM

POP:		MACRO
		IFC	"\1","ALL"
		movem.l	(sp)+,d0-a6
		ELSE	
		movem.l	(sp)+,\1
		ENDC
		ENDM

CALLLVO:	MACRO
        	jsr	_LVO\1(a6)
		ENDM
JUMPLVO:	MACRO
        	jmp	_LVO\1(a6)
		ENDM

CALLEXE:	MACRO
		move.l	rh_oSysBase(a5),a6
        	jsr	_LVO\1(a6)
		ENDM
JUMPEXE:	MACRO
		move.l	rh_oSysBase(a5),a6
        	jmp	_LVO\1(a6)
		ENDM

CALLDOS:	MACRO
		move.l	rh_oDOSBase(a5),a6
        	jsr	_LVO\1(a6)
		ENDM
JUMPDOS:	MACRO
		move.l	rh_oDOSBase(a5),a6
        	jmp	_LVO\1(a6)
		ENDM

CALLITN:	MACRO
		move.l	rh_oIntuiBase(a5),a6
        	jsr	_LVO\1(a6)
		ENDM
JUMPITN:	MACRO
		move.l	rh_oIntuiBase(a5),a6
        	jmp	_LVO\1(a6)
		ENDM

CALLREQ:	MACRO
		move.l	rh_oRTBase(a5),a6
		jsr	_LVO\1(a6)
		ENDM
JUMPREQ:	MACRO
		move.l	rh_oRTBase(a5),a6
		jmp	_LVO\1(a6)
		ENDM

		IFNE	MYDEBUG					* Debug macro. Link with include:
		XRef	KPrintF					* link/debug.lib & link/amiga.lib
		ENDC

DBUG:		MACRO
		IFNE	MYDEBUG
		IFNE	NARG-1
		subq.w	#1,.Ctr\@
		bne	.Skip\@
		move.w	#\2,.Ctr\@
		bra	.Debug\@
.Ctr\@:		dc.w	1
		ELSE
		bra	.Debug\@
		ENDC
.Str\@:		dc.b	"EAGL: ",\1,0
		EVEN
.Debug\@:	DBUGIT	.Str\@
.Skip\@:	*+-
		ENDC
		ENDM

DBUGIT:		MACRO
		IFNE	MYDEBUG
		PUSH	ALL
		move.l	4.w,a6
		CALLLVO	Forbid
		lea	\1,a0
		CLEARA	a1
		jsr	KPrintF
		CALLLVO	Permit
		IFNE	DEBTIME
		move.l	rh_oDOSBase(a5),d0
		beq	.Skip\@
		move.l	d0,a6
		move.l	#DEBTIME,d1
		CALLLVO	Delay
		ENDC
.Skip\@:	POP	ALL
		ENDC
		ENDM

LEASTR:		MACRO
		bsr	.skip\@
		dc.b	\1,0
		EVEN
.skip\@:	move.l	(sp)+,\2
		ENDM

SETERR:		MACRO
		tst.l	rh_oError(a5)				;Error code already set?
		bne	.Skip\@					;Yes, skip
		move.l	\1,rh_oError(a5)			;Set new error
.Skip\@:	*+-
		ENDM

ERRMSG:		MACRO
		LEASTR	\1,a0
		SETERR	a0
		ENDM

*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
*
*		ENGINE IDENTIFIER

er_Begin:	bra.w	er_Start				;MUST be a BRA.W !
		EUSN_Identifier					;Identifier "EPEngine"
		dc.l	0					;eus_next, Don`t Use!
		dc.w	0 ;-2*MYDEBUG				;eus_Usernr (don't use)
		dc.l	0,0,0					;eus_EPBase, Freetable, Taskadr
		dc.l	0,0,0					;eus_unused1-2, private jumptab
		dc.l	er_TagList				;eus_unused4
		dc.w	0,0					;eus_ticks, eus_tickcounter
		dc.l	EUIB_OnlyPlay!EUIB_OnlyActive 		;eus_tickflags
		dc.l	USMB_Zipwin!USMB_ChangeConfig!USMB_ChangeInterrupt ;eus_msgflags
		dc.l	er_EngineName				;eus_PName, processname of this Engine
		dc.l	er_MyParsecName				;Creatorname e.g Parsec
		dc.l	er_MyInfo				;tells something about this Engine.
		dc.w	39					;eus_Kickstart
		dc.l	EAGLEVERSION-1				;eus_EPVersion
		dc.w	1,2					;eus_version
		dc.l	er_MyUsername				;eus_username, Name for PullDownMenu (max.14 Chars)
		dc.w	268, 167				;eus_winx, eus_winy
		dc.w	EUSB_Openwin				;Flags (iconify/zipwin,openwin)
		dc.l	0,0,0					;EUS_Special1-3
		dc.l	22<<24!(9<<16)!1998			;EUS_Creatordate
		dc.b	-4					;EUS_Priority
		dc.b	EUTY_Scope				;Userprogramtype (0=unknown)
		dc.w	0					;Set zero, don`t change
		dc.l	0,0,0,0					;EUS_Reserved3-6
		IFNE	(*-er_Begin)-EUS_SizeOF			;Check that size is correct
		FAIL	"Men Hallå"
		ENDC

er_Version:	dc.b	"$VER: RaveScope-Engine 1.2 (22.9.98)"
		EVEN

er_TagList:	dc.l	EUT_SpecialinfoLNr,LNrE_SpecialInfo_SpaceScope
		dc.l	EUT_AttnFlags, AFF_68020
		dc.l	0

*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
*
*		Program start

er_Start:	lea	er_Data,a5
		DBUG	"** Entered er_Start\n"
		bsr	er_Init
		beq	.Error
		bsr	er_Main
		bsr	er_CleanUp
		moveq	#1,d0
		DBUG	"Exiting engine OK.\n"
		rts
.Error:		bsr	er_CleanUp
		DBUG	"Exiting engine because of ERROR.\n"
		moveq	#0,d0
		rts


*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
*
*		Main loop

er_Main:	DBUG	"Going to sleep in the main loop.\n\n"
.Loop:		move.l	rh_oSigMask(a5),d0			* Get signal mask
		CALLEXE	Wait					* and wait.

		move.b	er_oSignal(a5),d1
		bclr.l	d1,d0					* Got interrupt signal?
		beq	.NoInt

		move.l	d0,-(sp)
		lea	er_UpdChans,a2
		moveq	#4,d1					* Make room for 4 channels
		jsr	_rh_UpdateChans
		move.l	(sp)+,d0				* Any more signals set?
		beq	.Loop					* No, go back to sleep

.NoInt:		DBUG	"Yawn...\n"
.NoDeb:		bclr.l	#SIGBREAKB_CTRL_C,d0			* Got quit-signal?
		bne	.Quit

		move.b	([er_oMsgPort,a5],MP_SIGBIT),d1		* Got a message from Eagleplayer?
		bclr.l	d1,d0
		beq	.ChkRave				* No

		move.l	d0,-(sp)
.GetEagle:	move.l	er_oMsgPort(a5),a0			* Wait for message to arrive
		CALLEXE	GetMsg
		tst.l	d0					* Got message?
		beq	.EagleOk				* No, done
.GotEagle:	bsr	er_ProcMsg				* Process message
		bne	.GetEagle				* Continue
		move.l	(sp)+,d0				* Got quit-message
		bra	.Quit
.EagleOk:	move.l	(sp)+,d0

.ChkRave:	move.b	MP_SIGBIT(a5),d1			* Got a msg from the RaveScope?
		btst.l	d1,d0
		beq	er_Main					* No
		jsr	_rh_ProcMsgs
		bra	er_Main

.Quit:		st	rh_oHostQuit(a5)
.RemMsgs:	bsr	er_PollMsg				* Remove the last messages from
		bne	.RemMsgs				* the Eagleport and check for
		DBUG	"Exiting Main.\n\n"			* USClass_Exit
		rts


*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
*
*		Process message, return Z set if USClass_Exit message recieved.

er_ProcMsg:	move.l	d0,a1
		move.l	er_oMsgPort(a5),UM_UserPort(a1)

		lea	er_Begin,a2
		move.w	EUS_UserNr(a2),UM_UserNr(a1)
		move.l	rh_oThisTask(a5),UM_TaskAdr(a1)
		CLEAR	d0
		move.b	er_oSignal(a5),d0
		move.l	d0,UM_Signal(a1)

		move.w	UM_Class(a1),d3
		move.l	UM_Type(a1),d7
		move.l	UM_StructAdr(a1),er_oUPSStruct(a5)	* Get UPS_StructAdr

		IFNE	MYDEBUG					* Identify the message
		move.w	d3,d0
		cmp.w	#37,d0
		bls	.MsgOk
		moveq	#38,d0
.MsgOk:		move.l	(er_DebMsgPtrs,pc,d0*4),a0
		DBUG	"Got "
		DBUGIT	(a0)
		LEASTR	" message.\n",a0
		DBUGIT	(a0)
		ENDC

		move.l	a1,-(sp)
		cmp.w	#USClass_StartInt,d3			* Got the startint msg?
		bne	.NoStart
		jsr	_rh_PlyActive				* Tell the RaveScope that we're playing
		bra	.MsgDone

.NoStart:	cmp.w	#USClass_StopInt,d3			* Got the stopint msg?
		bne	.NoStop
		move.w	#RMSG_PLYHALTED,d0			* Tell the RaveScope (if we have
		clr.b	rh_oPlaying(a5)				* it) that we're not playing.
		jsr	_rh_SignalRave				* Set our local play-flag			
		bra	.MsgDone

.NoStop:	cmp.w	#USClass_Exit,d3			* Exit engine? (only to Engine)
		bne	.NoExit
		st	rh_oHostQuit(a5)			* Set the host quit flag
		clr.l	UM_Signal(a1)
		clr.l	UM_TaskAdr(a1)
		clr.b	er_oNotifyEP(a5)			* No need to notify EP about exit
		bra	.MsgDone

.NoExit:	cmp.w	#USClass_Hide,d3			* Iconify?
		bne	.NoHide
		move.w	#RMSG_DOICONIFY,d0
		jsr	_rh_TellRave
		bra	.MsgDone

.NoHide:	cmp.w	#USClass_Show,d3			* De-iconify?
		bne	.NoShow
		move.w	#RMSG_DEICONIFY,d0
		jsr	_rh_TellRave
		bra	.MsgDone

.NoShow:	cmp.w	#USClass_SaveConfig,d3
		bne	.NoSave
		bsr	er_GetCfgName				* Update config name
		beq	.MsgDone				* Couldn't, so don't save config
		move.w	#RMSG_SAVECONFIG,d0			* Then ask the RaveScope to save it
		jsr	_rh_TellRave
		bra	.MsgDone

.NoSave:	cmp.w	#USClass_Answer,d3			* Command came back, in UM_Arg
		bne	.MsgDone				* UM_Arg2 results...?
		move.l	UM_Argstring(a1),d0
		beq	.MsgDone
		clr.l	UM_Argstring(a1)

.MsgDone:	move.l	(sp)+,a1
		cmp.l	#USM_UserPrg,d7				* Did we send this message?
		beq	.NoReply				* Yes, so don't reply to it
		DBUG	"Replying to the message.\n"
		CALLEXE	ReplyMsg

.NoReply:	cmp.w	#USClass_Exit,d3			* Exit engine?
		rts


*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
*
*		Init everything

er_Init:	DBUG	"** Entered er_Init.\n"
		move.l	er_Begin+EUS_EPBase,a0			* UPSStructure valid?
		tst.l	EPG_UPS_Structure(a0)
		sne	rh_oPlaying(a5)				* Yes, that means msx is playing

		bsr	er_GetCfgName				* Get config path and name in a1
		beq	.Error					* Couldn't, so exit
		LEASTR	"EaglePlayer",a0			* Name of the host
		CLEARA	a2					* No tags!
		jsr	_rh_InitHost				* Init it...
		beq	.Error					* Serious error, quit and report failure...

		bsr	er_OpenTimer				* Open timer.device
		beq	.Error
		bsr	er_EagleInfo				* Get some info from EaglePlayer
		beq	.Error

		move.b	#SIGBREAKB_CTRL_C,d0			* Add CTRL-C signal to the mask
		jsr	_rh_AddSig
		jsr	_rh_AllocSig				* Allocate interrupt signal
		move.b	d0,er_oSignal(a5)
		bmi	.Error

		bsr	er_MakeMsgPort				* Create message port
		beq	.Error
		bra	er_FirstMsg				* Send the first message
.Error:		moveq	#0,d0
		rts

*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
*
*		Clean up everything

er_CleanUp:	DBUG	"** Entered er_CleanUp\n"
		tst.b	er_oNotifyEP(a5)			* Need to notify Eagleplayer?
		beq	.NoNotify				* No
		bsr	er_LastMsg				* Send last quit-message
.NoNotify:	bsr	er_FreeMsgPort				* Free the now emptied msg port

		lea	er_oSignal(a5),a0
		jsr	_rh_FreeSig				* Free the signal-bit
		bsr	er_CloseTimer				* Close timer.device &c
		jmp	_rh_FreeHost				* Free the host


*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
*
*		Get the full path and name to the config. Returns NULL=failure

er_GetCfgName:	CLEAR	d5					* d5 = Don't close libs
		tst.l	rh_oDOSBase(a5)				* Dosbase valid?
		bne	.DosOk
		jsr	_rh_OpenLibs				* No, open it
		beq	.Error					* Error!
		moveq	#1,d5					* d5 = Close libs when done

.DosOk:		move.l	er_Begin+EUS_EPBase,a0			* Get EP base
		move.l	EPG_ConfigDirArrayPtr(a0),d1		* Config dir specified in EP?
		beq	.NoCfgDir				* No, use current dir

		moveq	#SHARED_LOCK,d2
		CALLDOS	Lock					* Try to lock the config-dir
		move.l	d0,d1					* Successful?
		beq	.NoCfgDir				* No
		moveq	#1,d3					* d3 = Need to UnLock later
		move.l	d0,d4					* d4 = UnLock this later
		bra	.DirOk

.NoCfgDir:	CALLDOS	CurrentDir				* Get current directory
		move.l	d0,d4					* d4 = Old CD
		moveq	#-1,d3					* d3 = Need to CD back later

.DirOk:		move.l	d0,d1					* Get lock to config-dir
		lea	er_CfgPath,a2				* Store name here
		clr.b	(a2)					* Reset path
		move.l	a2,d2
		move.l	#512,d3					* Size of buffer
		CALLDOS	NameFromLock

		move.l	a2,d1					* Add the name to the path
		move.l	#er_CfgName,d2
		move.l	#512+19,d3
		CALLLVO	AddPart

		tst.l	d3					* Need to UnLock or CurrentDir ?
		bmi	.LastCD					* CurrentDir()...
		move.l	d4,d1					* UnLock() the lock that we locked before
		CALLDOS	UnLock
		bra	.Exit

.LastCD:	move.l	d4,d1					* Step back to old CD
		CALLDOS	CurrentDir

.Exit:		move.l	a2,a1					* Return a1 = full path to config
		IFNE	MYDEBUG
		DBUG	"Config path = "
		move.l	a1,a0
		DBUGIT	(a0)
		LEASTR	"\n",a0
		DBUGIT	(a0)
		ENDC

		tst.l	d5					* Close libs?
		beq	.Out
		jsr	_rh_CloseLibs
.Out:		moveq	#1,d0					* Set success
.Error:		rts

*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
*
*		Get some information from EaglePlayer

er_EagleInfo:	move.l	er_Begin+EUS_EPBase,d0			* Get Eagleplayer's globals
		beq	.Exit
		move.l	d0,a0
		move.l	EPG_SomePrefs(a0),er_oEPFlags(a5)	* Get some global EP flags
		moveq	#1,d0
.Exit:		rts		


*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
*
*		Open timer.device & related stuff

er_OpenTimer:	DBUG	"Creating msg-port for use with timer.device.\n"
		CALLEXE	CreateMsgPort
		move.l	d0,er_oTimePort(a5)
		beq	.Error

		DBUG	"Opening timer.device.\n"
		lea	er_oTimeReq(a5),a1			* set ReplyPort for TimeRequest
		move.l	d0,MN_REPLYPORT(a1)
		lea	er_TimerName,a0				* Get timer.device name
		moveq	#UNIT_VBLANK,d0
		CLEAR	d1
		CALLEXE	OpenDevice				* Open timer.device

		tst.l	d0					* Successful? (NULL)
		seq	er_oTimerOpen(a5)			* Set timer opened flag if so
		tst.b	er_oTimerOpen(a5)
.Error:		rts


*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
*
*		Close timer.device & related stuff

er_CloseTimer:	tst.b	er_oTimerOpen(a5)			* Was timer.device opened?
		beq	.NoTime
		DBUG	"Closing timer.device.\n"		* Yes, so close it.
		lea	er_oTimeReq(a5),a1
		clr.b	er_oTimerOpen(a5)
		CALLEXE	CloseDevice

.NoTime:	move.l	er_oTimePort(a5),d0			* Was msgport for timer created?
		beq	.Exit
		DBUG	"Deleting timer.device's msgport...\n"
		move.l	d0,a0					* Yes, delete it.
		clr.l	er_oTimePort(a5)
		JUMPEXE	DeleteMsgPort
.Exit:		rts


*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
*
*		Create message port to recieve messages from Eagleplayer

er_MakeMsgPort:	DBUG	"Creating message port...\n"
		CALLEXE	CreateMsgPort
		move.l	d0,er_oMsgPort(a5)
		beq	.Error
		move.b	([er_oMsgPort,a5],MP_SIGBIT),d0		* Get message ports signal bit
		jsr	_rh_AddSig
		moveq	#1,d0
		rts
.Error:		ERRMSG	"Couldn't create messageport!"
		moveq	#0,d0
		rts


*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
*
*		Free the eagleplayer dedicated message port

er_FreeMsgPort:	DBUG	"Freeing the message port...\n"
		move.l	er_oMsgPort(a5),d0
		beq	.Exit
.EmptyPort:	bsr	er_PollMsg				* Make sure there's no msg left
		bne	.EmptyPort
		move.l	d0,a0
		CALLEXE	DeleteMsgPort
		move.b	([er_oMsgPort,a5],MP_SIGBIT),d0		* Get message ports signal bit
		jsr	_rh_RemSig
		clr.l	er_oMsgPort(a5)
.Exit:		rts


*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
*
*		Send the first message, return Z for error

er_FirstMsg:	DBUG	"** Entered er_FirstMsg\n"
		bsr	er_FindPort				* Find EaglePlayer's port
		beq	.Exit

		st	er_oNotifyEP(a5)			* Must notify EP when quitting now
		move.l	er_oMsgPort(a5),d3
		move.l	rh_oThisTask(a5),d4
		CLEAR	d5
		move.b	er_oSignal(a5),d5
		move.w	#USClass_NewUserPrg,d6
		bsr	er_SendMsg
		CALLEXE	Permit
		moveq	#1,d0
.Exit:		rts

*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
*
*		Send the last message

er_LastMsg:	DBUG	"** Entered er_LastMsg\n"
		bsr	er_FindPort				* Eagleplayer still present?
		beq	.Exit					* No

		move.l	d0,a0					* Portadresse
		move.l	er_oMsgPort(a5),d3
		bne	.Send
		CALLEXE	Permit
		bra	.Exit

.Send:		CLEAR	d4
		CLEAR	d5
		move.w	#USClass_Exit,d6
		bsr	er_SendMsg
		CALLEXE	Permit
		DBUG	"Last message sent, waiting for reply..\n"
		clr.b	er_oNotifyEP(a5)

.Wait:		move.l	er_oMsgPort(a5),a0
		CALLEXE	WaitPort
		bsr	er_PollMsg
		ble	.Wait
.Exit:		rts

*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
*
*		TASK	Poll a message from our port and reply to it.
*		FLAGS	ZERO	If no message was found
*			NEG	If an eagleplayer message was recieved (and replied)
*			GT	If one of our messages was recieved (and freed)

er_PollMsg:	move.l	er_oMsgPort(a5),a0
		CALLEXE	GetMsg					* Get next message
		tst.l	d0
		beq	.Exit					* No message, exit
		move.l	d0,a1
		cmp.l	#USM_UserPrg,UM_Type(a1)
		beq	.Ours

		cmp.w	#USClass_Exit,UM_Class(a1)		* Got eagle's quit-message?
		bne	.NoQuit
		DBUG	"Got quit msg from EP (in PollMsg!)"
		clr.b	er_oNotifyEP(a5)			* Must not notify EP now

.NoQuit:	DBUG	"Found a message! Replying to it...\n"	* Got an eagleplayer message
		CALLLVO	ReplyMsg
		moveq	#-1,d0
		bra	.Exit

.Ours:		DBUG	"Reply to one of our msgs recieved.\n" * Got one of our messages back
		moveq	#1,d0
.Exit:		rts

*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
*
*		Send a message

er_SendMsg:	DBUG	"** Entered er_SendMsg\n"

		lea	er_oEagleMsg(a5),a1			* Messageadress
		move.w	#UM_SizeOf-20,MN_LENGTH(a1)
		move.b	#NT_MESSAGE,LN_TYPE(a1)			* Message type
		move.l	#USM_UserPrg,UM_Type(a1)

		lea	er_Begin,a2
		move.w	EUS_UserNr(a2),UM_UserNr(a1)

		move.l	d3,MN_REPLYPORT(a1)			;Portadresse,an die zuruckgesendet wird
		move.l	d3,UM_UserPort(a1)
		move.l	d4,UM_TaskAdr(a1)
		move.l	d5,UM_Signal(a1)
		move.w	d6,UM_Class(a1)

		clr.l	UM_Command(a1)
		clr.l	UM_Result(a1)
		clr.l	UM_Argstring(a1)

		DBUG	"Sending the message...\n"
		CALLEXE	PutMsg
		moveq	#1,d0
.Error:		rts

*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
*
*		Find the EaglePlayer port, return a0 = the port or NULL

er_FindPort:	DBUG	"Trying to find Eagleplayer's port...\n"
		CALLEXE	Forbid
		lea	er_EPortName,a1
		CALLLVO	FindPort
		move.l	d0,a0
		tst.l	d0
		bne	.Found
		DBUG	"Not found!\n"
		PUSH	d0/a0
		CALLLVO	Permit
		POP	d0/a0
		bra	.Exit
.Found:		DBUG	"Found!\n"
.Exit:		tst.l	d0
		rts


*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
*
*		Update the channel structures

er_UpdChans:	move.l	er_oUPSStruct(a5),d0			* A module playing?
		IFNE	MYDEBUG
		beq	.NoUPS
		ELSE
		beq	.Exit
		ENDC
		move.l	d0,a2					* a2 = UPS struct

		move.w	#64,scph_oMaxVolume(a4)
		move.w	#4,scph_oNumChans(a4)
		and.b	#~(SCPHF_16BITS!SCPHF_7BITS),scph_oFlags(a4)
		or.b	#SCPHF_8BITS!SCPHF_SIGNED,scph_oFlags(a4)
		move.l	scph_oChannels(a4),d0
		IFNE	MYDEBUG
		beq	.NoChans
		ENDC
		beq	.Exit
		move.l	a4,-(sp)
		move.l	d0,a4					* a4 = dest channel struct

		moveq	#-1,d2					* All Channels by default
		move.w	UPS_Flags(a2),d1
		and.w	#UPSB_DMACon,d1				* Correct?
		beq	.NoDmaCon				* No
		move.w	UPS_DMACon(a2),d2			* Get DMA mask
		IFNE	MYDEBUG
		move.w	d2,d7
		and.w	#$F,d7
		bne	.NoDmaCon
		DBUG	"DmaCon is zero!\n",10
		ENDC
.NoDmaCon:	lea	.PermerkLevm,a3				* Smplperiod and play time 1/50s
								* each 32 Bit = 2 words per channel
		moveq	#4-1,d7
.Loop:		bsr	.GetData
		IFNE	MYDEBUG
		tst.l	d0
		bne	.SmplOk
		add.b	#1,.Smpl
.SmplOk:	tst.l	a0
		bne	.LenOk
		add.b	#1,.Len
		ENDC
.LenOk:		move.l	d0,scpc_oSampleLeft(a4)
		move.l	d0,scpc_oLoopSize(a4)
		move.w	d1,scpc_oVolume(a4)
		move.l	a0,scpc_oSamplePos(a4)
		move.l	a0,scpc_oSampleLoop(a4)
		lea	scpc_SIZEOF(a4),a4
		lea	UPS_Modulo(a2),a2
		addq.w	#4,a3
		dbra	d7,.Loop

		IFNE	MYDEBUG
		cmp.w	#$404,.Smpl
		bne	.SthSet
		DBUG	"All sample pos and lens are zero!\n",10
		bra	.SthSet
.Smpl:		dc.b	0
.Len:		dc.b	0
.SthSet:	clr.w	.Smpl
		ENDC	

		move.l	(sp)+,a4
		moveq	#1,d0					* Signal channels updated
		rts
		IFNE	MYDEBUG
.NoUPS:		DBUG	"UPSStruct INVALID!\n",50
		bra	.Exit
.NoChans:	DBUG	"Channels INVALID!\n",1000
		ENDC
.Exit:		CLEAR	d0					* Signal channels not updated
		rts


.PermerkLevm:	ds.l	4

;-----------------------------------------------------------------------------------------------
;----------- fetch rest address, rest size, volume and period values from UPS-structure --------
;-----------------------------------------------------------------------------------------------
;	Input:	d2 = DMA mask (Bit 0 = 1 -> channel on, Bit 0 = 0 -> channel off)
;		a3 = buffer for period and playing time in 1/50 s of the sample of 
;            	     current channel (2 words)
;       	a2 = UPS_Structure for current channel
;
;	Output:	d2 = DMA Mask for next channel (1 Bit right shifted, D2 = D2>>1)
;         	a3 (unchanged)
;         	a2 (unchanged)
;         	a0 = address of the sample
;         	d0 = left size in Bytes
;         	d1 = volume
;         	d3 = period

.GetData:	move.l	d4,-(a7)
		lsr.w	#1,d2
		bcc	.null
		move.l	UPS_Voice1Adr(a2),d1
		beq	.null
		move.l	d1,A0
		move.w	UPS_Voice1Per(a2),d3
		beq	.ok

		move.w	d3,(a3)
		clr.w	2(a3)
		CLEAR	d0
		move.w	UPS_Voice1Len(a2),d0
		add.l	d0,d0			;Samplelänge Words -> Samplelänge Bytes
		bra	.triggered		;bra.s	.copyto

.ok		move.w	(a3),d3			;überhaupt keine Sampleperiod übergeben ?
		beq	.null
		CLEAR	d0
		move.w	UPS_Voice1Len(a2),d0
		add.l	d0,d0			;Samplelänge Words -> Samplelänge Bytes

		CLEAR	d4
		move.w	2(a3),d4
		cmp.w	#$180,d4		;nur zur Sicherheit
		blo	.hi1
		clr.w	2(A3)
		clr.w	d4

.hi1		swap	d4			;=d4*65535
		lsr.l	#2,d4
		divu	(a3),d4			;durch Sampleperiod
		and.l	#$ffff,d4
		lsl.l	#2,d4
		cmp.l	d0,d4			;größer als Samplelänge ?
		blo	.cbm_ok

		tst.w	UPS_Voice1Repeat(a2)
		beq	.cbm_loop

		CLEARA	a0			;lea	nulls(a5),a0
		subq.w	#1,2(a3)
		clr.w	(a3)
		CLEAR	d4
		CLEAR	d0			;move.w	#700,d0
		bra	.cbm_ok

.cbm_loop	tst.l	d0
		bne	.divu
		clr.w	2(a3)
		moveq	#0,d4
		move.w	#700,d0
		bra	.cbm_ok
.divu
		divu	d0,d4
		swap	d4
;		clr.w	2(a3)			;bloss raus lassen, dann sieht es
						;nochmal so gut aus !!
		and.l	#$ffff,d4

.cbm_ok		add.l	d4,a0			;Sampleadr
						;D0: Samplelen
						;D3: SamplePer

.triggered:	move.w	UPS_Voice1Vol(a2),d1	;

		cmp	#64,d1
		bls	.vol_ok
		moveq	#64,d1
.vol_ok
		addq.w	#1,2(a3)
.no		move.l	(a7)+,d4
		rts

.null:		CLEARA	a0		;lea	nulls(a5),a0
		CLEAR	d0		;move.w	#700,d0
		CLEAR	d1
		move.l	(a7)+,d4
		rts


*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
*
*		Misc data

er_EngineName:	dc.b	"RaveScope-Engine.1",0
er_MyUsername:	dc.b	"RaveScope",0
er_MyParsecName	dc.b	"Erik Spåre",0
er_MyInfo:	dc.b	"This engine makes it possible to use the RaveScope with Eagleplayer. "
		dc.b	"The RaveScope is a separate executable which, once you have specified its path, "
		dc.b	"will display waveforms in various ways.",10,10
		dc.b	"Remember: Removing this engine does not necessarily mean that the RaveScope will "
		dc.b	"quit too (unless you have checked the quit=kill menu item).",0
er_EPortName:	dc.b	"EAGLEPLAYERPORT",0
er_TimerName:	dc.b	"timer.device",0
er_CfgName:	dc.b	"RaveScope.cfg",0
		EVEN

		IFNE	MYDEBUG
er_DebMsgPtrs:	dc.l	01$,02$,03$,04$,05$,06$,07$,08$,09$,10$	* Pointers to all the various
		dc.l	11$,12$,13$,14$,15$,16$,17$,18$,19$,20$	* eagle player message names
		dc.l	21$,22$,23$,24$,25$,26$,27$,28$,29$,30$
		dc.l	31$,32$,33$,34$,35$,36$,37$,38$,39$
01$:		dc.b	"USClass_Dummy",0
02$:		dc.b	"USClass_Activate",0
03$:		dc.b	"USClass_DeActivate",0
04$:		dc.b	"USClass_Exit",0
05$:		dc.b	"USClass_Zipwin",0
06$:		dc.b	"USClass_Unzipwin",0
07$:		dc.b	"USClass_NewEngine",0
08$:		dc.b	"USClass_GetConfig",0
09$:		dc.b	"USClass_NewConfig",0
10$:		dc.b	"USClass_LockEP",0
11$:		dc.b	"USClass_UnLockEP",0
12$:		dc.b	"USClass_Command",0
13$:		dc.b	"USClass_Answer",0
14$:		dc.b	"USClass_QuitEagle",0
15$:		dc.b	"USClass_NewModule",0
16$:		dc.b	"USClass_NewSong",0
17$:		dc.b	"USClass_NewPreference",0
18$:		dc.b	"USClass_StartInt",0
19$:		dc.b	"USClass_StopInt",0
20$:		dc.b	"USClass_PlaySample",0
21$:		dc.b	"USClass_NewScrollText",0
22$:		dc.b	"USClass_NewDirectory",0
23$:		dc.b	"USClass_NewPlayer",0
24$:		dc.b	"USClass_NewEngineLoaded ",0
25$:		dc.b	"USClass_KillModule",0
26$:		dc.b	"USClass_Surface",0
27$:		dc.b	"USClass_ActiveSurface",0
28$:		dc.b	"USClass_NewAmplifierlist",0
29$:		dc.b	"USClass_Show",0
30$:		dc.b	"USClass_Hide",0
31$:		dc.b	"USClass_SaveConfig",0
32$:		dc.b	"USClass_RemPlayerList",0
33$:		dc.b	"USClass_RemEnginesList",0
34$:		dc.b	"USClass_RemModulesList",0
35$:		dc.b	"USClass_LoadConfig",0
36$:		dc.b	"USClass_SetWaitPointer",0
37$:		dc.b	"USClass_ClearWaitPointer",0
38$:		dc.b	"USClass_EngineCommand",0
39$:		dc.b	"ALIEN EP MESSAGE!"
		ENDC

*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
*
*
		SECTION EagleRaveBSS,BSS

er_Data:	ds.b	er_SIZEOF				* DATA USED BY RS-TABLE
er_CfgPath:	ds.b	512+20


