Reformat all the things. Have fun with merge conflicts.
This commit is contained in:
1 parent
2115e8a4a6
commit
3570c7f03a
1116 files changed
+187350
-180289
No files matched your search
+307
-296
@@ -24,31 +24,30 @@
|
||||
|
||||
namespace CoreTiming
|
||||
{
|
||||
|
||||
struct EventType
|
||||
{
|
||||
TimedCallback callback;
|
||||
std::string name;
|
||||
TimedCallback callback;
|
||||
std::string name;
|
||||
};
|
||||
|
||||
static std::vector<EventType> event_types;
|
||||
|
||||
struct BaseEvent
|
||||
{
|
||||
s64 time;
|
||||
u64 userdata;
|
||||
int type;
|
||||
s64 time;
|
||||
u64 userdata;
|
||||
int type;
|
||||
};
|
||||
|
||||
typedef LinkedListItem<BaseEvent> Event;
|
||||
|
||||
// STATE_TO_SAVE
|
||||
static Event *first;
|
||||
static Event* first;
|
||||
static std::mutex tsWriteLock;
|
||||
static Common::FifoQueue<BaseEvent, false> tsQueue;
|
||||
|
||||
// event pools
|
||||
static Event *eventPool = nullptr;
|
||||
static Event* eventPool = nullptr;
|
||||
|
||||
static float s_lastOCFactor;
|
||||
float g_lastOCFactor_inverted;
|
||||
@@ -70,21 +69,23 @@ static int ev_lost;
|
||||
|
||||
static Event* GetNewEvent()
|
||||
{
|
||||
if (!eventPool)
|
||||
return new Event;
|
||||
if (!eventPool)
|
||||
return new Event;
|
||||
|
||||
Event* ev = eventPool;
|
||||
eventPool = ev->next;
|
||||
return ev;
|
||||
Event* ev = eventPool;
|
||||
eventPool = ev->next;
|
||||
return ev;
|
||||
}
|
||||
|
||||
static void FreeEvent(Event* ev)
|
||||
{
|
||||
ev->next = eventPool;
|
||||
eventPool = ev;
|
||||
ev->next = eventPool;
|
||||
eventPool = ev;
|
||||
}
|
||||
|
||||
static void EmptyTimedCallback(u64 userdata, s64 cyclesLate) {}
|
||||
static void EmptyTimedCallback(u64 userdata, s64 cyclesLate)
|
||||
{
|
||||
}
|
||||
|
||||
// Changing the CPU speed in Dolphin isn't actually done by changing the physical clock rate,
|
||||
// but by changing the amount of work done in a particular amount of time. This tends to be more
|
||||
@@ -95,221 +96,229 @@ static void EmptyTimedCallback(u64 userdata, s64 cyclesLate) {}
|
||||
// but the effect is largely the same.
|
||||
static int DowncountToCycles(int downcount)
|
||||
{
|
||||
return (int)(downcount * g_lastOCFactor_inverted);
|
||||
return (int)(downcount * g_lastOCFactor_inverted);
|
||||
}
|
||||
|
||||
static int CyclesToDowncount(int cycles)
|
||||
{
|
||||
return (int)(cycles * s_lastOCFactor);
|
||||
return (int)(cycles * s_lastOCFactor);
|
||||
}
|
||||
|
||||
int RegisterEvent(const std::string& name, TimedCallback callback)
|
||||
{
|
||||
EventType type;
|
||||
type.name = name;
|
||||
type.callback = callback;
|
||||
EventType type;
|
||||
type.name = name;
|
||||
type.callback = callback;
|
||||
|
||||
// check for existing type with same name.
|
||||
// we want event type names to remain unique so that we can use them for serialization.
|
||||
for (auto& event_type : event_types)
|
||||
{
|
||||
if (name == event_type.name)
|
||||
{
|
||||
WARN_LOG(POWERPC, "Discarded old event type \"%s\" because a new type with the same name was registered.", name.c_str());
|
||||
// we don't know if someone might be holding on to the type index,
|
||||
// so we gut the old event type instead of actually removing it.
|
||||
event_type.name = "_discarded_event";
|
||||
event_type.callback = &EmptyTimedCallback;
|
||||
}
|
||||
}
|
||||
// check for existing type with same name.
|
||||
// we want event type names to remain unique so that we can use them for serialization.
|
||||
for (auto& event_type : event_types)
|
||||
{
|
||||
if (name == event_type.name)
|
||||
{
|
||||
WARN_LOG(
|
||||
POWERPC,
|
||||
"Discarded old event type \"%s\" because a new type with the same name was registered.",
|
||||
name.c_str());
|
||||
// we don't know if someone might be holding on to the type index,
|
||||
// so we gut the old event type instead of actually removing it.
|
||||
event_type.name = "_discarded_event";
|
||||
event_type.callback = &EmptyTimedCallback;
|
||||
}
|
||||
}
|
||||
|
||||
event_types.push_back(type);
|
||||
return (int)event_types.size() - 1;
|
||||
event_types.push_back(type);
|
||||
return (int)event_types.size() - 1;
|
||||
}
|
||||
|
||||
void UnregisterAllEvents()
|
||||
{
|
||||
if (first)
|
||||
PanicAlert("Cannot unregister events with events pending");
|
||||
event_types.clear();
|
||||
if (first)
|
||||
PanicAlert("Cannot unregister events with events pending");
|
||||
event_types.clear();
|
||||
}
|
||||
|
||||
void Init()
|
||||
{
|
||||
s_lastOCFactor = SConfig::GetInstance().m_OCEnable ? SConfig::GetInstance().m_OCFactor : 1.0f;
|
||||
g_lastOCFactor_inverted = 1.0f / s_lastOCFactor;
|
||||
PowerPC::ppcState.downcount = CyclesToDowncount(maxslicelength);
|
||||
g_slicelength = maxslicelength;
|
||||
g_globalTimer = 0;
|
||||
idledCycles = 0;
|
||||
globalTimerIsSane = true;
|
||||
s_lastOCFactor = SConfig::GetInstance().m_OCEnable ? SConfig::GetInstance().m_OCFactor : 1.0f;
|
||||
g_lastOCFactor_inverted = 1.0f / s_lastOCFactor;
|
||||
PowerPC::ppcState.downcount = CyclesToDowncount(maxslicelength);
|
||||
g_slicelength = maxslicelength;
|
||||
g_globalTimer = 0;
|
||||
idledCycles = 0;
|
||||
globalTimerIsSane = true;
|
||||
|
||||
ev_lost = RegisterEvent("_lost_event", &EmptyTimedCallback);
|
||||
ev_lost = RegisterEvent("_lost_event", &EmptyTimedCallback);
|
||||
}
|
||||
|
||||
void Shutdown()
|
||||
{
|
||||
std::lock_guard<std::mutex> lk(tsWriteLock);
|
||||
MoveEvents();
|
||||
ClearPendingEvents();
|
||||
UnregisterAllEvents();
|
||||
std::lock_guard<std::mutex> lk(tsWriteLock);
|
||||
MoveEvents();
|
||||
ClearPendingEvents();
|
||||
UnregisterAllEvents();
|
||||
|
||||
while (eventPool)
|
||||
{
|
||||
Event *ev = eventPool;
|
||||
eventPool = ev->next;
|
||||
delete ev;
|
||||
}
|
||||
while (eventPool)
|
||||
{
|
||||
Event* ev = eventPool;
|
||||
eventPool = ev->next;
|
||||
delete ev;
|
||||
}
|
||||
}
|
||||
|
||||
static void EventDoState(PointerWrap &p, BaseEvent* ev)
|
||||
static void EventDoState(PointerWrap& p, BaseEvent* ev)
|
||||
{
|
||||
p.Do(ev->time);
|
||||
p.Do(ev->time);
|
||||
|
||||
// this is why we can't have (nice things) pointers as userdata
|
||||
p.Do(ev->userdata);
|
||||
// this is why we can't have (nice things) pointers as userdata
|
||||
p.Do(ev->userdata);
|
||||
|
||||
// we can't savestate ev->type directly because events might not get registered in the same order (or at all) every time.
|
||||
// so, we savestate the event's type's name, and derive ev->type from that when loading.
|
||||
std::string name;
|
||||
if (p.GetMode() != PointerWrap::MODE_READ)
|
||||
name = event_types[ev->type].name;
|
||||
// we can't savestate ev->type directly because events might not get registered in the same order
|
||||
// (or at all) every time.
|
||||
// so, we savestate the event's type's name, and derive ev->type from that when loading.
|
||||
std::string name;
|
||||
if (p.GetMode() != PointerWrap::MODE_READ)
|
||||
name = event_types[ev->type].name;
|
||||
|
||||
p.Do(name);
|
||||
if (p.GetMode() == PointerWrap::MODE_READ)
|
||||
{
|
||||
bool foundMatch = false;
|
||||
for (unsigned int i = 0; i < event_types.size(); ++i)
|
||||
{
|
||||
if (name == event_types[i].name)
|
||||
{
|
||||
ev->type = i;
|
||||
foundMatch = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!foundMatch)
|
||||
{
|
||||
WARN_LOG(POWERPC, "Lost event from savestate because its type, \"%s\", has not been registered.", name.c_str());
|
||||
ev->type = ev_lost;
|
||||
}
|
||||
}
|
||||
p.Do(name);
|
||||
if (p.GetMode() == PointerWrap::MODE_READ)
|
||||
{
|
||||
bool foundMatch = false;
|
||||
for (unsigned int i = 0; i < event_types.size(); ++i)
|
||||
{
|
||||
if (name == event_types[i].name)
|
||||
{
|
||||
ev->type = i;
|
||||
foundMatch = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!foundMatch)
|
||||
{
|
||||
WARN_LOG(POWERPC,
|
||||
"Lost event from savestate because its type, \"%s\", has not been registered.",
|
||||
name.c_str());
|
||||
ev->type = ev_lost;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DoState(PointerWrap &p)
|
||||
void DoState(PointerWrap& p)
|
||||
{
|
||||
std::lock_guard<std::mutex> lk(tsWriteLock);
|
||||
p.Do(g_slicelength);
|
||||
p.Do(g_globalTimer);
|
||||
p.Do(idledCycles);
|
||||
p.Do(fakeDecStartValue);
|
||||
p.Do(fakeDecStartTicks);
|
||||
p.Do(g_fakeTBStartValue);
|
||||
p.Do(g_fakeTBStartTicks);
|
||||
p.Do(s_lastOCFactor);
|
||||
if (p.GetMode() == PointerWrap::MODE_READ)
|
||||
g_lastOCFactor_inverted = 1.0f / s_lastOCFactor;
|
||||
std::lock_guard<std::mutex> lk(tsWriteLock);
|
||||
p.Do(g_slicelength);
|
||||
p.Do(g_globalTimer);
|
||||
p.Do(idledCycles);
|
||||
p.Do(fakeDecStartValue);
|
||||
p.Do(fakeDecStartTicks);
|
||||
p.Do(g_fakeTBStartValue);
|
||||
p.Do(g_fakeTBStartTicks);
|
||||
p.Do(s_lastOCFactor);
|
||||
if (p.GetMode() == PointerWrap::MODE_READ)
|
||||
g_lastOCFactor_inverted = 1.0f / s_lastOCFactor;
|
||||
|
||||
p.DoMarker("CoreTimingData");
|
||||
p.DoMarker("CoreTimingData");
|
||||
|
||||
MoveEvents();
|
||||
MoveEvents();
|
||||
|
||||
p.DoLinkedList<BaseEvent, GetNewEvent, FreeEvent, EventDoState>(first);
|
||||
p.DoMarker("CoreTimingEvents");
|
||||
p.DoLinkedList<BaseEvent, GetNewEvent, FreeEvent, EventDoState>(first);
|
||||
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
|
||||
// This should only be called from the CPU thread, if you are calling it any other thread, you are
|
||||
// doing something evil
|
||||
u64 GetTicks()
|
||||
{
|
||||
u64 ticks = (u64)g_globalTimer;
|
||||
if (!globalTimerIsSane)
|
||||
{
|
||||
int downcount = DowncountToCycles(PowerPC::ppcState.downcount);
|
||||
ticks += g_slicelength - downcount;
|
||||
}
|
||||
return ticks;
|
||||
u64 ticks = (u64)g_globalTimer;
|
||||
if (!globalTimerIsSane)
|
||||
{
|
||||
int downcount = DowncountToCycles(PowerPC::ppcState.downcount);
|
||||
ticks += g_slicelength - downcount;
|
||||
}
|
||||
return ticks;
|
||||
}
|
||||
|
||||
u64 GetIdleTicks()
|
||||
{
|
||||
return (u64)idledCycles;
|
||||
return (u64)idledCycles;
|
||||
}
|
||||
|
||||
// This is to be called when outside threads, such as the graphics thread, wants to
|
||||
// schedule things to be executed on the main thread.
|
||||
void ScheduleEvent_Threadsafe(s64 cyclesIntoFuture, int event_type, u64 userdata)
|
||||
{
|
||||
_assert_msg_(POWERPC, !Core::IsCPUThread(), "ScheduleEvent_Threadsafe from wrong thread");
|
||||
if (Core::g_want_determinism)
|
||||
{
|
||||
ERROR_LOG(POWERPC, "Someone scheduled an off-thread \"%s\" event while netplay or movie play/record "
|
||||
"was active. This is likely to cause a desync.",
|
||||
event_types[event_type].name.c_str());
|
||||
}
|
||||
std::lock_guard<std::mutex> lk(tsWriteLock);
|
||||
Event ne;
|
||||
ne.time = g_globalTimer + cyclesIntoFuture;
|
||||
ne.type = event_type;
|
||||
ne.userdata = userdata;
|
||||
tsQueue.Push(ne);
|
||||
_assert_msg_(POWERPC, !Core::IsCPUThread(), "ScheduleEvent_Threadsafe from wrong thread");
|
||||
if (Core::g_want_determinism)
|
||||
{
|
||||
ERROR_LOG(POWERPC,
|
||||
"Someone scheduled an off-thread \"%s\" event while netplay or movie play/record "
|
||||
"was active. This is likely to cause a desync.",
|
||||
event_types[event_type].name.c_str());
|
||||
}
|
||||
std::lock_guard<std::mutex> lk(tsWriteLock);
|
||||
Event ne;
|
||||
ne.time = g_globalTimer + cyclesIntoFuture;
|
||||
ne.type = event_type;
|
||||
ne.userdata = userdata;
|
||||
tsQueue.Push(ne);
|
||||
}
|
||||
|
||||
// Executes an event immediately, then returns.
|
||||
void ScheduleEvent_Immediate(int event_type, u64 userdata)
|
||||
{
|
||||
_assert_msg_(POWERPC, Core::IsCPUThread(), "ScheduleEvent_Immediate from wrong thread");
|
||||
event_types[event_type].callback(userdata, 0);
|
||||
_assert_msg_(POWERPC, Core::IsCPUThread(), "ScheduleEvent_Immediate from wrong thread");
|
||||
event_types[event_type].callback(userdata, 0);
|
||||
}
|
||||
|
||||
// Same as ScheduleEvent_Threadsafe(0, ...) EXCEPT if we are already on the CPU thread
|
||||
// in which case this is the same as ScheduleEvent_Immediate.
|
||||
void ScheduleEvent_Threadsafe_Immediate(int event_type, u64 userdata)
|
||||
{
|
||||
if (Core::IsCPUThread())
|
||||
{
|
||||
event_types[event_type].callback(userdata, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
ScheduleEvent_Threadsafe(0, event_type, userdata);
|
||||
}
|
||||
if (Core::IsCPUThread())
|
||||
{
|
||||
event_types[event_type].callback(userdata, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
ScheduleEvent_Threadsafe(0, event_type, userdata);
|
||||
}
|
||||
}
|
||||
|
||||
// To be used from any thread, including the CPU thread
|
||||
void ScheduleEvent_AnyThread(s64 cyclesIntoFuture, int event_type, u64 userdata)
|
||||
{
|
||||
if (Core::IsCPUThread())
|
||||
ScheduleEvent(cyclesIntoFuture, event_type, userdata);
|
||||
else
|
||||
ScheduleEvent_Threadsafe(cyclesIntoFuture, event_type, userdata);
|
||||
if (Core::IsCPUThread())
|
||||
ScheduleEvent(cyclesIntoFuture, event_type, userdata);
|
||||
else
|
||||
ScheduleEvent_Threadsafe(cyclesIntoFuture, event_type, userdata);
|
||||
}
|
||||
|
||||
void ClearPendingEvents()
|
||||
{
|
||||
while (first)
|
||||
{
|
||||
Event *e = first->next;
|
||||
FreeEvent(first);
|
||||
first = e;
|
||||
}
|
||||
while (first)
|
||||
{
|
||||
Event* e = first->next;
|
||||
FreeEvent(first);
|
||||
first = e;
|
||||
}
|
||||
}
|
||||
|
||||
static void AddEventToQueue(Event* ne)
|
||||
{
|
||||
Event* prev = nullptr;
|
||||
Event** pNext = &first;
|
||||
for (;;)
|
||||
{
|
||||
Event*& next = *pNext;
|
||||
if (!next || ne->time < next->time)
|
||||
{
|
||||
ne->next = next;
|
||||
next = ne;
|
||||
break;
|
||||
}
|
||||
prev = next;
|
||||
pNext = &prev->next;
|
||||
}
|
||||
Event* prev = nullptr;
|
||||
Event** pNext = &first;
|
||||
for (;;)
|
||||
{
|
||||
Event*& next = *pNext;
|
||||
if (!next || ne->time < next->time)
|
||||
{
|
||||
ne->next = next;
|
||||
next = ne;
|
||||
break;
|
||||
}
|
||||
prev = next;
|
||||
pNext = &prev->next;
|
||||
}
|
||||
}
|
||||
|
||||
// This must be run ONLY from within the CPU thread
|
||||
@@ -317,231 +326,233 @@ static void AddEventToQueue(Event* ne)
|
||||
// than Advance
|
||||
void ScheduleEvent(s64 cyclesIntoFuture, int event_type, u64 userdata)
|
||||
{
|
||||
_assert_msg_(POWERPC, Core::IsCPUThread() || Core::GetState() == Core::CORE_PAUSE,
|
||||
"ScheduleEvent from wrong thread");
|
||||
_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 = GetTicks() + cyclesIntoFuture;
|
||||
Event* ne = GetNewEvent();
|
||||
ne->userdata = userdata;
|
||||
ne->type = event_type;
|
||||
ne->time = GetTicks() + cyclesIntoFuture;
|
||||
|
||||
// If this event needs to be scheduled before the next advance(), force one early
|
||||
if (!globalTimerIsSane)
|
||||
ForceExceptionCheck(cyclesIntoFuture);
|
||||
// If this event needs to be scheduled before the next advance(), force one early
|
||||
if (!globalTimerIsSane)
|
||||
ForceExceptionCheck(cyclesIntoFuture);
|
||||
|
||||
|
||||
AddEventToQueue(ne);
|
||||
AddEventToQueue(ne);
|
||||
}
|
||||
|
||||
void RemoveEvent(int event_type)
|
||||
{
|
||||
while (first && first->type == event_type)
|
||||
{
|
||||
Event* next = first->next;
|
||||
FreeEvent(first);
|
||||
first = next;
|
||||
}
|
||||
while (first && first->type == event_type)
|
||||
{
|
||||
Event* next = first->next;
|
||||
FreeEvent(first);
|
||||
first = next;
|
||||
}
|
||||
|
||||
if (!first)
|
||||
return;
|
||||
if (!first)
|
||||
return;
|
||||
|
||||
Event *prev = first;
|
||||
Event *ptr = prev->next;
|
||||
while (ptr)
|
||||
{
|
||||
if (ptr->type == event_type)
|
||||
{
|
||||
prev->next = ptr->next;
|
||||
FreeEvent(ptr);
|
||||
ptr = prev->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
prev = ptr;
|
||||
ptr = ptr->next;
|
||||
}
|
||||
}
|
||||
Event* prev = first;
|
||||
Event* ptr = prev->next;
|
||||
while (ptr)
|
||||
{
|
||||
if (ptr->type == event_type)
|
||||
{
|
||||
prev->next = ptr->next;
|
||||
FreeEvent(ptr);
|
||||
ptr = prev->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
prev = ptr;
|
||||
ptr = ptr->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RemoveAllEvents(int event_type)
|
||||
{
|
||||
MoveEvents();
|
||||
RemoveEvent(event_type);
|
||||
MoveEvents();
|
||||
RemoveEvent(event_type);
|
||||
}
|
||||
|
||||
void ForceExceptionCheck(s64 cycles)
|
||||
{
|
||||
if (s64(DowncountToCycles(PowerPC::ppcState.downcount)) > cycles)
|
||||
{
|
||||
// downcount is always (much) smaller than MAX_INT so we can safely cast cycles to an int here.
|
||||
g_slicelength -= (DowncountToCycles(PowerPC::ppcState.downcount) - (int)cycles); // Account for cycles already executed by adjusting the g_slicelength
|
||||
PowerPC::ppcState.downcount = CyclesToDowncount((int)cycles);
|
||||
}
|
||||
if (s64(DowncountToCycles(PowerPC::ppcState.downcount)) > cycles)
|
||||
{
|
||||
// downcount is always (much) smaller than MAX_INT so we can safely cast cycles to an int here.
|
||||
g_slicelength -=
|
||||
(DowncountToCycles(PowerPC::ppcState.downcount) -
|
||||
(int)cycles); // Account for cycles already executed by adjusting the g_slicelength
|
||||
PowerPC::ppcState.downcount = CyclesToDowncount((int)cycles);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//This raise only the events required while the fifo is processing data
|
||||
// This raise only the events required while the fifo is processing data
|
||||
void ProcessFifoWaitEvents()
|
||||
{
|
||||
MoveEvents();
|
||||
MoveEvents();
|
||||
|
||||
if (!first)
|
||||
return;
|
||||
if (!first)
|
||||
return;
|
||||
|
||||
while (first)
|
||||
{
|
||||
if (first->time <= g_globalTimer)
|
||||
{
|
||||
Event* evt = first;
|
||||
first = first->next;
|
||||
event_types[evt->type].callback(evt->userdata, (int)(g_globalTimer - evt->time));
|
||||
FreeEvent(evt);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (first)
|
||||
{
|
||||
if (first->time <= g_globalTimer)
|
||||
{
|
||||
Event* evt = first;
|
||||
first = first->next;
|
||||
event_types[evt->type].callback(evt->userdata, (int)(g_globalTimer - evt->time));
|
||||
FreeEvent(evt);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MoveEvents()
|
||||
{
|
||||
BaseEvent sevt;
|
||||
while (tsQueue.Pop(sevt))
|
||||
{
|
||||
Event *evt = GetNewEvent();
|
||||
evt->time = sevt.time;
|
||||
evt->userdata = sevt.userdata;
|
||||
evt->type = sevt.type;
|
||||
AddEventToQueue(evt);
|
||||
}
|
||||
BaseEvent sevt;
|
||||
while (tsQueue.Pop(sevt))
|
||||
{
|
||||
Event* evt = GetNewEvent();
|
||||
evt->time = sevt.time;
|
||||
evt->userdata = sevt.userdata;
|
||||
evt->type = sevt.type;
|
||||
AddEventToQueue(evt);
|
||||
}
|
||||
}
|
||||
|
||||
void Advance()
|
||||
{
|
||||
MoveEvents();
|
||||
MoveEvents();
|
||||
|
||||
int cyclesExecuted = g_slicelength - DowncountToCycles(PowerPC::ppcState.downcount);
|
||||
g_globalTimer += cyclesExecuted;
|
||||
s_lastOCFactor = SConfig::GetInstance().m_OCEnable ? SConfig::GetInstance().m_OCFactor : 1.0f;
|
||||
g_lastOCFactor_inverted = 1.0f / s_lastOCFactor;
|
||||
g_slicelength = maxslicelength;
|
||||
int cyclesExecuted = g_slicelength - DowncountToCycles(PowerPC::ppcState.downcount);
|
||||
g_globalTimer += cyclesExecuted;
|
||||
s_lastOCFactor = SConfig::GetInstance().m_OCEnable ? SConfig::GetInstance().m_OCFactor : 1.0f;
|
||||
g_lastOCFactor_inverted = 1.0f / s_lastOCFactor;
|
||||
g_slicelength = maxslicelength;
|
||||
|
||||
globalTimerIsSane = true;
|
||||
globalTimerIsSane = true;
|
||||
|
||||
while (first && first->time <= g_globalTimer)
|
||||
{
|
||||
//LOG(POWERPC, "[Scheduler] %s (%lld, %lld) ",
|
||||
// event_types[first->type].name ? event_types[first->type].name : "?", (u64)g_globalTimer, (u64)first->time);
|
||||
Event* evt = first;
|
||||
first = first->next;
|
||||
event_types[evt->type].callback(evt->userdata, (int)(g_globalTimer - evt->time));
|
||||
FreeEvent(evt);
|
||||
}
|
||||
while (first && first->time <= g_globalTimer)
|
||||
{
|
||||
// LOG(POWERPC, "[Scheduler] %s (%lld, %lld) ",
|
||||
// event_types[first->type].name ? event_types[first->type].name : "?",
|
||||
// (u64)g_globalTimer, (u64)first->time);
|
||||
Event* evt = first;
|
||||
first = first->next;
|
||||
event_types[evt->type].callback(evt->userdata, (int)(g_globalTimer - evt->time));
|
||||
FreeEvent(evt);
|
||||
}
|
||||
|
||||
globalTimerIsSane = false;
|
||||
globalTimerIsSane = false;
|
||||
|
||||
if (first)
|
||||
{
|
||||
g_slicelength = (int)(first->time - g_globalTimer);
|
||||
if (g_slicelength > maxslicelength)
|
||||
g_slicelength = maxslicelength;
|
||||
}
|
||||
if (first)
|
||||
{
|
||||
g_slicelength = (int)(first->time - g_globalTimer);
|
||||
if (g_slicelength > maxslicelength)
|
||||
g_slicelength = maxslicelength;
|
||||
}
|
||||
|
||||
PowerPC::ppcState.downcount = CyclesToDowncount(g_slicelength);
|
||||
|
||||
// Check for any external exceptions.
|
||||
// It's important to do this after processing events otherwise any exceptions will be delayed until the next slice:
|
||||
// Pokemon Box refuses to boot if the first exception from the audio DMA is received late
|
||||
PowerPC::CheckExternalExceptions();
|
||||
PowerPC::ppcState.downcount = CyclesToDowncount(g_slicelength);
|
||||
|
||||
// Check for any external exceptions.
|
||||
// It's important to do this after processing events otherwise any exceptions will be delayed
|
||||
// until the next slice:
|
||||
// Pokemon Box refuses to boot if the first exception from the audio DMA is received late
|
||||
PowerPC::CheckExternalExceptions();
|
||||
}
|
||||
|
||||
void LogPendingEvents()
|
||||
{
|
||||
Event *ptr = first;
|
||||
while (ptr)
|
||||
{
|
||||
INFO_LOG(POWERPC, "PENDING: Now: %" PRId64 " Pending: %" PRId64 " Type: %d", g_globalTimer, ptr->time, ptr->type);
|
||||
ptr = ptr->next;
|
||||
}
|
||||
Event* ptr = first;
|
||||
while (ptr)
|
||||
{
|
||||
INFO_LOG(POWERPC, "PENDING: Now: %" PRId64 " Pending: %" PRId64 " Type: %d", g_globalTimer,
|
||||
ptr->time, ptr->type);
|
||||
ptr = ptr->next;
|
||||
}
|
||||
}
|
||||
|
||||
void Idle()
|
||||
{
|
||||
//DEBUG_LOG(POWERPC, "Idle");
|
||||
// DEBUG_LOG(POWERPC, "Idle");
|
||||
|
||||
if (SConfig::GetInstance().bSyncGPUOnSkipIdleHack)
|
||||
{
|
||||
//When the FIFO is processing data we must not advance because in this way
|
||||
//the VI will be desynchronized. So, We are waiting until the FIFO finish and
|
||||
//while we process only the events required by the FIFO.
|
||||
ProcessFifoWaitEvents();
|
||||
Fifo::FlushGpu();
|
||||
}
|
||||
if (SConfig::GetInstance().bSyncGPUOnSkipIdleHack)
|
||||
{
|
||||
// When the FIFO is processing data we must not advance because in this way
|
||||
// the VI will be desynchronized. So, We are waiting until the FIFO finish and
|
||||
// while we process only the events required by the FIFO.
|
||||
ProcessFifoWaitEvents();
|
||||
Fifo::FlushGpu();
|
||||
}
|
||||
|
||||
idledCycles += DowncountToCycles(PowerPC::ppcState.downcount);
|
||||
PowerPC::ppcState.downcount = 0;
|
||||
idledCycles += DowncountToCycles(PowerPC::ppcState.downcount);
|
||||
PowerPC::ppcState.downcount = 0;
|
||||
}
|
||||
|
||||
std::string GetScheduledEventsSummary()
|
||||
{
|
||||
Event *ptr = first;
|
||||
std::string text = "Scheduled events\n";
|
||||
text.reserve(1000);
|
||||
while (ptr)
|
||||
{
|
||||
unsigned int t = ptr->type;
|
||||
if (t >= event_types.size())
|
||||
PanicAlertT("Invalid event type %i", t);
|
||||
Event* ptr = first;
|
||||
std::string text = "Scheduled events\n";
|
||||
text.reserve(1000);
|
||||
while (ptr)
|
||||
{
|
||||
unsigned int t = ptr->type;
|
||||
if (t >= event_types.size())
|
||||
PanicAlertT("Invalid event type %i", t);
|
||||
|
||||
const std::string& name = event_types[ptr->type].name;
|
||||
const std::string& name = event_types[ptr->type].name;
|
||||
|
||||
text += StringFromFormat("%s : %" PRIi64 " %016" PRIx64 "\n", name.c_str(), ptr->time, ptr->userdata);
|
||||
ptr = ptr->next;
|
||||
}
|
||||
return text;
|
||||
text += StringFromFormat("%s : %" PRIi64 " %016" PRIx64 "\n", name.c_str(), ptr->time,
|
||||
ptr->userdata);
|
||||
ptr = ptr->next;
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
u32 GetFakeDecStartValue()
|
||||
{
|
||||
return fakeDecStartValue;
|
||||
return fakeDecStartValue;
|
||||
}
|
||||
|
||||
void SetFakeDecStartValue(u32 val)
|
||||
{
|
||||
fakeDecStartValue = val;
|
||||
fakeDecStartValue = val;
|
||||
}
|
||||
|
||||
u64 GetFakeDecStartTicks()
|
||||
{
|
||||
return fakeDecStartTicks;
|
||||
return fakeDecStartTicks;
|
||||
}
|
||||
|
||||
void SetFakeDecStartTicks(u64 val)
|
||||
{
|
||||
fakeDecStartTicks = val;
|
||||
fakeDecStartTicks = val;
|
||||
}
|
||||
|
||||
u64 GetFakeTBStartValue()
|
||||
{
|
||||
return g_fakeTBStartValue;
|
||||
return g_fakeTBStartValue;
|
||||
}
|
||||
|
||||
void SetFakeTBStartValue(u64 val)
|
||||
{
|
||||
g_fakeTBStartValue = val;
|
||||
g_fakeTBStartValue = val;
|
||||
}
|
||||
|
||||
u64 GetFakeTBStartTicks()
|
||||
{
|
||||
return g_fakeTBStartTicks;
|
||||
return g_fakeTBStartTicks;
|
||||
}
|
||||
|
||||
void SetFakeTBStartTicks(u64 val)
|
||||
{
|
||||
g_fakeTBStartTicks = val;
|
||||
g_fakeTBStartTicks = val;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Reference in new issue
Block a user