mirror of
https://github.com/libretro/RetroArch
synced 2025-03-03 04:14:00 +00:00
Merge pull request #7187 from RetroSven/master
implement libretro private def to allow cores to tell RA to save states in background
This commit is contained in:
commit
27edbb58e3
@ -43,6 +43,7 @@
|
||||
#include "verbosity.h"
|
||||
#include "gfx/video_driver.h"
|
||||
#include "audio/audio_driver.h"
|
||||
#include "tasks/tasks_internal.h"
|
||||
|
||||
#ifdef HAVE_RUNAHEAD
|
||||
#include "runahead/copy_load_info.h"
|
||||
@ -298,6 +299,7 @@ bool core_load_game(retro_ctx_load_content_info_t *load_info)
|
||||
#endif
|
||||
|
||||
content_get_status(&contentless, &is_inited);
|
||||
set_save_state_in_background(false);
|
||||
|
||||
if (load_info && load_info->special)
|
||||
current_core.game_loaded = current_core.retro_load_game_special(
|
||||
|
10
dynamic.c
10
dynamic.c
@ -1387,6 +1387,16 @@ bool rarch_environment_cb(unsigned cmd, void *data)
|
||||
break;
|
||||
}
|
||||
|
||||
case RETRO_ENVIRONMENT_SET_SAVE_STATE_IN_BACKGROUND:
|
||||
{
|
||||
bool state = *(const bool*)data;
|
||||
RARCH_LOG("Environ SET_SAVE_STATE_IN_BACKGROUND: %s.\n", state ? "yes" : "no");
|
||||
|
||||
set_save_state_in_background(state) ;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case RETRO_ENVIRONMENT_GET_LIBRETRO_PATH:
|
||||
{
|
||||
const char **path = (const char**)data;
|
||||
|
@ -33,6 +33,8 @@
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
#define RETRO_ENVIRONMENT_SET_SAVE_STATE_IN_BACKGROUND RETRO_ENVIRONMENT_PRIVATE+1
|
||||
|
||||
enum rarch_ctl_state
|
||||
{
|
||||
RARCH_CTL_NONE = 0,
|
||||
|
@ -56,6 +56,7 @@
|
||||
|
||||
#define SAVE_STATE_CHUNK 4096
|
||||
|
||||
static bool save_state_in_background = false;
|
||||
static struct string_list *task_save_files = NULL;
|
||||
|
||||
struct ram_type
|
||||
@ -555,6 +556,33 @@ static void task_save_handler_finished(retro_task_t *task,
|
||||
free(state);
|
||||
}
|
||||
|
||||
void* get_serialized_data(const char *path, size_t serial_size)
|
||||
{
|
||||
retro_ctx_serialize_info_t serial_info;
|
||||
bool ret = false;
|
||||
void *data = NULL;
|
||||
|
||||
data = malloc(serial_size);
|
||||
|
||||
if (!data)
|
||||
return NULL;
|
||||
|
||||
RARCH_LOG("%s: %d %s.\n",
|
||||
msg_hash_to_str(MSG_STATE_SIZE),
|
||||
(int)serial_size,
|
||||
msg_hash_to_str(MSG_BYTES));
|
||||
|
||||
serial_info.data = data;
|
||||
serial_info.size = serial_size;
|
||||
ret = core_serialize(&serial_info);
|
||||
if ( !ret )
|
||||
{
|
||||
free(data) ;
|
||||
return NULL ;
|
||||
}
|
||||
return data ;
|
||||
}
|
||||
|
||||
/**
|
||||
* task_save_handler:
|
||||
* @task : the task being worked on
|
||||
@ -576,9 +604,22 @@ static void task_save_handler(retro_task_t *task)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!state->data)
|
||||
{
|
||||
state->data = get_serialized_data(state->path, state->size) ;
|
||||
}
|
||||
|
||||
remaining = MIN(state->size - state->written, SAVE_STATE_CHUNK);
|
||||
written = (int)intfstream_write(state->file,
|
||||
|
||||
if ( state->data )
|
||||
{
|
||||
written = (int)intfstream_write(state->file,
|
||||
(uint8_t*)state->data + state->written, remaining);
|
||||
}
|
||||
else
|
||||
{
|
||||
written = 0 ;
|
||||
}
|
||||
|
||||
state->written += written;
|
||||
|
||||
@ -1144,85 +1185,90 @@ error:
|
||||
**/
|
||||
bool content_save_state(const char *path, bool save_to_disk, bool autosave)
|
||||
{
|
||||
retro_ctx_serialize_info_t serial_info;
|
||||
retro_ctx_size_info_t info;
|
||||
bool ret = false;
|
||||
void *data = NULL;
|
||||
|
||||
core_serialize_size(&info);
|
||||
|
||||
RARCH_LOG("%s: \"%s\".\n",
|
||||
msg_hash_to_str(MSG_SAVING_STATE),
|
||||
path);
|
||||
|
||||
if (info.size == 0)
|
||||
return false;
|
||||
|
||||
data = malloc(info.size);
|
||||
|
||||
if (!data)
|
||||
return false;
|
||||
|
||||
RARCH_LOG("%s: %d %s.\n",
|
||||
msg_hash_to_str(MSG_STATE_SIZE),
|
||||
(int)info.size,
|
||||
msg_hash_to_str(MSG_BYTES));
|
||||
|
||||
serial_info.data = data;
|
||||
serial_info.size = info.size;
|
||||
ret = core_serialize(&serial_info);
|
||||
|
||||
if (ret)
|
||||
if ( !save_state_in_background )
|
||||
{
|
||||
if (save_to_disk)
|
||||
{
|
||||
if (filestream_exists(path) && !autosave)
|
||||
{
|
||||
/* Before overwritting the savestate file, load it into a buffer
|
||||
to allow undo_save_state() to work */
|
||||
/* TODO/FIXME - Use msg_hash_to_str here */
|
||||
RARCH_LOG("%s ...\n",
|
||||
msg_hash_to_str(MSG_FILE_ALREADY_EXISTS_SAVING_TO_BACKUP_BUFFER));
|
||||
RARCH_LOG("%s: \"%s\".\n",
|
||||
msg_hash_to_str(MSG_SAVING_STATE),
|
||||
path);
|
||||
|
||||
task_push_load_and_save_state(path, data, info.size, true, autosave);
|
||||
}
|
||||
else
|
||||
task_push_save_state(path, data, info.size, autosave);
|
||||
data = get_serialized_data(path, info.size) ;
|
||||
|
||||
|
||||
if (!data)
|
||||
{
|
||||
RARCH_ERR("%s \"%s\".\n",
|
||||
msg_hash_to_str(MSG_FAILED_TO_SAVE_STATE_TO),
|
||||
path);
|
||||
return false;
|
||||
}
|
||||
|
||||
RARCH_LOG("%s: %d %s.\n",
|
||||
msg_hash_to_str(MSG_STATE_SIZE),
|
||||
(int)info.size,
|
||||
msg_hash_to_str(MSG_BYTES));
|
||||
|
||||
}
|
||||
|
||||
if (save_to_disk)
|
||||
{
|
||||
if (filestream_exists(path) && !autosave)
|
||||
{
|
||||
/* Before overwritting the savestate file, load it into a buffer
|
||||
to allow undo_save_state() to work */
|
||||
/* TODO/FIXME - Use msg_hash_to_str here */
|
||||
RARCH_LOG("%s ...\n",
|
||||
msg_hash_to_str(MSG_FILE_ALREADY_EXISTS_SAVING_TO_BACKUP_BUFFER));
|
||||
|
||||
task_push_load_and_save_state(path, data, info.size, true, autosave);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* save_to_disk is false, which means we are saving the state
|
||||
in undo_load_buf to allow content_undo_load_state() to restore it */
|
||||
|
||||
/* If we were holding onto an old state already, clean it up first */
|
||||
if (undo_load_buf.data)
|
||||
{
|
||||
free(undo_load_buf.data);
|
||||
undo_load_buf.data = NULL;
|
||||
}
|
||||
|
||||
undo_load_buf.data = malloc(info.size);
|
||||
if (!undo_load_buf.data)
|
||||
{
|
||||
free(data);
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(undo_load_buf.data, data, info.size);
|
||||
free(data);
|
||||
undo_load_buf.size = info.size;
|
||||
strlcpy(undo_load_buf.path, path, sizeof(undo_load_buf.path));
|
||||
}
|
||||
task_push_save_state(path, data, info.size, autosave);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( data == NULL )
|
||||
data = get_serialized_data(path, info.size) ;
|
||||
|
||||
if ( data == NULL )
|
||||
{
|
||||
RARCH_ERR("%s \"%s\".\n",
|
||||
msg_hash_to_str(MSG_FAILED_TO_SAVE_STATE_TO),
|
||||
path);
|
||||
return false ;
|
||||
}
|
||||
/* save_to_disk is false, which means we are saving the state
|
||||
in undo_load_buf to allow content_undo_load_state() to restore it */
|
||||
|
||||
/* If we were holding onto an old state already, clean it up first */
|
||||
if (undo_load_buf.data)
|
||||
{
|
||||
free(undo_load_buf.data);
|
||||
undo_load_buf.data = NULL;
|
||||
}
|
||||
|
||||
undo_load_buf.data = malloc(info.size);
|
||||
if (!undo_load_buf.data)
|
||||
{
|
||||
free(data);
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(undo_load_buf.data, data, info.size);
|
||||
free(data);
|
||||
RARCH_ERR("%s \"%s\".\n",
|
||||
msg_hash_to_str(MSG_FAILED_TO_SAVE_STATE_TO),
|
||||
path);
|
||||
undo_load_buf.size = info.size;
|
||||
strlcpy(undo_load_buf.path, path, sizeof(undo_load_buf.path));
|
||||
}
|
||||
|
||||
return ret;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1546,3 +1592,8 @@ void *savefile_ptr_get(void)
|
||||
{
|
||||
return task_save_files;
|
||||
}
|
||||
|
||||
void set_save_state_in_background(bool state)
|
||||
{
|
||||
save_state_in_background = state ;
|
||||
}
|
||||
|
@ -267,6 +267,8 @@ bool task_push_audio_mixer_load(
|
||||
|
||||
extern const char* const input_builtin_autoconfs[];
|
||||
|
||||
void set_save_state_in_background(bool state) ;
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user