/*
 *
 *		Middleware MPEG Sofdec Kamui II Player Sample
 *
 */

/***************************************************************************
 *      Include file
 ***************************************************************************/
#include <shinobi.h>
#include <sg_sd2.h>
#include <sj.h>
#include <sg_mw2.h>
#include <sg_chain.h>

#define	USED_KAMUI2

#ifdef USED_KAMUI2
#include "km2smp.h"
#else
#include "nj_smp.h"
#endif

extern Void sdSysVsyncServer( Void *arg);

/***************************************************************************
 *      MACRO CONSTANT
 ***************************************************************************/

/***************************************************************************
  *      Process MACRO
 ***************************************************************************/

/*	Turn over flag(ON/OFF)	*/
#define NOT_FLAG(flag)		(((flag) == OFF) ? ON : OFF)

/***************************************************************************
 *		Variable Declaration
 ***************************************************************************/

/***************************************************************************
 *      Function Declaration
 ***************************************************************************/

/***
 *		Initialize sound section
 ***/

/*	Initialize sound library and load sound driver	*/
Void SoundInit(Void *ptr)
{
	SDMEMBLK	memblk = NULL;

	/*	Initialize Sound library	 */
	sdLibInit(NULL, 0, 0);			/*	This api's argument is dummy now.  */

	/* 	Download and Initialize Sound driver.	 */
	/*	Create Memory block handle  */
	sdMemBlkCreate(&memblk);

	/*  Setting Memoby block handle  */
	sdMemBlkSetPrm(memblk, ptr, 0, SDD_MEMBLK_SYNC_FUNC, NULL);

	/*	Initialize Sound driver  */
	sdDrvInit(memblk);
	sdMemBlkDestroy(memblk);

	/*	Setting transfer mode	*/
	sdMemBlkSetTransferMode(SDE_MEMBLK_TRANSFER_MODE_DMA);
}

/***
 *			Utility function
 ***/

/*	Load data into memory	*/
void *LoadFile(char *fname, long *len)
{
	GDFS			gdfs;
	long			fsize, nsct;
	void			*dat;

	gdfs = gdFsOpen(fname, NULL);
	if (gdfs == NULL) {
		for (;;) ;
	}
	gdFsGetFileSize(gdfs, &fsize);
	nsct = (fsize + 2047) / 2048;
	dat = syMalloc(nsct * 2048);
	if (dat == NULL) {
		for (;;) ;
	}
	gdFsRead(gdfs, nsct, dat);
	gdFsClose(gdfs);
	if (len != NULL) {
		*len = fsize;
	}

	return dat;
}

/*	msec -> time(hour,min,sec,frame)	*/
void Msec2Time(long mstime, long *hh, long *mm, long *ss, long *ff)
{
	*hh = mstime / (60*60*1000);
	*mm = (mstime - *hh*60*60*1000) / (60*1000);
	*ss = (mstime - *hh*60*60*1000 - *mm*60*1000) / 1000;
	*ff = mstime % 1000;
}

/***
 *			Playing middleware
 ***/

volatile Sint32 usr_mwerr_flag=1;

/*	Callback function when an error occur in middleware	*/
void UsrMwErrFunc(void *obj, char *ecode)
{
	while (usr_mwerr_flag)
		;
}


/*	Playing the animation file	*/
void SmpPlay(char *fname)
{
	MWPLY					ply;
	MWS_PLY_CPRM_SFD		cprm;
	MWE_PLY_STAT			stat;
	const PDS_PERIPHERAL	*per;

	/*	Create handle	*/
	memset(&cprm, 0, sizeof(cprm));		/*	Initialize reserved member		*/

	cprm.ftype			= MWD_PLY_FTYPE_SFD;
	cprm.dtype			= MWD_PLY_DTYPE_AUTO;	/*	Quality is good in case
												 *	of specified 'AUTO'.	*/

	cprm.max_bps = 450*1024*8;		/*	3,686,400 bps
									 *	Maximum number of bit per second
									 *	You can change this value to effect
									 * 	playback rate.  Adjust respective to quality
									 *	levels set in compressor. */


	cprm.max_width = 320;			/*	Maximum width of video stream		*/
	cprm.max_height = 480;			/*	Maximum height of video stream		*/
	cprm.nfrm_pool_wk = 8;			/*	Size of working area
									 *	Normall set to 3.
									 *	Increase it when frame drop occurs or
									 *	processing load changes.			*/

	cprm.wksize = mwPlyCalcWorkSofdec(
										/*	Calculation of working area size*/
								cprm.ftype,
								cprm.max_bps,
								cprm.max_width,
								cprm.max_height,
								cprm.nfrm_pool_wk);

	cprm.work = syMalloc(cprm.wksize);	/*	Allocation of working area		*/
	if (cprm.work == NULL)
		for (;;);
	ply = mwPlyCreateSofdec(&cprm);
	if (ply == NULL)
		for (;;) ;

	mwPlyStartFname(ply, (signed char *) fname);		/*	Start to play middleware		*/
	while (1) {
		mwPlyExecTexSvr();				/*	Load Texture (for Kamui2)		*/

		UsrBeginScene();
		mwPlyStartFrame();

		mwPlyExecDrawSvr();				/*	Draw polygons (for Kamui2)		*/

		per = pdGetPeripheral(PDD_PORT_A0);
		if (per->press & PDD_DGT_TX)
			mwPlyPause(ply, ON);		/*	Pause					*/
		if (per->press & PDD_DGT_TY)
			mwPlyPause(ply, OFF);		/*	Release pause 			*/
		if (per->press & PDD_DGT_TB)
			break;
		stat = mwPlyGetStat(ply);
		if ((stat == MWE_PLY_STAT_PLAYEND) || (stat == MWE_PLY_STAT_ERROR))
			break;
		UsrEndScene();
	}
	mwPlyStop(ply);						/*	Stop to play middleware		*/

	mwPlyDestroy(ply);					/*	Destroy handle				*/

	syFree(cprm.work);

	return;
}

/***
 *		MAIN
 ***/

/*	Finalize application		*/
void UsrExit(void)
{
#ifdef USED_KAMUI2
	mwPlyFinishSfdFx();		/*	Finalize Middleware					*/
#else
	mwPlyFinishSofdec();	/*	Finalize Middleware					*/
#endif
	sbExitSystem();			/*	Finalize SHINOBI					*/
	syBtExit();				/*	Jump to Simple player				*/
}

/*	Callback function when an error occur in GD file system	*/
void UsrGdErrFunc(void *obj, Sint32 errcode)
{
	if (errcode == GDD_ERR_TRAYOPEND || errcode == GDD_ERR_UNITATTENT) {
		UsrExit();					/*	Finalize application		*/
	}
}


void Wait3VBlanks (void)
{
    UsrBeginScene();
    UsrEndScene();
    UsrBeginScene();
    UsrEndScene();
    UsrBeginScene();
    UsrEndScene();
}


void main(void)
{
	MWS_PLY_INIT_SFD	iprm;
	void				*snddrv, *vtxbuf;
	Sint32				ltncy;
	SYCHAIN             SndChainID;

#ifdef __GNUC__
	shinobi_workaround();
#endif

    /*  Initialize system for middleware(call before sbInitSystem)  */
	mwPlyPreInitSofdec();

	/*	Initialize SHINOBI		*/
	sbInitSystem(SYS_MODE, SYS_FRAME, SYS_COUNT);
	vtxbuf = UsrDispInit(&ltncy);

	/*	Entry callback function of GD file system error	 */
	gdFsEntryErrFuncAll((void *)UsrGdErrFunc, NULL);

	/*	Prepare sound library		*/
	snddrv = LoadFile("manatee2.drv", NULL);

	UsrSetVSyncFunction();

										/*	Initialize middleware			*/
	memset(&iprm, 0, sizeof(iprm));		/*	To initialize reserved member		*/
	iprm.mode		= SYS_MODE;
	iprm.frame		= SYS_FRAME;
	iprm.count		= SYS_COUNT;
	iprm.latency	= ltncy;
#ifdef USED_KAMUI2
	mwPlyInitSfdFx(&iprm);
#else
	mwPlyInitSofdec(&iprm);
#endif
	mwPlySetVertexBuffer(vtxbuf);
	mwPlyEntryErrFunc(UsrMwErrFunc, NULL);

        SoundInit(snddrv);
        SndChainID = syChainAddHandler (SYD_CHAIN_EVENT_IML6_VBLANK, sdSysVsyncServer, 0x60, NULL);
        Wait3VBlanks();
    for (;;)
    {
        SmpPlay("SAMPLE.SFD");      /*  Playing animation   */
    }

        /* Here is the code to finish the movie player (although it is not called in this example) */
        Wait3VBlanks();
        syChainDeleteHandler (SndChainID);
        sdSysFinish();

	UsrExit();		/*	Finalize application		*/
}

/* end of file */
