openMSX
ReverseManager.hh
Go to the documentation of this file.
1 #ifndef REVERSEMANGER_HH
2 #define REVERSEMANGER_HH
3 
4 #include "Schedulable.hh"
5 #include "EventListener.hh"
6 #include "StateChangeListener.hh"
7 #include "Command.hh"
8 #include "EmuTime.hh"
9 #include "MemBuffer.hh"
10 #include "DeltaBlock.hh"
11 #include "span.hh"
12 #include "outer.hh"
13 #include <vector>
14 #include <map>
15 #include <memory>
16 #include <cstdint>
17 
18 namespace openmsx {
19 
20 class MSXMotherBoard;
21 class Keyboard;
22 class EventDelay;
23 class EventDistributor;
24 class TclObject;
25 class Interpreter;
26 
27 class ReverseManager final : private EventListener, private StateChangeRecorder
28 {
29 public:
30  explicit ReverseManager(MSXMotherBoard& motherBoard);
32 
33  // Keyboard is special because we need to transfer the host keyboard
34  // state on 'reverse goto' to be able to resynchronize when replay
35  // stops. See Keyboard::transferHostKeyMatrix() for more info.
36  void registerKeyboard(Keyboard& keyboard_) {
37  keyboard = &keyboard_;
38  }
39 
40  // To not loose any events we need to flush delayed events before
41  // switching machine. See comments in goTo() for more info.
42  void registerEventDelay(EventDelay& eventDelay_) {
43  eventDelay = &eventDelay_;
44  }
45 
46  // Should only be used by MSXMotherBoard to be able to transfer
47  // reRecordCount to ReverseManager for version 2 of MSXMotherBoard
48  // serializers.
49  void setReRecordCount(unsigned count) {
50  reRecordCount = count;
51  }
52 
53  bool isReplaying() const override;
54 
55 private:
56  struct ReverseChunk {
57  ReverseChunk() : time(EmuTime::zero()) {}
58 
59  EmuTime time;
60  std::vector<std::shared_ptr<DeltaBlock>> deltaBlocks;
61  MemBuffer<uint8_t> savestate;
62  size_t size;
63 
64  // Number of recorded events (or replay index) when this
65  // snapshot was created. So when going back replay should
66  // start at this index.
67  unsigned eventCount;
68  };
69  using Chunks = std::map<unsigned, ReverseChunk>;
70  using Events = std::vector<std::shared_ptr<StateChange>>;
71 
72  struct ReverseHistory {
73  void swap(ReverseHistory& other);
74  void clear();
75  unsigned getNextSeqNum(EmuTime::param time) const;
76 
77  Chunks chunks;
78  Events events;
79  LastDeltaBlocks lastDeltaBlocks;
80  };
81 
82  bool isCollecting() const { return collecting; }
83 
84  void start();
85  void stop();
86  void status(TclObject& result) const;
87  void debugInfo(TclObject& result) const;
88  void goBack(span<const TclObject> tokens);
89  void goTo(span<const TclObject> tokens);
90  void saveReplay(Interpreter& interp,
91  span<const TclObject> tokens, TclObject& result);
92  void loadReplay(Interpreter& interp,
93  span<const TclObject> tokens, TclObject& result);
94 
95  void signalStopReplay(EmuTime::param time);
96  EmuTime::param getEndTime(const ReverseHistory& history) const;
97  void goTo(EmuTime::param targetTime, bool novideo);
98  void goTo(EmuTime::param targetTime, bool novideo,
99  ReverseHistory& history, bool sameTimeLine);
100  void transferHistory(ReverseHistory& oldHistory,
101  unsigned oldEventCount);
102  void transferState(MSXMotherBoard& newBoard);
103  void takeSnapshot(EmuTime::param time);
104  void schedule(EmuTime::param time);
105  void replayNextEvent();
106  template<unsigned N> void dropOldSnapshots(unsigned count);
107 
108  // Schedulable
109  struct SyncNewSnapshot final : Schedulable {
110  friend class ReverseManager;
111  explicit SyncNewSnapshot(Scheduler& s) : Schedulable(s) {}
112  void executeUntil(EmuTime::param /*time*/) override {
113  auto& rm = OUTER(ReverseManager, syncNewSnapshot);
114  rm.execNewSnapshot();
115  }
116  } syncNewSnapshot;
117  struct SyncInputEvent final : Schedulable {
118  friend class ReverseManager;
119  explicit SyncInputEvent(Scheduler& s) : Schedulable(s) {}
120  void executeUntil(EmuTime::param /*time*/) override {
121  auto& rm = OUTER(ReverseManager, syncInputEvent);
122  rm.execInputEvent();
123  }
124  } syncInputEvent;
125 
126  void execNewSnapshot();
127  void execInputEvent();
128  EmuTime::param getCurrentTime() const { return syncNewSnapshot.getCurrentTime(); }
129 
130  // EventListener
131  int signalEvent(const std::shared_ptr<const Event>& event) override;
132 
133  // StateChangeRecorder
134  void signalStateChange(const std::shared_ptr<StateChange>& event) override;
135  void stopReplay(EmuTime::param time) override;
136 
137  MSXMotherBoard& motherBoard;
138  EventDistributor& eventDistributor;
139 
140  struct ReverseCmd final : Command {
141  explicit ReverseCmd(CommandController& controller);
142  void execute(span<const TclObject> tokens, TclObject& result) override;
143  std::string help(const std::vector<std::string>& tokens) const override;
144  void tabCompletion(std::vector<std::string>& tokens) const override;
145  } reverseCmd;
146 
147  Keyboard* keyboard;
148  EventDelay* eventDelay;
149  ReverseHistory history;
150  unsigned replayIndex;
151  bool collecting;
152  bool pendingTakeSnapshot;
153 
154  unsigned reRecordCount;
155 
156  friend struct Replay;
157 };
158 
159 } // namespace openmsx
160 
161 #endif
StateChangeListener.hh
utf8::unchecked::size
size_t size(std::string_view utf8)
Definition: utf8_unchecked.hh:227
EventListener.hh
LZ4::count
ALWAYS_INLINE unsigned count(const uint8_t *pIn, const uint8_t *pMatch, const uint8_t *pInLimit)
Definition: lz4.cc:207
Schedulable.hh
span
Definition: span.hh:126
DeltaBlock.hh
openmsx::ReverseManager::ReverseManager
ReverseManager(MSXMotherBoard &motherBoard)
Definition: ReverseManager.cc:138
OUTER
#define OUTER(type, member)
Definition: outer.hh:41
openmsx::ReverseManager::~ReverseManager
~ReverseManager()
Definition: ReverseManager.cc:157
openmsx::MSXMotherBoard
Definition: MSXMotherBoard.hh:61
openmsx::ReverseManager::setReRecordCount
void setReRecordCount(unsigned count)
Definition: ReverseManager.hh:49
openmsx::EventDelay
This class is responsible for translating host events into MSX events.
Definition: EventDelay.hh:27
openmsx::ReverseManager::registerEventDelay
void registerEventDelay(EventDelay &eventDelay_)
Definition: ReverseManager.hh:42
openmsx::Keyboard
Keyboard
Definition: Keyboard.cc:1385
openmsx::Keyboard
Definition: Keyboard.hh:37
MemBuffer.hh
openmsx::EventListener
Definition: EventListener.hh:11
span.hh
outer.hh
openmsx::Schedulable
Schedulable
Definition: Schedulable.cc:69
EmuTime.hh
std::swap
void swap(openmsx::MemBuffer< T > &l, openmsx::MemBuffer< T > &r) noexcept
Definition: MemBuffer.hh:202
openmsx::ReverseManager::isReplaying
bool isReplaying() const override
Definition: ReverseManager.cc:163
Command.hh
openmsx::ReverseManager
Definition: ReverseManager.hh:28
openmsx::Scheduler
Scheduler
Definition: Scheduler.cc:132
openmsx::ReverseManager::registerKeyboard
void registerKeyboard(Keyboard &keyboard_)
Definition: ReverseManager.hh:36
openmsx::StateChangeRecorder
Definition: StateChangeListener.hh:36
openmsx::Replay
Definition: ReverseManager.cc:60
openmsx
This file implemented 3 utility functions:
Definition: Autofire.cc:5