re3-mirror/src/core/Timer.cpp

330 lines
7.0 KiB
C++
Raw Normal View History

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