diff --git a/Core/CoreTiming.cpp b/Core/CoreTiming.cpp index ca30771568..0202a1e6d1 100644 --- a/Core/CoreTiming.cpp +++ b/Core/CoreTiming.cpp @@ -16,9 +16,9 @@ // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. #include -#include #include #include +#include #include "Common/Profiler/Profiler.h" @@ -48,6 +48,7 @@ struct EventType { }; std::vector 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 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(p, first, (Event **) NULL); diff --git a/Core/CoreTiming.h b/Core/CoreTiming.h index 4c5cb013c8..e0c7dba35d 100644 --- a/Core/CoreTiming.h +++ b/Core/CoreTiming.h @@ -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, diff --git a/Core/CwCheat.cpp b/Core/CwCheat.cpp index be1edd7a23..ff53aacbc5 100644 --- a/Core/CwCheat.cpp +++ b/Core/CwCheat.cpp @@ -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; } diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index efc2e3c9cc..68fe36f541 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -299,7 +299,8 @@ void __DisplayDoState(PointerWrap &p) { ScheduleLagSync(); } } else { - lagSyncEvent = CoreTiming::RegisterEvent("LagSync", &hleLagSync); + lagSyncEvent = -1; + CoreTiming::RestoreRegisterEvent(lagSyncEvent, "LagSync", &hleLagSync); ScheduleLagSync(); } diff --git a/Core/HLE/sceNet.cpp b/Core/HLE/sceNet.cpp index 448b0ba66e..386d01ff8c 100644 --- a/Core/HLE/sceNet.cpp +++ b/Core/HLE/sceNet.cpp @@ -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; diff --git a/Core/HLE/sceNetAdhoc.cpp b/Core/HLE/sceNetAdhoc.cpp index 21dc1c0ef2..451589555b 100644 --- a/Core/HLE/sceNetAdhoc.cpp +++ b/Core/HLE/sceNetAdhoc.cpp @@ -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); diff --git a/Core/HLE/scePsmf.cpp b/Core/HLE/scePsmf.cpp index 985b36d18e..df696b0a6d 100644 --- a/Core/HLE/scePsmf.cpp +++ b/Core/HLE/scePsmf.cpp @@ -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); } diff --git a/Core/HLE/sceSas.cpp b/Core/HLE/sceSas.cpp index 25cb02f392..9772d35d0e 100644 --- a/Core/HLE/sceSas.cpp +++ b/Core/HLE/sceSas.cpp @@ -213,9 +213,7 @@ void __SasDoState(PointerWrap &p) { __SasDisableThread(); } - if (sasMixEvent != -1) { - CoreTiming::RestoreRegisterEvent(sasMixEvent, "SasMix", sasMixFinish); - } + CoreTiming::RestoreRegisterEvent(sasMixEvent, "SasMix", sasMixFinish); } void __SasShutdown() { diff --git a/Core/HLE/sceUmd.cpp b/Core/HLE/sceUmd.cpp index 51c44b72ae..8f61204230 100644 --- a/Core/HLE/sceUmd.cpp +++ b/Core/HLE/sceUmd.cpp @@ -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() diff --git a/Core/HLE/sceUsbMic.cpp b/Core/HLE/sceUsbMic.cpp index 086b968f45..99d151d0a7 100644 --- a/Core/HLE/sceUsbMic.cpp +++ b/Core/HLE/sceUsbMic.cpp @@ -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);