SaveState: Make event restoring more obvious.

We still must restore all events, but everything can be taken care of
during the save state load.
This commit is contained in:
Unknown W. Brackets
2020-12-28 13:29:19 -08:00
parent 52c6169a59
commit 06f8ab5a49
10 changed files with 60 additions and 78 deletions
+33 -18
View File
@@ -16,9 +16,9 @@
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include <atomic>
#include <vector>
#include <cstdio>
#include <mutex>
#include <vector>
#include "Common/Profiler/Profiler.h"
@@ -48,6 +48,7 @@ struct EventType {
};
std::vector<EventType> event_types;
int nextEventTypeRestoreId = -1;
struct BaseEvent {
s64 time;
@@ -160,29 +161,33 @@ void FreeTsEvent(Event* ev)
allocatedTsEvents--;
}
int RegisterEvent(const char *name, TimedCallback callback)
{
int RegisterEvent(const char *name, TimedCallback callback) {
for (const auto &ty : event_types) {
if (!strcmp(ty.name, name)) {
_assert_msg_(false, "Event type %s already registered", name);
// Try to make sure it doesn't work so we notice for sure.
return -1;
}
}
int id = (int)event_types.size();
event_types.push_back(EventType{ callback, name });
return (int)event_types.size() - 1;
return id;
}
void AntiCrashCallback(u64 userdata, int cyclesLate)
{
void AntiCrashCallback(u64 userdata, int cyclesLate) {
ERROR_LOG(SAVESTATE, "Savestate broken: an unregistered event was called.");
Core_EnableStepping(true);
}
void RestoreRegisterEvent(int event_type, const char *name, TimedCallback callback)
{
_assert_msg_(event_type >= 0, "Invalid event type %d", event_type)
if (event_type >= (int) event_types.size())
event_types.resize(event_type + 1, EventType{ AntiCrashCallback, "INVALID EVENT" });
void RestoreRegisterEvent(int &event_type, const char *name, TimedCallback callback) {
if (event_type == -1)
event_type = nextEventTypeRestoreId++;
_assert_msg_(event_type >= 0 && event_type < event_types.size(), "Invalid event type %d", event_type);
event_types[event_type] = EventType{ callback, name };
}
void UnregisterAllEvents()
{
void UnregisterAllEvents() {
_dbg_assert_msg_(first == nullptr, "Unregistering events with events pending - this isn't good.");
event_types.clear();
}
@@ -672,18 +677,28 @@ void Event_DoStateOld(PointerWrap &p, BaseEvent *ev)
Do(p, *ev);
}
void DoState(PointerWrap &p)
{
void DoState(PointerWrap &p) {
std::lock_guard<std::mutex> lk(externalEventLock);
auto s = p.Section("CoreTiming", 1, 3);
if (!s)
return;
int n = (int) event_types.size();
int n = (int)event_types.size();
int current = n;
Do(p, n);
if (n > current) {
WARN_LOG(SAVESTATE, "Savestate failure: more events than current (can't ever remove an event)");
p.SetError(p.ERROR_FAILURE);
return;
}
// These (should) be filled in later by the modules.
event_types.resize(n, EventType{ AntiCrashCallback, "INVALID EVENT" });
for (int i = 0; i < current; ++i) {
event_types[i].callback = AntiCrashCallback;
event_types[i].name = "INVALID EVENT";
}
nextEventTypeRestoreId = n;
if (s >= 3) {
DoLinkedList<BaseEvent, GetNewEvent, FreeEvent, Event_DoState>(p, first, (Event **) NULL);
+1 -1
View File
@@ -86,7 +86,7 @@ namespace CoreTiming
// Returns the event_type identifier.
int RegisterEvent(const char *name, TimedCallback callback);
// For save states.
void RestoreRegisterEvent(int event_type, const char *name, TimedCallback callback);
void RestoreRegisterEvent(int &event_type, const char *name, TimedCallback callback);
void UnregisterAllEvents();
// userdata MAY NOT CONTAIN POINTERS. userdata might get written and reloaded from disk,
+2
View File
@@ -301,6 +301,8 @@ void __CheatShutdown() {
void __CheatDoState(PointerWrap &p) {
auto s = p.Section("CwCheat", 0, 2);
if (!s) {
CheatEvent = -1;
CoreTiming::RestoreRegisterEvent(CheatEvent, "CheatEvent", &hleCheat);
return;
}
+2 -1
View File
@@ -299,7 +299,8 @@ void __DisplayDoState(PointerWrap &p) {
ScheduleLagSync();
}
} else {
lagSyncEvent = CoreTiming::RegisterEvent("LagSync", &hleLagSync);
lagSyncEvent = -1;
CoreTiming::RestoreRegisterEvent(lagSyncEvent, "LagSync", &hleLagSync);
ScheduleLagSync();
}
+3 -9
View File
@@ -153,9 +153,6 @@ static void __ApctlState(u64 userdata, int cyclesLate) {
int ScheduleApctlState(int event, int newState, int usec, const char* reason) {
int uid = event + 1;
if (apctlStateEvent < 0)
apctlStateEvent = CoreTiming::RegisterEvent("__ApctlState", __ApctlState);
u64 param = ((u64)__KernelGetCurThread()) << 32 | uid;
CoreTiming::ScheduleEvent(usToCycles(usec), apctlStateEvent, param);
__KernelWaitCurThread(WAITTYPE_NET, uid, newState, 0, false, reason);
@@ -304,14 +301,11 @@ void __NetDoState(PointerWrap &p) {
}
if (s >= 5) {
Do(p, apctlStateEvent);
if (apctlStateEvent != -1) {
CoreTiming::RestoreRegisterEvent(apctlStateEvent, "__ApctlState", __ApctlState);
}
}
else {
} else {
apctlStateEvent = -1;
}
CoreTiming::RestoreRegisterEvent(apctlStateEvent, "__ApctlState", __ApctlState);
if (p.mode == p.MODE_READ) {
// Let's not change "Inited" value when Loading SaveState in the middle of multiplayer to prevent memory & port leaks
netApctlInited = cur_netApctlInited;
+7 -30
View File
@@ -351,9 +351,6 @@ int WaitBlockingAdhocctlSocket(AdhocctlRequest request, int usec, const char* re
return ERROR_NET_ADHOCCTL_BUSY;
}
if (adhocctlNotifyEvent < 0)
adhocctlNotifyEvent = CoreTiming::RegisterEvent("__AdhocctlNotify", __AdhocctlNotify);
u64 param = ((u64)__KernelGetCurThread()) << 32 | uid;
adhocctlStartTime = (u64)(time_now_d() * 1000000.0);
adhocctlRequests[uid] = request;
@@ -368,9 +365,6 @@ int WaitBlockingAdhocctlSocket(AdhocctlRequest request, int usec, const char* re
int ScheduleAdhocctlState(int event, int newState, int usec, const char* reason) {
int uid = event + 1;
if (adhocctlStateEvent < 0)
adhocctlStateEvent = CoreTiming::RegisterEvent("__AdhocctlState", __AdhocctlState);
u64 param = ((u64)__KernelGetCurThread()) << 32 | uid;
CoreTiming::ScheduleEvent(usToCycles(usec), adhocctlStateEvent, param);
__KernelWaitCurThread(WAITTYPE_NET, uid, newState, 0, false, reason);
@@ -382,9 +376,6 @@ int StartGameModeScheduler(int bufSize) {
if (gameModeSocket < 0)
return -1;
if (gameModeNotifyEvent < 0)
gameModeNotifyEvent = CoreTiming::RegisterEvent("__GameModeNotify", __GameModeNotify);
INFO_LOG(SCENET, "GameMode Scheduler (%d, %d) has started", gameModeSocket, bufSize);
u64 param = ((u64)__KernelGetCurThread()) << 32 | bufSize;
CoreTiming::ScheduleEvent(usToCycles(GAMEMODE_INIT_DELAY), gameModeNotifyEvent, param);
@@ -902,9 +893,6 @@ int WaitBlockingAdhocSocket(u64 threadSocketId, int type, int pspSocketId, void*
return ERROR_NET_ADHOC_BUSY; // ERROR_NET_ADHOC_TIMEOUT
}
if (adhocSocketNotifyEvent < 0)
adhocSocketNotifyEvent = CoreTiming::RegisterEvent("__AdhocSocketNotify", __AdhocSocketNotify);
//changeBlockingMode(socketId, 1);
u32 tmout = timeoutUS;
@@ -1000,38 +988,27 @@ void __NetAdhocDoState(PointerWrap &p) {
Do(p, adhocConnectionType);
Do(p, adhocctlState);
Do(p, adhocctlNotifyEvent);
if (adhocctlNotifyEvent != -1) {
CoreTiming::RestoreRegisterEvent(adhocctlNotifyEvent, "__AdhocctlNotify", __AdhocctlNotify);
}
Do(p, adhocSocketNotifyEvent);
if (adhocSocketNotifyEvent != -1) {
CoreTiming::RestoreRegisterEvent(adhocSocketNotifyEvent, "__AdhocSocketNotify", __AdhocSocketNotify);
}
}
else {
} else {
adhocConnectionType = ADHOC_CONNECT;
adhocctlState = ADHOCCTL_STATE_DISCONNECTED;
adhocctlNotifyEvent = -1;
adhocSocketNotifyEvent = -1;
}
CoreTiming::RestoreRegisterEvent(adhocctlNotifyEvent, "__AdhocctlNotify", __AdhocctlNotify);
CoreTiming::RestoreRegisterEvent(adhocSocketNotifyEvent, "__AdhocSocketNotify", __AdhocSocketNotify);
if (s >= 6) {
Do(p, gameModeNotifyEvent);
if (gameModeNotifyEvent != -1) {
CoreTiming::RestoreRegisterEvent(gameModeNotifyEvent, "__GameModeNotify", __GameModeNotify);
}
}
else {
} else {
gameModeNotifyEvent = -1;
}
CoreTiming::RestoreRegisterEvent(gameModeNotifyEvent, "__GameModeNotify", __GameModeNotify);
if (s >= 7) {
Do(p, adhocctlStateEvent);
if (adhocctlStateEvent != -1) {
CoreTiming::RestoreRegisterEvent(adhocctlStateEvent, "__AdhocctlState", __AdhocctlState);
}
}
else {
} else {
adhocctlStateEvent = -1;
}
CoreTiming::RestoreRegisterEvent(adhocctlStateEvent, "__AdhocctlState", __AdhocctlState);
if (s >= 8) {
Do(p, isAdhocctlBusy);
Do(p, netAdhocGameModeEntered);
+1 -6
View File
@@ -709,10 +709,8 @@ void __PsmfPlayerDoState(PointerWrap &p) {
eventPsmfPlayerStatusChange = -1;
} else {
Do(p, eventPsmfPlayerStatusChange);
if (eventPsmfPlayerStatusChange != -1) {
CoreTiming::RestoreRegisterEvent(eventPsmfPlayerStatusChange, "PsmfPlayerStatusChangeEvent", &__PsmfPlayerStatusChange);
}
}
CoreTiming::RestoreRegisterEvent(eventPsmfPlayerStatusChange, "PsmfPlayerStatusChangeEvent", &__PsmfPlayerStatusChange);
if (s < 2) {
// Assume the latest, which is what we were emulating before.
psmfPlayerLibVersion = 0x06060010;
@@ -731,9 +729,6 @@ void __PsmfShutdown() {
}
static void DelayPsmfStateChange(u32 psmfPlayer, u32 newState, s64 delayUs) {
if (eventPsmfPlayerStatusChange == -1) {
eventPsmfPlayerStatusChange = CoreTiming::RegisterEvent("PsmfPlayerStatusChange", &__PsmfPlayerStatusChange);
}
CoreTiming::ScheduleEvent(usToCycles(delayUs), eventPsmfPlayerStatusChange, (u64)psmfPlayer << 32 | newState);
}
+1 -3
View File
@@ -213,9 +213,7 @@ void __SasDoState(PointerWrap &p) {
__SasDisableThread();
}
if (sasMixEvent != -1) {
CoreTiming::RestoreRegisterEvent(sasMixEvent, "SasMix", sasMixFinish);
}
CoreTiming::RestoreRegisterEvent(sasMixEvent, "SasMix", sasMixFinish);
}
void __SasShutdown() {
+4 -3
View File
@@ -105,11 +105,12 @@ void __UmdDoState(PointerWrap &p)
}
if (s > 2) {
Do(p, umdInsertChangeEvent);
CoreTiming::RestoreRegisterEvent(umdInsertChangeEvent, "UmdInsertChange", __UmdInsertChange);
Do(p, UMDInserted);
}
else
} else {
umdInsertChangeEvent = -1;
UMDInserted = true;
}
CoreTiming::RestoreRegisterEvent(umdInsertChangeEvent, "UmdInsertChange", __UmdInsertChange);
}
static u8 __KernelUmdGetState()
+6 -7
View File
@@ -71,8 +71,6 @@ static void __MicBlockingResume(u64 userdata, int cyclesLate) {
waitingThreads.erase(waitingThreads.begin() + count);
} else {
u64 waitTimeus = (waitingThread.needSize - Microphone::getReadMicDataLength()) * 1000000 / 2 / waitingThread.sampleRate;
if(eventMicBlockingResume == -1)
eventMicBlockingResume = CoreTiming::RegisterEvent("MicBlockingResume", &__MicBlockingResume);
CoreTiming::ScheduleEvent(usToCycles(waitTimeus), eventMicBlockingResume, userdata);
}
} else {
@@ -119,6 +117,10 @@ void __UsbMicShutdown() {
void __UsbMicDoState(PointerWrap &p) {
auto s = p.Section("sceUsbMic", 0, 3);
if (!s) {
// Still need to restore the event.
eventMicBlockingResume = -1;
CoreTiming::RestoreRegisterEvent(eventMicBlockingResume, "MicBlockingResume", &__MicBlockingResume);
waitingThreads.clear();
return;
}
bool isMicStartedNow = Microphone::isMicStarted();
@@ -130,12 +132,11 @@ void __UsbMicDoState(PointerWrap &p) {
Do(p, micState);
if (s > 1) {
Do(p, eventMicBlockingResume);
if (eventMicBlockingResume != -1) {
CoreTiming::RestoreRegisterEvent(eventMicBlockingResume, "MicBlockingResume", &__MicBlockingResume);
}
} else {
eventMicBlockingResume = -1;
}
CoreTiming::RestoreRegisterEvent(eventMicBlockingResume, "MicBlockingResume", &__MicBlockingResume);
if (s > 2) {
Do(p, curTargetAddr);
Do(p, readMicDataLength);
@@ -452,8 +453,6 @@ u32 __MicInput(u32 maxSamples, u32 sampleRate, u32 bufAddr, MICTYPE type, bool b
}
u64 waitTimeus = (size - Microphone::availableAudioBufSize()) * 1000000 / 2 / sampleRate;
if (eventMicBlockingResume == -1)
eventMicBlockingResume = CoreTiming::RegisterEvent("MicBlockingResume", &__MicBlockingResume);
CoreTiming::ScheduleEvent(usToCycles(waitTimeus), eventMicBlockingResume, __KernelGetCurThread());
MicWaitInfo waitInfo = { __KernelGetCurThread(), bufAddr, size, sampleRate };
waitingThreads.push_back(waitInfo);