 
/*********************************************************************
*                                                                    *
*       PRF module                                                   *
*                                                                    *
**********************************************************************
*                                                                    *
*  This module is a profiler                                         *
*                                                                    *
*  Define USE_PROFILER to use it                                     *
*                                                                    *
*  Author : Alexis Vaise                                             *
*  Revision : fabien Bole-Feysot
*                                                                    *
*********************************************************************/
 
#if defined(USE_PROFILER) && !defined(PRESS_DEMO)
 
#if !defined(U64)
#include <windows.h>
#else  /* U64 */
	#include <ultra64.h>
#endif /* U64 */
 
#include <stdio.h>
#include "PRF.h"
 
 
#include <assert.h>
 
#ifdef U64
#undef assert
#define assert(test)
/*
#define assert(test) \
	{\
	if (!test)\
		M_PrintfN64(("Assert in Profile.c\n"));\
		}
*/
#endif
 
#define PRF_C_sz
typedef char tdstVariableName[40];
/* ======================================== Variables ========================================*/
 
PRF_tdstFunctionInformation PRF_g_a_stFunctionInformation [PRF_C_lMaxNbFunction];
PRF_tdstVariableInformation PRF_g_a_stVariableInformation [PRF_C_lMaxNbVariable];
BOOL						PRF_g_bModuleInitialized = FALSE;
#if defined(U64) /* {*/
unsigned long PRG_g_ulStartTime = 0;
#endif /* U64 }*/
/* ======================================== private Variables ========================================*/
long				a_lIndependantVariable[PRF_C_lMaxNbIndependantVariable];
char			   *a_szIndependantVariableName[PRF_C_lMaxNbIndependantVariable];
float				a_fFloatIndependantVariable[PRF_C_lMaxNbFloatIndependantVariable];
char			   *a_szFloatIndependantVariableName[PRF_C_lMaxNbFloatIndependantVariable];
unsigned long		ulTimerFrequency;
unsigned long		ulMonitorFrequency;
unsigned long		ulNbTotalStartAndStop;
unsigned long		ulNbTotalHistoryVar;
BOOL				bReinitDone = TRUE;
/* ======================================== Macros ========================================*/
#define PRF_C_IndexError    ((int)-1)
 
/* ======================================== Functions ========================================*/
 
 
/*-----------------------------------------------------------------------------*/
 
#include "Specif/profile.cxx"
 
/* PRF_fn_vDesInitProfileModule*/
/* DesInit module*/
/*-----------------------------------------------------------------------------*/
void PRF_fn_vDesInitProfileModule()
{
    unsigned long i;
    PRF_tdstFunctionInformation * p_Function;
    PRF_tdstVariableInformation * p_Variable;
 
    for (i = 0 , p_Function = PRF_g_a_stFunctionInformation ; i < PRF_C_lMaxNbFunction ; i ++, p_Function++)
    {
		if( p_Function->p_stFrameHistory )
		{
			free( p_Function->p_stFrameHistory );
			p_Function->p_stFrameHistory = NULL;
		}
		if( p_Function->p_stUserDataSummary )
		{
			free( p_Function->p_stUserDataSummary  );
			p_Function->p_stUserDataSummary  = NULL;
		}
    }
 
    for (i = 0 , p_Variable = PRF_g_a_stVariableInformation ; i < PRF_C_lMaxNbVariable ; i ++, p_Variable++)
    {
		if( p_Variable->p_stFrameHistory )
		{
			free( p_Variable->p_stFrameHistory );
			p_Variable->p_stFrameHistory = NULL;
		}
		if( p_Variable->p_stUserDataSummary )
		{
			free( p_Variable->p_stUserDataSummary  );
			p_Variable->p_stUserDataSummary  = NULL;
		}
    }
	PRF_g_bModuleInitialized = FALSE;
}
 
 
/*-----------------------------------------------------------------------------*/
/* PRF_fn_vComputeMinMaxTotalStructure*/
/* must be called once a frame is finished.*/
/* compute the new structure values according to the last executed frame*/
/*-----------------------------------------------------------------------------*/
void PRF_fn_vComputeMinMaxTotalStructure(PRF_tdstMinMaxTotalStructure *pp, unsigned long ulNbFrame)
{
	int iIndex;		/* index in average-related history array for this frame*/
	int i;
 
	/* if a reinit all has benn done, don't compute anything until start of next frame*/
	if (bReinitDone) return;
 
	iIndex = ulNbFrame % PRF_C_lNbTramesForAverage;
 
	/* compute new total value for average*/
	/* remove oldest frame value*/
	pp->ulTotalValueForAverage -= pp->a_ulValuesHistory[iIndex];
	/* and add this frame value*/
	pp->ulTotalValueForAverage += pp->ulThisFrameValue;
	/* if oldest frame value was the max, compute new max*/
	if (pp->a_ulValuesHistory[iIndex] == pp->ulMaxValue)
	{
		unsigned long ulNewMax;
 
		ulNewMax = pp->ulThisFrameValue;
		for (i=1;i<PRF_C_lNbTramesForAverage;i++)	/* don't count 0*/
		{
			if (pp->a_ulValuesHistory[(iIndex + i) % PRF_C_lNbTramesForAverage] > ulNewMax)
				ulNewMax = pp->a_ulValuesHistory[(iIndex + i) % PRF_C_lNbTramesForAverage];
		}
		pp->ulMaxValue = ulNewMax;
 
	}
	/* if oldest frame value was the min, compute new min*/
	if (pp->a_ulValuesHistory[iIndex] == pp -> ulMinValue)
	{
		unsigned long ulNewMin;
 
		ulNewMin = pp->ulThisFrameValue;
		for (i=1;i<PRF_C_lNbTramesForAverage;i++)	/* don't count 0*/
		{
			if (pp->a_ulValuesHistory[(iIndex + i) % PRF_C_lNbTramesForAverage] < ulNewMin)
				ulNewMin = pp->a_ulValuesHistory[(iIndex + i) % PRF_C_lNbTramesForAverage];
		}
		pp->ulMinValue = ulNewMin;
	}
	/* put this frame value in history*/
	pp->a_ulValuesHistory[iIndex] = pp->ulThisFrameValue;
	/* compute average value...*/
	pp->ulAverageValue = pp->ulTotalValueForAverage / PRF_C_lNbTramesForAverage;
	/* check if max or min has changed*/
	if (pp->ulThisFrameValue < pp->ulMinValue)  pp->ulMinValue = pp->ulThisFrameValue;
	if (pp->ulThisFrameValue > pp->ulMaxValue)  pp->ulMaxValue = pp->ulThisFrameValue;
}
 
 
 
/*-----------------------------------------------------------------------------*/
/* PRF_fn_vInitChrono*/
/* Must be called once to create and give a name to a chrono*/
/*-----------------------------------------------------------------------------*/
void PRF_fn_vInitChrono (unsigned long _lFunctionNumber , char * _szFunctionName,
                         unsigned long _ulHistorySize, unsigned long _ulMaxNumberOfUserData)
{
    PRF_tdstFunctionInformation * p = & PRF_g_a_stFunctionInformation [_lFunctionNumber];
 
    p->ulHistorySize        = _ulHistorySize;
    p->p_stFrameHistory     = (PRF_tdstHistory*) malloc( p->ulHistorySize * sizeof(PRF_tdstHistory) );
 
    p->ulUserDataSize       = _ulMaxNumberOfUserData;
    p->p_stUserDataSummary  = (PRF_tdstUserDataSummary*) malloc( p->ulUserDataSize * sizeof(PRF_tdstUserDataSummary) );
 
    p->szFunctionName = _szFunctionName;
 
    PRF_fn_vReInitChrono( p );
}
 
/*-----------------------------------------------------------------------------*/
/* PRF_fn_vInitVariable*/
/* Must be called once to create and give a name to a variable*/
/*-----------------------------------------------------------------------------*/
void PRF_fn_vInitVariable (unsigned long _lVariableNumber , char * _szVariableName,
                         unsigned long _ulHistorySize, unsigned long _ulMaxNumberOfUserData)
{
    PRF_tdstVariableInformation * p = & PRF_g_a_stVariableInformation [_lVariableNumber];
 
    p->ulHistorySize        = _ulHistorySize;
    p->p_stFrameHistory     = (PRF_tdstHistory*) malloc( p->ulHistorySize * sizeof(PRF_tdstHistory) );
 
    p->ulUserDataSize       = _ulMaxNumberOfUserData;
    p->p_stUserDataSummary  = (PRF_tdstUserDataSummary*) malloc( p->ulUserDataSize * sizeof(PRF_tdstUserDataSummary) );
 
    p->szVariableName = _szVariableName;
 
    PRF_fn_vReInitVariable( p );
}
 
/*-----------------------------------------------------------------------------*/
/* PRF_fn_vReInitChrono*/
/* ReInit a function raster*/
/*-----------------------------------------------------------------------------*/
void PRF_fn_vReInitChrono(PRF_tdstFunctionInformation *_pFunction)
{
    _pFunction->ulNbFrame      = 0;
    _pFunction->ulHistoryIndex = 0;
    _pFunction->iNbUserData    = 0;
    _pFunction->iRunning       = 0;
 
    if( _pFunction->ulHistorySize )		memset( _pFunction->p_stFrameHistory,     0, _pFunction->ulHistorySize * sizeof(PRF_tdstHistory) );
    if( _pFunction->ulUserDataSize )	memset( _pFunction->p_stUserDataSummary,  0, _pFunction->ulUserDataSize * sizeof(PRF_tdstUserDataSummary) );
 
    memset( &_pFunction->stFunctionDuration,  0, sizeof(PRF_tdstMinMaxTotalStructure) );
    memset( &_pFunction->stNbTimeCalled,      0, sizeof(PRF_tdstMinMaxTotalStructure) );
 
    _pFunction -> stNbTimeCalled. ulMinValue     = 1000000000;
    _pFunction -> stFunctionDuration. ulMinValue = 1000000000;
}
 
/*-----------------------------------------------------------------------------*/
/* PRF_fn_vReInitVariable*/
/* ReInit a variable raster*/
/*-----------------------------------------------------------------------------*/
void PRF_fn_vReInitVariable(PRF_tdstVariableInformation *_pVariable)
{
    _pVariable->ulNbFrame      = 0;
    _pVariable->ulHistoryIndex = 0;
    _pVariable->iNbUserData    = 0;
 
    if( _pVariable->ulHistorySize )		memset( _pVariable->p_stFrameHistory,     0, _pVariable->ulHistorySize * sizeof(PRF_tdstHistory) );
    if( _pVariable->ulUserDataSize )	memset( _pVariable->p_stUserDataSummary,  0, _pVariable->ulUserDataSize * sizeof(PRF_tdstUserDataSummary) );
 
    memset( &_pVariable->stVariableValue,     0, sizeof(PRF_tdstMinMaxTotalStructure) );
 
    _pVariable->stVariableValue.ulMinValue = 1000000000;
}
 
/*-----------------------------------------------------------------------------*/
/* PRF_fn_vReinitAllChrono*/
/* Must be called when reinitializing the map*/
/*-----------------------------------------------------------------------------*/
void PRF_fn_vReinitAllChrono (void)
{
    unsigned long i;
    PRF_tdstFunctionInformation * p_Function;
    PRF_tdstVariableInformation * p_Variable;
 
    for (i = 0 , p_Function = PRF_g_a_stFunctionInformation ; i < PRF_C_lMaxNbFunction ; i ++, p_Function++)
    {
        PRF_fn_vReInitChrono (p_Function);
    }
 
    for (i = 0 , p_Variable = PRF_g_a_stVariableInformation ; i < PRF_C_lMaxNbVariable ; i ++, p_Variable++)
    {
        PRF_fn_vReInitVariable (p_Variable);
    }
 
	bReinitDone = TRUE;
 
#if defined(U64) /* {*/
	PRG_g_ulStartTime = TMR_fn_ulFastGetInternalCounter();
#endif /* U64 }*/
}
 
/*-----------------------------------------------------------------------------*/
/* fn_iGetIndex*/
/* get the index for this user data in the summary array*/
/*-----------------------------------------------------------------------------*/
int fn_iGetIndex(void *_p_vData, PRF_tdstUserDataSummary* a_Summary, int lenght, int iMax)
{
	int i;
 
	if (bReinitDone)
		return 0;
 
	for (i = 0; i<iMax; i++)
	{
		/* check if we find the data*/
		if (a_Summary[i].p_vUserData == _p_vData)
			return i;
	}
	/* check if there is some room left*/
	if (iMax+1 == lenght)
	{
		/* too much UserData*/
        return PRF_C_IndexError;
 
	}
	/*assert(iMax+1 != lenght);*/
	/* we didn't find the data, it is a new one*/
	a_Summary[iMax].p_vUserData = _p_vData;
	a_Summary[iMax].ulValueForThisFrame = 0;
	a_Summary[iMax].ucStartStopCounter = 0;
	return iMax;
}
 
/*-----------------------------------------------------------------------------*/
/* PRF_fn_vComputeChrono*/
/* Compute the result (average, min, max...) for one chrono (must be called each frame before writing the result)*/
/*-----------------------------------------------------------------------------*/
void PRF_fn_vComputeChrono (unsigned long _lFunctionNumber)
{
	unsigned int i;
	int j;
	PRF_tdstFunctionInformation * p = & PRF_g_a_stFunctionInformation [_lFunctionNumber];
	PRF_tdstHistory				* p_stHistory;
	PRF_tdstUserDataSummary		* p_stUserDataSummary;
	unsigned long				ulTimerValue = TMR_fn_ulFastGetInternalCounter();
 
	if (bReinitDone)
		return;
 
	/* if the raster is not active, return...*/
	if (p->szFunctionName == 0) return;
 
	/* before computing min / max / average, we have to analyse the*/
	/* history array to find the total time spent in the function,*/
	/* the number of different user data used, and*/
	/* the total time spent for each of them*/
 
 
	if (p->ulHistoryIndex == p->ulHistorySize + 2)
	{
#ifdef _DEBUG
		/* too much start/stop*/
/*XB*/
#ifndef U64
		FILE *pFile = fopen( "PRF.log" , "at" );
		if( pFile )
		{
			fprintf( pFile,"Function : %4i : not enought history\n\n", _lFunctionNumber );
			fclose( pFile );
		}
#else
		M_PrintfN64(("Function : %4i : not enought history\n\n", _lFunctionNumber ));
#endif
/*End XB*/
#endif /* _DEBUG */
        p->ulHistoryIndex = p->ulHistorySize;
	}
 
	ulNbTotalStartAndStop += p->ulHistoryIndex;
 
	/* clear the summary array first element (other elements will be cleared when new entries will be added)*/
    p->p_stUserDataSummary[0].ulValueForThisFrame = 0;
    p->p_stUserDataSummary[0].p_vUserData = NULL;
    p->p_stUserDataSummary[0].ucStartStopCounter = 0;
 
	p->iNbUserData = 0;
	p->stNbTimeCalled.ulThisFrameValue = 0;
 
	/* loop to process history*/
	for (i=0 , p_stHistory=p->p_stFrameHistory ; i<p->ulHistoryIndex; i++,p_stHistory++)
	{		
		int				iIndex;
 
		/* find the index for this user data*/
        iIndex = fn_iGetIndex(p_stHistory->p_vUserData,p->p_stUserDataSummary,p->ulUserDataSize,p->iNbUserData);
 
#ifndef _DEBUG
        if (iIndex == PRF_C_IndexError)     continue;
#endif /* _DEBUG */
 
		if (p->iNbUserData < iIndex+1)
			p->iNbUserData = iIndex+1;
		/* if this entry is a start chrono*/
		if ((p_stHistory->ulValue & 0x00000001) == 0)
		{
			/* if the chrono is not working, start it*/
            if (p->p_stUserDataSummary[iIndex].ucStartStopCounter++ == 0)
			{
                p->p_stUserDataSummary[iIndex].ulValueForThisFrame -= p_stHistory->ulValue;
			}
		}
		else
		{
			/* this is a stop chrono*/
/*XB*/
#ifdef U64
			if(p->p_stUserDataSummary[iIndex].ucStartStopCounter == 0)
			{
				M_PrintfN64(("Function : %4i user data : %ld : stop without a start!!\n\n",
											_lFunctionNumber,p->p_stUserDataSummary[iIndex].p_vUserData ));
				/**/
				p->p_stUserDataSummary[iIndex].ucStartStopCounter++;
				p->p_stUserDataSummary[iIndex].ulValueForThisFrame -= PRG_g_ulStartTime;
			}
#else
			/* verify that the chrono is running...*/
            assert(p->p_stUserDataSummary[iIndex].ucStartStopCounter != 0);
#endif
/*End XB*/
			/* if the chrono must be stopped, stop it*/
            if (p->p_stUserDataSummary[iIndex].ucStartStopCounter-- == 1)
			{
                p->p_stUserDataSummary[iIndex].ulValueForThisFrame += p_stHistory->ulValue;
			}
			p->stNbTimeCalled.ulThisFrameValue++;
		}
	}
 
	/* the hole history array was processed, check if every chrono is correctly stopped*/
	/* and compute the time for the hole raster*/
	p->stFunctionDuration.ulThisFrameValue = 0;
	p_stUserDataSummary = p->p_stUserDataSummary;
	for (j=0; j<p->iNbUserData; j++,p_stUserDataSummary++)
	{
        assert(p_stUserDataSummary->ucStartStopCounter < 2);
		if(p_stUserDataSummary->ucStartStopCounter < 2)
		{
			if(p_stUserDataSummary->ucStartStopCounter == 1)
			{
				/* miss a stop*/
				p_stUserDataSummary->ulValueForThisFrame += ulTimerValue;
			}
			p->stFunctionDuration.ulThisFrameValue += p_stUserDataSummary->ulValueForThisFrame;
		}
	}
 
	/* the summary array is filled and checked*/
	/* so compute the complete min/max structure*/
	p->ulNbFrame ++;
 
	/* the only data the following function uses is the 'ulThisFrameValue' member of the structure.*/
	/* this member is up to date at this point*/
	PRF_fn_vComputeMinMaxTotalStructure (&p->stFunctionDuration,p->ulNbFrame);
	PRF_fn_vComputeMinMaxTotalStructure (&p->stNbTimeCalled,p->ulNbFrame);
}
 
/*-----------------------------------------------------------------------------*/
/* PRF_fn_vComputeVariable*/
/* Compute the result (mean, min, max...) for one variable (must be called each frame before writing the result)*/
/*-----------------------------------------------------------------------------*/
void PRF_fn_vComputeVariable (unsigned long _lVariableNumber)
{
	unsigned int i;
	int j;
    PRF_tdstVariableInformation * p = & PRF_g_a_stVariableInformation [_lVariableNumber];
	PRF_tdstHistory *p_stHistory;
	PRF_tdstUserDataSummary *p_stUserDataSummary;
 
	if (bReinitDone)
		return;
 
	/* if the raster is not active, return...*/
	if (p->szVariableName == 0) return;
 
	/* before computing min / max / average, we have to analyse the*/
	/* history array to find the final value for this variable,*/
	/* the number of different user data used, and*/
	/* the final value for each of them*/
 
	if (p->ulHistoryIndex == p->ulHistorySize + 2)
	{
#ifdef _DEBUG
		/* too much start/stop*/
/*XB*/
#ifndef U64
		FILE *pFile = fopen( "PRF.log" , "at" );
		if( pFile )
		{
			fprintf( pFile,"Variable : %4i : not enought history\n\n", _lVariableNumber );
			fclose( pFile );
		}
#else
		M_PrintfN64(("Variable : %4i : not enought history\n\n", _lVariableNumber ));
#endif
#endif /* _DEBUG */
        p->ulHistoryIndex = p->ulHistorySize;
	}
 
	ulNbTotalHistoryVar += p->ulHistoryIndex;
 
	/* clear the summary array first element (other elements will be cleared when new entries will be added)*/
    p->p_stUserDataSummary[0].ulValueForThisFrame = 0;
    p->p_stUserDataSummary[0].p_vUserData = NULL;
    p->p_stUserDataSummary[0].ucStartStopCounter = 0;
 
	p->iNbUserData = 0;
 
	/* loop to process history*/
	for (i=0,p_stHistory=p->p_stFrameHistory; i<p->ulHistoryIndex; i++,p_stHistory++)
	{
		int				iIndex;
 
		/* find the index for this user data*/
        iIndex = fn_iGetIndex(p_stHistory->p_vUserData,p->p_stUserDataSummary,p->ulUserDataSize,p->iNbUserData);
 
#ifndef _DEBUG
        if (iIndex == PRF_C_IndexError)     continue;
#endif /* _DEBUG */
 
        if (p->iNbUserData < iIndex+1)
			p->iNbUserData = iIndex+1;
 
        p->p_stUserDataSummary[iIndex].ulValueForThisFrame += p_stHistory->ulValue;
	}
 
	/* the hole history array was processed, compute the value for the hole raster*/
	p->stVariableValue.ulThisFrameValue = 0;
	p_stUserDataSummary = p->p_stUserDataSummary;
	for (j=0; j<p->iNbUserData; j++,p_stUserDataSummary++)
	{
        p->stVariableValue.ulThisFrameValue += p_stUserDataSummary->ulValueForThisFrame;
	}
 
	/* the summary array is filled and checked*/
	/* so compute the complete min/max structure*/
	p->ulNbFrame ++;
 
	/* the only data the following function uses is the 'ulThisFrameValue' member of the structure.*/
	/* this member is up to date at this point*/
    PRF_fn_vComputeMinMaxTotalStructure (&p->stVariableValue,p->ulNbFrame);
}
 
/*-----------------------------------------------------------------------------*/
/* PRF_fn_vComputeAllChrono*/
/* Must be called each frame before writing the result*/
/*-----------------------------------------------------------------------------*/
void PRF_fn_vComputeAllChrono (void)
{
    unsigned long i;
 
	if (bReinitDone)
		return;
 
	ulNbTotalStartAndStop = 0;
	ulNbTotalHistoryVar   = 0;
 
    for (i = 0 ; i < PRF_C_lMaxNbFunction ; i ++)
        if (PRF_g_a_stFunctionInformation [i] . szFunctionName != 0)
            PRF_fn_vComputeChrono (i);
 
    for (i = 0 ; i < PRF_C_lMaxNbVariable ; i ++)
        if (PRF_g_a_stVariableInformation [i] . szVariableName != 0)
            PRF_fn_vComputeVariable (i);
}
 
/*-----------------------------------------------------------------------------*/
/* PRF_fn_vResetChrono*/
/* Reset the chrono (must be called each frame after writing the result)*/
/*-----------------------------------------------------------------------------*/
void PRF_fn_vResetChrono (unsigned long _lFunctionNumber)
{
    PRF_g_a_stFunctionInformation[_lFunctionNumber].ulHistoryIndex = 0;
}
 
/*-----------------------------------------------------------------------------*/
/* PRF_fn_vResetVariable*/
/* Reset the variable (must be called each frame after writing the result)*/
/*-----------------------------------------------------------------------------*/
void PRF_fn_vResetVariable (unsigned long _lVariableNumber)
{
    PRF_g_a_stVariableInformation [_lVariableNumber].ulHistoryIndex = 0;
}
 
/*-----------------------------------------------------------------------------*/
/* PRF_fn_vResetAllChrono*/
/* Must be called each frame after writing the result*/
/*-----------------------------------------------------------------------------*/
void PRF_fn_vResetAllChrono (void)
{
    unsigned long i;
 
    for (i = 0 ; i < PRF_C_lMaxNbFunction ; i ++)
        if (PRF_g_a_stFunctionInformation [i] . szFunctionName != 0)
            PRF_fn_vResetChrono (i);
 
    for (i = 0 ; i < PRF_C_lMaxNbVariable ; i ++)
        if (PRF_g_a_stVariableInformation [i] . szVariableName != 0)
            PRF_fn_vResetVariable (i);
 
	bReinitDone = FALSE;
}
 
/*-----------------------------------------------------------------------------*/
/* PRF_fn_ulTimerCount2Duration*/
/* get PRF Duration corresponding to TimerCount duration*/
/*-----------------------------------------------------------------------------*/
unsigned long PRF_fn_ulTimerCount2Duration(unsigned long ulDuration)
{
	unsigned long div;
 
	div = ulTimerFrequency * 100 / ulMonitorFrequency;
 
    return ulDuration / div;
}
 
 
/*===========================================================================================*/
/*============================= Functions to get results for functions ======================*/
/*===========================================================================================*/
 
 
/*-----------------------------------------------------------------------------*/
/* PRF_fn_ulGetFunctionDuration*/
/* returns the duration of the function for the last processed frame*/
/* scale : 1000 <==> 1 trame*/
/*-----------------------------------------------------------------------------*/
unsigned long PRF_fn_ulGetFunctionDuration(unsigned long _ulFunctionNumber)
{
	unsigned long div;
 
	div = ulTimerFrequency * 100 / ulMonitorFrequency;
 
	return PRF_g_a_stFunctionInformation[_ulFunctionNumber].stFunctionDuration.ulThisFrameValue / div;
}
 
/*-----------------------------------------------------------------------------*/
/* PRF_fn_ulGetFunctionAverageDuration*/
/* returns the average duration of the function for the N last processed frame*/
/* scale : 1000 <==> 1 trame*/
/*-----------------------------------------------------------------------------*/
unsigned long PRF_fn_ulGetFunctionAverageDuration(unsigned long _ulFunctionNumber)
{
	unsigned long div;
 
	div = ulTimerFrequency * 100 / ulMonitorFrequency;
 
	return PRF_g_a_stFunctionInformation[_ulFunctionNumber].stFunctionDuration.ulAverageValue / div;
}
 
/*-----------------------------------------------------------------------------*/
/* PRF_fn_ulGetFunctionMaxDuration*/
/* returns the max duration of the function during the N last frame*/
/* scale : 1000 <==> 1 trame*/
/*-----------------------------------------------------------------------------*/
unsigned long PRF_fn_ulGetFunctionMaxDuration(unsigned long _ulFunctionNumber)
{
	unsigned long div;
 
	div = ulTimerFrequency * 100 / ulMonitorFrequency;
 
	return PRF_g_a_stFunctionInformation[_ulFunctionNumber].stFunctionDuration.ulMaxValue / div;
}
 
/*-----------------------------------------------------------------------------*/
/* PRF_fn_ulGetFunctionMinDuration*/
/* returns the min duration of the function during the N last frame*/
/* scale : 1000 <==> 1 trame*/
/*-----------------------------------------------------------------------------*/
 
#ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */
unsigned long PRF_fn_ulGetFunctionMinDuration(unsigned long _ulFunctionNumber)
{
	unsigned long div;
 
	div = ulTimerFrequency * 100 / ulMonitorFrequency;
 
	return PRF_g_a_stFunctionInformation[_ulFunctionNumber].stFunctionDuration.ulMinValue / div;
}
 
/*-----------------------------------------------------------------------------*/
/* PRF_fn_p_cGetFunctionName*/
/* returns the function name*/
/*-----------------------------------------------------------------------------*/
char *PRF_fn_p_cGetFunctionName(unsigned long _ulFunctionNumber)
{
	return (PRF_g_a_stFunctionInformation[_ulFunctionNumber].szFunctionName);
}
#endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */
 
 
 
/*-----------------------------------------------------------------------------*/
/* PRF_fn_ulGetFunctionDurationWithData*/
/* returns the function duration for the given user data*/
/* scale : 1000 <==> 1 trame*/
/*-----------------------------------------------------------------------------*/
unsigned long PRF_fn_ulGetFunctionDurationWithData(unsigned long _ulFunctionNumber, void *_p_vUserData)
{
	int iIndex;
	void *dummy;
 
    PRF_tdstFunctionInformation * p = & PRF_g_a_stFunctionInformation [_ulFunctionNumber];
 
	/* first, find the summary for this user data*/
    iIndex = fn_iGetIndex(_p_vUserData,p->p_stUserDataSummary,p->ulUserDataSize,p->iNbUserData);
    if ( (iIndex == p->iNbUserData) || (iIndex == PRF_C_IndexError) )
	{
		/* a new entry has been added, so the userdata does not exist...*/
		return 0;
	}
	/* and return the result...*/
	return PRF_fn_ulGetFunctionDurationWithIndex(_ulFunctionNumber,&dummy,iIndex);
}
 
/*-----------------------------------------------------------------------------*/
/* PRF_fn_iGetNumberOfUserDataForFunction*/
/* returns the number of user data found for this trame*/
/*-----------------------------------------------------------------------------*/
int PRF_fn_iGetNumberOfUserDataForFunction(unsigned long _ulFunctionNumber)
{
	return PRF_g_a_stFunctionInformation [_ulFunctionNumber].iNbUserData;
}
 
 
/*-----------------------------------------------------------------------------*/
/* PRF_fn_ulGetFunctionDurationWithIndex*/
/* returns the function duration & user data for the given index*/
/* scale : 1000 <==> 1 trame*/
/*-----------------------------------------------------------------------------*/
unsigned long PRF_fn_ulGetFunctionDurationWithIndex(unsigned long _ulFunctionNumber, void **_p_p_vUserData, int _iIndex)
{
	unsigned long div;
	PRF_tdstFunctionInformation * p = & PRF_g_a_stFunctionInformation [_ulFunctionNumber];
 
	if (p->iNbUserData <= _iIndex)
		return 0;
 
    *_p_p_vUserData = p->p_stUserDataSummary[_iIndex].p_vUserData;
 
	div = ulTimerFrequency * 100 / ulMonitorFrequency;
    return p->p_stUserDataSummary[_iIndex].ulValueForThisFrame / div;
}
 
/*-----------------------------------------------------------------------------*/
/* PRF_fn_iGetFunctionNumberOfStart*/
/* get the current number of start less number of stop*/
/*-----------------------------------------------------------------------------*/
int PRF_fn_iGetFunctionNumberOfStart(unsigned long _ulFunctionNumber, void **_p_p_vUserData)
{
	PRF_tdstFunctionInformation * p = & PRF_g_a_stFunctionInformation [_ulFunctionNumber];
 
	/*YLT BLINDAGE, CAUSE BUG NON TROUVE (car valeurs p->ulHistoryIndex immenses => plantages ...)*/
    if( (p->ulHistoryIndex>0) && (p->ulHistoryIndex<p->ulHistorySize) )
        *_p_p_vUserData = p->p_stFrameHistory[p->ulHistoryIndex-1].p_vUserData;
	else
		 *_p_p_vUserData = 0;
 
    return p -> iRunning;
}
 
/*-----------------------------------------------------------------------------*/
/* PRF_fn_iGetFunctionNbStartStop*/
/* get the number of start and stop in the history*/
/*-----------------------------------------------------------------------------*/
int PRF_fn_iGetFunctionNbStartAndStop (unsigned long _ulFunctionNumber)
{
    return PRF_g_a_stFunctionInformation [_ulFunctionNumber] . ulHistoryIndex;
}
 
/*-----------------------------------------------------------------------------*/
/* PRF_fn_ulGetFunctionStartOrStop*/
/* get a start or a stop time from the history*/
/*-----------------------------------------------------------------------------*/
unsigned long PRF_fn_ulGetFunctionStartOrStop (unsigned long _ulFunctionNumber , unsigned long _ulStartStopNumber ,
                                               void * * _p_p_vData , BOOL * _p_bThisIsAStart)
{
	unsigned long                 div     = ulTimerFrequency * 100 / ulMonitorFrequency;
    PRF_tdstFunctionInformation * p       = & PRF_g_a_stFunctionInformation [_ulFunctionNumber];
    unsigned long                 ulValue = p -> p_stFrameHistory [_ulStartStopNumber] . ulValue;
 
    * _p_p_vData       = p -> p_stFrameHistory [_ulStartStopNumber] . p_vUserData;
    * _p_bThisIsAStart = (ulValue & 1) == 0;
    return ulValue / div;
}
 
 
 
/*===========================================================================================*/
/*============================= Functions to get results for independant variables ==========*/
/*===========================================================================================*/
 
/*-----------------------------------------------------------------------------*/
/* PRF_fn_vSetIndependantVariableName*/
/* Sets the name of the independant Variable Number i*/
/*-----------------------------------------------------------------------------*/
void PRF_fn_vSetIndependantVariableName(unsigned long i, char *_szName)
{
	assert ((i >= 0) && (i < PRF_C_lMaxNbIndependantVariable));
	assert (strlen (_szName) < 40);
	a_szIndependantVariableName[i] = _szName;
}
 
/*-----------------------------------------------------------------------------*/
/* PRF_fn_lGetIndependantVariable*/
/* returns the Value of the independant Variable Number i*/
/*-----------------------------------------------------------------------------*/
long PRF_fn_lGetIndependantVariable(unsigned long i)
{
	assert(i >= 0 && i < PRF_C_lMaxNbIndependantVariable);
	return a_lIndependantVariable[i];
}
 
/*-----------------------------------------------------------------------------*/
/* PRF_fn_vSetIndependantVariable*/
/* Sets the Value of the independant Variable Number i*/
/*-----------------------------------------------------------------------------*/
void PRF_fn_vSetIndependantVariable(unsigned long i, long lValue)
{
	assert(i >= 0 && i < PRF_C_lMaxNbIndependantVariable);
	a_lIndependantVariable[i] = lValue;
}
 
/*-----------------------------------------------------------------------------*/
/* PRF_fn_lIncIndependantVariable*/
/* add the value to the independant Variable Number i*/
/*-----------------------------------------------------------------------------*/
long PRF_fn_lIncIndependantVariable(unsigned long i, long lValue)
{
	assert(i >= 0 && i < PRF_C_lMaxNbIndependantVariable);
	a_lIndependantVariable[i] += lValue;
	return a_lIndependantVariable[i];
}
 
/*-----------------------------------------------------------------------------*/
/* PRF_fn_szGetIndependantVariableName*/
/* returns the name of independant Variable Number i*/
/*-----------------------------------------------------------------------------*/
char *PRF_fn_szGetIndependantVariableName(unsigned long i)
{
	assert(i >= 0 && i < PRF_C_lMaxNbIndependantVariable);
	return a_szIndependantVariableName[i];
}
 
/*=================================================================================================*/
/*============================= Functions to get results for float independant variables ==========*/
/*=================================================================================================*/
 
/*-----------------------------------------------------------------------------*/
/* PRF_fn_vSetFloatIndependantVariableName*/
/* Sets the name of the float independant Variable Number i*/
/*-----------------------------------------------------------------------------*/
 
#ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */
void PRF_fn_vSetFloatIndependantVariableName(unsigned long i, char *_szName)
{
	assert ((i >= 0) && (i < PRF_C_lMaxNbFloatIndependantVariable));
	assert (strlen (_szName) < 40);
	a_szFloatIndependantVariableName[i] = _szName;
}
#endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */
 
 
/*-----------------------------------------------------------------------------*/
/* PRF_fn_fGetFloatIndependantVariable*/
/* returns the Value of the float independant Variable Number i*/
/*-----------------------------------------------------------------------------*/
float PRF_fn_fGetFloatIndependantVariable(unsigned long i)
{
	assert(i >= 0 && i < PRF_C_lMaxNbFloatIndependantVariable);
	return a_fFloatIndependantVariable[i];
}
 
/*-----------------------------------------------------------------------------*/
/* PRF_fn_vSetFloatIndependantVariable*/
/* Sets the Value of the float independant Variable Number i*/
/*-----------------------------------------------------------------------------*/
 
#ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */
void PRF_fn_vSetFloatIndependantVariable(unsigned long i, float fValue)
{
	assert(i >= 0 && i < PRF_C_lMaxNbFloatIndependantVariable);
	a_fFloatIndependantVariable[i] = fValue;
}
 
/*-----------------------------------------------------------------------------*/
/* PRF_fn_fIncFloatIndependantVariable*/
/* add the value to the float independant Variable Number i*/
/*-----------------------------------------------------------------------------*/
float PRF_fn_fIncFloatIndependantVariable(unsigned long i, float fValue)
{
	assert(i >= 0 && i < PRF_C_lMaxNbFloatIndependantVariable);
	a_fFloatIndependantVariable[i] += fValue;
	return a_fFloatIndependantVariable[i];
}
#endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */
 
 
/*-----------------------------------------------------------------------------*/
/* PRF_fn_szGetFloatIndependantVariableName*/
/* returns the name of float independant Variable Number i*/
/*-----------------------------------------------------------------------------*/
char *PRF_fn_szGetFloatIndependantVariableName(unsigned long i)
{
	assert(i >= 0 && i < PRF_C_lMaxNbFloatIndependantVariable);
	return a_szFloatIndependantVariableName[i];
}
 
/*===========================================================================================*/
/*============================= Functions to get results for variables ======================*/
/*===========================================================================================*/
 
 
/*-----------------------------------------------------------------------------*/
/* PRF_fn_ulGetVariableValue*/
/* returns the Value of the Variable for the last processed frame*/
/*-----------------------------------------------------------------------------*/
unsigned long PRF_fn_ulGetVariableValue(unsigned long _ulVariableNumber)
{
	return PRF_g_a_stVariableInformation[_ulVariableNumber].stVariableValue.ulThisFrameValue;
}
 
/*-----------------------------------------------------------------------------*/
/* PRF_fn_ulGetVariableAverageValue*/
/* returns the average Value of the Variable for the N last processed frame*/
/*-----------------------------------------------------------------------------*/
 
#ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */
unsigned long PRF_fn_ulGetVariableAverageValue(unsigned long _ulVariableNumber)
{
	return PRF_g_a_stVariableInformation[_ulVariableNumber].stVariableValue.ulAverageValue;
}
 
/*-----------------------------------------------------------------------------*/
/* PRF_fn_ulGetVariableMaxValue*/
/* returns the max Value of the Variable during the N last frame*/
/*-----------------------------------------------------------------------------*/
unsigned long PRF_fn_ulGetVariableMaxValue(unsigned long _ulVariableNumber)
{
	return PRF_g_a_stVariableInformation[_ulVariableNumber].stVariableValue.ulMaxValue;
}
 
/*-----------------------------------------------------------------------------*/
/* PRF_fn_ulGetVariableMinValue*/
/* returns the min Value of the Variable during the N last frame*/
/*-----------------------------------------------------------------------------*/
unsigned long PRF_fn_ulGetVariableMinValue(unsigned long _ulVariableNumber)
{
	return PRF_g_a_stVariableInformation[_ulVariableNumber].stVariableValue.ulMinValue;
}
 
/*-----------------------------------------------------------------------------*/
/* PRF_fn_p_cGetVariableName*/
/* returns the Variable name*/
/*-----------------------------------------------------------------------------*/
char *PRF_fn_p_cGetVariableName(unsigned long _ulVariableNumber)
{
	return (PRF_g_a_stVariableInformation[_ulVariableNumber].szVariableName);
}
#endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */
 
 
 
/*-----------------------------------------------------------------------------*/
/* PRF_fn_ulGetVariableValueWithData*/
/* returns the Variable Value for the given user data*/
/*-----------------------------------------------------------------------------*/
unsigned long PRF_fn_ulGetVariableValueWithData(unsigned long _ulVariableNumber, void *_p_vUserData)
{
	int iIndex;
	void *dummy;
 
    PRF_tdstVariableInformation * p = & PRF_g_a_stVariableInformation [_ulVariableNumber];
 
	/* first, find the summary for this user data*/
    iIndex = fn_iGetIndex(_p_vUserData,p->p_stUserDataSummary,p->ulUserDataSize,p->iNbUserData);
    if ( (iIndex == p->iNbUserData) || (iIndex == PRF_C_IndexError) )
	{
		/* a new entry has been added, so the userdata does not exist...*/
		return 0;
	}
	/* and return the result...*/
	return PRF_fn_ulGetVariableValueWithIndex(_ulVariableNumber,&dummy,iIndex);
}
 
/*-----------------------------------------------------------------------------*/
/* PRF_fn_iGetNumberOfUserDataForVariable*/
/* returns the number of user data found for this trame*/
/*-----------------------------------------------------------------------------*/
int PRF_fn_iGetNumberOfUserDataForVariable(unsigned long _ulVariableNumber)
{
	return PRF_g_a_stVariableInformation [_ulVariableNumber].iNbUserData;
}
 
 
/*-----------------------------------------------------------------------------*/
/* PRF_fn_ulGetVariableValueWithIndex*/
/* returns the Variable Value & user data for the given index*/
/*-----------------------------------------------------------------------------*/
unsigned long PRF_fn_ulGetVariableValueWithIndex(unsigned long _ulVariableNumber, void **_p_p_vUserData, int _iIndex)
{
	PRF_tdstVariableInformation * p = & PRF_g_a_stVariableInformation [_ulVariableNumber];
 
	if (p->iNbUserData <= _iIndex)
		return 0;
 
    *_p_p_vUserData = p->p_stUserDataSummary[_iIndex].p_vUserData;
 
    return p->p_stUserDataSummary[_iIndex].ulValueForThisFrame;
}
 
 
#ifndef _FIRE_DEADCODE_U64_ /* Added by RUC */
unsigned long PRF_fn_ulGetCPUFrequency(void)
{
	return (PRF_g_bModuleInitialized ? ulTimerFrequency : 0);
}
#endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC */
 
 
#endif  /* USE_PROFILER && PRESS_DEMO */
