const uint32 ticksPerSecond = 1000; class cTimer { private: bool isClassInit; uint32 framesPerSecond; float32 hzPerSecondTicks; uint64 hzPerSecondRdtsc; static uint64 rdtscPerMillesecond; static uint64 rdtscPerSecond; static bool usePerformanceCounter; uint64 startTimeKeyRdtsc; ulong32 startTimeKeyTicks; uint64 startTimeKeyRdtscFPS; ulong32 startTimeKeyTicksFPS; uint64 startTimeKeyFPS; float32 frameCount; float32 timeElapsed; uint64 timeKeyRdtsc; ulong32 timeKeyTicks; uint64 timeDifferenceRdtsc; float32 timeDifferenceTicks; uint64 timeRdtsc; ulong32 timeTicks; public: cTimer( ) { isClassInit = false; } ~cTimer( ) { } void TimerInit( uint32 ); const float32& TimerFPS( ); bool TimerAlarm( ); void TimerElapsedTime( ulong32* , uint64* = NULL ); }; _INLINE bool cTimer::TimerAlarm( ) { if( !isClassInit ) { //ASSERTPRINT( isClassInit != false ); return false; } if( framesPerSecond ) { if( usePerformanceCounter ) { TimerElapsedTime( NULL, &timeKeyRdtsc ); timeDifferenceRdtsc = timeKeyRdtsc - startTimeKeyRdtsc; if( timeDifferenceRdtsc >= hzPerSecondRdtsc ) { startTimeKeyRdtsc = timeKeyRdtsc; return true; } else return false; } else { TimerElapsedTime( &timeKeyTicks ); if( timeKeyTicks < startTimeKeyTicks ) startTimeKeyTicks = 0; timeDifferenceTicks = (float32)(timeKeyTicks - startTimeKeyTicks); if( timeDifferenceTicks >= hzPerSecondTicks ) { startTimeKeyTicks = timeKeyTicks; return true; } else return false; } } else return true; } _INLINE const float32& cTimer::TimerFPS( ) { if( !isClassInit ) { //ASSERTPRINT( isClassInit != false ); return frameCount; } if( usePerformanceCounter ) { TimerElapsedTime( NULL, &timeKeyRdtsc ); timeDifferenceRdtsc = timeKeyRdtsc - startTimeKeyRdtscFPS; if( timeDifferenceRdtsc == 0 ) { //ASSERTPRINT( timeDifferenceRdtsc == 0 ); timeDifferenceRdtsc = 1; } frameCount = (float32)( rdtscPerSecond / timeDifferenceRdtsc ); startTimeKeyRdtscFPS = timeKeyRdtsc; } else { TimerElapsedTime( &timeKeyTicks ); if( timeKeyTicks < startTimeKeyTicksFPS ) startTimeKeyTicksFPS = 0; timeDifferenceTicks = (float32)( timeKeyTicks - startTimeKeyTicksFPS ); if( timeDifferenceTicks < FLOAT32_EPSILON ) { //ASSERTPRINT( timeDifferenceTicks >= FLOAT32_EPSILON ); timeDifferenceTicks = FLOAT32_EPSILON; } frameCount = (float32)ticksPerSecond / timeDifferenceTicks; startTimeKeyTicksFPS = timeKeyTicks; } return frameCount; } _INLINE void cTimer::TimerElapsedTime( ulong32* timeTicks, uint64* timeRdtsc ) { if( !isClassInit ) { //ASSERTPRINT( isClassInit != false ); return; } if( timeRdtsc && usePerformanceCounter ) { ulong32 dwLow, dwHigh; __asm { rdtsc mov dwLow, eax mov dwHigh, edx } *timeRdtsc = ( (uint64)dwHigh << 32 ) | (uint64)dwLow; } if( timeTicks ) { timeBeginPeriod( 1 ); *timeTicks = timeGetTime( ); timeEndPeriod( 1 ); } } uint64 cTimer::rdtscPerMillesecond = 0; uint64 cTimer::rdtscPerSecond = 0; bool cTimer::usePerformanceCounter = false; void cTimer::TimerInit( uint32 fps ) { if( isClassInit ) { //ASSERTPRINT( isClassInit != true ); return; } isClassInit = true; static bool isInit = false; if( !isInit ) { __try { ulong32 dwLow1, dwHigh1; ulong32 dwLow2, dwHigh2; uint64 time; uint64 time2; __asm { rdtsc mov dwLow1, eax mov dwHigh1, edx } Sleep( 50 ); __asm { rdtsc mov dwLow2, eax mov dwHigh2, edx } time = ( (unsigned __int64)dwHigh1 << 32 ) | (unsigned __int64)dwLow1; time2 = ( (unsigned __int64)dwHigh2 << 32 ) | (unsigned __int64)dwLow2; time2 -= time; rdtscPerSecond = time2; __asm { rdtsc mov dwLow1, eax mov dwHigh1, edx } Sleep( 50 ); __asm { rdtsc mov dwLow2, eax mov dwHigh2, edx } time = ( (unsigned __int64)dwHigh1 << 32 ) | (unsigned __int64)dwLow1; time2 = ( (unsigned __int64)dwHigh2 << 32 ) | (unsigned __int64)dwLow2; time2 -= time; rdtscPerSecond += time2; rdtscPerSecond *= 10; rdtscPerMillesecond = rdtscPerSecond / (uint64)ticksPerSecond; usePerformanceCounter = true; DebugMsg( "Accurate rdtsc Timer Activated" ); LogEntry( "Accurate rdtsc Timer Activated\n\n"); } __except( EXCEPTION_EXECUTE_HANDLER ) { usePerformanceCounter = false; DebugMsg( "TimeGetTime Timer Activated" ); LogEntry( "TimeGetTime Timer Activated\n\n"); } isInit = true; } framesPerSecond = fps; if( framesPerSecond ) { hzPerSecondTicks = (float32)ticksPerSecond/(float32)framesPerSecond; if( usePerformanceCounter ) hzPerSecondRdtsc = rdtscPerSecond / framesPerSecond; } TimerElapsedTime( &startTimeKeyTicks, &startTimeKeyRdtsc ); startTimeKeyTicksFPS = startTimeKeyTicks; startTimeKeyRdtscFPS = startTimeKeyRdtsc; }