Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[New Feature] Load save states from command-line or playlist #13354

Merged
merged 4 commits into from
Dec 14, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions command.c
Original file line number Diff line number Diff line change
Expand Up @@ -1082,6 +1082,10 @@ bool command_event_save_auto_state(
bool ret = false;
char savestate_name_auto[PATH_MAX_LENGTH];

#ifdef HAVE_ENTRYSTATES
asciibeats marked this conversation as resolved.
Show resolved Hide resolved
if (!path_is_empty(RARCH_PATH_STATE))
asciibeats marked this conversation as resolved.
Show resolved Hide resolved
return false;
#endif
if (!savestate_auto_save)
return false;
if (current_core_type == CORE_TYPE_DUMMY)
Expand Down Expand Up @@ -1139,6 +1143,34 @@ void command_event_init_cheats(
}
#endif

#ifdef HAVE_ENTRYSTATES
void command_event_load_entry_state(void)
{
const char *state_path = path_get(RARCH_PATH_STATE);
bool ret = false;
#ifdef HAVE_CHEEVOS
if (rcheevos_hardcore_active())
return;
#endif
#ifdef HAVE_NETWORKING
if (netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_ENABLED, NULL))
return;
#endif

if (!path_is_valid(state_path))
asciibeats marked this conversation as resolved.
Show resolved Hide resolved
return;

ret = content_load_state(state_path, false, true);

RARCH_LOG("%s: %s\n%s \"%s\" %s.\n",
msg_hash_to_str(MSG_FOUND_ENTRYSTATE_IN),
state_path,
msg_hash_to_str(MSG_LOADING_ENTRYSTATE_FROM),
state_path, ret ? "succeeded" : "failed"
);
}
#endif

void command_event_load_auto_state(void)
{
char savestate_name_auto[PATH_MAX_LENGTH];
Expand Down
4 changes: 4 additions & 0 deletions command.h
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,10 @@ void command_event_set_volume(
void command_event_init_controllers(rarch_system_info_t *info,
settings_t *settings, unsigned num_active_users);

#ifdef HAVE_ENTRYSTATES
void command_event_load_entry_state(void);
#endif

void command_event_load_auto_state(void);

void command_event_set_savestate_auto_index(
Expand Down
10 changes: 10 additions & 0 deletions intl/msg_hash_us.h
Original file line number Diff line number Diff line change
Expand Up @@ -12899,3 +12899,13 @@ MSG_HASH(
"Scan Finished.<br><br>\nIn order for content to be correctly scanned, you must:\n<ul><li>have a compatible core already downloaded</li>\n<li>have \"Core Info Files\" updated via Online Updater</li>\n<li>have \"Databases\" updated via Online Updater</li>\n<li>restart RetroArch if any of the above was just done</li></ul>\nFinally, the content must match existing databases from <a href=\"https://docs.libretro.com/guides/roms-playlists-thumbnails/#sources\">here</a>. If it is still not working, consider <a href=\"https://www.github.com/libretro/RetroArch/issues\">submitting a bug report</a>."
)
#endif
#ifdef HAVE_ENTRYSTATES
MSG_HASH(
MSG_FOUND_ENTRYSTATE_IN,
asciibeats marked this conversation as resolved.
Show resolved Hide resolved
"Found entry state in"
)
MSG_HASH(
MSG_LOADING_ENTRYSTATE_FROM,
"Loading entry state from"
)
#endif
3 changes: 3 additions & 0 deletions manual_content_scan.c
Original file line number Diff line number Diff line change
Expand Up @@ -1395,6 +1395,9 @@ void manual_content_scan_add_content_to_playlist(
* > The push function reads our entry as const,
* so these casts are safe */
entry.path = (char*)playlist_content_path;
#ifdef HAVE_ENTRYSTATES
entry.state = '\0';
asciibeats marked this conversation as resolved.
Show resolved Hide resolved
#endif
entry.label = label;
entry.core_path = (char*)FILE_PATH_DETECT;
entry.core_name = (char*)FILE_PATH_DETECT;
Expand Down
62 changes: 62 additions & 0 deletions menu/cbs/menu_cbs_ok.c
Original file line number Diff line number Diff line change
Expand Up @@ -2160,15 +2160,23 @@ static int default_action_ok_load_content_with_core_from_menu(const char *_path,
}

static int default_action_ok_load_content_from_playlist_from_menu(const char *_path,
#ifdef HAVE_ENTRYSTATES
const char *path, const char *entry_state, const char *entry_label)
#else
const char *path, const char *entry_label)
#endif
{
content_ctx_info_t content_info;
content_info.argc = 0;
content_info.argv = NULL;
content_info.args = NULL;
content_info.environ_get = NULL;
if (!task_push_load_content_from_playlist_from_menu(
#ifdef HAVE_ENTRYSTATES
_path, path, entry_state, entry_label,
#else
_path, path, entry_label,
#endif
&content_info,
NULL, NULL))
return -1;
Expand Down Expand Up @@ -2333,11 +2341,44 @@ static bool playlist_entry_path_is_valid(const char *entry_path)
return false;
}

#ifdef HAVE_ENTRYSTATES
static bool playlist_entry_state_is_valid(const char *entry_state)
{
char *file_path = NULL;

if (string_is_empty(entry_state))
return true;

file_path = strdup(entry_state);
asciibeats marked this conversation as resolved.
Show resolved Hide resolved

if (!path_is_valid(file_path))
goto error;

/* File is valid */
free(file_path);
file_path = NULL;

return true;

error:
if (file_path)
{
free(file_path);
file_path = NULL;
}

return false;
}
#endif

static int action_ok_playlist_entry_collection(const char *path,
const char *label, unsigned type, size_t idx, size_t entry_idx)
{
playlist_config_t playlist_config;
char content_path[PATH_MAX_LENGTH];
#ifdef HAVE_ENTRYSTATES
char content_state[PATH_MAX_LENGTH];
#endif
char content_label[PATH_MAX_LENGTH];
char core_path[PATH_MAX_LENGTH];
size_t selection_ptr = entry_idx;
Expand All @@ -2362,6 +2403,9 @@ static int action_ok_playlist_entry_collection(const char *path,
playlist_config_set_base_content_directory(&playlist_config, settings->bools.playlist_portable_paths ? settings->paths.directory_menu_content : NULL);

content_path[0] = '\0';
#ifdef HAVE_ENTRYSTATES
content_state[0] = '\0';
#endif
content_label[0] = '\0';
core_path[0] = '\0';

Expand Down Expand Up @@ -2416,6 +2460,15 @@ static int action_ok_playlist_entry_collection(const char *path,
playlist_resolve_path(PLAYLIST_LOAD, false, content_path, sizeof(content_path));
}

#ifdef HAVE_ENTRYSTATES
/* Cache entry state */
if (!string_is_empty(entry->state))
{
strlcpy(content_state, entry->state, sizeof(content_state));
playlist_resolve_path(PLAYLIST_LOAD, false, content_state, sizeof(content_state));
}
#endif

/* Cache entry label */
if (!string_is_empty(entry->label))
strlcpy(content_label, entry->label, sizeof(content_label));
Expand Down Expand Up @@ -2532,6 +2585,11 @@ static int action_ok_playlist_entry_collection(const char *path,
if (!playlist_entry_path_is_valid(content_path))
goto error;

#ifdef HAVE_ENTRYSTATES
if (!playlist_entry_state_is_valid(content_state))
asciibeats marked this conversation as resolved.
Show resolved Hide resolved
goto error;
#endif

/* Free temporary playlist, if required */
if (playlist_initialized && tmp_playlist)
{
Expand All @@ -2544,7 +2602,11 @@ static int action_ok_playlist_entry_collection(const char *path,
* may be free()'d by above playlist_free() - but need
* to pass NULL explicitly if label is empty */
return default_action_ok_load_content_from_playlist_from_menu(
#ifdef HAVE_ENTRYSTATES
core_path, content_path, content_state, string_is_empty(content_label) ? NULL : content_label);
#else
core_path, content_path, string_is_empty(content_label) ? NULL : content_label);
#endif

error:
runloop_msg_queue_push(
Expand Down
4 changes: 4 additions & 0 deletions msg_hash.h
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,10 @@ enum msg_hash_enums
#endif
MSG_UNSUPPORTED_VIDEO_MODE,
MSG_CORE_INFO_CACHE_UNSUPPORTED,
#ifdef HAVE_ENTRYSTATES
MSG_LOADING_ENTRYSTATE_FROM,
MSG_FOUND_ENTRYSTATE_IN,
#endif

MENU_LABEL(MENU_XMB_ANIMATION_HORIZONTAL_HIGHLIGHT),
MENU_LABEL(MENU_XMB_ANIMATION_MOVE_UP_DOWN),
Expand Down
3 changes: 3 additions & 0 deletions paths.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ enum rarch_path_type
RARCH_PATH_NAMES,
RARCH_PATH_CONFIG,
RARCH_PATH_CONTENT,
#ifdef HAVE_ENTRYSTATES
RARCH_PATH_STATE,
#endif
RARCH_PATH_CONFIG_APPEND,
RARCH_PATH_CORE_OPTIONS,
RARCH_PATH_DEFAULT_SHADER_PRESET,
Expand Down
65 changes: 65 additions & 0 deletions playlist.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,12 @@
#endif

#ifndef PLAYLIST_ENTRIES
#ifdef HAVE_ENTRYSTATES
#define PLAYLIST_ENTRIES 7
asciibeats marked this conversation as resolved.
Show resolved Hide resolved
#else
#define PLAYLIST_ENTRIES 6
#endif
#endif

#define WINDOWS_PATH_DELIMITER '\\'
#define POSIX_PATH_DELIMITER '/'
Expand Down Expand Up @@ -1356,6 +1360,14 @@ bool playlist_push(playlist_t *playlist,
continue;
}

#ifdef HAVE_ENTRYSTATES
if (playlist->entries[i].state != entry->state)
{
playlist->entries[i].state = strdup(entry->state);
asciibeats marked this conversation as resolved.
Show resolved Hide resolved
entry_updated = true;
}
#endif

/* If content was previously loaded via file browser
* or command line, certain entry values will be missing.
* If we are now loading the same content from a playlist,
Expand Down Expand Up @@ -1445,6 +1457,12 @@ bool playlist_push(playlist_t *playlist,
playlist->entries[0].path_id = path_id;
path_id = NULL;

#ifdef HAVE_ENTRYSTATES
playlist->entries[0].state = NULL;

if (!string_is_empty(entry->state))
playlist->entries[0].state = strdup(entry->state);
#endif
if (!string_is_empty(entry->label))
playlist->entries[0].label = strdup(entry->label);
if (!string_is_empty(real_core_path))
Expand Down Expand Up @@ -1689,6 +1707,9 @@ void playlist_write_file(playlist_t *playlist)
for (i = 0, len = RBUF_LEN(playlist->entries); i < len; i++)
intfstream_printf(file, "%s\n%s\n%s\n%s\n%s\n%s\n",
playlist->entries[i].path ? playlist->entries[i].path : "",
#ifdef HAVE_ENTRYSTATES
playlist->entries[i].state ? playlist->entries[i].state : "",
#endif
playlist->entries[i].label ? playlist->entries[i].label : "",
playlist->entries[i].core_path ? playlist->entries[i].core_path : "",
playlist->entries[i].core_name ? playlist->entries[i].core_name : "",
Expand Down Expand Up @@ -1873,6 +1894,16 @@ void playlist_write_file(playlist_t *playlist)
rjsonwriter_add_string(writer, playlist->entries[i].path);
rjsonwriter_add_comma(writer);

#ifdef HAVE_ENTRYSTATES
rjsonwriter_add_newline(writer);
rjsonwriter_add_spaces(writer, 6);
rjsonwriter_add_string(writer, "state");
rjsonwriter_add_colon(writer);
rjsonwriter_add_space(writer);
rjsonwriter_add_string(writer, playlist->entries[i].state);
asciibeats marked this conversation as resolved.
Show resolved Hide resolved
rjsonwriter_add_comma(writer);
#endif

rjsonwriter_add_newline(writer);
rjsonwriter_add_spaces(writer, 6);
rjsonwriter_add_string(writer, "label");
Expand Down Expand Up @@ -2363,6 +2394,10 @@ static bool JSONObjectMemberHandler(void *context, const char *pValue, size_t le
pCtx->current_string_val = &pCtx->current_entry->subsystem_name;
else if (string_is_equal(pValue, "subsystem_roms"))
pCtx->in_subsystem_roms = true;
#ifdef HAVE_ENTRYSTATES
else if (string_is_equal(pValue, "state"))
pCtx->current_string_val = &pCtx->current_entry->state;
#endif
break;
}
}
Expand Down Expand Up @@ -2601,6 +2636,35 @@ static bool playlist_read_file(playlist_t *playlist)

memset(entry, 0, sizeof(*entry));

#ifdef HAVE_ENTRYSTATES
/* path */
if (!string_is_empty(line_buf[0]))
entry->path = strdup(line_buf[0]);

/* state */
if (!string_is_empty(line_buf[1]))
entry->state = strdup(line_buf[1]);

/* label */
if (!string_is_empty(line_buf[2]))
entry->label = strdup(line_buf[2]);

/* core_path */
if (!string_is_empty(line_buf[3]))
entry->core_path = strdup(line_buf[3]);

/* core_name */
if (!string_is_empty(line_buf[4]))
entry->core_name = strdup(line_buf[4]);

/* crc32 */
if (!string_is_empty(line_buf[5]))
entry->crc32 = strdup(line_buf[5]);

/* db_name */
if (!string_is_empty(line_buf[6]))
entry->db_name = strdup(line_buf[6]);
#else
/* path */
if (!string_is_empty(line_buf[0]))
entry->path = strdup(line_buf[0]);
Expand All @@ -2624,6 +2688,7 @@ static bool playlist_read_file(playlist_t *playlist)
/* db_name */
if (!string_is_empty(line_buf[5]))
entry->db_name = strdup(line_buf[5]);
#endif
}
/* If fewer than 'PLAYLIST_ENTRIES' lines were
* read, then this is metadata */
Expand Down
3 changes: 3 additions & 0 deletions playlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ typedef struct
struct playlist_entry
{
char *path;
#ifdef HAVE_ENTRYSTATES
char *state;
asciibeats marked this conversation as resolved.
Show resolved Hide resolved
#endif
char *label;
char *core_path;
char *core_name;
Expand Down
Loading