/*=========================================================================
* CPAEngin.cpp :       Kernel base of CPA project.
* This is a part of the CPA project.
*
* Version              1.0
* Creation date        20/06/96
* Revision date
*
* That file is C pure (it's a .CPP cause of ACTIVE_EDITOR capabilities).
* That file needs to be compatible for all platforms.
*
* (c) Ubi Studios 1996
*=======================================================================*/
 
#if !defined(U64)
#include <direct.h>  /**** pour les tests ****/
#else /* U64 */
#include <cpa_std.h>
#endif /* U64 */
 
 
#include "ToolsCPA.h"
 
#include "Main.h"
 
#include "Options/InLine.h"
#include "Macros.h"
 
#include "Actions/AllActs.h"
 
#include "Structur/Objects.h"
#include "Structur/EngMode.h"
#include "Structur/ErrGame.h"
#include "Structur/Input_S.h"
#include "Structur/MemGame.h"
#include "Structur/StdObjSt.h"
 
#include "Always.h"
#include "Basic.h"
#include "Engine.h"
#include "InitEng.h"
#include "Input.h"
#include "GameEng.h"
#include "GamSave.h"
/*#include "GamExtra.h"*/
#include "GamOpt.h"
#include "ObjInit.h"
#include "ObjType.h"
#include "zemem.h"

#include "acp_driver.h"

#ifdef GAM_USE_SNA
#include "sna.h"
#endif /* GAM_USE_SNA */
 
#include "PRF.h"
extern void GAM_fn_vRasterDisplayInit ();

/*XB(Profile)*/
#ifdef U64
/*#define ASM_PROFILER*/
#ifdef ASM_PROFILER
extern void fn_vInitProfile(void);
extern unsigned long	*g_p_ulNbEngineFrames;
#endif /* ASM_PROFILER */ 
#endif /* U64 */
 
/* ANNECY AV DEMO {*/
#ifndef U64
    #include "Specif/Demos.h"
#ifndef RETAIL
	#include "PlayAnim/interpol/a3x_Mem.h" /* for fn_vAnimStackLog*/
#endif
#endif
/* END ANNECY AV }*/
 
 
#ifdef ACTIVE_EDITOR
extern ACP_tdxBool g_bUseSAIWithEditor;
#endif /* ACTIVE_EDITOR */
 
 
#ifdef U64
#include "u_cfb.h"
#include "ino.h"
#endif
 
/*===========================================================================
*      Pointers that can be init in fn_vChooseTheGoodInit()
==========================================================================*/
void fn_vEmptyFunction(void) {};
 
void (*p_fn_vReadInput)()  = fn_vEngineReadInput;     /**** Never change it ****/
void (*p_fn_vNetEngine)()  = fn_vEmptyFunction;
void (*p_fn_vEngine)()     = fn_vEmptyFunction;
void (*p_fn_vDisplayAll)() = fn_vEmptyFunction;
 
/*###########################################################################
*      Empty functions to be fill for each project.
*#########################################################################*/
/*===========================================================================
*      Description:    
*---------------------------------------------------------------------------
*		Automatic tests
*---------------------------------------------------------------------------
*      Revision date:                                                                                          
*	   Author:  YLG
*=========================================================================*/
#if !defined(U64) && !defined(RETAIL)
#include <sys/types.h>
#include <sys/timeb.h>
#include <time.h>
 
extern  char         TEST_g_cAllMaps;	
extern  char         TEST_g_cChangeMapWithRestart;	
extern  ACP_tdxBool  TEST_g_bAutomaticTest;
extern  char         TEST_g_cWriteLogFile;
extern  long         TEST_g_lWaitBeforeChangeLevel;
extern  long         TEST_g_lWaitMin;	
extern  long         TEST_g_lWaitMax;	
extern  long         TEST_g_lNbChangeMapBeforeExit;
extern  long         TEST_g_lAnimStack;
extern  long         TEST_g_lNbMapInSequence;
extern  char         TEST_g_a_szMapSequence[200][50];

long  TEST_g_lCptWait = 0;


/*****************  FabPerez InfoTrame  *****************/
#if defined(WIN32) && defined(_DEBUG)
	extern void fn_InitMapSectorStruct(void);
#endif /*WIN32 _DEBUG*/
/*****************  Fin FabPerez InfoTrame  *****************/

void fn_vWriteAnimStackLogFile()
{
	FILE * fLogFile;
	/* open file in appending mode and add log*/
	fLogFile = fopen("AnimStack.log","a");
	if (fLogFile) {
		fprintf(fLogFile,"=========> MAP : %s\n",g_stEngineStructure.szLevelName);
		fn_vAnimStackLog(fLogFile);
		fclose(fLogFile);
	}
 
}

/* Used for test (test.ini)
 * Get next level name to go to.
 * Return 0 if we must change level or 1 if we must exit game.
 */
int GAM_fn_iGetNextLevelName( char **_p_szLevelName )
{
	static long ucLastLevel = 0;
	unsigned char ucLevelId;

	if( TEST_g_lNbChangeMapBeforeExit-- == 0 )
	{
		*_p_szLevelName = NULL;
		return 1;
	}

	switch( TEST_g_cAllMaps )
	{
		case 0: /* Test all maps then test maps in random order */
		case 1: /* Test all maps then exit */
			if( ucLastLevel+1 < g_stEngineStructure.ucNumberOfLevels )
			{
				ucLastLevel++;
				*_p_szLevelName = g_stEngineStructure.a_szLevelName[ ucLastLevel ];
				return 0;
			}

			/* We already have tested all map */ 
			switch( TEST_g_cAllMaps )
			{
				case 0: /* Test all maps then test map in random order */
					ucLevelId = (unsigned char)RND_fn_lGetLongRandomValue(0, 0, g_stEngineStructure.ucNumberOfLevels-1);
					*_p_szLevelName = g_stEngineStructure.a_szLevelName[ ucLevelId ];
					return 0;
					break;

				case 1: /* Test all maps then exit */
					*_p_szLevelName = NULL;
					return 1;
					break;
			}
			break;

		/* next case for FIRST switch */
		case 2: /* Test sequence of map then exit */
			if( ucLastLevel < TEST_g_lNbMapInSequence )
			{
				*_p_szLevelName = TEST_g_a_szMapSequence[ ucLastLevel ];
				ucLastLevel++;
				return 0;
			}
			else
			{
				*_p_szLevelName = NULL;
				return 1;
			}
	}
}
 

void	GAM_fn_vAutomaticChangeLevelOrRestartLevel()
{
	static long lActionCount = 0;
	char szActionString[100];
	char *p_szNextLevelName;

	/* Increase trame counter */
	TEST_g_lCptWait++;

	if( TEST_g_lCptWait >= TEST_g_lWaitBeforeChangeLevel )
	{
		TEST_g_lWaitBeforeChangeLevel = RND_fn_lGetLongRandomValue(0, TEST_g_lWaitMin, TEST_g_lWaitMax);
		TEST_g_lCptWait = 0;

		lActionCount ++;

		/* If we are in RESTARTONLY mode  OR if we can and choose to restart */
		if( (TEST_g_cAllMaps == 3)
		    || (TEST_g_cChangeMapWithRestart && RND_fn_lGetLongRandomValue(0, 1, 100) > 40) )
		{
			/* Restart level */
			fn_vChangeEngineMode(EM_ModePlayerDead);
			strcpy( szActionString, "*** Restart level" );
		}
		else
		{
			/* Change level */
			switch( GAM_fn_iGetNextLevelName( &p_szNextLevelName ) )
			{
				case 0: /* We change level */
					GAM_fn_vAskToChangeLevel( p_szNextLevelName , TRUE );
					sprintf( szActionString, "--- Change to map %s", p_szNextLevelName );
					break;
				case 1: /* We exit */
					fn_vChangeEngineMode(EM_ModeStoppingProgram);
					strcpy( szActionString, "Stopping Program" );
					break;
			}

			/* Write log file for stacks */
			if (TEST_g_lAnimStack)
				fn_vWriteAnimStackLogFile();
		}

		/* Write log file for level change or restart */
		if( TEST_g_cWriteLogFile )
		{
			char       szLocalTime[255];
			struct tm  *p_stTime;
			time_t     xTime;
			FILE       *hFile = NULL;

			if( (hFile = fopen("Test.log", "a+")) != NULL )
			{
				time ( &xTime );
				p_stTime = localtime( &xTime );
				sprintf( szLocalTime, "%02d/%02d/%02d %02d:%02d:%02d", p_stTime->tm_mday, p_stTime->tm_mon + 1, p_stTime->tm_year, p_stTime->tm_hour, p_stTime->tm_min, p_stTime->tm_sec );
				fprintf(hFile,"%i %s at %s\n", lActionCount, szActionString, szLocalTime );
				fclose( hFile );
			}
		}
	}
}

#endif /* U64*/
/*===========================================================================
*      Description:    Determins if game needs to be close.
*      Creation date:  20 Jun 96
*      Author:                 CB
*
*      g_bAppSaysBye is set to '1' by application when user requests end of
*      game. You must test that flag to exit all your eventual loop.
*---------------------------------------------------------------------------
*      Return <>0 if TRUE, 0 if FALSE
*---------------------------------------------------------------------------
*      Revision date:                                                                                          Author:
*=========================================================================*/
GAME_INLINE unsigned char fn_bEndOfGame(void)
{
	unsigned char ucReturn = 0;
	
	if (g_stEngineStructure.eEngineMode==EM_ModeStoppingProgram)
		ucReturn = 1;
	
	return(ucReturn);
}
 
/*===========================================================================
*      Description:    Determins if VBL loop needs to be quit.
*      Creation date:  20 Jun 96
*      Author:                 CB
*
*      g_bAppSaysBye is set to '1' by application when user requests end of
*      game. You must test that flag to exit all your eventual loop.
*---------------------------------------------------------------------------
*      Return <>0 if TRUE, 0 if FALSE
*---------------------------------------------------------------------------
*      Revision date:                                                                                          Author:
*=========================================================================*/
#ifndef U64 
#ifndef ACTIVE_EDITOR
#ifdef _DEBUG

EXTERN ACP_tdxBool	g_bDreamcast;

#endif /* _DEBUG */
#endif /* ACTIVE_EDITOR */
#endif /* U64 */

GAME_INLINE unsigned char fn_bEndOfOneStep(void)
{
	unsigned char ucReturn = 0;
	
	PRF_fn_vStartChrono( PRF_C_ulFctMainMisc, NULL );
	
#if defined(GAM_USE_SNA)
#ifndef ACTIVE_EDITOR
#ifdef _DEBUG
		 if (g_bDreamcast)
			g_stEngineStructure.eEngineMode=EM_ModeStoppingProgram;
#endif /* _DEBUG */
#endif /* ACTIVE_EDITOR */
#endif /* GAM_USE_SNA */

	if (  g_stEngineStructure.eEngineMode==EM_ModeStoppingProgram
		/*||g_stEngineStructure.eEngineMode==EM_ModeQuitGame*/
		||g_stEngineStructure.eEngineMode==EM_ModeChangeLevel
		||g_stEngineStructure.eEngineMode==EM_ModePlayerDead
#if defined(GAM_USE_SNA)
		||(SNA_fn_ucGetLoadType()==SNA_SAVE_SNAPSHOT)
#endif /* GAM_USE_SNA */
		)
		ucReturn = 1;
 
	PRF_fn_vStopChrono( PRF_C_ulFctMainMisc, NULL );
	
	return(ucReturn);
}
 
/*===========================================================================
*      Description:    Choose the good init before VBL loop.
*                                      This function needs to set p_fn_v?? pointers.
*      Creation date:  20 Jun 96
*      Author:                 CB
*
*      g_bAppSaysBye is set to '1' by application when user requests end of
*      game. You must test that flag to exit all your eventual loop.
*---------------------------------------------------------------------------
*      Return void
*---------------------------------------------------------------------------
*      Revision date:                                                                                          Author:
*=========================================================================*/
#ifdef U64
void CPAK_DrawCenteredStringSet(int oy, char *opString);
extern char g_bControllerWasPluggedAtInitialisation;
char g_cEndOfDemo = 0;
extern short g_wWhichFrameBuffer;
extern char g_bMustSwitchResolution;
void SwitchTo300x224(void);
void SwitchTo300x224PAL(void);
void SwitchTo300x224MPAL(void);
void fn_vStartLoad(void);
void fn_vLoadFat( short _wLevelId );
void fn_vLoadAllVector3D(U64_tdxIndex _xVector3DId,unsigned short _uwVector3DNb);
void fn_vLoadAllTripledIndex(U64_tdxIndex _xTripledIndexId,unsigned short _uwTripledIndexNb);
void Fon_fn_vDisplayBackGround(char *p_cDestRamAdr, char *p_cLoadRamAdr, U64_tdxIndex _xBkGrdIndex, unsigned char _ucPaletteNumber);
void fn_vEndLoad();
void fn_vSwitchToDemoLevel(void);
void RES_vHighOrLowResolution(int parameter);
void CPAK_vDrawAButton(unsigned short *pScreen,int oX, int oY, int buttoncode);
void CPAK_vGetScreenZone(int oy);
void CPAK_ClearCenteredStringSet(int oy, char _cNbCar);

char g_cLogoIsDisplayed = FALSE;
#endif




#if !defined(RETAIL) && !defined(U64)
void SNA_fn_vCheckMMGBlock( unsigned char _ucModule, unsigned char _ucBlock, unsigned char _ucLog );
#endif
GAME_INLINE void fn_vChooseTheGoodInit(void)
{

// FB for demo
#ifdef U64
	char cFlag = 0;
	unsigned long ulPreviousTime,ulInitTime;
#endif

	switch(g_stEngineStructure.eEngineMode)
	{
	case EM_ModeStartingProgram:
#ifdef U64
#ifdef ASM_PROFILER
/*XB(Profile)*/
   fn_vInitProfile();
#endif /* ASM_PROFILER */ 
#endif /* U64 */ 
		fn_vFirstInitEngine();
		
/* XB 23/06/99 */
#ifndef U64		
		/*bart990105 :*/
		if (fn_bIsEngineInPause())
			fn_vChangeWindowTitle("Rayman II - pause");
		else
			fn_vChangeWindowTitle("Rayman II");
#endif /* U64 */
/* End XB 23/06/99 */
 
		fn_vFreeNextLevelName();
	  /* to make sure that everything goes fine*/
	  fn_vChangeEngineMode(EM_ModeEnterGame);
		
	case EM_ModeEnterGame:
#ifdef GAM_USE_SNA
		SNA_M_InitLoadRelocationTable();	/* MT 30/03/99 : PC protection */
#endif

#ifdef U64
		g_stEngineStructure.xDemoMode=FALSE;

			if(!g_cLogoIsDisplayed)
			{
			fn_vZBufferSynchro();
			fast_memclear(&cfb[g_wWhichFrameBuffer*g_ulFrameBufferSize],g_ulFrameBufferSize*2);
			osWritebackDCacheAll();
			}
			// low res
			if (osTvType==1) SwitchTo300x224(); 
			else if (osTvType==0) SwitchTo300x224PAL();
			else  SwitchTo300x224MPAL();

/*necessary for Fon_fn_vDisplayBackGround*/
			fn_vStartLoad();
			fn_vLoadFat(-1);
			Fon_fn_vDisplayBackGround((char *)(&cfb[g_wWhichFrameBuffer*g_ulFrameBufferSize]),
																(char *)(&cfb[(g_wWhichFrameBuffer^1)*g_ulFrameBufferSize]),
																/*4*/1|D_BINSCR_IsInFixFixFat,
																0);
			CPAK_DrawCenteredStringSet(30, "990824 _ v59");
			fn_vEndLoad();


			if (g_bControllerWasPluggedAtInitialisation)
			{
			CPAK_vGetScreenZone(180);
			CPAK_vDrawAButton((&cfb[g_wWhichFrameBuffer*g_ulFrameBufferSize]), 180, 180, 3);
			}
			else
			{
				CPAK_vDrawAButton( ((unsigned short *)(&cfb[g_wWhichFrameBuffer*g_ulFrameBufferSize])),150, 180, 4);
			}

			osSetTime(0);

			ulPreviousTime = osGetTime();
			ulInitTime = osGetTime();

			if (g_bControllerWasPluggedAtInitialisation)
			{

			IPT_fn_vReadInput();
			do
			{
				MON_M_vThreadStillRunning(); 
				IPT_fn_vReadInput();

				if (osGetTime()-ulPreviousTime>20000000)
				{
					ulPreviousTime = osGetTime();
					cFlag=1-cFlag;
					if (cFlag)
						CPAK_ClearCenteredStringSet(180,6);
					else
						CPAK_vDrawAButton((&cfb[g_wWhichFrameBuffer*g_ulFrameBufferSize]), 180, 180, 3);
						
				}
			} while ((INO_fn_wJoystickButtonJustPressed(0,START_BUTTON)== C_wJoyFalse)
					  && (osGetTime()-ulInitTime<46000000*10));
			}
			else
			{
				while (osGetTime()-ulInitTime<46000000*5);
		}

		g_cLogoIsDisplayed = FALSE;

		if (osMemSize>4*1024*1024)
			RES_vHighOrLowResolution(2);
		else
			RES_vHighOrLowResolution(1);

		if ((INO_fn_wJoystickButtonJustPressed(0,START_BUTTON)== C_wJoyFalse) || !g_bControllerWasPluggedAtInitialisation)
		{	
			// Launch demos
			INO_fn_vU64PlayDemo();
			fn_vSwitchToDemoLevel();
		}
		else
		{
			fn_vFreeNextLevelName();
		}

#endif

		GAM_fn_vActualizeAllGameViewportSize();
		fn_vInitGameLoop();
		p_fn_vEngine=fn_vEngine;
		p_fn_vDisplayAll=fn_vDisplayAll;
		fn_vChangeEngineMode(EM_ModePlaying);
		fn_vValidateAllOption();
		fn_vFreeNextLevelName();
#ifdef U64
		fn_vResetEngineFromPaused();
#endif
		/*bart990105 : fn_vResetEngineFromPaused();*/
	
		/* CGHT*/
#if defined(GAM_USE_SNA)
		if (SNA_fn_ucGetLoadType()==SNA_SAVE_SNAPSHOT)
		{
			fn_vChangeEngineMode(EM_ModeStoppingProgram);
		}
#endif /* GAM_USE_SNA */

/* ANNECY MT - 28/06/99 { */
	/**** Start the timer ****/
	fn_vStartEngineClock();
/* END ANNECY MT } */
		break;
		
	case EM_ModeEnterLevel:
		GAM_fn_vActualizeAllGameViewportSize();
		p_fn_vEngine=fn_vEngine;
		p_fn_vDisplayAll=fn_vDisplayAll;
    /* if we come from above, fn_vInitLevelLoop() has already been called, so dont do it twice...*/
		fn_vInitLevelLoop();
		fn_vChangeEngineMode(EM_ModePlaying);
		fn_vValidateAllOption();

/* Used for testing fragmentation of block tmp.
 * enable it to get file Block0a00.log in exe\main (file is updated at each level change)
#if !defined(RETAIL) && !defined(U64)
		SNA_fn_vCheckMMGBlock( 10, 0, 1 );
#endif
 */
		
		break;
		
	case EM_ModeDeadLoop:
		fn_vInitDeadLoop();
		fn_vValidateAllOption();
		fn_vChangeEngineMode(EM_ModePlaying);
		break;
		
	default:
		M_GameFatalError(E_uwGameChooseTheGoodInitInvalidMode);
		break;
 }

/*****************  FabPerez InfoTrame  *****************/
#if defined(WIN32) && defined(_DEBUG)
	fn_InitMapSectorStruct();
#endif /*WIN32 _DEBUG*/
/*****************  Fin FabPerez InfoTrame  *****************/

}
 
/*===========================================================================
*      Description:    Choose the good init after VBL loop (fn_vEndOfOneStep
*                                      returned TRUE).
*      Creation date:  20 Jun 96
*      Author:                 CB
*
*      g_bAppSaysBye is set to '1' by application when user requests end of
*      game. You must test that flag to exit all your eventual loop.
*---------------------------------------------------------------------------
*      Return void
*---------------------------------------------------------------------------
*      Revision date:                                                                                          Author:
*=========================================================================*/
GAME_INLINE void fn_vChooseTheGoodDesInit(void)
{
	switch(g_stEngineStructure.eEngineMode)
	{
#ifndef U64
	case  EM_ModeStoppingProgram:
 
		/* Tests pour les fuites de mémoire :*/
		fn_vDesInitLevelLoop();
 
 
		fn_vLastDesinitEngine();
		break;
		
	/*case EM_ModeQuitGame:
		fn_vDesInitGameLoop();
		PRF_fn_vDesInitProfileModule ();
		fn_vChangeEngineMode(EM_ModeStoppingProgram);
		break;*/
#endif /*U64*/
		
	case EM_ModeChangeLevel:
 
#ifdef ACTIVE_EDITOR
		if (g_bUseSAIWithEditor) {
#endif /* ACTIVE_EDITOR */
 
#ifdef U64			
		if (g_cEndOfDemo==0)
		{
#endif
		/* If we have to save the current game status (always, except when we load a saved game).*/
		if( GAM_g_ucSaveGameBeforeChangeLevel )
		{
			/* generate a "player" saved info -> ie info that is common to all maps -> fields saved here MUST be in the FIX memory area*/
			fn_bPlayerSaveGameAll(); /*inactif pour l'instant, en attendant de voir ...*/
			fn_bLevelSaveGameAll();
		}
		else
			GAM_g_ucSaveGameBeforeChangeLevel = 1;
#ifdef U64
		}
#endif
 
#ifdef ACTIVE_EDITOR
		}
#endif /* ACTIVE_EDITOR */
 
		fn_vDesInitLevelLoop();
//FB for demo
#ifdef U64
		if (g_cEndOfDemo)
		{
			g_cEndOfDemo = 0;
			fn_vChangeEngineMode(EM_ModeEnterGame);
		}
		else
		{
			fn_vSetLevelName(fn_p_szGetNextLevelName());
			fn_vChangeEngineMode(EM_ModeEnterLevel);
		}
#else
		fn_vSetLevelName(fn_p_szGetNextLevelName());
		fn_vChangeEngineMode(EM_ModeEnterLevel);
#endif
		break;
		
	case EM_ModePlayerDead:
		fn_vDesInitDeadLoop();
		fn_vChangeEngineMode(EM_ModeDeadLoop);
		break;
		
	default:
		M_GameFatalError(E_uwGameChooseTheGoodDesinitInvalidMode);
		break;
	}
}
 
/*###########################################################################
*
*      CPA COMMON ENGINE FUNCTIONS.
*
*#########################################################################*/
 
 
/*===========================================================================
*      Description:    Call at each trame.
*      Creation date:  20 Jun 96
*      Author:                 CB
*---------------------------------------------------------------------------
*      Return void
*---------------------------------------------------------------------------
*      Revision date:                                                                                          Author:
*=========================================================================*/
GAME_INLINE void fn_vOneTrame(void)
{
#ifdef U64
#ifdef ASM_PROFILER
/*XB(Profile)*/
	(*g_p_ulNbEngineFrames)++;
#endif /* ASM_PROFILER */ 
#endif /* U64 */ 
 
#ifdef _DEBUG
#ifndef ACTIVE_EDITOR
	fn_vGameTestMemory();
#endif
#endif
 

	PRF_fn_vStartChrono( PRF_C_ulFctDisplay , PRF_C_pvRest );
	PRF_fn_vStartChrono( PRF_C_ulFctDisplayCommon , PRF_C_pvGetDevice );
 
/* XB 23/06/99 */
#ifndef U64 
	g_stEngineStructure.hGLDDevice   = fn_hGetGLDDevice(0);
	g_stEngineStructure.hGLDViewport = fn_hGetGLDViewport(0);
	g_stEngineStructure.hDrawSem     = fn_hGetDrawSemaphore();
#endif /* U64 */
/* End XB 23/06/99 */
	
	PRF_fn_vStopChrono( PRF_C_ulFctDisplayCommon , PRF_C_pvGetDevice );
	PRF_fn_vStopChrono( PRF_C_ulFctDisplay , PRF_C_pvRest );
	
	/*
	*	BE CAREFUL !!!
	*  Net library must not be called beetween
	*  - IDirectDrawSurface::Lock and IDirectDrawSurface::Unlock
	*  - IDirectDrawSurface::GetDC and IDirectDrawSurface::ReleaseDC
	*  So thanks MicroFlop !
	*/
	
    PRF_fn_vStartChrono( PRF_C_ulFctMainMisc, NULL );
	
	p_fn_vNetEngine();                      /* For multi player game */
	
	PRF_fn_vStopChrono( PRF_C_ulFctMainMisc, NULL );
	

#if !defined(PRESS_DEMO)
/**************** FabPerez SectorAnalyse  ************/
/*****************************************************/
#if defined(WIN32) && defined(_DEBUG)
	fn_RecupInfoTrameSecteur();
#endif /*WIN32 & _DEBUG*/
/************** Fin FabPerez SectorAnalyse  ***********/
/******************************************************/
#endif /* PRESS_DEMO */

    if (fn_bEndOfGame())
	{
		return;
	}
	
	p_fn_vEngine();                         /* Engine one step */
	if (g_stEngineStructure.eEngineMode==EM_ModeStoppingProgram)
	{
		return;
	}
/* LOL #if !defined(U64) || !defined(RETAIL)*/
	#if !defined(U64) && !defined(RETAIL)
	if (TEST_g_bAutomaticTest)
		GAM_fn_vAutomaticChangeLevelOrRestartLevel();
#endif /* U64 & RETAIL*/
 
	p_fn_vDisplayAll();                     /* Display all results */
	
    /*
    PRF_fn_vStartChrono( PRF_C_ulFctDisplaySpecific, PRF_C_pvRest );
	GLI_vEndOfTurnEngine();
	PRF_fn_vStopChrono( PRF_C_ulFctDisplaySpecific, PRF_C_pvRest );
    */
	
#if defined(ACTIVE_EDITOR)
    PRF_fn_vStartChrono( PRF_C_ulFctEditor, NULL );
	fn_vEditorDrawObjectExpect0();
    PRF_fn_vStopChrono( PRF_C_ulFctEditor, NULL );
#endif /* ACTIVE_EDITOR */
	
#ifdef ACTIVE_EDITOR
    PRF_fn_vStartChrono( PRF_C_ulFctEditor, NULL );
	/* To refresh all editors with actual engine datas */
	fn_vEditorDataHasChange();
    PRF_fn_vStopChrono( PRF_C_ulFctEditor, NULL );
#endif /* ACTIVE_EDITOR */
	
	
    PRF_fn_vStartChrono( PRF_C_ulFctInput, NULL );
	
	p_fn_vReadInput();                      /* Read input from user */
	
    PRF_fn_vStopChrono( PRF_C_ulFctInput, NULL );
 
/* ANNECY AV DEMO {*/
#ifndef U64
    DEMO_fn_vCloseFirstInit();
#endif
/* END ANNECY AV }*/
}
 

/*===========================================================================
*      Description:    Main loop of engine.
*                      In WIN32, that thread is paused when we are in edit mode,
*                      so it's not used to test M_bEditorsActive().
*      Creation date:  20 Jun 96
*      Author:         CB
*---------------------------------------------------------------------------
*      Return code for end of application
*---------------------------------------------------------------------------
*      Revision date:                                                                                          Author:
*=========================================================================*/
unsigned int fn_uiEngineMainLoop(void)
{
	unsigned long ulTimeMainLoop;
	short wTimerMainLoop;
	stTimerCount stTimerCountMainLoop;
	unsigned long ulTimerFrequency;
	
	/*XB980517 (from Oliv')*/
#if defined(USE_PROFILER) && !defined(PRESS_DEMO)
	PRF_fn_vInitProfileModule ();
	PRF_fn_vInitChrono        ( PRF_C_ulFctMainLoop			, "Total",				16  , 2  );
	/*PRF_GLI PRF_fn_vInitChrono        ( PRF_C_ulFctDisplay       , "Display", 2048, 13);*/
	PRF_fn_vInitChrono        ( PRF_C_ulFctDisplay       , "Display", 3000, 20);
	PRF_fn_vInitChrono        ( PRF_C_ulFctAI				, "AI",					1024, 128);
	PRF_fn_vInitChrono        ( PRF_C_ulFctCollisions		, "All Collisions",		1024, 128);
	PRF_fn_vInitChrono        ( PRF_C_ulFctCollisionsChar	, "Collisions with others Actors", 1024, 128);
	PRF_fn_vInitChrono        ( PRF_C_ulFctDNM				, "Mechanics",			1024, 128);
	PRF_fn_vInitChrono        ( PRF_C_ulFctAnimPlayer		, "Player",				1024 ,128);
	PRF_fn_vInitChrono        ( PRF_C_ulFctInput			, "Input",				8   , 2  );
	PRF_fn_vInitChrono        ( PRF_C_ulFctEditor			, "Editor",				8   , 2  );
	PRF_fn_vInitChrono        ( PRF_C_ulFctSound		     , "Sound", 128, 5);
	PRF_fn_vInitChrono        ( PRF_C_ulFctFlip				, "Flip",				64  , 2  );
	PRF_fn_vInitChrono        ( PRF_C_ulFctMainMisc			, "Misc",				512 , 2  );
	PRF_fn_vInitChrono        ( PRF_C_ulFctIADNMPLAMisc		, "Misc AI/DNM/PLA",	512 , 2  );
	PRF_fn_vInitChrono        ( PRF_C_ulFctHIE				, "AI+DNM+PLA",			8   , 2  );
	PRF_fn_vInitChrono        ( PRF_C_ulWaitFor3dFx			, "Wait for 3dFx",		8	, 2  );
	PRF_fn_vInitChrono        ( PRF_C_ulFctDisplaySpecific  , "Display Specific",	1500, 5  );
	PRF_fn_vInitChrono        ( PRF_C_ulFctDisplayCommon	, "Display Specific 2",	3072, 10 );
	PRF_fn_vInitChrono        ( PRF_C_ulFctDisplaySprite	, "Display Sprite",		128, 10 );
 
    /*VL raster and var for GLI*/
    PRF_fn_vInitChrono        ( PRF_C_ulGLI1                , "Gli1"         , 512, 2  );
    PRF_fn_vInitChrono        ( PRF_C_ulGLI2                , "Gli2"         , 512, 2  );
    PRF_fn_vInitChrono        ( PRF_C_ulGLI3                , "Gli3"         , 512, 2  );
    PRF_fn_vInitChrono        ( PRF_C_ulGLI4                , "Gli4"         , 512, 2  );
    PRF_fn_vInitChrono        ( PRF_C_ulGLI5                , "Gli5"         , 512, 2  );
    PRF_fn_vInitChrono        ( PRF_C_ulGLI6                , "Gli6"         , 512, 2  );
    PRF_fn_vInitChrono        ( PRF_C_ulGLI7                , "Gli7"         , 512, 2  );
    PRF_fn_vInitChrono        ( PRF_C_ulGLI8                , "Gli8"         , 512, 2  );
 
    PRF_fn_vInitVariable      ( PRF_C_ulVarGLI1             , "VarGli1",	512 , 4  );
    PRF_fn_vInitVariable      ( PRF_C_ulVarGLI2             , "VarGli2",	512 , 4  );
    PRF_fn_vInitVariable      ( PRF_C_ulVarGLI3             , "VarGli3",	512 , 4  );
    PRF_fn_vInitVariable      ( PRF_C_ulVarGLI4             , "VarGli4",	512 , 4  );
    PRF_fn_vInitVariable      ( PRF_C_ulVarGLI5             , "VarGli5",	512 , 4  );
    PRF_fn_vInitVariable      ( PRF_C_ulVarGLI6             , "VarGli6",	512 , 4  );
    PRF_fn_vInitVariable      ( PRF_C_ulVarGLI7             , "VarGli7",	512 , 4  );
    PRF_fn_vInitVariable      ( PRF_C_ulVarGLI8             , "VarGli8",	512 , 4  );
    /*EVL*/
 
 
    /*VL raster and var for GLI*/
    PRF_fn_vInitChrono        ( PRF_C_ulGLI1                , "Gli1"         , 512, 2  );
    PRF_fn_vInitChrono        ( PRF_C_ulGLI2                , "Gli2"         , 512, 2  );
    PRF_fn_vInitChrono        ( PRF_C_ulGLI3                , "Gli3"         , 512, 2  );
    PRF_fn_vInitChrono        ( PRF_C_ulGLI4                , "Gli4"         , 512, 2  );
    PRF_fn_vInitChrono        ( PRF_C_ulGLI5                , "Gli5"         , 512, 2  );
    PRF_fn_vInitChrono        ( PRF_C_ulGLI6                , "Gli6"         , 512, 2  );
    PRF_fn_vInitChrono        ( PRF_C_ulGLI7                , "Gli7"         , 512, 2  );
    PRF_fn_vInitChrono        ( PRF_C_ulGLI8                , "Gli8"         , 512, 2  );
 
    PRF_fn_vInitVariable      ( PRF_C_ulVarGLI1             , "VarGli1",	512 , 4  );
    PRF_fn_vInitVariable      ( PRF_C_ulVarGLI2             , "VarGli2",	512 , 4  );
    PRF_fn_vInitVariable      ( PRF_C_ulVarGLI3             , "VarGli3",	512 , 4  );
    PRF_fn_vInitVariable      ( PRF_C_ulVarGLI4             , "VarGli4",	512 , 4  );
    PRF_fn_vInitVariable      ( PRF_C_ulVarGLI5             , "VarGli5",	512 , 4  );
    PRF_fn_vInitVariable      ( PRF_C_ulVarGLI6             , "VarGli6",	512 , 4  );
    PRF_fn_vInitVariable      ( PRF_C_ulVarGLI7             , "VarGli7",	512 , 4  );
    PRF_fn_vInitVariable      ( PRF_C_ulVarGLI8             , "VarGli8",	512 , 4  );
    /*EVL*/
 
 
	PRF_fn_vInitVariable      ( PRF_C_ulVarCurrentSector	, "Current Sector",		3   , 3  );
	PRF_fn_vInitVariable      ( PRF_C_ulVarDynObjects		, "dynam objects",		512 , 4  );
	PRF_fn_vInitVariable      ( PRF_C_ulVarStaObjects		, "static objects",		512 , 4  );
	PRF_fn_vInitVariable      ( PRF_C_ulVarFixObjects		, "Fix objects",		128 , 4  );
	PRF_fn_vInitVariable      ( PRF_C_ulVarShwObjects		, "Shadow objects",		128 , 4  );
	PRF_fn_vInitVariable      ( PRF_C_ulVarDynFaces			, "dynam faces",		512 , 4  );
	PRF_fn_vInitVariable      ( PRF_C_ulVarStaFaces			, "static faces",		512 , 4  );
	PRF_fn_vInitVariable      ( PRF_C_ulVarFixFaces			, "Fix faces",			512 , 4  );
	PRF_fn_vInitVariable      ( PRF_C_ulVarShwFaces			, "Shadow faces",		512 , 4  );
	PRF_fn_vInitVariable	  ( PRF_C_ulVarSectors			, "nb displayed sectors", 64, 128);
	PRF_fn_vInitVariable      ( PRF_C_ulVarStaColl			, "Number of objects of the map in collision with the main character", 512, 128);
	PRF_fn_vInitVariable      ( PRF_C_ulVarDynColl			, "Number of actors in collision with the main character", 512, 128);
	PRF_fn_vInitVariable      ( PRF_C_ulVarDynElements		, "Dynam Elements",		512 , 4  );
	PRF_fn_vInitVariable      ( PRF_C_ulVarStaElements		, "Static Elements",	512 , 4  );
	PRF_fn_vInitVariable      ( PRF_C_ulVarFixElements		, "Fix Elements",		512 , 4  );
	PRF_fn_vInitVariable      ( PRF_C_ulVarShwElements		, "Shadow Elements",	512 , 4  );
 
	PRF_fn_vSetIndependantVariableName( PRF_C_ulIdpNbSkippedAnims , "Skipped anims" );
 
	PRF_fn_vSetIndependantVariableName( PRF_C_ulIdpNbMaxAllocSPO , "max alloc PLA SPO" );
	PRF_fn_vSetIndependantVariableName( PRF_C_ulIdpNbAllocSPO , "alloc PLA SPO" );
	PRF_fn_vSetIndependantVariableName( PRF_C_ulIdpNbMaxAllocCHA , "max alloc Channels" );
	PRF_fn_vSetIndependantVariableName( PRF_C_ulIdpNbAllocCHA , "alloc Channels" );
 
#ifdef U64
	PRF_fn_vSetIndependantVariableName( PRF_C_ulIdpGfxList ,            "GfxList usage" );
	PRF_fn_vSetIndependantVariableName( PRF_C_ulIdpMaxGfxList ,         "Max GfxList usage" );
	PRF_fn_vSetIndependantVariableName( PRF_C_ulIdpAllowedGfxList ,     "Allowed GfxList usage" );
 
	PRF_fn_vSetIndependantVariableName( PRF_C_ulIdpGfxList2 ,           "GfxList2 usage" );
	PRF_fn_vSetIndependantVariableName( PRF_C_ulIdpMaxGfxList2 ,        "Max GfxList2 usage" );
	PRF_fn_vSetIndependantVariableName( PRF_C_ulIdpAllowedGfxList2 ,    "Allowed GfxList2 usage" );
 
	PRF_fn_vSetIndependantVariableName( PRF_C_ulIdpMtxList ,            "MtxList usage" );
	PRF_fn_vSetIndependantVariableName( PRF_C_ulIdpMaxMtxList ,         "Max MtxList usage" );
	PRF_fn_vSetIndependantVariableName( PRF_C_ulIdpAllowedMtxList ,     "Allowed MtxList usage" );
 
	PRF_fn_vSetIndependantVariableName( PRF_C_ulIdpLightList ,          "LightList usage" );
	PRF_fn_vSetIndependantVariableName( PRF_C_ulIdpMaxLightList ,       "Max LightList usage" );
	PRF_fn_vSetIndependantVariableName( PRF_C_ulIdpAllowedLightList,    "Allowed LightList usage" );
 
	PRF_fn_vSetIndependantVariableName( PRF_C_ulIdpMaxMainStackSize ,   "Max MainStack usage" );
	PRF_fn_vSetIndependantVariableName( PRF_C_ulIdpAllowedMainStackSize,"Allowed MainStack usage" );
 
	PRF_fn_vSetIndependantVariableName( PRF_C_ulIdpMaxNbCollisions ,		"Max Nb Collisions" );
	PRF_fn_vSetIndependantVariableName( PRF_C_ulIdpAllowedNbCollisions,	"Allowed Nb Collisions" );
 
	PRF_fn_vSetIndependantVariableName( PRF_C_ulIdpAAMode,"AA Mode" );
#endif
	
	GAM_fn_vRasterDisplayInit ();
#endif /* USE_PROFILER && PRESS_DEMO */
 
#ifdef USE_DIRECTX
	wTimerMainLoop = TMR_fn_wCreateTimer(C_wTimerFrequencyMedium);
	TMR_fn_wGetTimerFrequency(wTimerMainLoop,&ulTimerFrequency);
	ulTimerFrequency /= 1000000;
#endif


	/*g_b_lBackFaceOn = 0;*/
	while	(!fn_bEndOfGame())
	{
		fn_vChooseTheGoodInit();
        PRF_fn_vStartChrono( PRF_C_ulFctMainLoop, NULL );

		while(!fn_bEndOfOneStep())            /* App can force engine to stop in WIN32 */
		{

#ifdef USE_DIRECTX
			TMR_fn_wResetTimer(wTimerMainLoop);
			TMR_fn_wStartTimer(wTimerMainLoop);
#endif

			/**** Save the game ****/
#if !defined(ACTIVE_EDITOR)
			/*
			if (g_stSavedGame.bSaveAsked&&!fn_bIsCommandsDisplayed())
			{
			fn_bPlayerSaveGameAll();
			fn_vDisplayCommandValue(TRUE);
			}
			if (g_stExtrasGame.bSaveAsked&&!fn_bIsCommandsDisplayed())
			{
			fn_bSaveCurrentExtrasGame();
			fn_vDisplayCommandValue(TRUE);
			}
			*/
#endif /* ACTIVE_EDITOR */
			
#if defined(WIN32)
			PRF_fn_vStartChrono( PRF_C_ulFctMainMisc, NULL );
			fn_vCheckPause();
			fn_vCheckEnd();
 
			PRF_fn_vStopChrono( PRF_C_ulFctMainMisc, NULL );
			if (g_stEngineStructure.eEngineMode!=EM_ModeStoppingProgram)
#endif /* WIN32 */
				
				/* One VBL step */
				fn_vOneTrame();
			//chbani
#ifdef USE_DIRECTX
			TMR_fn_wStopTimer(wTimerMainLoop);
			TMR_fn_wReadTimer( wTimerMainLoop, &stTimerCountMainLoop);
			ulTimeMainLoop = stTimerCountMainLoop.m_ulLowPart/ulTimerFrequency;//MicroSecond
			{
				int diff ;
				static int sFrameDisared  = 16666 ;//micro sec  60 FPS
				if(sFrameDisared > ulTimeMainLoop )
				{
					diff = (sFrameDisared - ulTimeMainLoop)/1000;//milsecond
					Sleep(diff);
				}
			}
#endif
	
		}
        PRF_fn_vStopChrono( PRF_C_ulFctMainLoop, NULL );
	
		fn_vChooseTheGoodDesInit();
	}
	
	/**** tell the appli that it's over...*/
#if defined(WIN32)
	fn_vEngineHasFinished();
#endif
	
	return 0;
}
