#define C_szSynchroOn		"ON"
#define C_szSynchroOff		"OFF"
 
/* change frame rate under 70 %*/
unsigned char g_ucSynchroLowLimit = 70;
unsigned char g_ucDftSynchro = C_AutoSynchro;
 
/* ##F===================================================================================
NAME :          GLD_vSetFrameSynchro
DESCRIPTION :   This function set the type of synchro used with its parameter 
				For script interpretation
INPUT :         Synchro ON or OFF
				NbTrame (0 for hysteresis system)
				Percent use to decrease NbTrame
=========================================================================================
CREATION : Carlos Torres / 11-12-1997
=======================================================================================*/
void GLD_vSetFrameSynchro(char * szOnOff,char * szNbTrame,char * szPctLowLimit) {
	int iNumber;
 
	/* Synchro OFF*/
	if (!stricmp(szOnOff,C_szSynchroOff)) 
		g_ucDftSynchro = C_NoSynchro;
	
	/* Synchro ON*/
	else if (!stricmp(szOnOff,C_szSynchroOn)) 
	{
		iNumber = atoi(szNbTrame);
 
		/* set nb trame use for synchro*/
		if ((iNumber >= C_AutoSynchro) && (iNumber <= C_MaxFrameSynchro))
			g_ucDftSynchro = (unsigned char) iNumber;
	}
 
	/* set % low limit*/
	iNumber = atoi(szPctLowLimit);
	if ((iNumber >= 0) && (iNumber <= 100))
		g_ucSynchroLowLimit = (unsigned char) iNumber;
}
 
/* ##F===================================================================================
NAME :          GLD_vIdle
DESCRIPTION :   for NoSynchro -> just call grSstIdle
				forAutosynchro -> wait a calculted number of trame
				Defaultsynchro -> depends on the choice set with SetFrameSynchro
				other -> wait the specified number of trame
INPUT :         Synchro choice
=========================================================================================
CREATION : Carlos Torres / 11-12-1997
MODIF                    / 22-12-1997 change frame length evaluation
=======================================================================================*/
#ifdef GLIDE
void GLD_vIdle(enum Synchro eSynchro) {	
	static short s_wTime = 0;
	static unsigned long s_ulFrameLength = 0;
	static unsigned char s_ucFrameFrequency = 3;
	stTimerCount C={0,0};
	unsigned int uiTramePassed;
	unsigned char ucUsedSynchro=(eSynchro == C_DefaultSynchro)?g_ucDftSynchro:eSynchro;
	unsigned long	ulState;
 
	/* No synchro*/
	if ((ucUsedSynchro == C_NoSynchro)) {
		grSstIdle();
		return;
	}
 
	/* first passage*/
	if (!s_wTime) {
		s_wTime = TMR_fn_wCreateTimer(C_wTimerFrequencyMedium);
		
		ulState = grSstStatus();
		/* mesurement of trame length*/
		while (grSstVideoLine() != 0);
		while (grSstVideoLine() != 1);
		TMR_fn_wStartTimer(s_wTime);
		while (grSstVideoLine() != 0);
		while (grSstVideoLine() != 1);
		TMR_fn_wReadTimer(s_wTime,&C);
		TMR_fn_wStopTimer(s_wTime);
		TMR_fn_wResetTimer(s_wTime);
		/* Add a delta to majorate frmae length*/
		s_ulFrameLength = (unsigned long)(C.m_ulLowPart*1.05);
		s_ulFrameLength = C.m_ulLowPart;
	}
	else {
		/* Auto Syncho*/
		if (ucUsedSynchro == C_AutoSynchro) {
			/* get the last length of time for rendering*/
			TMR_fn_wReadTimer(s_wTime,&C);
 
			/* length is over the previous limit -> increase Frame frequency*/
			if ((C.m_ulLowPart > (s_ucFrameFrequency*s_ulFrameLength)) && (s_ucFrameFrequency < C_MaxFrameSynchro)) {
				s_ucFrameFrequency++;
			}
			/* length is under the Synchro Limit  -> decrease Frame frequency*/
			else
				if ((s_ucFrameFrequency > 1) && ((100*C.m_ulLowPart) < ((100*s_ucFrameFrequency - 200 + g_ucSynchroLowLimit)*s_ulFrameLength))) 
					s_ucFrameFrequency--;
			ucUsedSynchro = s_ucFrameFrequency;
		}
 
		/* get the last length of time for rendering*/
		TMR_fn_wStopTimer(s_wTime);
		TMR_fn_wReadTimer(s_wTime,&C);
	 }
   	  
	 /* compute VBL already passed during rendering*/
	for (uiTramePassed=0;C.m_ulLowPart>s_ulFrameLength;uiTramePassed++,C.m_ulLowPart-=s_ulFrameLength);
 
	 /* Wa	it the next end of screen*/
	 do {
		/* between end of screen and VBL -> wait*/
		if (uiTramePassed && 
			(grSstVideoLine() >= (unsigned long) 480) && 
			(uiTramePassed < ucUsedSynchro)) {
			while(grSstVideoLine()) ;
		}
 
		/* Avoid evaluation error*/
		if (!grSstVideoLine() && ((C.m_ulLowPart << 1) > s_ulFrameLength))
			uiTramePassed++;
 
		/* Remain RAZ*/
		C.m_ulLowPart=0;
		
		while ((grSstVideoLine() < (unsigned long) 480) &&
			(grSstVideoLine() || (uiTramePassed < ucUsedSynchro)));
 
	 } while (++uiTramePassed < ucUsedSynchro);
	
 
	TMR_fn_wResetTimer(s_wTime);
	TMR_fn_wStartTimer(s_wTime);
}
#endif /* GLIDE */
 
long GLD_lComputeWaitFrameForSynchro (enum Synchro eSynchro) 
{	
	static short			s_wTime = 0;
	static unsigned char	s_ucFrameFrequency = 1;
	stTimerCount			C={0,0};
	unsigned char			ucUsedSynchro = (eSynchro == C_DefaultSynchro) ? g_ucDftSynchro : eSynchro;
	long					lTramePassed , lTrameReturn;
	
	/* No synchro*/
	if (ucUsedSynchro == C_NoSynchro) 
		return 0;
 
	/* first passage*/
	if (!s_wTime) 
	{
		s_wTime = TMR_fn_wCreateTimer(C_wTimerFrequencyMedium);
		TMR_fn_wResetTimer(s_wTime);
		TMR_fn_wStartTimer(s_wTime);
		return 0;
	}
	
	/* Auto Synchro*/
	if (ucUsedSynchro == C_AutoSynchro) 
	{
		/* get the last length of time for rendering*/
		TMR_fn_wReadTimer(s_wTime, &C);
 
		/* length is over the previous limit -> increase Frame frequency*/
		if ( (C.m_ulLowPart > (s_ucFrameFrequency * GLI_g_ulFrameLength) ) && (s_ucFrameFrequency < C_MaxFrameSynchro)) 
		{
			s_ucFrameFrequency++;
		}
		/* length is under the Synchro Limit  -> decrease Frame frequency*/
		else
		{
			if ( (s_ucFrameFrequency > 1) && ((100*C.m_ulLowPart) < ((100*s_ucFrameFrequency - 200 + g_ucSynchroLowLimit)*GLI_g_ulFrameLength)) ) 
				s_ucFrameFrequency--;
		}
		ucUsedSynchro = s_ucFrameFrequency;
	}
 
	/* get the last length of time for rendering*/
	TMR_fn_wStopTimer(s_wTime);
	TMR_fn_wReadTimer(s_wTime,&C);
   	  
	 /* compute VBL already passed during rendering*/
	for (lTramePassed = 0 ; C.m_ulLowPart > GLI_g_ulFrameLength; lTramePassed++, C.m_ulLowPart-=GLI_g_ulFrameLength);
 
	if (lTramePassed > s_ucFrameFrequency )
		lTrameReturn = 1;
	else
		lTrameReturn = s_ucFrameFrequency - lTramePassed + 1;
	
	TMR_fn_wResetTimer(s_wTime);
	TMR_fn_wStartTimer(s_wTime);
 
	/*return s_ucFrameFrequency;*/
	return lTrameReturn;
}


static unsigned short gs_wTimerForSmoothSyncro = 0xbeef;
long GLD_fn_lComputeWaitFrameForSmoothSynchro()
{
#define C_ulFrameRateHistorySize 5
    static long gas_ulFrameRateHistory[] = 
{ 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0 };
    static unsigned long    ulTotalFrameRate = 0;
    static unsigned long    ulCurrentFrame = 0;
    stTimerCount            stDeltaTime;
    unsigned long           ulTramePassed;
    unsigned long           ulTrameReturn = 1;
 
    if( gs_wTimerForSmoothSyncro == 0xbeef )
    {
        /* First time, create the timer. */
        gs_wTimerForSmoothSyncro = TMR_fn_wCreateTimer(C_wTimerFrequencyMedium);
        TMR_fn_wResetTimer(gs_wTimerForSmoothSyncro);
        TMR_fn_wStartTimer(gs_wTimerForSmoothSyncro);
        return 1;
    }
 
    TMR_fn_wReadTimer(gs_wTimerForSmoothSyncro, &stDeltaTime);
 
    /* Compute duration passed for engine + rendering (rounded up) */
    ulTramePassed = ( stDeltaTime.m_ulLowPart + ((GLI_g_ulFrameLength*95)/100) ) / GLI_g_ulFrameLength;

    /* Too slow. We don't do anything */
    if( ulTramePassed > 4 )
        return 1;
 
    /* Compute number of frames to wait for */
    if( ulTramePassed << C_ulFrameRateHistorySize < ulTotalFrameRate )
        ulTrameReturn = 
              1 
            + ((ulTotalFrameRate + (1<<C_ulFrameRateHistorySize) - 1) >> C_ulFrameRateHistorySize)
            - ulTramePassed;
 
    /* Update frame history */
    ulTotalFrameRate -= gas_ulFrameRateHistory[ulCurrentFrame];
    ulTotalFrameRate += ulTramePassed;
    gas_ulFrameRateHistory[ulCurrentFrame] = ulTramePassed;
    ulCurrentFrame ++;
    ulCurrentFrame &= (1<<C_ulFrameRateHistorySize) - 1;
 
    return (long)ulTrameReturn;
}