2019-05-30 00:47:33 +02:00
|
|
|
#include <Windows.h>
|
2019-05-15 16:52:37 +02:00
|
|
|
#include "common.h"
|
|
|
|
#include "patcher.h"
|
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"
|
|
|
|
|
|
|
|
uint32 &CTimer::m_snTimeInMilliseconds = *(uint32*)0x885B48;
|
|
|
|
uint32 &CTimer::m_snTimeInMillisecondsPauseMode = *(uint32*)0x5F7614;
|
|
|
|
uint32 &CTimer::m_snTimeInMillisecondsNonClipped = *(uint32*)0x9412E8;
|
|
|
|
uint32 &CTimer::m_snPreviousTimeInMilliseconds = *(uint32*)0x8F29E4;
|
|
|
|
uint32 &CTimer::m_FrameCounter = *(uint32*)0x9412EC;
|
|
|
|
float &CTimer::ms_fTimeScale = *(float*)0x8F2C20;
|
|
|
|
float &CTimer::ms_fTimeStep = *(float*)0x8E2CB4;
|
|
|
|
float &CTimer::ms_fTimeStepNonClipped = *(float*)0x8E2C4C;
|
|
|
|
bool &CTimer::m_UserPause = *(bool*)0x95CD7C;
|
|
|
|
bool &CTimer::m_CodePause = *(bool*)0x95CDB1;
|
2019-05-29 20:02:58 +02:00
|
|
|
|
2019-06-02 05:00:38 +02:00
|
|
|
//UInt32 oldPcTimer;
|
2019-06-17 00:16:38 +02:00
|
|
|
uint32 &oldPcTimer = *(uint32*)0x9434F4;
|
2019-05-29 20:02:58 +02:00
|
|
|
|
2019-06-02 05:00:38 +02:00
|
|
|
//UInt32 suspendPcTimer;
|
2019-06-17 00:16:38 +02:00
|
|
|
uint32 &suspendPcTimer = *(uint32*)0x62A308;
|
2019-05-29 20:02:58 +02:00
|
|
|
|
2019-06-02 05:00:38 +02:00
|
|
|
//UInt32 _nCyclesPerMS = 1;
|
2019-06-17 00:16:38 +02:00
|
|
|
uint32 &_nCyclesPerMS = *(uint32*)0x5F7610;
|
2019-05-29 20:02:58 +02:00
|
|
|
|
2019-06-02 05:00:38 +02:00
|
|
|
//LARGE_INTEGER _oldPerfCounter;
|
|
|
|
LARGE_INTEGER &_oldPerfCounter = *(LARGE_INTEGER*)0x62A310;
|
|
|
|
|
|
|
|
//LARGE_INTEGER perfSuspendCounter;
|
|
|
|
LARGE_INTEGER &perfSuspendCounter = *(LARGE_INTEGER*)0x62A318;
|
|
|
|
|
|
|
|
//UInt32 suspendDepth;
|
2019-06-17 00:16:38 +02:00
|
|
|
uint32 &suspendDepth = *(uint32*)0x62A320;
|
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;
|
|
|
|
|
|
|
|
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
|
|
|
|
{
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
2019-05-31 11:44:43 +02:00
|
|
|
#if 1
|
|
|
|
WRAPPER void CTimer::Update(void) { EAXJMP(0x4ACF70); }
|
|
|
|
#else
|
2019-05-29 20:02:58 +02:00
|
|
|
void CTimer::Update(void)
|
|
|
|
{
|
|
|
|
m_snPreviousTimeInMilliseconds = m_snTimeInMilliseconds;
|
|
|
|
|
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);
|
|
|
|
|
2019-06-17 00:16:38 +02:00
|
|
|
int32 updInCycles = (pc.LowPart - _oldPerfCounter.LowPart) & 0x7FFFFFFF;
|
2019-05-29 20:02:58 +02:00
|
|
|
|
|
|
|
_oldPerfCounter = pc;
|
|
|
|
|
2019-06-17 00:16:38 +02:00
|
|
|
double updInCyclesScaled = (double)updInCycles * ms_fTimeScale;
|
2019-05-29 20:02:58 +02:00
|
|
|
|
2019-06-17 00:16:38 +02:00
|
|
|
double upd = updInCyclesScaled / (double)_nCyclesPerMS;
|
2019-05-29 20:02:58 +02:00
|
|
|
|
2019-05-31 19:02:26 +02:00
|
|
|
m_snTimeInMillisecondsPauseMode = (Int64)(m_snTimeInMillisecondsPauseMode + upd);
|
2019-05-29 20:02:58 +02:00
|
|
|
|
|
|
|
if ( GetIsPaused() )
|
|
|
|
ms_fTimeStep = 0.0f;
|
|
|
|
else
|
|
|
|
{
|
2019-05-31 19:02:26 +02:00
|
|
|
m_snTimeInMilliseconds = (Int64)(m_snTimeInMilliseconds + upd);
|
|
|
|
m_snTimeInMillisecondsNonClipped = (Int64)(m_snTimeInMillisecondsNonClipped + upd);
|
2019-06-17 00:16:38 +02:00
|
|
|
ms_fTimeStep = updInCyclesScaled / (double)_nCyclesPerMS / 20.0;
|
2019-05-29 20:02:58 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-06-17 00:16:38 +02:00
|
|
|
uint32 timer = RsTimer();
|
2019-05-29 20:02:58 +02:00
|
|
|
|
2019-06-17 00:16:38 +02:00
|
|
|
uint32 updInMs = timer - oldPcTimer;
|
2019-05-29 20:02:58 +02:00
|
|
|
|
2019-06-17 00:16:38 +02:00
|
|
|
double upd = (double)updInMs * ms_fTimeScale;
|
2019-05-29 20:02:58 +02:00
|
|
|
|
|
|
|
oldPcTimer = timer;
|
|
|
|
|
2019-05-31 19:02:26 +02:00
|
|
|
m_snTimeInMillisecondsPauseMode = (Int64)(m_snTimeInMillisecondsPauseMode + upd);
|
2019-05-29 20:02:58 +02:00
|
|
|
|
|
|
|
if ( GetIsPaused() )
|
|
|
|
ms_fTimeStep = 0.0f;
|
|
|
|
else
|
|
|
|
{
|
2019-05-31 19:02:26 +02:00
|
|
|
m_snTimeInMilliseconds = (Int64)(m_snTimeInMilliseconds + upd);
|
|
|
|
m_snTimeInMillisecondsNonClipped = (Int64)(m_snTimeInMillisecondsNonClipped + upd);
|
2019-05-29 20:02:58 +02:00
|
|
|
ms_fTimeStep = upd / 1000.0f * 50.0f;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( ms_fTimeStep < 0.01f && !GetIsPaused() )
|
|
|
|
ms_fTimeStep = 0.01f;
|
|
|
|
|
|
|
|
ms_fTimeStepNonClipped = ms_fTimeStep;
|
|
|
|
|
|
|
|
if ( CRecordDataForGame::RecordingState != _TODOCONST(2) )
|
|
|
|
{
|
|
|
|
ms_fTimeStep = min(3.0f, ms_fTimeStep);
|
|
|
|
|
|
|
|
if ( (m_snTimeInMilliseconds - m_snPreviousTimeInMilliseconds) > 60 )
|
|
|
|
m_snTimeInMilliseconds = m_snPreviousTimeInMilliseconds + 60;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( CRecordDataForChase::Status == _TODOCONST(1) )
|
|
|
|
{
|
|
|
|
ms_fTimeStep = 1.0f;
|
|
|
|
m_snTimeInMilliseconds = m_snPreviousTimeInMilliseconds + 16;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_FrameCounter++;
|
|
|
|
}
|
2019-05-31 11:44:43 +02:00
|
|
|
#endif
|
2019-05-29 20:02:58 +02:00
|
|
|
|
|
|
|
void CTimer::Suspend(void)
|
|
|
|
{
|
|
|
|
if ( ++suspendDepth > 1 )
|
|
|
|
return;
|
|
|
|
|
2019-06-17 00:16:38 +02:00
|
|
|
if ( (double)_nCyclesPerMS != 0.0 )
|
2019-05-29 20:02:58 +02:00
|
|
|
QueryPerformanceCounter(&perfSuspendCounter);
|
|
|
|
else
|
|
|
|
suspendPcTimer = RsTimer();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CTimer::Resume(void)
|
|
|
|
{
|
|
|
|
if ( --suspendDepth != 0 )
|
|
|
|
return;
|
|
|
|
|
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
|
|
|
|
oldPcTimer += RsTimer() - suspendPcTimer;
|
|
|
|
}
|
|
|
|
|
2019-06-17 00:16:38 +02:00
|
|
|
uint32 CTimer::GetCyclesPerMillisecond(void)
|
2019-05-29 20:02:58 +02:00
|
|
|
{
|
|
|
|
if (_nCyclesPerMS != 0)
|
|
|
|
return _nCyclesPerMS;
|
|
|
|
else
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2019-06-17 00:16:38 +02:00
|
|
|
uint32 CTimer::GetCurrentTimeInCycles(void)
|
2019-05-29 20:02:58 +02:00
|
|
|
{
|
|
|
|
if ( _nCyclesPerMS != 0 )
|
|
|
|
{
|
|
|
|
LARGE_INTEGER pc;
|
|
|
|
QueryPerformanceCounter(&pc);
|
|
|
|
return (pc.LowPart - _oldPerfCounter.LowPart) & 0x7FFFFFFF;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
STARTPATCHES
|
|
|
|
InjectHook(0x4ACE60, CTimer::Initialise, PATCH_JUMP);
|
|
|
|
InjectHook(0x4ACF60, CTimer::Shutdown, PATCH_JUMP);
|
|
|
|
InjectHook(0x4ACF70, CTimer::Update, PATCH_JUMP);
|
|
|
|
InjectHook(0x4AD310, CTimer::Suspend, PATCH_JUMP);
|
|
|
|
InjectHook(0x4AD370, CTimer::Resume, PATCH_JUMP);
|
|
|
|
InjectHook(0x4AD3F0, CTimer::GetCyclesPerMillisecond, PATCH_JUMP);
|
|
|
|
InjectHook(0x4AD410, CTimer::GetCurrentTimeInCycles, PATCH_JUMP);
|
|
|
|
InjectHook(0x4AD450, CTimer::GetIsSlowMotionActive, PATCH_JUMP);
|
|
|
|
InjectHook(0x4AD480, CTimer::Stop, PATCH_JUMP);
|
|
|
|
InjectHook(0x4AD490, CTimer::StartUserPause, PATCH_JUMP);
|
|
|
|
InjectHook(0x4AD4A0, CTimer::EndUserPause, PATCH_JUMP);
|
|
|
|
ENDPATCHES
|
|
|
|
#endif
|