#include <shinobi.h>
#include "main.h"
#include <sg_mw.h>
#include "usr.h"
#include "main.h"
#include "options.h"

#include "islvideo.h"
#include "card.h"
#include "startup.h"

extern int storeTex;
extern TextureBankType *streamed_bank;

extern int byteToDecibelLUT[256];


int softReset;
#define NOT_FLAG(flag)		(((flag) == OFF) ? ON : OFF)

AP_OBJ ap_obj = {
	OFF,						//	Execute App.
	ON,							//	Display Info.
	OFF,						//	not puase
	"ACT1COMPLETE.SFD",			//	File name
	NULL,						//	Player
};

VideoInfo	vidInfo;
UBYTE		skipable;

/*	Callback function when an error occur in middleware	*/
void ap_mw_err_func(void *obj, char *errmsg)
{
	AP ap=(AP)obj;

	if(ap)
	{
		mwPlyStop(ap->ply);					/*	再生停止 					*/
										/*	Stop to play middleware		*/
		mwPlyDestroy(ap->ply);				/*	ハンドル消去				*/
										/*	Destroy handle				*/
		ap->ply = NULL;
		syFree(ap->cprm.work);				/*	作業領域の開放				*/
										/*	Release work area			*/
		ap->cprm.work = NULL;
	}

	resetToBootROM();
}



/*	ミドルウェアの初期化				*/
/*	Initialize Middleware				*/
void ApInitMw(AP ap,
		Sint32 mod, Sint32 frm, Sint32 cnt, Sint32 ltncy, void *vtxbuf)
{
	MWS_PLY_INIT_SFD	iprm;

	memset(&iprm, 0, sizeof(iprm));	/*	予約メンバのゼロ設定			*/
									/*	initialize reserved member		*/
	iprm.mode		= mod;			/*	Resolution, NTSC, PAL, VGA		*/
	iprm.frame		= frm;			/*	RGB565, ARGB8888				*/
	iprm.count		= cnt;			/*	Game period by the V-Sync count */
	iprm.latency	= ltncy;		/*	Latency (2V or 3V)				*/
	mwPlyInitSfdFx(&iprm);
	mwPlySetVertexBuffer(vtxbuf);
	mwPlyEntryErrFunc(ap_mw_err_func, ap);
}

/*	ミドルウェアの終了					*/
/*	Finalize Middleware					*/
void ApFinishMw(AP ap)
{
	mwPlyFinishSfdFx();
}

/*	アプリケーション開始処理	*/
/*	Start application		*/
void ApStart(AP ap)
{
	MWS_PLY_CPRM_SFD		*cprm=&ap->cprm;

	/*	ハンドルの生成	*/
	/*	Create handle	*/

	memset(cprm, 0, sizeof(cprm));		/*	予約メンバのゼロ設定			*/
										/*	To initialize reserved member	*/
	cprm->compo_mode = MWD_PLY_COMPO_OPEQ;
	cprm->ftype	= MWD_PLY_FTYPE_SFD;
	cprm->dtype	= MWD_PLY_DTYPE_AUTO;	/*	AUTOの方が画質が良い			*/
										/*	Quality is good in case 
										 *	of specified 'AUTO'.			*/

	cprm->max_bps = 450*1024*8;	
									/*	最大ビットストリーム量(bit/sec)	
									 *	実際よりも少なくすることも可能。
									 *	ムービーが途中でフリーズするときは
									 *	この値を増やしてください。			*/
									/*	Maximum number of bit per second
									 *	You can reduce it than a fact.
									 *	Increase this value when the movie
									 *	stops on the way.					*/
	cprm->max_width = 640;			/*	再生画像サイズの最大幅				*/
									/*	Maximum width of video stream		*/
	cprm->max_height = 480;			/*	再生画像サイズの最大高さ			*/
									/*	Maximum height of video stream		*/
	cprm->nfrm_pool_wk = 8;			
									/*	システム領域のフレームプール数
									 *	標準的には３で良いが、処理負荷の
									 *	変動によりコマ落ちが発生する場合は
									 *	増やしてください。					*/
									/*	Size of working area
									 *	It is good with 3 normally. But please
									 *	increase it when frame drop occurs by
									 *	processing load change.				*/
	/*	作業領域の大きさの計算				*/
	/*	Calculation of working area size	*/
	cprm->wksize = mwPlyCalcWorkCprmSfd(cprm);
	/*	作業領域の確保						*/
	/*	Allocation of working area			*/
	cprm->work = syMalloc(cprm->wksize);
	ap->ply = mwPlyCreateSofdec(cprm);
	if (ap->ply == NULL) {
		for (;;) ;
	}

	mwPlyStartFname(ap->ply, ap->fname);/*	再生開始						*/
	softResetAllowed = 0;
}

/*	アプリケーション停止処理	*/
/*	Stop application		*/
void ApStop(AP ap)
{
	mwPlyStop(ap->ply);					/*	再生停止 					*/
										/*	Stop to play middleware		*/
	mwPlyDestroy(ap->ply);				/*	ハンドル消去				*/
										/*	Destroy handle				*/
	ap->ply = NULL;
	syFree(ap->cprm.work);				/*	作業領域の開放				*/
										/*	Release work area			*/
	ap->cprm.work = NULL;
	if((softReset == 0) || ((preTitle == 0) && (globalAbortFlag == 0)))
		overlayLoadingBegin(2);
}

/*	情報の表示			*/
/*	Display infomation	*/
void ap_disp_info(AP ap)
{
	Sint32	time, tunit, hh, mm, ss, ff;

	mwPlyGetTime(ap->ply, &time, &tunit);
	UsrSfcnt2time(tunit, time, &hh, &mm, &ss, &ff);
	UsrPrintf(0, 0, "File: %s  Time:%02d:%02d:%02d.%02d", 
							ap->fname, hh, mm, ss, ff);

}

/*	動画の再生					*/
/*	Playing the animation file	*/
extern int padPort[4];
Sint32 ApExec(AP ap)
{
	MWPLY					ply=ap->ply;
	MWE_PLY_STAT			stat;
	const PDS_PERIPHERAL	*per;

	mwPlySetOutVol(ap->ply,byteToDecibelLUT[optionData.sound.musicvol] / 10);
	padHandler();
//	if(firstPad != -1)
	{
		if(softResetAllowed > softresetlimit)
		{
			if((pReadPad->digital[0] & (PAD_START + PAD_CROSS + PAD_CIRCLE + PAD_TRIANGLE + PAD_SQUARE)) == PAD_START + PAD_CROSS + PAD_CIRCLE + PAD_TRIANGLE + PAD_SQUARE)
			{
				overlayLoadingBegin(1);
				softReset = YES;
				return FALSE;
			}
			if((pReadPad->debounce[0] & PAD_START) && (skipable))
			{
				overlayLoadingBegin(1);
				return FALSE;
			}
		}
/*
		per = pdGetPeripheral(padPort[firstPad]);

		if((per->press & (PDD_DGT_ST + PDD_DGT_TA + PDD_DGT_TB + PDD_DGT_TX + PDD_DGT_TY)) == PDD_DGT_ST + PDD_DGT_TA + PDD_DGT_TB + PDD_DGT_TX + PDD_DGT_TY)
		{
			pauseEndQuitGame();
			return FALSE;
		}

		if ((per->press & PDD_DGT_ST) && (skipable)) 
		{
			return FALSE;
	//		ap->pause = NOT_FLAG(ap->pause);
	//		mwPlyPause(ply, ap->pause);
		}
*/
	}
//	if (per->press & PDD_DGT_TA)
//		ap->disp_flag = NOT_FLAG(ap->disp_flag);
//	if (per->press & PDD_DGT_TB)
//		return FALSE;

	/*	Checking status												*/
	stat = mwPlyGetStat(ply);
	if ((stat == MWE_PLY_STAT_PLAYEND) || (stat == MWE_PLY_STAT_ERROR))
		return FALSE;
	if ( ap->disp_flag == ON )
		ap_disp_info(ap);

	return TRUE;
}

/***
 *		メイン処理
 *		MAIN
 ***/

/*	GDファイルシステムのエラー発生時に起動する関数			*/
/*	Callback function when an error occur in GD file system	*/
void ApGdErrFunc(void *obj, Sint32 errcode)
{
	AP ap=(AP)obj;
	if (errcode == GDD_ERR_TRAYOPEND || errcode == GDD_ERR_UNITATTENT)
		ap->term_flag = ON;			/*	アプリケーションの終了		*/
									/*	Terminate application		*/
}

/*	ユーザがV-SYNC割り込みに登録する関数	*/
/*	Callback function when V-sync interrupt	*/
void ApVsyncFunc(void)
{
	UsrCheckDoorOpen();
}


extern int demoVideo;
int videoLanguage;
videoPlayStream(char *name)
{
	ap_obj.fname = name;
	softReset = NO;

	//give us more vram
//	emptyDestroyRenderTexture();
	
	gdFsChangeDir("\\VIDEO");
	if(videoLanguage)
	{
		switch(gameTextLang)
		{
			case LANG_F:
				gdFsChangeDir("FRE");
				break;

			case LANG_D:
				gdFsChangeDir("GER");
				break;

			case LANG_IT:
				gdFsChangeDir("ITA");
				break;

			case LANG_SP:
				gdFsChangeDir("SPA");
				break;

			default:
				break;
		}
	}
	ApStart(vidInfo.ap);
	while (1) 
	{
		if(globalAbortFlag)
		{
			softReset = YES;
			break;
		}

		mwPlyExecTexSvr();			
		UsrBeginDraw();

		mwPlyExecDrawSvr();			
		vidInfo.ret = ApExec(vidInfo.ap);

		if(demoVideo)
			fontPrintCentred(font,0,90,TEXTSTR(TEXTSTR_PRESS_START_LEGAL),128,128,128);

		UsrEndDraw();
		
		softResetAllowed++;
		if ( vidInfo.ret == FALSE || vidInfo.ap->term_flag == ON)
			break;
		UsrWaitVBlank();
	}
	ApStop(vidInfo.ap);

	if((softReset) && ((preTitle) || (globalAbortFlag)))
		resetToBootROM();

	//and grab it back again
//	emptyInitRenderTexture();
}


extern void optionsCycle(void);
extern int noControllerInputTime;
KMUINT32 afterVidSize,afterVidMaxblock;
int disableEggFlip = 0;
void video_PlayVid(int n, int make_avail)
{
	int i;


	if(inDraw)
	{
		inDraw = NO;
		kmEndPass(&vertexBufferDesc);
  		kmRender(KM_RENDER_FLIP);
		kmEndScene(&kmSystemConfig);
	}

	disableEggFlip = 1;
  /*
	//clears any textures not needed
	for(i=originalTexCount;i<DCKnumTextures;i++)
	{
		kmFreeTexture(DCKtextureList[i].surfacePtr);
	} 

	DCKnumTextures = originalTexCount;

	//and clears the inventory textures
	for(i = 900;i < storeTex;i++)
	{
		kmFreeTexture(DCKtextureList[i].surfacePtr);
	} 
	storeTex = 900;
	*/ 
//	for(i=originalTexCount;i<1000;i++)


	sound_XA_EnsurePaused();
			 
	if(make_avail)
		gameSaveData.movies_available[n] = 1;
	for(i=texNumAfterFont;i<DCKnumTextures;i++)
	{
		if(DCKtextureList[i].surfacePtr)
			dcFreeTexture(&DCKtextureList[i].surface);
	} 
 	kmGarbageCollectTexture();
	reInitStrips();

  //	emptyFixTextures();

	kmGetFreeTextureMem(&afterVidSize,&afterVidMaxblock);
	debug_printf("totala vram %d  biggest block%d\n",afterVidSize,afterVidMaxblock);
	DCKnumTextures = texNumAfterFont;//originalTexCount;
	storeTex = 900;

	skipable=1;
	videoLanguage = YES;
	switch(n)
	{			  
	case MOVIENO_BLITZ:
		if(cycle_routine != optionsCycle)
			skipable=0;
		videoLanguage = NO;
		videoPlayStream("BLITZBIG.SFD");
		break;
	case MOVIENO_DREAMWORKS:
		if(cycle_routine != optionsCycle)
			skipable=0;
		videoLanguage = NO;
		videoPlayStream("DW.SFD");
		break;
	case MOVIENO_EIDOS:	  
		if(cycle_routine != optionsCycle)
			skipable=0;
		videoLanguage = NO;
		videoPlayStream("EIDOS20FPS.SFD");
		break;
	case MOVIENO_AARDMAN:
		if(cycle_routine != optionsCycle)
			skipable=0;
		videoLanguage = NO;
		videoPlayStream("AA.SFD");
		break;

	case MOVIENO_ACT1_INTRO:
		videoLanguage = NO;
		videoPlayStream("ACT1INTRO.SFD");
		break;
	case MOVIENO_BOSS1_INTRO:
		videoLanguage = NO;
		videoPlayStream("ACT1INTROBOSS.SFD");
		break;
	case MOVIENO_BOSS1_FAIL:
		videoLanguage = NO;
		videoPlayStream("ACT1FAILED.SFD");
		break;
	case MOVIENO_BOSS1_DONE:
		videoLanguage = YES;
		videoPlayStream("ACT1COMPLETE.SFD");
		break;

	case MOVIENO_ACT2_INTRO:
		videoLanguage = YES;
		videoPlayStream("ACT2INTRO.SFD");
		break;
	case MOVIENO_BOSS2_INTRO:
		videoLanguage = YES;
		videoPlayStream("ACT2INTROBOSS.SFD");
		break;
	case MOVIENO_BOSS2_DONE:
		videoLanguage = YES;
		videoPlayStream("ACT2OUTRO.SFD");
		break;

	case MOVIENO_ACT4_INTRO:
		videoLanguage = YES;
		videoPlayStream("ACT3INTRO.SFD");
		break;
	case MOVIENO_BOSS4_INTRO:
		videoLanguage = YES;
		videoPlayStream("ACT3INTROBOSS.SFD");
		break;
	case MOVIENO_BOSS4_DONE:
		videoLanguage = YES;
		videoPlayStream("ACT3OUTRO.SFD");
		break;
	case MOVIENO_GAME_COMPLETE:
		videoLanguage = YES;
		videoPlayStream("ACT3XBONUS.SFD");
		break;
	}
	textureLoadBank("SHELL\\DCBITS.SPT");
	{
		TextureBankType *generic_textures;
		TextureType *sprs[9];
			char *names[9] = {"Y_BUTTON","B_BUTTON","A_BUTTON","X_BUTTON", "L1", "L2", "R1", "R2", "STARTBUTTON"};
			int i;

			generic_textures = textureLoadInOneGo("SHELL\\GENERIC.SPT");

			for(i = 0; i < 9; i++)
			{
				sprs[i] = textureFindInAllBanks(names[i]);
			}

			fontRegisterButtonSprites(sprs[0],sprs[1],sprs[2],sprs[3]);

			fontRegisterOtherSprites('L', sprs[4]);
			fontRegisterOtherSprites('l', sprs[5]);
			fontRegisterOtherSprites('R', sprs[6]);
			fontRegisterOtherSprites('r', sprs[7]);
			fontRegisterOtherSprites('A', sprs[8]);
	}  
//	emptyFixTextures();
	kmGetFreeTextureMem(&afterVidSize,&afterVidMaxblock);
	debug_printf("totalb vram %d  biggest block%d\n",afterVidSize,afterVidMaxblock);

	padHandler();

	kmGarbageCollectTexture();
	reInitStrips();
	 
	kmGetFreeTextureMem(&afterVidSize,&afterVidMaxblock);
	debug_printf("totalc vram %d  biggest block%d\n",afterVidSize,afterVidMaxblock);

	noControllerInputTime = 0;

	disableEggFlip = 0;
	
	if(softReset)
	{
		if(!titleScreen)
			pauseEndQuitGame();
	}
}
