mirror of
https://github.com/libretro/RetroArch
synced 2025-02-21 09:39:56 +00:00
More correct save state and rewind handling.
This commit is contained in:
parent
f4cc8a4bca
commit
bc66841a29
21
file.c
21
file.c
@ -413,11 +413,14 @@ bool save_state(const char *path)
|
||||
}
|
||||
|
||||
SSNES_LOG("State size: %d bytes.\n", (int)size);
|
||||
psnes_serialize((uint8_t*)data, size);
|
||||
bool ret = dump_to_file(path, data, size);
|
||||
free(data);
|
||||
bool ret = psnes_serialize((uint8_t*)data, size);
|
||||
if (ret)
|
||||
ret = dump_to_file(path, data, size);
|
||||
|
||||
if (!ret)
|
||||
SSNES_ERR("Failed to save state to \"%s\".\n", path);
|
||||
|
||||
free(data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -426,13 +429,14 @@ bool load_state(const char *path)
|
||||
SSNES_LOG("Loading state: \"%s\".\n", path);
|
||||
void *buf = NULL;
|
||||
ssize_t size = read_file(path, &buf);
|
||||
|
||||
if (size < 0)
|
||||
{
|
||||
SSNES_ERR("Failed to load state from \"%s\".\n", path);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
bool ret = true;
|
||||
SSNES_LOG("State size: %d bytes.\n", (int)size);
|
||||
|
||||
uint8_t *block_buf[2] = {NULL, NULL};
|
||||
@ -486,10 +490,10 @@ bool load_state(const char *path)
|
||||
}
|
||||
}
|
||||
|
||||
psnes_unserialize((uint8_t*)buf, size);
|
||||
ret = psnes_unserialize((uint8_t*)buf, size);
|
||||
|
||||
// Flush back :D
|
||||
for (unsigned i = 0; i < 2; i++)
|
||||
for (unsigned i = 0; i < 2 && ret; i++)
|
||||
{
|
||||
if (block_buf[i])
|
||||
{
|
||||
@ -502,10 +506,9 @@ bool load_state(const char *path)
|
||||
for (unsigned i = 0; i < 2; i++)
|
||||
if (block_buf[i])
|
||||
free(block_buf[i]);
|
||||
}
|
||||
|
||||
free(buf);
|
||||
return true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void load_ram_file(const char *path, int type)
|
||||
|
@ -277,6 +277,7 @@ struct global
|
||||
// Rewind support.
|
||||
state_manager_t *state_manager;
|
||||
void *state_buf;
|
||||
size_t state_size;
|
||||
bool frame_is_reverse;
|
||||
|
||||
// Movie playback/recording support.
|
||||
|
56
ssnes.c
56
ssnes.c
@ -1115,17 +1115,35 @@ static void deinit_cheats(void)
|
||||
|
||||
static void init_rewind(void)
|
||||
{
|
||||
if (g_settings.rewind_enable)
|
||||
if (!g_settings.rewind_enable)
|
||||
return;
|
||||
|
||||
g_extern.state_size = psnes_serialize_size();
|
||||
|
||||
// Make sure we allocate at least 4-byte multiple.
|
||||
size_t aligned_state_size = (g_extern.state_size + 3) & ~3;
|
||||
g_extern.state_buf = calloc(1, aligned_state_size);
|
||||
|
||||
if (!g_extern.state_buf)
|
||||
{
|
||||
size_t serial_size = psnes_serialize_size();
|
||||
g_extern.state_buf = calloc(1, (serial_size + 3) & ~3); // Make sure we allocate at least 4-byte multiple.
|
||||
psnes_serialize((uint8_t*)g_extern.state_buf, serial_size);
|
||||
SSNES_ERR("Failed to allocate memory for rewind buffer!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!psnes_serialize((uint8_t*)g_extern.state_buf, g_extern.state_size))
|
||||
{
|
||||
SSNES_ERR("Failed to perform initial serialization for rewind!\n");
|
||||
free(g_extern.state_buf);
|
||||
g_extern.state_buf = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
SSNES_LOG("Initing rewind buffer with size: %u MB\n", (unsigned)(g_settings.rewind_buffer_size / 1000000));
|
||||
g_extern.state_manager = state_manager_new((serial_size + 3) & ~3, g_settings.rewind_buffer_size, g_extern.state_buf);
|
||||
g_extern.state_manager = state_manager_new(aligned_state_size, g_settings.rewind_buffer_size, g_extern.state_buf);
|
||||
|
||||
if (!g_extern.state_manager)
|
||||
SSNES_WARN("Failed to init rewind buffer. Rewinding will be disabled!\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void deinit_rewind(void)
|
||||
{
|
||||
@ -1415,17 +1433,18 @@ static void check_savestates(void)
|
||||
else
|
||||
snprintf(save_path, sizeof(save_path), "%s", g_extern.savestate_name);
|
||||
|
||||
if (!save_state(save_path))
|
||||
char msg[512];
|
||||
if (save_state(save_path))
|
||||
{
|
||||
msg_queue_clear(g_extern.msg_queue);
|
||||
char msg[512];
|
||||
snprintf(msg, sizeof(msg), "Failed to save state to \"%s\"", save_path);
|
||||
msg_queue_push(g_extern.msg_queue, msg, 2, 180);
|
||||
snprintf(msg, sizeof(msg), "Saved state to slot #%u!", g_extern.state_slot);
|
||||
msg_queue_push(g_extern.msg_queue, msg, 1, 180);
|
||||
}
|
||||
else
|
||||
{
|
||||
msg_queue_clear(g_extern.msg_queue);
|
||||
msg_queue_push(g_extern.msg_queue, "Saved state!", 1, 180);
|
||||
snprintf(msg, sizeof(msg), "Failed to save state to \"%s\"", save_path);
|
||||
msg_queue_push(g_extern.msg_queue, msg, 2, 180);
|
||||
}
|
||||
}
|
||||
old_should_savestate = should_savestate;
|
||||
@ -1441,17 +1460,18 @@ static void check_savestates(void)
|
||||
else
|
||||
snprintf(load_path, sizeof(load_path), "%s", g_extern.savestate_name);
|
||||
|
||||
if (!load_state(load_path))
|
||||
char msg[512];
|
||||
if (load_state(load_path))
|
||||
{
|
||||
msg_queue_clear(g_extern.msg_queue);
|
||||
char msg[512];
|
||||
snprintf(msg, sizeof(msg), "Failed to load state from \"%s\"", load_path);
|
||||
msg_queue_push(g_extern.msg_queue, msg, 2, 180);
|
||||
snprintf(msg, sizeof(msg), "Loaded state from slot #%u!", g_extern.state_slot);
|
||||
msg_queue_push(g_extern.msg_queue, msg, 1, 180);
|
||||
}
|
||||
else
|
||||
{
|
||||
msg_queue_clear(g_extern.msg_queue);
|
||||
msg_queue_push(g_extern.msg_queue, "Loaded state!", 1, 180);
|
||||
snprintf(msg, sizeof(msg), "Failed to load state from \"%s\"", load_path);
|
||||
msg_queue_push(g_extern.msg_queue, msg, 2, 180);
|
||||
}
|
||||
}
|
||||
old_should_loadstate = should_loadstate;
|
||||
@ -1587,7 +1607,7 @@ static void check_rewind(void)
|
||||
setup_rewind_audio();
|
||||
|
||||
msg_queue_push(g_extern.msg_queue, "Rewinding!", 0, g_extern.is_paused ? 1 : 30);
|
||||
psnes_unserialize((uint8_t*)buf, psnes_serialize_size());
|
||||
psnes_unserialize((uint8_t*)buf, g_extern.state_size);
|
||||
|
||||
if (g_extern.bsv.movie)
|
||||
bsv_movie_frame_rewind(g_extern.bsv.movie);
|
||||
@ -1601,7 +1621,7 @@ static void check_rewind(void)
|
||||
cnt = (cnt + 1) % (g_settings.rewind_granularity ? g_settings.rewind_granularity : 1); // Avoid possible SIGFPE.
|
||||
if (cnt == 0 || g_extern.bsv.movie)
|
||||
{
|
||||
psnes_serialize((uint8_t*)g_extern.state_buf, psnes_serialize_size());
|
||||
psnes_serialize((uint8_t*)g_extern.state_buf, g_extern.state_size);
|
||||
state_manager_push(g_extern.state_manager, g_extern.state_buf);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user