Skip to content

Commit

Permalink
SaveState: Automatically fix duplicate event types.
Browse files Browse the repository at this point in the history
Some states during certain version ranges have broken state IDs.  This
will auto-heal those on load as best we can.
  • Loading branch information
unknownbrackets committed Mar 3, 2021
1 parent 6e4dc3f commit 2303cad
Showing 1 changed file with 28 additions and 2 deletions.
30 changes: 28 additions & 2 deletions Core/CoreTiming.cpp
Expand Up @@ -18,6 +18,7 @@
#include <atomic>
#include <cstdio>
#include <mutex>
#include <set>
#include <vector>

#include "Common/Profiler/Profiler.h"
Expand Down Expand Up @@ -47,8 +48,11 @@ struct EventType {
const char *name;
};

std::vector<EventType> event_types;
int nextEventTypeRestoreId = -1;
static std::vector<EventType> event_types;
// Only used during restore.
static std::set<int> usedEventTypes;
static std::set<int> restoredEventTypes;
static int nextEventTypeRestoreId = -1;

struct BaseEvent {
s64 time;
Expand Down Expand Up @@ -172,6 +176,7 @@ int RegisterEvent(const char *name, TimedCallback callback) {

int id = (int)event_types.size();
event_types.push_back(EventType{ callback, name });
usedEventTypes.insert(id);
return id;
}

Expand All @@ -181,15 +186,32 @@ void AntiCrashCallback(u64 userdata, int cyclesLate) {
}

void RestoreRegisterEvent(int &event_type, const char *name, TimedCallback callback) {
// Some old states have a duplicate restore, do our best to fix...
if (restoredEventTypes.count(event_type) != 0)
event_type = -1;
if (event_type == -1)
event_type = nextEventTypeRestoreId++;
if (event_type >= event_types.size()) {
// Give it any unused event id starting from the end.
// Older save states with messed up ids have gaps near the end.
for (int i = (int)event_types.size() - 1; i >= 0; --i) {
if (usedEventTypes.count(i) == 0) {
event_type = i;
break;
}
}
}
_assert_msg_(event_type >= 0 && event_type < event_types.size(), "Invalid event type %d", event_type);
event_types[event_type] = EventType{ callback, name };
usedEventTypes.insert(event_type);
restoredEventTypes.insert(event_type);
}

void UnregisterAllEvents() {
_dbg_assert_msg_(first == nullptr, "Unregistering events with events pending - this isn't good.");
event_types.clear();
usedEventTypes.clear();
restoredEventTypes.clear();
}

void Init()
Expand Down Expand Up @@ -661,11 +683,13 @@ void Event_DoState(PointerWrap &p, BaseEvent *ev)
Do(p, ev->time);
Do(p, ev->userdata);
Do(p, ev->type);
usedEventTypes.insert(ev->type);
}

void Event_DoStateOld(PointerWrap &p, BaseEvent *ev)
{
Do(p, *ev);
usedEventTypes.insert(ev->type);
}

void DoState(PointerWrap &p) {
Expand All @@ -690,6 +714,8 @@ void DoState(PointerWrap &p) {
event_types[i].name = "INVALID EVENT";
}
nextEventTypeRestoreId = n - 1;
usedEventTypes.clear();
restoredEventTypes.clear();

if (s >= 3) {
DoLinkedList<BaseEvent, GetNewEvent, FreeEvent, Event_DoState>(p, first, (Event **) NULL);
Expand Down

0 comments on commit 2303cad

Please sign in to comment.