/************************************************************************************
	GLOVER PS	(c) 1998-9 ISL

	xa.c:		XA audio stream code

************************************************************************************/

//#include "global.h"

#include "glover.h"
#include "xa.h"
#include <string.h>


typedef struct _XADataType {
	CdlCB		oldCallback;
	char		buffer[2340];
	int			currChannel;
	int			activeChannel;
	int			currSector;
	XAFileType	*currXA;
	XAFileType	*prevXA;
	int			prevChannel;
	int			prevSector;
} XADataType;


XADataType	XAData;
int			XAenable;
int			XAplaying = 0;
XAFileType		XAfile[XAFILE_MAX];


/**************************************************************************
	FUNCTION:	Init_XA_Tracks()()
	PURPOSE:	Stores all addresses of XA tracks, ready for instant playing
	PARAMETERS:	
	RETURNS:	
**************************************************************************/

void Init_XA_Tracks(){
	XAgetFileInfo("ATLANTIS",&XAfile[XAFILE_ATLANTIS]);
	XAgetFileInfo("CARNIVAL",&XAfile[XAFILE_CARNIVAL]);
	XAgetFileInfo("PIRATES",&XAfile[XAFILE_PIRATES]);
	XAgetFileInfo("PREHIST",&XAfile[XAFILE_PREHISTORIC]);
	XAgetFileInfo("FORTRESS",&XAfile[XAFILE_FORTRESS]);
	XAgetFileInfo("OOTW",&XAfile[XAFILE_OOTW]);
}
/**************************************************************************
	FUNCTION:	XAcallback()
	PURPOSE:	Callback for XA audio stream
	PARAMETERS:	
	RETURNS:	
**************************************************************************/
static void XAcallback(int intr, u_char *result)
{
	ULONG	*cAddress = (ULONG *)XAData.buffer;
	int		ID;

	if (intr == CdlDataReady)
	{
		CdGetSector(cAddress, 8);
		ID = *(unsigned short *)(cAddress+3);
		// video sector channel number format = 1CCCCC0000000001
		XAData.currChannel = *((unsigned short *)(cAddress+3)+1);
		XAData.currChannel = (XAData.currChannel & 31744)>>10;

		XAData.currSector++;
		if((ID == 352) && (XAData.currChannel==XAData.activeChannel))	// Check for end sector marker
		{
	        CdControlF(CdlPause,0);
			if (XAData.currXA->loop)
			{
				XAplayChannel(XAData.currXA, XAData.activeChannel, XAData.currXA->loop);
			}
			else
			{
				XAData.currXA->status = 0;
				XAData.currXA = NULL;
				XAstop();
			}
//	        SsSetSerialVol(SS_SERIAL_A,0,0);
		}
	}
	else
		debugPrintf("UnHandled Callback Occured\n");	
}

/**************************************************************************
	FUNCTION:	XAgetFileInfo()
	PURPOSE:	Get position information for XA file
	PARAMETERS:	Filename
	RETURNS:	
**************************************************************************/
void XAgetFileInfo(char *fileName,XAFileType *xaf)
{
	char		fName[40];

	sprintf(fName, "%s", fileName);
	strcpy(fName, "\\AUDIO\\");
	strcat(fName, fileName);
	strcat(fName, ".XA;1");
	if (!XAenable)
	{
//		debugPrintf("XA track '%s' disabled\n", fName);
		return;
	}
	if (CdSearchFile(&xaf->fileInfo, fName)==0)
	{
//		debugPrintf("XA file '%s' not found\n", fName);
		return;
	}
	xaf->startPos = CdPosToInt(&xaf->fileInfo.pos);
	xaf->endPos = xaf->startPos + (xaf->fileInfo.size/2048)-1;
	xaf->status = 0;
//	debugPrintf("XA track '%s' %d->%d\n", fName, xaf->startPos,xaf->endPos);
	return; // xaf;
}

/**************************************************************************/
int XA_SetMusicGoing(int track, int loop)
{
	int cdfilenum;
	if (music==NO) return 0;
	
	if(track >= TRACK_SP1)
	{
		track-= TRACK_SP1;
		cdfilenum=XAFILE_OOTW;
	}
	else if(track >= TRACK_FF1)
	{
		track -= TRACK_FF1;
		cdfilenum=XAFILE_FORTRESS;
	}
	else if(track >= TRACK_PR1)
	{
		track -= TRACK_PR1;
		cdfilenum=XAFILE_PREHISTORIC;
	}
	else if(track >= TRACK_PI1)
	{
		track -= TRACK_PI1;
		cdfilenum=XAFILE_PIRATES;
	}
	else if(track >= TRACK_CA1)
	{
		track -= TRACK_CA1;
		cdfilenum=XAFILE_CARNIVAL;
	}
	else
	{
		cdfilenum=XAFILE_ATLANTIS;
	}

//	SsInit();						// RESET SOUND SYSTEM 

	XAstart(1);
	XAplayChannel(&XAfile[cdfilenum], track, loop);
	return 1;
}


/**************************************************************************
	FUNCTION:	XAstart()
	PURPOSE:	Get CD ready to play XA audio stream
	PARAMETERS:	CD speed 0=single 1=double
	RETURNS:	
**************************************************************************/

void XAstart(int speed)
{
	u_char param[4];

	if (!XAenable)
		return;
	if (speed)
		param[0] = CdlModeSpeed|CdlModeRT|CdlModeSF|CdlModeSize1;
	else
		param[0] = CdlModeRT|CdlModeSF|CdlModeSize1;
	CdControlB(CdlSetmode, param, 0);
	CdControlF(CdlPause,0);

	XAData.oldCallback = CdReadyCallback((CdlCB)XAcallback);
	XAData.currXA = NULL;
	XAplaying = YES;
}

/**************************************************************************
	FUNCTION:	XAstop()
	PURPOSE:	CD back to data - finished playing XA audio streams
	PARAMETERS:	
	RETURNS:	
**************************************************************************/

void XAstop()
{
	u_char param[4];

	XAplaying = NO;

	if (!XAenable)
		return;
	CdControlF(CdlPause,0);
	CdReadyCallback((void *)XAData.oldCallback);
	param[0] = CdlModeSpeed;
	CdControlB(CdlSetmode, param, 0);
}

/**************************************************************************
	FUNCTION:	XAplayChannel()
	PURPOSE:	Start playing channel from given XA audio stream
	PARAMETERS:	XA file, channel number
	RETURNS:	
**************************************************************************/
void XAplayChannel(XAFileType *xaF, int channel, int loop)
{
	CdlLOC		loc;
	CdlFILTER	theFilter;

	if (!XAenable)
	{
		debugPrintf("XAplayChannel: disabled\n");
		xaF->status = 0;
		return;
	}
	if (xaF==NULL)
	{
		debugPrintf("XAplayChannel: stream not found\n");
		return;
	}
	theFilter.file = 1;
	theFilter.chan = channel;
	XAData.activeChannel = channel;
	CdControlF(CdlSetfilter, (u_char *)&theFilter);
	CdIntToPos(xaF->startPos, &loc);
	CdControlF(CdlReadS, (u_char *)&loc);
	XAData.currXA = xaF;
	XAData.currSector = xaF->startPos;
	xaF->status = 1;
	xaF->loop = loop;
	debugPrintf("XAplayChannel: %d->%d\n", xaF->startPos,xaF->endPos);
}


/**************************************************************************
	FUNCTION:	XAcheckPlay()
	PURPOSE:	Test if XA has begun playback
	PARAMETERS:	
	RETURNS:	0 = Not playing yet, 1 = Is playing now
**************************************************************************/

int XAcheckPlay()
{
	UBYTE	result[8];

	if (!XAenable)
		return 1;
	CdControlB(CdlNop, 0, result);
	return ((result[0] & CdlStatRead) && (!(result[0] & CdlStatSeek)));
}

/**************************************************************************
	FUNCTION:	XAstorePrevious()
	PURPOSE:	Store current XA playback track/channel
	PARAMETERS:	
	RETURNS:	
**************************************************************************/
void XAstorePrevious()
{
	XAData.prevXA = XAData.currXA;
	XAData.prevChannel = XAData.activeChannel;
	XAData.prevSector = XAData.currSector;
}

/**************************************************************************
	FUNCTION:	XArestartPrevious()
	PURPOSE:	Restart previously stored XA playback track/channel
	PARAMETERS:	
	RETURNS:	
**************************************************************************/
void XArestartPrevious()
{
	CdlLOC		loc;
	CdlFILTER	theFilter;

	if (!XAenable)
	{
		debugPrintf("XArestartPrevious: disabled\n");
		XAData.prevXA->status = 0;
		return;
	}
	if (XAData.prevXA==NULL)
	{
		debugPrintf("XArestartPrevious: stream not found\n");
		return;
	}
	theFilter.file = 1;
	theFilter.chan = XAData.prevChannel;
	XAData.activeChannel = XAData.prevChannel;
	CdControlF(CdlSetfilter, (u_char *)&theFilter);
	CdIntToPos(XAData.prevSector, &loc);
	CdControlF(CdlReadS, (u_char *)&loc);
	XAData.currXA = XAData.prevXA;
	XAData.currSector = XAData.prevSector;
	XAData.prevXA->status = 1;
	debugPrintf("XArestartPrevious: %d [%d->%d]\n", XAData.prevSector,XAData.prevXA->startPos,XAData.prevXA->endPos);
}

