2010-05-23 10:05:41 +00:00
|
|
|
#include "stdafx.h"
|
2008-09-18 03:15:49 +00:00
|
|
|
|
2010-05-23 10:05:41 +00:00
|
|
|
CSystemTimer::CSystemTimer( int & NextTimer ) :
|
2010-07-05 11:29:46 +00:00
|
|
|
m_NextTimer(NextTimer),
|
|
|
|
m_inFixTimer(false)
|
2010-05-23 10:05:41 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void CSystemTimer::Reset ( void )
|
|
|
|
{
|
|
|
|
//initialise Structure
|
|
|
|
for (int i = 0; i < MaxTimer; i++)
|
|
|
|
{
|
|
|
|
m_TimerDetatils[i].Active = false;
|
|
|
|
m_TimerDetatils[i].CyclesToTimer = 0;
|
|
|
|
}
|
2010-07-05 11:29:46 +00:00
|
|
|
m_Current = UnknownTimer;
|
|
|
|
m_LastUpdate = 0;
|
|
|
|
m_NextTimer = 0;
|
2010-06-12 02:02:06 +00:00
|
|
|
|
|
|
|
SetTimer(ViTimer,50000,false);
|
2010-07-05 11:29:46 +00:00
|
|
|
SetCompareTimer();
|
2010-05-23 10:05:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CSystemTimer::SetTimer ( TimerType Type, DWORD Cycles, bool bRelative )
|
|
|
|
{
|
|
|
|
if (Type >= MaxTimer || Type == UnknownTimer)
|
|
|
|
{
|
2012-11-17 00:58:31 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__,__LINE__);
|
2010-05-23 10:05:41 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
UpdateTimers();
|
|
|
|
|
|
|
|
m_TimerDetatils[Type].Active = true;
|
|
|
|
if (bRelative)
|
|
|
|
{
|
|
|
|
if (m_TimerDetatils[Type].Active)
|
|
|
|
{
|
|
|
|
m_TimerDetatils[Type].CyclesToTimer += Cycles; //Add to the timer
|
|
|
|
} else {
|
2010-07-05 11:29:46 +00:00
|
|
|
m_TimerDetatils[Type].CyclesToTimer = (__int64)Cycles - (__int64)m_NextTimer; //replace the new cycles
|
2010-05-23 10:05:41 +00:00
|
|
|
}
|
|
|
|
} else {
|
2010-07-05 11:29:46 +00:00
|
|
|
m_TimerDetatils[Type].CyclesToTimer = (__int64)Cycles - (__int64)m_NextTimer; //replace the new cycles
|
2010-05-23 10:05:41 +00:00
|
|
|
}
|
|
|
|
FixTimers();
|
|
|
|
}
|
|
|
|
|
2010-06-14 21:14:58 +00:00
|
|
|
DWORD CSystemTimer::GetTimer ( TimerType Type )
|
|
|
|
{
|
|
|
|
if (Type >= MaxTimer || Type == UnknownTimer)
|
|
|
|
{
|
2012-11-17 00:58:31 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__,__LINE__);
|
2010-06-14 21:14:58 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (!m_TimerDetatils[Type].Active)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
2010-10-23 18:53:01 +00:00
|
|
|
__int64 CyclesToTimer = m_TimerDetatils[Type].CyclesToTimer + m_NextTimer;
|
|
|
|
if (CyclesToTimer < 0)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (CyclesToTimer > 0x7FFFFFFF)
|
|
|
|
{
|
|
|
|
return 0x7FFFFFFF;
|
|
|
|
}
|
|
|
|
return (DWORD)CyclesToTimer;
|
2010-06-14 21:14:58 +00:00
|
|
|
}
|
|
|
|
|
2010-05-23 10:05:41 +00:00
|
|
|
void CSystemTimer::StopTimer ( TimerType Type )
|
|
|
|
{
|
|
|
|
if (Type >= MaxTimer || Type == UnknownTimer)
|
|
|
|
{
|
2012-11-17 00:58:31 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__,__LINE__);
|
2010-05-23 10:05:41 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
m_TimerDetatils[Type].Active = false;
|
|
|
|
FixTimers();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CSystemTimer::FixTimers (void)
|
|
|
|
{
|
2010-07-05 11:29:46 +00:00
|
|
|
|
|
|
|
if (m_inFixTimer)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
m_inFixTimer = true;
|
2010-05-23 10:05:41 +00:00
|
|
|
|
2010-07-05 11:29:46 +00:00
|
|
|
UpdateTimers();
|
|
|
|
if (GetTimer(CompareTimer) > 0x60000000)
|
|
|
|
{
|
|
|
|
SetCompareTimer();
|
|
|
|
}
|
|
|
|
|
2010-05-23 10:05:41 +00:00
|
|
|
//Update the cycles for the remaining number of cycles to timer
|
2010-07-05 11:29:46 +00:00
|
|
|
int count;
|
2010-05-23 10:05:41 +00:00
|
|
|
for (count = 0; count < MaxTimer; count++)
|
|
|
|
{
|
|
|
|
if (!m_TimerDetatils[count].Active)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
2010-07-05 11:29:46 +00:00
|
|
|
m_TimerDetatils[count].CyclesToTimer += m_NextTimer;
|
2010-05-23 10:05:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//Set Max timer
|
2010-07-05 11:29:46 +00:00
|
|
|
m_NextTimer = 0x7FFFFFFF;
|
2010-05-23 10:05:41 +00:00
|
|
|
|
|
|
|
//Find the smallest timer left to go
|
|
|
|
for (count = 0; count < MaxTimer; count++)
|
|
|
|
{
|
|
|
|
if (!m_TimerDetatils[count].Active)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
2010-07-05 11:29:46 +00:00
|
|
|
if (m_TimerDetatils[count].CyclesToTimer >= m_NextTimer)
|
2010-05-23 10:05:41 +00:00
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
2010-10-23 18:53:01 +00:00
|
|
|
m_NextTimer = (int)m_TimerDetatils[count].CyclesToTimer;
|
2010-05-23 10:05:41 +00:00
|
|
|
m_Current = (TimerType)count;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Move the timer back this value
|
|
|
|
for (count = 0; count < MaxTimer; count++)
|
|
|
|
{
|
|
|
|
if (!m_TimerDetatils[count].Active)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
2010-07-05 11:29:46 +00:00
|
|
|
m_TimerDetatils[count].CyclesToTimer -= m_NextTimer;
|
2010-05-23 10:05:41 +00:00
|
|
|
}
|
2010-07-05 11:29:46 +00:00
|
|
|
m_LastUpdate = m_NextTimer;
|
|
|
|
m_inFixTimer = false;
|
2010-05-23 10:05:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CSystemTimer::UpdateTimers ( void )
|
|
|
|
{
|
2010-07-05 11:29:46 +00:00
|
|
|
int TimeTaken = m_LastUpdate - m_NextTimer;
|
2010-05-23 10:05:41 +00:00
|
|
|
if (TimeTaken != 0)
|
|
|
|
{
|
2010-07-05 11:29:46 +00:00
|
|
|
m_LastUpdate = m_NextTimer;
|
2010-05-23 10:05:41 +00:00
|
|
|
_Reg->COUNT_REGISTER += TimeTaken;
|
2012-09-28 20:07:45 +00:00
|
|
|
_Reg->RANDOM_REGISTER -= TimeTaken / CountPerOp();
|
2010-05-23 10:05:41 +00:00
|
|
|
while ((int)_Reg->RANDOM_REGISTER < (int)_Reg->WIRED_REGISTER)
|
|
|
|
{
|
|
|
|
_Reg->RANDOM_REGISTER += 32 - _Reg->WIRED_REGISTER;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CSystemTimer::TimerDone (void)
|
|
|
|
{
|
|
|
|
UpdateTimers();
|
2008-09-18 03:15:49 +00:00
|
|
|
|
2010-05-23 10:05:41 +00:00
|
|
|
/* DWORD LastTimer;
|
|
|
|
if (Profiling) {
|
|
|
|
LastTimer = StartTimer(Timer_Done);
|
|
|
|
}
|
|
|
|
#if (!defined(EXTERNAL_RELEASE))
|
|
|
|
if (LogOptions.GenerateLog && LogOptions.LogExceptions && !LogOptions.NoInterrupts) {
|
|
|
|
LogMessage("%08X: Timer Done (Type: %d CurrentTimer: %d)", *_PROGRAM_COUNTER, m_Current, *_Timer );
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
*/
|
|
|
|
switch (m_Current) {
|
|
|
|
case CSystemTimer::CompareTimer:
|
|
|
|
_Reg->FAKE_CAUSE_REGISTER |= CAUSE_IP7;
|
2010-06-04 06:25:07 +00:00
|
|
|
_Reg->CheckInterrupts();
|
2010-05-23 10:05:41 +00:00
|
|
|
UpdateCompareTimer();
|
|
|
|
break;
|
|
|
|
case CSystemTimer::SoftResetTimer:
|
|
|
|
_SystemTimer->StopTimer(CSystemTimer::SoftResetTimer);
|
2010-06-12 02:02:06 +00:00
|
|
|
_System->ExternalEvent(SysEvent_ResetCPU_SoftDone);
|
2010-05-23 10:05:41 +00:00
|
|
|
break;
|
|
|
|
case CSystemTimer::SiTimer:
|
|
|
|
_SystemTimer->StopTimer(CSystemTimer::SiTimer);
|
|
|
|
_Reg->MI_INTR_REG |= MI_INTR_SI;
|
|
|
|
_Reg->SI_STATUS_REG |= SI_STATUS_INTERRUPT;
|
2010-06-04 06:25:07 +00:00
|
|
|
_Reg->CheckInterrupts();
|
2010-05-23 10:05:41 +00:00
|
|
|
break;
|
|
|
|
case CSystemTimer::PiTimer:
|
|
|
|
_SystemTimer->StopTimer(CSystemTimer::PiTimer);
|
|
|
|
_Reg->PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY;
|
|
|
|
_Reg->MI_INTR_REG |= MI_INTR_PI;
|
2010-06-04 06:25:07 +00:00
|
|
|
_Reg->CheckInterrupts();
|
2010-05-23 10:05:41 +00:00
|
|
|
break;
|
|
|
|
case CSystemTimer::ViTimer:
|
2010-06-07 02:23:58 +00:00
|
|
|
try
|
|
|
|
{
|
2010-06-12 02:02:06 +00:00
|
|
|
_System->RefreshScreen();
|
2010-06-07 02:23:58 +00:00
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
WriteTraceF(TraceError,"Exception caught in Refresh Screen\nFile: %s\nLine: %d",__FILE__,__LINE__);
|
|
|
|
}
|
2010-05-23 10:05:41 +00:00
|
|
|
_Reg->MI_INTR_REG |= MI_INTR_VI;
|
2010-06-04 06:25:07 +00:00
|
|
|
_Reg->CheckInterrupts();
|
2010-05-23 10:05:41 +00:00
|
|
|
break;
|
|
|
|
case CSystemTimer::RspTimer:
|
|
|
|
_SystemTimer->StopTimer(CSystemTimer::RspTimer);
|
2012-09-30 06:07:08 +00:00
|
|
|
try {
|
|
|
|
_System->RunRSP();
|
|
|
|
} catch (...) {
|
2012-11-17 00:58:31 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__,__LINE__);
|
2012-09-30 06:07:08 +00:00
|
|
|
}
|
2010-05-23 10:05:41 +00:00
|
|
|
break;
|
2012-10-05 23:53:11 +00:00
|
|
|
case CSystemTimer::RSPTimerDlist:
|
|
|
|
_SystemTimer->StopTimer(CSystemTimer::RSPTimerDlist);
|
|
|
|
_Reg->m_GfxIntrReg |= MI_INTR_DP;
|
|
|
|
_Reg->CheckInterrupts();
|
|
|
|
break;
|
2010-05-23 10:05:41 +00:00
|
|
|
case CSystemTimer::AiTimer:
|
|
|
|
_SystemTimer->StopTimer(CSystemTimer::AiTimer);
|
2010-06-14 21:14:58 +00:00
|
|
|
_Audio->TimerDone();
|
2010-05-23 10:05:41 +00:00
|
|
|
break;
|
|
|
|
default:
|
2012-11-17 00:58:31 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__,__LINE__);
|
2010-05-23 10:05:41 +00:00
|
|
|
}
|
|
|
|
//CheckTimer();
|
|
|
|
/*if (Profiling) {
|
|
|
|
StartTimer(LastTimer);
|
|
|
|
}*/
|
|
|
|
}
|
|
|
|
|
2010-07-05 11:29:46 +00:00
|
|
|
void CSystemTimer::SetCompareTimer ( void )
|
2008-09-18 03:15:49 +00:00
|
|
|
{
|
2010-07-05 11:29:46 +00:00
|
|
|
DWORD NextCompare = 0x7FFFFFFF;
|
|
|
|
if (_Reg)
|
2010-05-23 10:05:41 +00:00
|
|
|
{
|
2010-07-05 11:29:46 +00:00
|
|
|
NextCompare = _Reg->COMPARE_REGISTER - _Reg->COUNT_REGISTER;
|
|
|
|
if ((NextCompare & 0x80000000) != 0)
|
|
|
|
{
|
|
|
|
NextCompare = 0x7FFFFFFF;
|
|
|
|
}
|
2010-05-23 10:05:41 +00:00
|
|
|
}
|
2010-07-05 11:29:46 +00:00
|
|
|
SetTimer(CompareTimer,NextCompare,false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CSystemTimer::UpdateCompareTimer ( void )
|
|
|
|
{
|
|
|
|
SetCompareTimer();
|
2008-09-18 03:15:49 +00:00
|
|
|
}
|
|
|
|
|
2010-06-14 21:14:58 +00:00
|
|
|
bool CSystemTimer::SaveAllowed ( void )
|
|
|
|
{
|
2010-07-05 11:29:46 +00:00
|
|
|
if (GetTimer(CompareTimer) <= 0)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2010-06-14 21:14:58 +00:00
|
|
|
for (int i = 0; i < MaxTimer; i++)
|
|
|
|
{
|
|
|
|
if (i == CompareTimer) { continue; }
|
|
|
|
if (i == ViTimer) { continue; }
|
|
|
|
if (m_TimerDetatils[i].Active)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2008-09-18 03:15:49 +00:00
|
|
|
}
|
2010-06-14 21:14:58 +00:00
|
|
|
return true;
|
2008-09-18 03:15:49 +00:00
|
|
|
}
|
2010-10-23 18:53:01 +00:00
|
|
|
|
|
|
|
void CSystemTimer::SaveData ( void * file ) const
|
|
|
|
{
|
|
|
|
DWORD TimerDetailsSize = sizeof(TIMER_DETAILS);
|
|
|
|
DWORD Entries = sizeof(m_TimerDetatils)/sizeof(m_TimerDetatils[0]);
|
|
|
|
zipWriteInFileInZip(file,&TimerDetailsSize,sizeof(TimerDetailsSize));
|
|
|
|
zipWriteInFileInZip(file,&Entries,sizeof(Entries));
|
|
|
|
zipWriteInFileInZip(file,(void *)&m_TimerDetatils,sizeof(m_TimerDetatils));
|
|
|
|
zipWriteInFileInZip(file,(void *)&m_LastUpdate,sizeof(m_LastUpdate));
|
|
|
|
zipWriteInFileInZip(file,&m_NextTimer,sizeof(m_NextTimer));
|
|
|
|
zipWriteInFileInZip(file,(void *)&m_Current,sizeof(m_Current));
|
|
|
|
}
|
|
|
|
|
|
|
|
void CSystemTimer::LoadData ( void * file )
|
|
|
|
{
|
|
|
|
DWORD TimerDetailsSize, Entries;
|
|
|
|
|
|
|
|
unzReadCurrentFile( file,&TimerDetailsSize,sizeof(TimerDetailsSize));
|
|
|
|
unzReadCurrentFile( file,&Entries,sizeof(Entries));
|
|
|
|
|
2012-11-17 00:58:31 +00:00
|
|
|
if (TimerDetailsSize != sizeof(TIMER_DETAILS)) { g_Notify->BreakPoint(__FILE__,__LINE__); return; }
|
|
|
|
if (Entries != sizeof(m_TimerDetatils)/sizeof(m_TimerDetatils[0])) { g_Notify->BreakPoint(__FILE__,__LINE__); return; }
|
2010-10-23 18:53:01 +00:00
|
|
|
|
|
|
|
unzReadCurrentFile(file,(void *)&m_TimerDetatils,sizeof(m_TimerDetatils));
|
|
|
|
unzReadCurrentFile(file,(void *)&m_LastUpdate,sizeof(m_LastUpdate));
|
|
|
|
unzReadCurrentFile(file,&m_NextTimer,sizeof(m_NextTimer));
|
|
|
|
unzReadCurrentFile(file,(void *)&m_Current,sizeof(m_Current));
|
2012-09-23 22:18:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CSystemTimer::RecordDifference( CLog &LogFile, const CSystemTimer& rSystemTimer)
|
|
|
|
{
|
|
|
|
if (m_LastUpdate != rSystemTimer.m_LastUpdate)
|
|
|
|
{
|
|
|
|
LogFile.LogF("Timer-LastUpdate: %X %X\r\n",m_LastUpdate,rSystemTimer.m_LastUpdate);
|
|
|
|
}
|
|
|
|
if (m_NextTimer != rSystemTimer.m_NextTimer)
|
|
|
|
{
|
|
|
|
LogFile.LogF("Timer-NextTimer: %X %X\r\n",m_NextTimer,rSystemTimer.m_NextTimer);
|
|
|
|
}
|
|
|
|
if (m_Current != rSystemTimer.m_Current)
|
|
|
|
{
|
|
|
|
LogFile.LogF("Timer-Current %X %X\r\n",m_Current,rSystemTimer.m_Current);
|
|
|
|
}
|
|
|
|
if (m_inFixTimer != rSystemTimer.m_inFixTimer)
|
|
|
|
{
|
|
|
|
LogFile.LogF("Timer-inFixTimer %X %X\r\n",(int)m_inFixTimer,(int)rSystemTimer.m_inFixTimer);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < MaxTimer; i++)
|
|
|
|
{
|
|
|
|
if (m_TimerDetatils[i].Active != rSystemTimer.m_TimerDetatils[i].Active)
|
|
|
|
{
|
|
|
|
LogFile.LogF("Timer-m_TimerDetatils[%d] %X %X\r\n",i,(int)m_TimerDetatils[i].Active,(int)rSystemTimer.m_TimerDetatils[i].Active);
|
|
|
|
}
|
|
|
|
if (m_TimerDetatils[i].CyclesToTimer != rSystemTimer.m_TimerDetatils[i].CyclesToTimer)
|
|
|
|
{
|
|
|
|
LogFile.LogF("Timer-m_TimerDetatils[%d] 0x%08X, 0x%08X\r\n",i,(DWORD)m_TimerDetatils[i].CyclesToTimer,(DWORD)rSystemTimer.m_TimerDetatils[i].CyclesToTimer );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CSystemTimer::operator == (const CSystemTimer& rSystemTimer) const
|
|
|
|
{
|
|
|
|
if (m_LastUpdate != rSystemTimer.m_LastUpdate) { return false; }
|
|
|
|
if (m_NextTimer != rSystemTimer.m_NextTimer) { return false; }
|
|
|
|
if (m_Current != rSystemTimer.m_Current) { return false; }
|
|
|
|
if (m_inFixTimer != rSystemTimer.m_inFixTimer) { return false; }
|
|
|
|
|
|
|
|
for (int i = 0; i < MaxTimer; i++)
|
|
|
|
{
|
|
|
|
if (m_TimerDetatils[i].Active != rSystemTimer.m_TimerDetatils[i].Active) { return false; }
|
|
|
|
if (m_TimerDetatils[i].CyclesToTimer != rSystemTimer.m_TimerDetatils[i].CyclesToTimer) { return false; }
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CSystemTimer::operator != (const CSystemTimer& rSystemTimer) const
|
|
|
|
{
|
|
|
|
return !(*this == rSystemTimer);
|
|
|
|
}
|