Adjust cycle counts so they are accurate to the jit block level

Previously GlobalTimer was only updated at the end of each slice
when CoreTiming::Advance() was called, so it could be upto 20,000
cycles off.

This was causing huge problems with games which made heavy use of
the time base register, such as OoT (virtual console) and Pokemon
puzzle.

I've also made it so event scheduling will be accurate to the jit
block level, instead of accurate to the slice.
This commit is contained in:
Scott Mansell committed 2016-03-24 04:24:53 +13:00
1 parent 3ff56aa192
commit 2ebbfd6f85
3 files changed
+33 -4

No files matched your search

+24 -3
View File
@@ -50,7 +50,7 @@ static Common::FifoQueue<BaseEvent, false> tsQueue;
// event pools
static Event *eventPool = nullptr;
static float lastOCFactor;
float lastOCFactor;
int slicelength;
static int maxSliceLength = MAX_SLICE_LENGTH;
@@ -58,6 +58,9 @@ static s64 idledCycles;
static u32 fakeDecStartValue;
static u64 fakeDecStartTicks;
// Are we in a function that has been called from Advance()
static bool GlobalTimerIsSane;
s64 globalTimer;
u64 fakeTBStartValue;
u64 fakeTBStartTicks;
@@ -137,6 +140,7 @@ void Init()
slicelength = maxSliceLength;
globalTimer = 0;
idledCycles = 0;
GlobalTimerIsSane = true;
ev_lost = RegisterEvent("_lost_event", &EmptyTimedCallback);
}
@@ -209,9 +213,16 @@ void DoState(PointerWrap &p)
p.DoMarker("CoreTimingEvents");
}
// This should only be called from the CPU thread, if you are calling it any other thread, you are doing something evil
u64 GetTicks()
{
return (u64)globalTimer;
u64 ticks = (u64)globalTimer;
if (!GlobalTimerIsSane)
{
int downcount = DowncountToCycles(PowerPC::ppcState.downcount);
ticks += slicelength - downcount;
}
return ticks;
}
u64 GetIdleTicks()
@@ -303,10 +314,16 @@ void ScheduleEvent(int cyclesIntoFuture, int event_type, u64 userdata)
{
_assert_msg_(POWERPC, Core::IsCPUThread() || Core::GetState() == Core::CORE_PAUSE,
"ScheduleEvent from wrong thread");
Event *ne = GetNewEvent();
ne->userdata = userdata;
ne->type = event_type;
ne->time = globalTimer + cyclesIntoFuture;
ne->time = GetTicks() + cyclesIntoFuture;
// If this event needs to be scheduled before the next advance(), force one early
if (!GlobalTimerIsSane)
ForceExceptionCheck(cyclesIntoFuture);
AddEventToQueue(ne);
}
@@ -402,6 +419,8 @@ void Advance()
lastOCFactor = SConfig::GetInstance().m_OCEnable ? SConfig::GetInstance().m_OCFactor : 1.0f;
PowerPC::ppcState.downcount = CyclesToDowncount(slicelength);
GlobalTimerIsSane = true;
while (first && first->time <= globalTimer)
{
//LOG(POWERPC, "[Scheduler] %s (%lld, %lld) ",
@@ -412,6 +431,8 @@ void Advance()
FreeEvent(evt);
}
GlobalTimerIsSane = false;
if (!first)
{
WARN_LOG(POWERPC, "WARNING - no events in queue. Setting downcount to 10000");