mirror of
https://github.com/libretro/Play-.git
synced 2025-02-13 04:52:32 +00:00
Changed way ticks are counted to make sure the speed hacks are activated when both the EE and IOP are idle. EE/IOP time synchronization is probably not quite right yet though.
git-svn-id: http://svn.purei.org/purei/trunk@1006 b36208d7-6611-0410-8bec-b1987f11c4a2
This commit is contained in:
parent
4233c33cfe
commit
30dfc3fe28
161
Source/PS2VM.cpp
161
Source/PS2VM.cpp
@ -92,6 +92,8 @@ CPS2VM::CPS2VM()
|
||||
, m_singleStepVu1(false)
|
||||
, m_vblankTicks(0)
|
||||
, m_inVblank(false)
|
||||
, m_eeExecutionTicks(0)
|
||||
, m_iopExecutionTicks(0)
|
||||
, m_spuUpdateTicks(SPU_UPDATE_TICKS)
|
||||
, m_pCDROM0(NULL)
|
||||
, m_dmac(m_ram, m_spr, m_pVUMem0, m_EE)
|
||||
@ -520,6 +522,9 @@ void CPS2VM::ResetVM()
|
||||
m_vblankTicks = ONSCREEN_TICKS;
|
||||
m_inVblank = false;
|
||||
|
||||
m_eeExecutionTicks = 0;
|
||||
m_iopExecutionTicks = 0;
|
||||
|
||||
RegisterModulesInPadHandler();
|
||||
FillFakeIopRam();
|
||||
|
||||
@ -1038,6 +1043,79 @@ void CPS2VM::ReloadExecutable(const char* executablePath, const CPS2OS::Argument
|
||||
m_os->BootFromCDROM(arguments);
|
||||
}
|
||||
|
||||
int CPS2VM::ExecuteEe(int quota)
|
||||
{
|
||||
int executed = 0;
|
||||
if(m_EE.m_State.callMsEnabled)
|
||||
{
|
||||
if(!m_vif.IsVu0Running())
|
||||
{
|
||||
//callMs mode over
|
||||
memcpy(&m_EE.m_State.nCOP2, &m_VU0.m_State.nCOP2, sizeof(m_EE.m_State.nCOP2));
|
||||
memcpy(&m_EE.m_State.nCOP2A, &m_VU0.m_State.nCOP2A, sizeof(m_EE.m_State.nCOP2A));
|
||||
m_EE.m_State.callMsEnabled = 0;
|
||||
}
|
||||
}
|
||||
else if(!m_EE.m_State.nHasException)
|
||||
{
|
||||
executed = (quota - m_executor.Execute(quota));
|
||||
}
|
||||
if(m_EE.m_State.nHasException)
|
||||
{
|
||||
switch(m_EE.m_State.nHasException)
|
||||
{
|
||||
case MIPS_EXCEPTION_SYSCALL:
|
||||
m_os->SysCallHandler();
|
||||
break;
|
||||
case MIPS_EXCEPTION_CALLMS:
|
||||
assert(m_EE.m_State.callMsEnabled);
|
||||
if(m_EE.m_State.callMsEnabled)
|
||||
{
|
||||
//We are in callMs mode
|
||||
assert(!m_vif.IsVu0Running());
|
||||
//Copy the COP2 state to VPU0
|
||||
memcpy(&m_VU0.m_State.nCOP2, &m_EE.m_State.nCOP2, sizeof(m_VU0.m_State.nCOP2));
|
||||
memcpy(&m_VU0.m_State.nCOP2A, &m_EE.m_State.nCOP2A, sizeof(m_VU0.m_State.nCOP2A));
|
||||
m_vif.StartVu0MicroProgram(m_EE.m_State.callMsAddr);
|
||||
m_EE.m_State.nHasException = 0;
|
||||
}
|
||||
break;
|
||||
case MIPS_EXCEPTION_CHECKPENDINGINT:
|
||||
{
|
||||
m_EE.m_State.nHasException = MIPS_EXCEPTION_NONE;
|
||||
if(m_intc.IsInterruptPending())
|
||||
{
|
||||
m_os->ExceptionHandler();
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
assert(!m_EE.m_State.nHasException);
|
||||
}
|
||||
return executed;
|
||||
}
|
||||
|
||||
bool CPS2VM::IsEeIdle() const
|
||||
{
|
||||
CBasicBlock* nextBlock = m_executor.FindBlockAt(m_EE.m_State.nPC);
|
||||
if(nextBlock && nextBlock->GetSelfLoopCount() > 5000)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if(m_os->IsIdle())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if(m_EE.m_State.nPC >= 0x1FC03100 && m_EE.m_State.nPC <= 0x1FC03110)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CPS2VM::EmuThread()
|
||||
{
|
||||
while(1)
|
||||
@ -1117,73 +1195,23 @@ void CPS2VM::EmuThread()
|
||||
}
|
||||
}
|
||||
|
||||
int executed = 0;
|
||||
if(m_EE.m_State.callMsEnabled)
|
||||
{
|
||||
if(!m_vif.IsVu0Running())
|
||||
{
|
||||
//callMs mode over
|
||||
memcpy(&m_EE.m_State.nCOP2, &m_VU0.m_State.nCOP2, sizeof(m_EE.m_State.nCOP2));
|
||||
memcpy(&m_EE.m_State.nCOP2A, &m_VU0.m_State.nCOP2A, sizeof(m_EE.m_State.nCOP2A));
|
||||
m_EE.m_State.callMsEnabled = 0;
|
||||
}
|
||||
}
|
||||
else if(!m_EE.m_State.nHasException)
|
||||
{
|
||||
int executeQuota = m_singleStepEe ? 1 : 5000;
|
||||
executed += (executeQuota - m_executor.Execute(executeQuota));
|
||||
}
|
||||
if(m_EE.m_State.nHasException)
|
||||
{
|
||||
switch(m_EE.m_State.nHasException)
|
||||
{
|
||||
case MIPS_EXCEPTION_SYSCALL:
|
||||
m_os->SysCallHandler();
|
||||
break;
|
||||
case MIPS_EXCEPTION_CALLMS:
|
||||
assert(m_EE.m_State.callMsEnabled);
|
||||
if(m_EE.m_State.callMsEnabled)
|
||||
{
|
||||
//We are in callMs mode
|
||||
assert(!m_vif.IsVu0Running());
|
||||
//Copy the COP2 state to VPU0
|
||||
memcpy(&m_VU0.m_State.nCOP2, &m_EE.m_State.nCOP2, sizeof(m_VU0.m_State.nCOP2));
|
||||
memcpy(&m_VU0.m_State.nCOP2A, &m_EE.m_State.nCOP2A, sizeof(m_VU0.m_State.nCOP2A));
|
||||
m_vif.StartVu0MicroProgram(m_EE.m_State.callMsAddr);
|
||||
m_EE.m_State.nHasException = 0;
|
||||
}
|
||||
break;
|
||||
case MIPS_EXCEPTION_CHECKPENDINGINT:
|
||||
{
|
||||
m_EE.m_State.nHasException = MIPS_EXCEPTION_NONE;
|
||||
if(m_intc.IsInterruptPending())
|
||||
{
|
||||
m_os->ExceptionHandler();
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
assert(!m_EE.m_State.nHasException);
|
||||
}
|
||||
//EE CPU is 8 times faster than the IOP CPU
|
||||
|
||||
static const int tickStep = 4800;
|
||||
m_eeExecutionTicks += tickStep;
|
||||
m_iopExecutionTicks += tickStep / 8;
|
||||
|
||||
m_eeExecutionTicks -= ExecuteEe(m_singleStepEe ? 1 : m_eeExecutionTicks);
|
||||
|
||||
unsigned int iopExecuted = m_iop.ExecuteCpu(m_singleStepIop ? 1 : m_iopExecutionTicks);
|
||||
m_iopExecutionTicks -= iopExecuted;
|
||||
|
||||
int executed = tickStep;
|
||||
if(IsEeIdle() && m_iop.IsCpuIdle())
|
||||
{
|
||||
CBasicBlock* nextBlock = m_executor.FindBlockAt(m_EE.m_State.nPC);
|
||||
const int skipAmount = 50000;
|
||||
if(nextBlock && nextBlock->GetSelfLoopCount() > 5000)
|
||||
{
|
||||
executed += skipAmount;
|
||||
}
|
||||
else if(m_os->IsIdle())
|
||||
{
|
||||
executed += skipAmount;
|
||||
}
|
||||
else if(m_EE.m_State.nPC >= 0x1FC03100 && m_EE.m_State.nPC <= 0x1FC03110)
|
||||
{
|
||||
executed += skipAmount;
|
||||
}
|
||||
executed *= 16;
|
||||
m_eeExecutionTicks = 0;
|
||||
m_iopExecutionTicks = 0;
|
||||
}
|
||||
|
||||
m_EE.m_State.nCOP0[CCOP_SCU::COUNT] += executed;
|
||||
@ -1191,8 +1219,7 @@ void CPS2VM::EmuThread()
|
||||
m_spuUpdateTicks -= executed;
|
||||
m_timer.Count(executed);
|
||||
|
||||
//IOP Execution
|
||||
m_iop.ExecuteCpu(m_singleStepIop);
|
||||
m_iop.CountTicks(iopExecuted);
|
||||
|
||||
#ifdef DEBUGGER_INCLUDED
|
||||
static bool wasVu1Running = false;
|
||||
|
@ -138,6 +138,8 @@ public:
|
||||
int m_vblankTicks;
|
||||
bool m_inVblank;
|
||||
int m_spuUpdateTicks;
|
||||
int m_eeExecutionTicks;
|
||||
int m_iopExecutionTicks;
|
||||
|
||||
CISO9660* m_pCDROM0;
|
||||
|
||||
@ -174,6 +176,8 @@ private:
|
||||
void RegisterModulesInPadHandler();
|
||||
void FillFakeIopRam();
|
||||
|
||||
int ExecuteEe(int);
|
||||
bool IsEeIdle() const;
|
||||
void EmuThread();
|
||||
|
||||
boost::thread* m_thread;
|
||||
|
@ -218,9 +218,34 @@ uint32 CSubSystem::WriteIoRegister(uint32 address, uint32 value)
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int CSubSystem::ExecuteCpu(bool singleStep)
|
||||
bool CSubSystem::IsCpuIdle()
|
||||
{
|
||||
int ticks = 0;
|
||||
if(m_bios->IsIdle())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 physicalPc = m_cpu.m_pAddrTranslator(&m_cpu, m_cpu.m_State.nPC);
|
||||
CBasicBlock* nextBlock = m_executor.FindBlockAt(physicalPc);
|
||||
if(nextBlock && nextBlock->GetSelfLoopCount() > 5000)
|
||||
{
|
||||
//Go a little bit faster if we're "stuck"
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CSubSystem::CountTicks(int ticks)
|
||||
{
|
||||
m_counters.Update(ticks);
|
||||
m_bios->CountTicks(ticks);
|
||||
}
|
||||
|
||||
int CSubSystem::ExecuteCpu(int quota)
|
||||
{
|
||||
int executed = 0;
|
||||
if(!m_cpu.m_State.nHasException)
|
||||
{
|
||||
if(m_intc.HasPendingInterrupt())
|
||||
@ -230,45 +255,11 @@ unsigned int CSubSystem::ExecuteCpu(bool singleStep)
|
||||
}
|
||||
if(!m_cpu.m_State.nHasException)
|
||||
{
|
||||
bool isIdle = false;
|
||||
int quota = singleStep ? 1 : 500;
|
||||
|
||||
{
|
||||
if(m_bios->IsIdle())
|
||||
{
|
||||
isIdle = true;
|
||||
ticks += (quota * 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 physicalPc = m_cpu.m_pAddrTranslator(&m_cpu, m_cpu.m_State.nPC);
|
||||
CBasicBlock* nextBlock = m_executor.FindBlockAt(physicalPc);
|
||||
if(nextBlock && nextBlock->GetSelfLoopCount() > 5000)
|
||||
{
|
||||
//Go a little bit faster if we're "stuck"
|
||||
isIdle = true;
|
||||
ticks += (quota * 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(isIdle && !singleStep)
|
||||
{
|
||||
quota /= 50;
|
||||
}
|
||||
|
||||
ticks += (quota - m_executor.Execute(quota));
|
||||
assert(ticks >= 0);
|
||||
|
||||
if(ticks > 0)
|
||||
{
|
||||
m_counters.Update(ticks);
|
||||
m_bios->CountTicks(ticks);
|
||||
}
|
||||
executed = (quota - m_executor.Execute(quota));
|
||||
}
|
||||
if(m_cpu.m_State.nHasException)
|
||||
{
|
||||
m_bios->HandleException();
|
||||
}
|
||||
return ticks;
|
||||
return executed;
|
||||
}
|
||||
|
@ -28,7 +28,9 @@ namespace Iop
|
||||
virtual ~CSubSystem();
|
||||
|
||||
void Reset();
|
||||
unsigned int ExecuteCpu(bool);
|
||||
int ExecuteCpu(int);
|
||||
bool IsCpuIdle();
|
||||
void CountTicks(int);
|
||||
|
||||
void SetBios(const BiosPtr&);
|
||||
|
||||
|
@ -66,7 +66,8 @@ void CPsfSubSystem::Update(bool singleStep, CSoundHandler* soundHandler)
|
||||
{
|
||||
#ifdef DEBUGGER_INCLUDED
|
||||
uint64 frameTime = (CHighResTimer::MICROSECOND / FRAMES_PER_SEC);
|
||||
int ticks = m_iop.ExecuteCpu(singleStep);
|
||||
int ticks = m_iop.ExecuteCpu(singleStep ? 1 : 500);
|
||||
m_iop.CountTicks(ticks);
|
||||
|
||||
static int frameCounter = m_frameTicks;
|
||||
static uint64 currentTime = CHighResTimer::GetTime();
|
||||
@ -95,9 +96,21 @@ void CPsfSubSystem::Update(bool singleStep, CSoundHandler* soundHandler)
|
||||
}
|
||||
else
|
||||
{
|
||||
int ticks = m_iop.ExecuteCpu(false);
|
||||
m_spuUpdateCounter -= ticks;
|
||||
m_frameCounter -= ticks;
|
||||
//Execute CPU and step devices
|
||||
{
|
||||
int ticks = 0;
|
||||
int quota = 500;
|
||||
if(m_iop.IsCpuIdle())
|
||||
{
|
||||
ticks += (quota * 2);
|
||||
quota /= 50;
|
||||
}
|
||||
ticks += m_iop.ExecuteCpu(quota);
|
||||
m_iop.CountTicks(ticks);
|
||||
m_spuUpdateCounter -= ticks;
|
||||
m_frameCounter -= ticks;
|
||||
}
|
||||
|
||||
if(m_spuUpdateCounter < 0)
|
||||
{
|
||||
m_spuUpdateCounter += m_spuUpdateTicks;
|
||||
|
Loading…
x
Reference in New Issue
Block a user