2020-04-21 12:28:06 +02:00
|
|
|
#define WITHWINDOWS
|
2019-05-15 16:52:37 +02:00
|
|
|
#include "common.h"
|
2020-05-11 04:55:57 +02:00
|
|
|
#include "crossplatform.h"
|
2020-04-17 15:31:11 +02:00
|
|
|
|
2019-05-29 20:02:58 +02:00
|
|
|
#include "DMAudio.h"
|
2019-05-30 00:47:33 +02:00
|
|
|
#include "Record.h"
|
2019-05-15 16:52:37 +02:00
|
|
|
#include "Timer.h"
|
|
|
|
|
2020-04-17 07:54:14 +02:00
|
|
|
uint32 CTimer::m_snTimeInMilliseconds;
|
|
|
|
uint32 CTimer::m_snTimeInMillisecondsPauseMode = 1;
|
|
|
|
uint32 CTimer::m_snTimeInMillisecondsNonClipped;
|
|
|
|
uint32 CTimer::m_snPreviousTimeInMilliseconds;
|
|
|
|
uint32 CTimer::m_FrameCounter;
|
|
|
|
float CTimer::ms_fTimeScale;
|
|
|
|
float CTimer::ms_fTimeStep;
|
|
|
|
float CTimer::ms_fTimeStepNonClipped;
|
|
|
|
bool CTimer::m_UserPause;
|
|
|
|
bool CTimer::m_CodePause;
|
2021-05-28 18:03:16 +02:00
|
|
|
#ifdef FIX_BUGS
|
|
|
|
uint32 CTimer::m_LogicalFrameCounter;
|
2021-05-29 10:57:51 +02:00
|
|
|
uint32 CTimer::m_LogicalFramesPassed;
|
2021-05-28 18:03:16 +02:00
|
|
|
#endif
|
2020-04-17 07:54:14 +02:00
|
|
|
|
|
|
|
uint32 _nCyclesPerMS = 1;
|
|
|
|
|
2020-05-11 04:55:57 +02:00
|
|
|
#ifdef _WIN32
|
2020-04-17 07:54:14 +02:00
|
|
|
LARGE_INTEGER _oldPerfCounter;
|
|
|
|
LARGE_INTEGER perfSuspendCounter;
|
2020-05-11 04:55:57 +02:00
|
|
|
#define RsTimerType uint32
|
|
|
|
#else
|
|
|
|
#define RsTimerType double
|
|
|
|
#endif
|
|
|
|
|
|
|
|
RsTimerType oldPcTimer;
|
|
|
|
|
|
|
|
RsTimerType suspendPcTimer;
|
2020-04-17 07:54:14 +02:00
|
|
|
|
|
|
|
uint32 suspendDepth;
|
2019-05-29 20:02:58 +02:00
|
|
|
|
|
|
|
void CTimer::Initialise(void)
|
|
|
|
{
|
|
|
|
debug("Initialising CTimer...\n");
|
|
|
|
|
|
|
|
ms_fTimeScale = 1.0f;
|
|
|
|
ms_fTimeStep = 1.0f;
|
|
|
|
suspendDepth = 0;
|
|
|
|
m_UserPause = false;
|
|
|
|
m_CodePause = false;
|
|
|
|
m_snTimeInMillisecondsNonClipped = 0;
|
|
|
|
m_snPreviousTimeInMilliseconds = 0;
|
|
|
|
m_snTimeInMilliseconds = 1;
|
2021-05-28 18:03:16 +02:00
|
|
|
#ifdef FIX_BUGS
|
|
|
|
m_LogicalFrameCounter = 0;
|
2021-05-29 10:57:51 +02:00
|
|
|
m_LogicalFramesPassed = 0;
|
2021-05-28 18:03:16 +02:00
|
|
|
#endif
|
2019-05-29 20:02:58 +02:00
|
|
|
|
2020-05-11 04:55:57 +02:00
|
|
|
#ifdef _WIN32
|
2019-05-29 20:02:58 +02:00
|
|
|
LARGE_INTEGER perfFreq;
|
|
|
|
if ( QueryPerformanceFrequency(&perfFreq) )
|
|
|
|
{
|
|
|
|
OutputDebugString("Performance counter available\n");
|
2019-06-17 00:16:38 +02:00
|
|
|
_nCyclesPerMS = uint32(perfFreq.QuadPart / 1000);
|
2019-05-29 20:02:58 +02:00
|
|
|
QueryPerformanceCounter(&_oldPerfCounter);
|
|
|
|
}
|
|
|
|
else
|
2020-05-11 04:55:57 +02:00
|
|
|
#endif
|
2019-05-29 20:02:58 +02:00
|
|
|
{
|
|
|
|
OutputDebugString("Performance counter not available, using millesecond timer\n");
|
|
|
|
_nCyclesPerMS = 0;
|
|
|
|
oldPcTimer = RsTimer();
|
|
|
|
}
|
|
|
|
|
|
|
|
m_snTimeInMilliseconds = m_snPreviousTimeInMilliseconds;
|
|
|
|
|
|
|
|
m_FrameCounter = 0;
|
|
|
|
|
|
|
|
DMAudio.ResetTimers(m_snPreviousTimeInMilliseconds);
|
|
|
|
|
|
|
|
debug("CTimer ready\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
void CTimer::Shutdown(void)
|
|
|
|
{
|
|
|
|
;
|
|
|
|
}
|
2021-06-25 01:33:40 +02:00
|
|
|
#ifdef FIX_BUGS
|
2019-05-29 20:02:58 +02:00
|
|
|
void CTimer::Update(void)
|
|
|
|
{
|
2021-05-29 15:50:20 +02:00
|
|
|
static double frameTimeLogical = 0.0;
|
|
|
|
static double frameTimeFraction = 0.0;
|
|
|
|
static double frameTimeFractionScaled = 0.0;
|
2021-06-25 01:33:40 +02:00
|
|
|
double frameTime;
|
|
|
|
double dblUpdInMs;
|
2021-05-29 15:50:20 +02:00
|
|
|
|
2019-05-29 20:02:58 +02:00
|
|
|
m_snPreviousTimeInMilliseconds = m_snTimeInMilliseconds;
|
|
|
|
|
2020-05-11 04:55:57 +02:00
|
|
|
#ifdef _WIN32
|
2019-06-17 00:16:38 +02:00
|
|
|
if ( (double)_nCyclesPerMS != 0.0 )
|
2019-05-29 20:02:58 +02:00
|
|
|
{
|
|
|
|
LARGE_INTEGER pc;
|
|
|
|
QueryPerformanceCounter(&pc);
|
|
|
|
|
2020-01-11 18:36:46 +01:00
|
|
|
int32 updInCycles = (pc.LowPart - _oldPerfCounter.LowPart); // & 0x7FFFFFFF; pointless
|
2019-05-29 20:02:58 +02:00
|
|
|
|
|
|
|
_oldPerfCounter = pc;
|
2021-05-29 15:50:20 +02:00
|
|
|
|
|
|
|
// bugfix from VC
|
2021-06-26 00:56:29 +02:00
|
|
|
double updInCyclesScaled = GetIsPaused() ? updInCycles : updInCycles * ms_fTimeScale;
|
2021-06-25 01:33:40 +02:00
|
|
|
|
|
|
|
frameTime = updInCyclesScaled / (double)_nCyclesPerMS;
|
|
|
|
|
|
|
|
dblUpdInMs = (double)updInCycles / (double)_nCyclesPerMS;
|
|
|
|
}
|
|
|
|
else
|
2020-04-10 17:06:49 +02:00
|
|
|
#endif
|
2021-06-25 01:33:40 +02:00
|
|
|
{
|
|
|
|
RsTimerType timer = RsTimer();
|
|
|
|
|
|
|
|
RsTimerType updInMs = timer - oldPcTimer;
|
2021-06-26 00:56:29 +02:00
|
|
|
|
|
|
|
// bugfix from VC
|
|
|
|
frameTime = GetIsPaused() ? (double)updInMs : (double)updInMs * ms_fTimeScale;
|
2021-05-29 15:50:20 +02:00
|
|
|
|
2021-06-25 01:33:40 +02:00
|
|
|
oldPcTimer = timer;
|
2019-05-29 20:02:58 +02:00
|
|
|
|
2021-06-25 01:33:40 +02:00
|
|
|
dblUpdInMs = (double)updInMs;
|
|
|
|
}
|
2021-05-28 18:03:16 +02:00
|
|
|
|
2021-06-25 01:33:40 +02:00
|
|
|
// count frames as if we're running at 30 fps
|
|
|
|
m_LogicalFramesPassed = 0;
|
|
|
|
frameTimeLogical += dblUpdInMs;
|
|
|
|
while(frameTimeLogical >= 1000.0 / 30.0) {
|
|
|
|
frameTimeLogical -= 1000.0 / 30.0;
|
|
|
|
m_LogicalFramesPassed++;
|
|
|
|
}
|
|
|
|
m_LogicalFrameCounter += m_LogicalFramesPassed;
|
|
|
|
|
|
|
|
frameTimeFraction += dblUpdInMs;
|
|
|
|
frameTimeFractionScaled += frameTime;
|
2021-05-29 13:31:37 +02:00
|
|
|
|
2021-06-25 01:33:40 +02:00
|
|
|
m_snTimeInMillisecondsPauseMode += uint32(frameTimeFraction);
|
|
|
|
|
|
|
|
if ( GetIsPaused() )
|
|
|
|
ms_fTimeStep = 0.0f;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_snTimeInMilliseconds += uint32(frameTimeFractionScaled);
|
|
|
|
m_snTimeInMillisecondsNonClipped += uint32(frameTimeFractionScaled);
|
|
|
|
ms_fTimeStep = frameTime / 1000.0f * 50.0f;
|
|
|
|
}
|
|
|
|
frameTimeFraction -= uint32(frameTimeFraction);
|
|
|
|
frameTimeFractionScaled -= uint32(frameTimeFractionScaled);
|
|
|
|
|
|
|
|
if ( ms_fTimeStep < 0.01f && !GetIsPaused() )
|
|
|
|
ms_fTimeStep = 0.01f;
|
|
|
|
|
|
|
|
ms_fTimeStepNonClipped = ms_fTimeStep;
|
|
|
|
|
|
|
|
if ( !CRecordDataForGame::IsPlayingBack() )
|
|
|
|
{
|
|
|
|
ms_fTimeStep = Min(3.0f, ms_fTimeStep);
|
|
|
|
|
|
|
|
if ( (m_snTimeInMilliseconds - m_snPreviousTimeInMilliseconds) > 60 )
|
|
|
|
m_snTimeInMilliseconds = m_snPreviousTimeInMilliseconds + 60;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( CRecordDataForChase::IsRecording() )
|
|
|
|
{
|
|
|
|
ms_fTimeStep = 1.0f;
|
|
|
|
m_snTimeInMilliseconds = m_snPreviousTimeInMilliseconds + 16;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_FrameCounter++;
|
|
|
|
}
|
2021-05-29 13:31:37 +02:00
|
|
|
#else
|
2021-06-25 01:33:40 +02:00
|
|
|
void CTimer::Update(void)
|
|
|
|
{
|
|
|
|
m_snPreviousTimeInMilliseconds = m_snTimeInMilliseconds;
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
if ( (double)_nCyclesPerMS != 0.0 )
|
|
|
|
{
|
|
|
|
LARGE_INTEGER pc;
|
|
|
|
QueryPerformanceCounter(&pc);
|
|
|
|
|
|
|
|
int32 updInCycles = (pc.LowPart - _oldPerfCounter.LowPart); // & 0x7FFFFFFF; pointless
|
|
|
|
|
|
|
|
_oldPerfCounter = pc;
|
|
|
|
|
|
|
|
float updInCyclesScaled = updInCycles * ms_fTimeScale;
|
|
|
|
|
|
|
|
double frameTime = updInCyclesScaled / (double)_nCyclesPerMS;
|
2020-04-10 17:06:49 +02:00
|
|
|
m_snTimeInMillisecondsPauseMode = m_snTimeInMillisecondsPauseMode + frameTime;
|
2019-05-29 20:02:58 +02:00
|
|
|
|
|
|
|
if ( GetIsPaused() )
|
|
|
|
ms_fTimeStep = 0.0f;
|
|
|
|
else
|
|
|
|
{
|
2020-04-10 17:06:49 +02:00
|
|
|
m_snTimeInMilliseconds = m_snTimeInMilliseconds + frameTime;
|
|
|
|
m_snTimeInMillisecondsNonClipped = m_snTimeInMillisecondsNonClipped + frameTime;
|
|
|
|
ms_fTimeStep = frameTime / 1000.0f * 50.0f;
|
2019-05-29 20:02:58 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2020-05-11 04:55:57 +02:00
|
|
|
#endif
|
2019-05-29 20:02:58 +02:00
|
|
|
{
|
2020-05-11 04:55:57 +02:00
|
|
|
RsTimerType timer = RsTimer();
|
2019-05-29 20:02:58 +02:00
|
|
|
|
2020-05-11 04:55:57 +02:00
|
|
|
RsTimerType updInMs = timer - oldPcTimer;
|
2019-05-29 20:02:58 +02:00
|
|
|
|
2021-05-29 15:50:20 +02:00
|
|
|
double frameTime = (double)updInMs * ms_fTimeScale;
|
|
|
|
|
|
|
|
oldPcTimer = timer;
|
2019-05-29 20:02:58 +02:00
|
|
|
|
2020-04-10 17:06:49 +02:00
|
|
|
m_snTimeInMillisecondsPauseMode = m_snTimeInMillisecondsPauseMode + frameTime;
|
2019-05-29 20:02:58 +02:00
|
|
|
|
|
|
|
if ( GetIsPaused() )
|
|
|
|
ms_fTimeStep = 0.0f;
|
|
|
|
else
|
|
|
|
{
|
2020-04-10 17:06:49 +02:00
|
|
|
m_snTimeInMilliseconds = m_snTimeInMilliseconds + frameTime;
|
|
|
|
m_snTimeInMillisecondsNonClipped = m_snTimeInMillisecondsNonClipped + frameTime;
|
|
|
|
ms_fTimeStep = frameTime / 1000.0f * 50.0f;
|
2019-05-29 20:02:58 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( ms_fTimeStep < 0.01f && !GetIsPaused() )
|
|
|
|
ms_fTimeStep = 0.01f;
|
|
|
|
|
|
|
|
ms_fTimeStepNonClipped = ms_fTimeStep;
|
|
|
|
|
2020-04-10 10:03:38 +02:00
|
|
|
if ( !CRecordDataForGame::IsPlayingBack() )
|
2019-05-29 20:02:58 +02:00
|
|
|
{
|
2020-04-19 18:34:08 +02:00
|
|
|
ms_fTimeStep = Min(3.0f, ms_fTimeStep);
|
2019-05-29 20:02:58 +02:00
|
|
|
|
|
|
|
if ( (m_snTimeInMilliseconds - m_snPreviousTimeInMilliseconds) > 60 )
|
|
|
|
m_snTimeInMilliseconds = m_snPreviousTimeInMilliseconds + 60;
|
|
|
|
}
|
|
|
|
|
2020-04-11 01:03:42 +02:00
|
|
|
if ( CRecordDataForChase::IsRecording() )
|
2019-05-29 20:02:58 +02:00
|
|
|
{
|
|
|
|
ms_fTimeStep = 1.0f;
|
|
|
|
m_snTimeInMilliseconds = m_snPreviousTimeInMilliseconds + 16;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_FrameCounter++;
|
|
|
|
}
|
2021-06-25 01:33:40 +02:00
|
|
|
#endif
|
2019-05-29 20:02:58 +02:00
|
|
|
|
|
|
|
void CTimer::Suspend(void)
|
|
|
|
{
|
|
|
|
if ( ++suspendDepth > 1 )
|
|
|
|
return;
|
|
|
|
|
2020-05-11 04:55:57 +02:00
|
|
|
#ifdef _WIN32
|
2019-06-17 00:16:38 +02:00
|
|
|
if ( (double)_nCyclesPerMS != 0.0 )
|
2019-05-29 20:02:58 +02:00
|
|
|
QueryPerformanceCounter(&perfSuspendCounter);
|
|
|
|
else
|
2020-05-11 04:55:57 +02:00
|
|
|
#endif
|
2019-05-29 20:02:58 +02:00
|
|
|
suspendPcTimer = RsTimer();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CTimer::Resume(void)
|
|
|
|
{
|
|
|
|
if ( --suspendDepth != 0 )
|
|
|
|
return;
|
|
|
|
|
2020-05-11 04:55:57 +02:00
|
|
|
#ifdef _WIN32
|
2019-06-17 00:16:38 +02:00
|
|
|
if ( (double)_nCyclesPerMS != 0.0 )
|
2019-05-29 20:02:58 +02:00
|
|
|
{
|
|
|
|
LARGE_INTEGER pc;
|
|
|
|
QueryPerformanceCounter(&pc);
|
|
|
|
|
|
|
|
_oldPerfCounter.LowPart += pc.LowPart - perfSuspendCounter.LowPart;
|
|
|
|
}
|
|
|
|
else
|
2020-05-11 04:55:57 +02:00
|
|
|
#endif
|
2019-05-29 20:02:58 +02:00
|
|
|
oldPcTimer += RsTimer() - suspendPcTimer;
|
|
|
|
}
|
|
|
|
|
2019-06-17 00:16:38 +02:00
|
|
|
uint32 CTimer::GetCyclesPerMillisecond(void)
|
2019-05-29 20:02:58 +02:00
|
|
|
{
|
2020-05-11 04:55:57 +02:00
|
|
|
#ifdef _WIN32
|
2019-05-29 20:02:58 +02:00
|
|
|
if (_nCyclesPerMS != 0)
|
|
|
|
return _nCyclesPerMS;
|
|
|
|
else
|
2020-05-11 04:55:57 +02:00
|
|
|
#endif
|
2019-05-29 20:02:58 +02:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2019-06-17 00:16:38 +02:00
|
|
|
uint32 CTimer::GetCurrentTimeInCycles(void)
|
2019-05-29 20:02:58 +02:00
|
|
|
{
|
2020-05-11 04:55:57 +02:00
|
|
|
#ifdef _WIN32
|
2019-05-29 20:02:58 +02:00
|
|
|
if ( _nCyclesPerMS != 0 )
|
|
|
|
{
|
|
|
|
LARGE_INTEGER pc;
|
|
|
|
QueryPerformanceCounter(&pc);
|
2020-01-11 18:36:46 +01:00
|
|
|
return (pc.LowPart - _oldPerfCounter.LowPart); // & 0x7FFFFFFF; pointless
|
2019-05-29 20:02:58 +02:00
|
|
|
}
|
|
|
|
else
|
2020-05-11 04:55:57 +02:00
|
|
|
#endif
|
2019-05-29 20:02:58 +02:00
|
|
|
return RsTimer() - oldPcTimer;
|
|
|
|
}
|
|
|
|
|
2019-06-17 00:16:38 +02:00
|
|
|
bool CTimer::GetIsSlowMotionActive(void)
|
2019-05-29 20:02:58 +02:00
|
|
|
{
|
|
|
|
return ms_fTimeScale < 1.0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CTimer::Stop(void)
|
|
|
|
{
|
|
|
|
m_snPreviousTimeInMilliseconds = m_snTimeInMilliseconds;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CTimer::StartUserPause(void)
|
|
|
|
{
|
|
|
|
m_UserPause = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CTimer::EndUserPause(void)
|
|
|
|
{
|
|
|
|
m_UserPause = false;
|
|
|
|
}
|
|
|
|
|
2020-03-31 12:30:13 +02:00
|
|
|
uint32 CTimer::GetCyclesPerFrame()
|
|
|
|
{
|
|
|
|
return 20;
|
|
|
|
}
|
|
|
|
|