diff --git a/menu/menu_driver.c b/menu/menu_driver.c index cc8217fd20..ac16bceb47 100644 --- a/menu/menu_driver.c +++ b/menu/menu_driver.c @@ -4665,9 +4665,6 @@ bool menu_driver_init(bool video_is_threaded) settings_t *settings = config_get_ptr(); struct menu_state *menu_st = &menu_driver_state; - command_event(CMD_EVENT_CORE_INFO_INIT, NULL); - command_event(CMD_EVENT_LOAD_CORE_PERSIST, NULL); - if ( menu_st->driver_data || menu_driver_init_internal( menu_st, p_disp, settings, diff --git a/runloop.c b/runloop.c index 7fb50b3ae8..3dfb1074b3 100644 --- a/runloop.c +++ b/runloop.c @@ -655,6 +655,9 @@ static void runloop_update_runtime_log( /* Update 'last played' entry */ runtime_log_set_last_played_now(runtime_log); + /* Update state slot */ + runtime_log->state_slot = config_get_ptr()->ints.state_slot; + /* Save runtime log file */ runtime_log_save(runtime_log); @@ -4376,6 +4379,7 @@ static bool event_init_content( static void runloop_runtime_log_init(runloop_state_t *runloop_st) { + settings_t *settings = config_get_ptr(); const char *content_path = path_get(RARCH_PATH_CONTENT); const char *core_path = path_get(RARCH_PATH_CORE); @@ -4407,6 +4411,19 @@ static void runloop_runtime_log_init(runloop_state_t *runloop_st) strlcpy(runloop_st->runtime_core_path, core_path, sizeof(runloop_st->runtime_core_path)); + + if ( !settings->bools.content_runtime_log + && !settings->bools.content_runtime_log_aggregate) + return; + + if ( !string_is_empty(content_path) + && !string_is_empty(core_path)) + runtime_log_init( + runloop_st->runtime_content_path, + runloop_st->runtime_core_path, + settings->paths.directory_runtime_log, + settings->paths.directory_playlist, + true); } void runloop_set_frame_limit( @@ -4655,16 +4672,9 @@ bool runloop_event_init_core( float fastforward_ratio = 0.0f; rarch_system_info_t *sys_info = &runloop_st->system; -#ifdef HAVE_NETWORKING - if (netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_ENABLED, NULL)) - { - /* We need this in order for core_info_current_supports_netplay - to work correctly at init_netplay, - called later at event_init_content. */ - command_event(CMD_EVENT_CORE_INFO_INIT, NULL); - command_event(CMD_EVENT_LOAD_CORE_PERSIST, NULL); - } -#endif + /* Init core info files */ + command_event(CMD_EVENT_CORE_INFO_INIT, NULL); + command_event(CMD_EVENT_LOAD_CORE_PERSIST, NULL); /* Load symbols */ if (!runloop_init_libretro_symbols(runloop_st, @@ -4792,7 +4802,12 @@ bool runloop_event_init_core( runloop_set_frame_limit(&video_st->av_info, fastforward_ratio); runloop_st->frame_limit_last_time = cpu_features_get_time_usec(); + /* Init runtime log and read current state slot */ runloop_runtime_log_init(runloop_st); + + if (runloop_st->entry_state_slot > -1) + configuration_set_int(settings, settings->ints.state_slot, runloop_st->entry_state_slot); + return true; } diff --git a/runtime_file.c b/runtime_file.c index 18246ba3d1..a65698a474 100644 --- a/runtime_file.c +++ b/runtime_file.c @@ -55,6 +55,7 @@ typedef struct char **current_entry_val; char *runtime_string; char *last_played_string; + char *state_slot; } RtlJSONContext; static bool RtlJSONObjectMemberHandler(void *ctx, const char *s, size_t len) @@ -71,6 +72,8 @@ static bool RtlJSONObjectMemberHandler(void *ctx, const char *s, size_t len) p_ctx->current_entry_val = &p_ctx->runtime_string; else if (string_is_equal(s, "last_played")) p_ctx->current_entry_val = &p_ctx->last_played_string; + else if (string_is_equal(s, "state_slot")) + p_ctx->current_entry_val = &p_ctx->state_slot; /* Ignore unknown members */ } @@ -113,6 +116,8 @@ static void runtime_log_read_file(runtime_log_t *runtime_log) unsigned last_played_minute = 0; unsigned last_played_second = 0; + unsigned state_slot = 0; + RtlJSONContext context = {0}; /* Attempt to open log file */ RFILE *file = filestream_open(runtime_log->path, @@ -193,6 +198,24 @@ static void runtime_log_read_file(runtime_log_t *runtime_log) } } + /* State slot */ + if (!string_is_empty(context.state_slot)) + { + if (sscanf(context.state_slot, + "%04u", + &state_slot) != 1) + { + RARCH_ERR("[Runtime] Invalid \"state slot\" entry detected: \"%s\".\n", runtime_log->path); + goto end; + } + } + + if (state_slot > 0) + { + runloop_state_t *runloop_st = runloop_state_get_ptr(); + runloop_st->entry_state_slot = state_slot; + } + /* If we reach this point then all is well * > Assign values to runtime_log object */ runtime_log->runtime.hours = runtime_hours; @@ -206,12 +229,16 @@ static void runtime_log_read_file(runtime_log_t *runtime_log) runtime_log->last_played.minute = last_played_minute; runtime_log->last_played.second = last_played_second; + runtime_log->state_slot = state_slot; + end: /* Clean up leftover strings */ if (context.runtime_string) free(context.runtime_string); if (context.last_played_string) free(context.last_played_string); + if (context.state_slot) + free(context.state_slot); /* Close log file */ filestream_close(file); @@ -317,8 +344,10 @@ runtime_log_t *runtime_log_init( * no content is provided, 'content' is simply * the name of the core itself */ if (supports_no_game) - fill_pathname(content_name, core_name, - ".lrtl", sizeof(content_name)); + fill_pathname(content_name, + core_name, + FILE_PATH_RUNTIME_EXTENSION, + sizeof(content_name)); } /* NOTE: TyrQuake requires a specific hack, since all * content has the same name... */ @@ -334,12 +363,16 @@ runtime_log_t *runtime_log_init( strlcpy(tmp_buf, content_path, _len * sizeof(char)); fill_pathname(content_name, - path_basename(tmp_buf), ".lrtl", sizeof(content_name)); + path_basename(tmp_buf), + FILE_PATH_RUNTIME_EXTENSION, + sizeof(content_name)); } } } else - fill_pathname(content_name, path_basename(content_path), ".lrtl", + fill_pathname(content_name, + path_basename(content_path), + FILE_PATH_RUNTIME_EXTENSION, sizeof(content_name)); if (string_is_empty(content_name)) @@ -369,6 +402,8 @@ runtime_log_t *runtime_log_init( runtime_log->last_played.minute = 0; runtime_log->last_played.second = 0; + runtime_log->state_slot = 0; + runtime_log->path[0] = '\0'; strlcpy(runtime_log->path, log_file_path, sizeof(runtime_log->path)); @@ -468,6 +503,8 @@ void runtime_log_reset(runtime_log_t *runtime_log) runtime_log->last_played.hour = 0; runtime_log->last_played.minute = 0; runtime_log->last_played.second = 0; + + runtime_log->state_slot = 0; } /* Getters */ @@ -1112,6 +1149,20 @@ void runtime_log_save(runtime_log_t *runtime_log) rjsonwriter_raw(writer, ":", 1); rjsonwriter_raw(writer, " ", 1); rjsonwriter_add_string(writer, value_string); + rjsonwriter_raw(writer, ",", 1); + rjsonwriter_raw(writer, "\n", 1); + + /* > Current state slot */ + value_string[0] = '\0'; + snprintf(value_string, sizeof(value_string), + "%u", + runtime_log->state_slot); + + rjsonwriter_add_spaces(writer, 2); + rjsonwriter_add_string(writer, "state_slot"); + rjsonwriter_raw(writer, ":", 1); + rjsonwriter_raw(writer, " ", 1); + rjsonwriter_add_string(writer, value_string); rjsonwriter_raw(writer, "\n", 1); /* > Finalise */ diff --git a/runtime_file.h b/runtime_file.h index e485e686e0..c694e7ff21 100644 --- a/runtime_file.h +++ b/runtime_file.h @@ -57,6 +57,7 @@ typedef struct { rtl_runtime_t runtime; /* unsigned alignment */ rtl_last_played_t last_played; /* unsigned alignment */ + unsigned state_slot; char path[PATH_MAX_LENGTH]; } runtime_log_t;