Skip to content

Commit 3e01774

Browse files
committed
added in-ram savestates
1 parent 75feafb commit 3e01774

File tree

7 files changed

+69
-10
lines changed

7 files changed

+69
-10
lines changed

core/input/gamepad.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ enum DreamcastKey
5252
EMU_BTN_SAVESTATE,
5353
EMU_BTN_NEXTSLOT,
5454
EMU_BTN_PREVSLOT,
55+
EMU_BTN_LOADSTATE_RAM,
56+
EMU_BTN_SAVESTATE_RAM,
5557
EMU_BTN_BYPASS_KB,
5658
EMU_BTN_SCREENSHOT,
5759
EMU_BTN_SRVMODE, // used internally by virtual gamepad

core/input/gamepad_device.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,14 @@ bool GamepadDevice::handleButtonInput(int port, DreamcastKey key, bool pressed)
110110
if (pressed)
111111
gui_cycleSaveStateSlot(-1);
112112
break;
113+
case EMU_BTN_LOADSTATE_RAM:
114+
if (pressed)
115+
gui_loadState(true);
116+
break;
117+
case EMU_BTN_SAVESTATE_RAM:
118+
if (pressed)
119+
gui_saveState(false, true);
120+
break;
113121
case EMU_BTN_SCREENSHOT:
114122
if (pressed)
115123
gui_takeScreenshot();

core/input/mapping.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ button_list[] =
6464
{ EMU_BTN_SAVESTATE, "emulator", "btn_quick_save" },
6565
{ EMU_BTN_NEXTSLOT, "emulator", "btn_next_slot" },
6666
{ EMU_BTN_PREVSLOT, "emulator", "btn_prev_slot" },
67+
{ EMU_BTN_LOADSTATE_RAM, "emulator", "btn_jump_state_ram" },
68+
{ EMU_BTN_SAVESTATE_RAM, "emulator", "btn_quick_save_ram" },
6769
{ EMU_BTN_BYPASS_KB, "emulator", "btn_bypass_kb" },
6870
{ EMU_BTN_SCREENSHOT, "emulator", "btn_screenshot" },
6971
};

core/nullDC.cpp

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626

2727
static std::string lastStateFile;
2828
static time_t lastStateTime;
29+
const u32 QUICKSAVE_DEFAULT_SIZE = 32 * 1024 * 1024; // 32 MB
30+
static int quicksave_buf[QUICKSAVE_DEFAULT_SIZE] = {0};
2931

3032
struct SavestateHeader
3133
{
@@ -182,8 +184,21 @@ void dc_savestate(int index, const u8 *pngData, u32 pngSize)
182184
ser = Serializer(data, ser.size());
183185
dc_serialize(ser);
184186

185-
std::string filename = hostfs::getSavestatePath(index, true);
186-
FILE *f = nowide::fopen(filename.c_str(), "wb");
187+
FILE *f = nullptr;
188+
std::string filename = "";
189+
if (index == -2)
190+
{
191+
// in-ram savestate
192+
filename = "RAM";
193+
f = fmemopen(quicksave_buf, QUICKSAVE_DEFAULT_SIZE, "wb");
194+
}
195+
else
196+
{
197+
// regular file savestate
198+
filename = hostfs::getSavestatePath(index, true);
199+
f = nowide::fopen(filename.c_str(), "wb");
200+
}
201+
187202
if (f == nullptr)
188203
{
189204
WARN_LOG(SAVESTATE, "Failed to save state - could not open %s for writing", filename.c_str());
@@ -235,8 +250,21 @@ void dc_loadstate(int index)
235250
return;
236251
u32 total_size = 0;
237252

238-
std::string filename = hostfs::getSavestatePath(index, false);
239-
FILE *f = hostfs::storage().openFile(filename, "rb");
253+
FILE *f = nullptr;
254+
std::string filename = "";
255+
if (index == -2)
256+
{
257+
// in-ram savestate
258+
filename = "RAM";
259+
f = fmemopen(quicksave_buf, QUICKSAVE_DEFAULT_SIZE, "rb");
260+
}
261+
else
262+
{
263+
// regular file savestate
264+
filename = hostfs::getSavestatePath(index, false);
265+
f = hostfs::storage().openFile(filename, "rb");
266+
}
267+
240268
if (f == nullptr)
241269
{
242270
WARN_LOG(SAVESTATE, "Failed to load state - could not open %s for reading", filename.c_str());

core/ui/gui.cpp

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1736,30 +1736,45 @@ void gui_error(const std::string& what) {
17361736
error_msg = what;
17371737
}
17381738

1739-
void gui_loadState()
1739+
void gui_loadState(bool inRam)
17401740
{
17411741
const LockGuard lock(guiMutex);
17421742
if (gui_state == GuiState::Closed && dc_savestateAllowed())
17431743
{
17441744
try {
17451745
emu.stop();
1746-
dc_loadstate(config::SavestateSlot);
1746+
if (inRam)
1747+
dc_loadstate(-2); // special slot used for inRam states
1748+
else
1749+
dc_loadstate(config::SavestateSlot);
17471750
emu.start();
17481751
} catch (const FlycastException& e) {
17491752
gui_stop_game(e.what());
17501753
}
17511754
}
17521755
}
17531756

1754-
void gui_saveState(bool stopRestart)
1757+
void gui_saveState(bool stopRestart, bool inRam)
17551758
{
17561759
const LockGuard lock(guiMutex);
17571760
if ((gui_state == GuiState::Closed || !stopRestart) && dc_savestateAllowed())
17581761
{
17591762
try {
17601763
if (stopRestart)
17611764
emu.stop();
1762-
savestate();
1765+
1766+
if (inRam)
1767+
{
1768+
int oldSavestateSlot = config::SavestateSlot; // backup
1769+
config::SavestateSlot = -2; // special slot used for inRam states
1770+
savestate();
1771+
config::SavestateSlot = oldSavestateSlot; // restore
1772+
}
1773+
else
1774+
{
1775+
savestate();
1776+
}
1777+
17631778
if (stopRestart)
17641779
emu.start();
17651780
} catch (const FlycastException& e) {

core/ui/gui.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ void gui_stop_game(const std::string& message = "");
4848
void gui_start_game(const std::string& path);
4949
void gui_error(const std::string& what);
5050
void gui_setOnScreenKeyboardCallback(void (*callback)(bool show));
51-
void gui_loadState();
52-
void gui_saveState(bool stopRestart = true);
51+
void gui_loadState(bool inRam = false);
52+
void gui_saveState(bool stopRestart = true, bool inRam = false);
5353
void gui_cycleSaveStateSlot(int step);
5454
std::string gui_getCurGameBoxartUrl();
5555
void gui_takeScreenshot();

core/ui/settings_controls.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,8 @@ static Mapping dcButtons[] = {
221221
{ EMU_BTN_FFORWARD, Tnop("Fast-forward") },
222222
{ EMU_BTN_LOADSTATE, Tnop("Load State") },
223223
{ EMU_BTN_SAVESTATE, Tnop("Save State") },
224+
{ EMU_BTN_LOADSTATE_RAM, Tnop("Load State in RAM") },
225+
{ EMU_BTN_SAVESTATE_RAM, Tnop("Save State in RAM") },
224226
{ EMU_BTN_NEXTSLOT, Tnop("Next Save State Slot") },
225227
{ EMU_BTN_PREVSLOT, Tnop("Previous Save State Slot") },
226228
{ EMU_BTN_BYPASS_KB, Tnop("Bypass Emulated Keyboard") },
@@ -277,6 +279,8 @@ static Mapping arcadeButtons[] = {
277279
{ EMU_BTN_FFORWARD, Tnop("Fast-forward") },
278280
{ EMU_BTN_LOADSTATE, Tnop("Load State") },
279281
{ EMU_BTN_SAVESTATE, Tnop("Save State") },
282+
{ EMU_BTN_LOADSTATE_RAM, Tnop("Load State in RAM") },
283+
{ EMU_BTN_SAVESTATE_RAM, Tnop("Save State in RAM") },
280284
{ EMU_BTN_NEXTSLOT, Tnop("Next Save State Slot") },
281285
{ EMU_BTN_PREVSLOT, Tnop("Previous Save State Slot") },
282286
{ EMU_BTN_BYPASS_KB, Tnop("Bypass Emulated Keyboard") },

0 commit comments

Comments
 (0)