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 "Command.hh"
7#include "EmuTime.hh"
8
9#include "MemBuffer.hh"
10#include "DeltaBlock.hh"
11#include "outer.hh"
12#include "view.hh"
13
14#include <cstdint>
15#include <deque>
16#include <span>
17#include <map>
18#include <memory>
19#include <string_view>
20#include <vector>
21
22namespace openmsx {
23
24class EventDelay;
25class EventDistributor;
26class Interpreter;
27class MSXMotherBoard;
28class StateChange;
29class TclObject;
30
31class ReverseManager final : private EventListener
32{
33public:
34 static constexpr std::string_view REPLAY_DIR = "replays";
35 static constexpr std::string_view REPLAY_EXTENSION = ".omr";
36
37public:
38 explicit ReverseManager(MSXMotherBoard& motherBoard);
40
41 // To not loose any events we need to flush delayed events before
42 // switching machine. See comments in goTo() for more info.
43 void registerEventDelay(EventDelay& eventDelay_) {
44 eventDelay = &eventDelay_;
45 }
46
47 // Should only be used by MSXMotherBoard to be able to transfer
48 // reRecordCount to ReverseManager for version 2 of MSXMotherBoard
49 // serializers.
50 void setReRecordCount(unsigned count) {
51 reRecordCount = count;
52 }
53
54 [[nodiscard]] bool isReplaying() const;
55 void stopReplay(EmuTime::param time) noexcept;
56
57 template<typename T, typename... Args>
58 StateChange& record(EmuTime::param time, Args&& ...args) {
59 assert(!isReplaying());
60 ++replayIndex;
61 history.events.push_back(std::make_unique<T>(time, std::forward<Args>(args)...));
62 return *history.events.back();
63 }
64
65 [[nodiscard]] bool isCollecting() const { return collecting; }
66 [[nodiscard]] bool isViewOnlyMode() const;
67 [[nodiscard]] double getBegin() const;
68 [[nodiscard]] double getEnd() const;
69 [[nodiscard]] double getCurrent() const;
70 [[nodiscard]] auto getSnapshotTimes() const {
71 return view::transform(history.chunks, [](auto& p) {
72 return (p.second.time - EmuTime::zero()).toDouble();
73 });
74 }
75
76private:
77 struct ReverseChunk {
78 EmuTime time = EmuTime::zero();
79 std::vector<std::shared_ptr<DeltaBlock>> deltaBlocks;
80 MemBuffer<uint8_t> savestate;
81
82 // Number of recorded events (or replay index) when this
83 // snapshot was created. So when going back replay should
84 // start at this index.
85 unsigned eventCount;
86 };
87 using Chunks = std::map<unsigned, ReverseChunk>;
88 using Events = std::deque<std::unique_ptr<StateChange>>;
89
90 struct ReverseHistory {
91 void swap(ReverseHistory& other) noexcept;
92 void clear();
93 [[nodiscard]] unsigned getNextSeqNum(EmuTime::param time) const;
94
95 Chunks chunks;
96 Events events;
97 LastDeltaBlocks lastDeltaBlocks;
98 };
99
100 void start();
101 void stop();
102 void status(TclObject& result) const;
103 void debugInfo(TclObject& result) const;
104 void goBack(std::span<const TclObject> tokens);
105 void goTo(std::span<const TclObject> tokens);
106 void saveReplay(Interpreter& interp,
107 std::span<const TclObject> tokens, TclObject& result);
108 void loadReplay(Interpreter& interp,
109 std::span<const TclObject> tokens, TclObject& result);
110
111 void signalStopReplay(EmuTime::param time);
112 [[nodiscard]] EmuTime::param getEndTime(const ReverseHistory& history) const;
113 void goTo(EmuTime::param targetTime, bool noVideo);
114 void goTo(EmuTime::param targetTime, bool noVideo,
115 ReverseHistory& history, bool sameTimeLine);
116 void transferHistory(ReverseHistory& oldHistory,
117 unsigned oldEventCount);
118 void transferState(MSXMotherBoard& newBoard);
119 void takeSnapshot(EmuTime::param time);
120 void schedule(EmuTime::param time);
121 void replayNextEvent();
122 template<unsigned N> void dropOldSnapshots(unsigned count);
123
124 // Schedulable
125 struct SyncNewSnapshot final : Schedulable {
126 friend class ReverseManager;
127 explicit SyncNewSnapshot(Scheduler& s) : Schedulable(s) {}
128 void executeUntil(EmuTime::param /*time*/) override {
129 auto& rm = OUTER(ReverseManager, syncNewSnapshot);
130 rm.execNewSnapshot();
131 }
132 } syncNewSnapshot;
133 struct SyncInputEvent final : Schedulable {
134 friend class ReverseManager;
135 explicit SyncInputEvent(Scheduler& s) : Schedulable(s) {}
136 void executeUntil(EmuTime::param /*time*/) override {
137 auto& rm = OUTER(ReverseManager, syncInputEvent);
138 rm.execInputEvent();
139 }
140 } syncInputEvent;
141
142 void execNewSnapshot();
143 void execInputEvent();
144 [[nodiscard]] EmuTime::param getCurrentTime() const { return syncNewSnapshot.getCurrentTime(); }
145
146 // EventListener
147 bool signalEvent(const Event& event) override;
148
149private:
150 MSXMotherBoard& motherBoard;
151 EventDistributor& eventDistributor;
152
153 struct ReverseCmd final : Command {
154 explicit ReverseCmd(CommandController& controller);
155 void execute(std::span<const TclObject> tokens, TclObject& result) override;
156 [[nodiscard]] std::string help(std::span<const TclObject> tokens) const override;
157 void tabCompletion(std::vector<std::string>& tokens) const override;
158 } reverseCmd;
159
160 EventDelay* eventDelay = nullptr;
161 ReverseHistory history;
162 unsigned replayIndex = 0;
163 bool collecting = false;
164 bool pendingTakeSnapshot = false;
165
166 unsigned reRecordCount = 0;
167
168 friend struct Replay;
169};
170
171} // namespace openmsx
172
173#endif
This class is responsible for translating host events into MSX events.
Definition EventDelay.hh:27
This class manages the lifetime of a block of memory.
Definition MemBuffer.hh:32
void setReRecordCount(unsigned count)
void stopReplay(EmuTime::param time) noexcept
static constexpr std::string_view REPLAY_DIR
void registerEventDelay(EventDelay &eventDelay_)
static constexpr std::string_view REPLAY_EXTENSION
StateChange & record(EmuTime::param time, Args &&...args)
Schedulable(const Schedulable &)=delete
Base class for all external MSX state changing events.
This file implemented 3 utility functions:
Definition Autofire.cc:11
std::variant< KeyUpEvent, KeyDownEvent, MouseMotionEvent, MouseButtonUpEvent, MouseButtonDownEvent, MouseWheelEvent, JoystickAxisMotionEvent, JoystickHatEvent, JoystickButtonUpEvent, JoystickButtonDownEvent, OsdControlReleaseEvent, OsdControlPressEvent, WindowEvent, TextEvent, FileDropEvent, QuitEvent, FinishFrameEvent, CliCommandEvent, GroupEvent, BootEvent, FrameDrawnEvent, BreakEvent, SwitchRendererEvent, TakeReverseSnapshotEvent, AfterTimedEvent, MachineLoadedEvent, MachineActivatedEvent, MachineDeactivatedEvent, MidiInReaderEvent, MidiInWindowsEvent, MidiInCoreMidiEvent, MidiInCoreMidiVirtualEvent, MidiInALSAEvent, Rs232TesterEvent, Rs232NetEvent, ImGuiDelayedActionEvent, ImGuiActiveEvent > Event
Definition Event.hh:445
constexpr auto transform(Range &&range, UnaryOp op)
Definition view.hh:441
#define OUTER(type, member)
Definition outer.hh:42