@@ -54,6 +54,43 @@ bool PCSX::Widgets::MemcardManager::draw(GUI* gui, const char* title) {
54
54
return false ;
55
55
}
56
56
57
+ const bool undoDisabled = m_undo.size () == 0 ;
58
+ if (undoDisabled) ImGui::BeginDisabled ();
59
+ bool isLatest = m_undo.size () == m_undoIndex;
60
+ const bool wasLatest = isLatest;
61
+ if (ImGui::SliderInt (_ (" Undo" ), &m_undoIndex, 0 , m_undo.size (), " " )) {
62
+ isLatest = m_undo.size () == m_undoIndex;
63
+ const auto dataCard1 = g_emulator->m_sio ->getMcdData (1 );
64
+ const auto dataCard2 = g_emulator->m_sio ->getMcdData (2 );
65
+ if (isLatest) {
66
+ std::memcpy (dataCard1, m_latest.get (), SIO::MCD_SIZE);
67
+ std::memcpy (dataCard2, m_latest.get () + SIO::MCD_SIZE, SIO::MCD_SIZE);
68
+ } else {
69
+ if (wasLatest) {
70
+ std::unique_ptr<uint8_t []> latest (new uint8_t [SIO::MCD_SIZE * 2 ]);
71
+ std::memcpy (latest.get (), dataCard1, SIO::MCD_SIZE);
72
+ std::memcpy (latest.get () + SIO::MCD_SIZE, dataCard2, SIO::MCD_SIZE);
73
+ m_latest.swap (latest);
74
+ }
75
+ std::memcpy (dataCard1, m_undo[m_undoIndex].second .get (), SIO::MCD_SIZE);
76
+ std::memcpy (dataCard2, m_undo[m_undoIndex].second .get () + SIO::MCD_SIZE, SIO::MCD_SIZE);
77
+ }
78
+ g_emulator->m_sio ->saveMcd (1 );
79
+ g_emulator->m_sio ->saveMcd (2 );
80
+ }
81
+ ImGui::TextUnformatted (_ (" Undo version: " ));
82
+ ImGui::SameLine ();
83
+ if (isLatest) {
84
+ ImGui::TextUnformatted (_ (" Latest" ));
85
+ } else {
86
+ ImGui::TextUnformatted (m_undo[m_undoIndex].first .c_str ());
87
+ }
88
+ if (undoDisabled) ImGui::EndDisabled ();
89
+ if (ImGui::Button (_ (" Clear Undo buffer" ))) {
90
+ m_undo.clear ();
91
+ m_undoIndex = 0 ;
92
+ }
93
+
57
94
// Insert or remove memory cards. Send a SIO IRQ to the emulator if this happens as well.
58
95
if (ImGui::Checkbox (_ (" Memory Card 1 inserted" ),
59
96
&g_emulator->settings .get <Emulator::SettingMcd1Inserted>().value )) {
@@ -125,15 +162,29 @@ bool PCSX::Widgets::MemcardManager::draw(GUI* gui, const char* title) {
125
162
// can't handle multiple buttons with the same name well
126
163
auto buttonName = fmt::format (_ (" Erase##{}" ), i);
127
164
if (ImGui::SmallButton (buttonName.c_str ())) {
165
+ auto latest = getLatest ();
128
166
g_emulator->m_sio ->eraseMcdFile (block);
167
+ saveUndoBuffer (std::move (latest),
168
+ fmt::format (_ (" Erased file {}({}) off card {}" ), block.number ,
169
+ gui->hasJapanese () ? block.titleUtf8 : block.titleAscii , block.mcd ));
170
+ g_emulator->m_sio ->saveMcd (card);
129
171
}
130
172
ImGui::SameLine ();
131
173
132
174
buttonName = fmt::format (_ (" Copy##{}" ), i);
133
175
if (otherFreeSpace >= size) {
134
176
if (ImGui::SmallButton (buttonName.c_str ())) {
177
+ auto latest = getLatest ();
135
178
bool success = g_emulator->m_sio ->copyMcdFile (block);
136
- if (!success) gui->addNotification (" Error while copying save file" );
179
+ if (!success) {
180
+ gui->addNotification (" Error while copying save file" );
181
+ } else {
182
+ saveUndoBuffer (
183
+ std::move (latest),
184
+ fmt::format (_ (" Copied file {}({}) from card {} to card {}" ), block.number ,
185
+ gui->hasJapanese () ? block.titleUtf8 : block.titleAscii , card, othercard));
186
+ g_emulator->m_sio ->saveMcd (othercard);
187
+ }
137
188
}
138
189
} else {
139
190
ImGui::BeginDisabled ();
@@ -145,11 +196,18 @@ bool PCSX::Widgets::MemcardManager::draw(GUI* gui, const char* title) {
145
196
buttonName = fmt::format (_ (" Move##{}" ), i);
146
197
if (otherFreeSpace >= size) {
147
198
if (ImGui::SmallButton (buttonName.c_str ())) {
199
+ auto latest = getLatest ();
148
200
bool success = g_emulator->m_sio ->copyMcdFile (block);
149
201
if (!success) {
150
202
gui->addNotification (" Error while copying save file" );
151
203
} else {
152
204
g_emulator->m_sio ->eraseMcdFile (block);
205
+ saveUndoBuffer (
206
+ std::move (latest),
207
+ fmt::format (_ (" Moved file {}({}) from card {} to card {}" ), block.number ,
208
+ gui->hasJapanese () ? block.titleUtf8 : block.titleAscii , card, othercard));
209
+ g_emulator->m_sio ->saveMcd (1 );
210
+ g_emulator->m_sio ->saveMcd (2 );
153
211
}
154
212
}
155
213
} else {
@@ -295,3 +353,8 @@ void PCSX::Widgets::MemcardManager::copyToClipboard(const SIO::McdBlock& block)
295
353
const auto pixels = getIconRGBA8888 (block);
296
354
clip::set_image (pixels);
297
355
}
356
+
357
+ void PCSX::Widgets::MemcardManager::saveUndoBuffer (std::unique_ptr<uint8_t []>&& tosave, const std::string& action) {
358
+ m_undo.resize (m_undoIndex++);
359
+ m_undo.push_back ({action, std::move (tosave)});
360
+ }
0 commit comments