mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-07-11 01:25:07 +02:00
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:
+33
-18
@@ -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
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
@@ -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()
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user