mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-07 08:36:02 -10:00
rewind: the buffer a load asks for is set up on the frame after
The drivers stage marks the rewind buffer pending instead of setting it up, and runloop_check_state sets it up on the next frame, before the core runs, so the full serialize it takes is no longer part of the load. Rewind init and deinit clear the pending mark. The content_load harness checks no frame of a load sets up the buffer and the first frame after does.
This commit is contained in:
1 parent
3e8307ca8f
commit
f451993965
5 files changed
+79
-5
No files matched your search
+3
-1
@@ -9074,7 +9074,9 @@ bool retroarch_main_init_drivers(bool staged,
|
||||
command_event(CMD_EVENT_CONTROLLER_INIT, NULL);
|
||||
|
||||
#ifdef HAVE_REWIND
|
||||
command_event(CMD_EVENT_REWIND_INIT, NULL);
|
||||
/* Set up on the frame after the load, before the core runs: the
|
||||
* buffer is one full serialize of the core */
|
||||
runloop_st->rewind_st.flags |= STATE_MGR_REWIND_ST_FLAG_INIT_PENDING;
|
||||
#endif
|
||||
|
||||
if (*rec_st->path)
|
||||
|
||||
@@ -7029,6 +7029,17 @@ static void runloop_idle_wait(void)
|
||||
retro_sleep(10);
|
||||
}
|
||||
|
||||
#ifdef HAVE_REWIND
|
||||
/* The rewind buffer a load asked for: one full serialize of the core,
|
||||
* taken on the frame after the load, before the core runs. */
|
||||
static VIDEO_NOINLINE void runloop_rewind_init_pending(
|
||||
runloop_state_t *runloop_st)
|
||||
{
|
||||
runloop_st->rewind_st.flags &= ~STATE_MGR_REWIND_ST_FLAG_INIT_PENDING;
|
||||
command_event(CMD_EVENT_REWIND_INIT, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
static enum runloop_state_enum runloop_check_state(
|
||||
input_driver_state_t *input_st,
|
||||
audio_driver_state_t *audio_st,
|
||||
@@ -8203,6 +8214,9 @@ static enum runloop_state_enum runloop_check_state(
|
||||
return RUNLOOP_STATE_PAUSE;
|
||||
}
|
||||
|
||||
if (runloop_st->rewind_st.flags & STATE_MGR_REWIND_ST_FLAG_INIT_PENDING)
|
||||
runloop_rewind_init_pending(runloop_st);
|
||||
|
||||
rewinding = state_manager_check_rewind(
|
||||
&runloop_st->rewind_st,
|
||||
&runloop_st->current_core,
|
||||
|
||||
@@ -68,6 +68,7 @@
|
||||
#include "../../../content.h"
|
||||
#include "../../../input/input_driver.h"
|
||||
#include "../../../runahead.h"
|
||||
#include "../../../state_manager.h"
|
||||
#ifdef HAVE_NETWORKING
|
||||
#include "../../../network/netplay/netplay.h"
|
||||
#endif
|
||||
@@ -510,6 +511,54 @@ static void lane_contentless_names(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_REWIND
|
||||
/* The rewind buffer is one full serialize of the core: a load leaves
|
||||
* it for the frame after, which takes it before the core runs. */
|
||||
static void lane_rewind_after_load(void)
|
||||
{
|
||||
struct load_frame log[LOAD_FRAMES];
|
||||
settings_t *settings = config_get_ptr();
|
||||
runloop_state_t *runloop_st = runloop_state_get_ptr();
|
||||
bool rewind_enable = settings->bools.rewind_enable;
|
||||
unsigned n, i;
|
||||
unsigned had = failures;
|
||||
|
||||
configuration_set_bool(settings, settings->bools.rewind_enable, true);
|
||||
open_menu();
|
||||
CHECK(task_push_load_contentless_core_from_menu(core_path),
|
||||
"the load was not started");
|
||||
for (n = 0; n < LOAD_FRAMES && runloop_is_content_switching(); n++)
|
||||
{
|
||||
runloop_iterate();
|
||||
task_queue_check();
|
||||
CHECK(!(runloop_st->rewind_st.flags
|
||||
& STATE_MGR_REWIND_ST_FLAG_INIT_ATTEMPTED),
|
||||
"frame %u of the load set up the rewind buffer", n);
|
||||
}
|
||||
CHECK(!runloop_is_content_switching() && core_is_up(),
|
||||
"the load did not finish");
|
||||
CHECK(runloop_st->rewind_st.flags & STATE_MGR_REWIND_ST_FLAG_INIT_PENDING,
|
||||
"the load did not leave the rewind buffer for the frame after");
|
||||
for (i = 0; i < 2 && !(runloop_st->rewind_st.flags
|
||||
& STATE_MGR_REWIND_ST_FLAG_INIT_ATTEMPTED); i++)
|
||||
{
|
||||
runloop_iterate();
|
||||
task_queue_check();
|
||||
}
|
||||
CHECK(i == 1,
|
||||
"the rewind buffer was set up %u frames after the load, not on "
|
||||
"the first", i);
|
||||
CHECK(!(runloop_st->rewind_st.flags & STATE_MGR_REWIND_ST_FLAG_INIT_PENDING),
|
||||
"the rewind buffer is still pending after it was set up");
|
||||
|
||||
command_event(CMD_EVENT_REWIND_DEINIT, NULL);
|
||||
configuration_set_bool(settings, settings->bools.rewind_enable,
|
||||
rewind_enable);
|
||||
if (failures == had)
|
||||
fprintf(stderr, "[pass] rewind-after-load lane\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
static void lane_one_at_a_time(void)
|
||||
{
|
||||
struct load_frame log[LOAD_FRAMES];
|
||||
@@ -2062,6 +2111,9 @@ int main(int argc, char *argv[])
|
||||
lane_probe_cached();
|
||||
#endif
|
||||
lane_one_at_a_time();
|
||||
#ifdef HAVE_REWIND
|
||||
lane_rewind_after_load();
|
||||
#endif
|
||||
lane_reinit_deferred();
|
||||
lane_fallback();
|
||||
lane_fallback_threaded();
|
||||
|
||||
+6
-3
@@ -767,9 +767,11 @@ void state_manager_event_init(
|
||||
core_info_t *core_info = NULL;
|
||||
void *state = NULL;
|
||||
|
||||
if ( !rewind_st
|
||||
|| (rewind_st->flags & STATE_MGR_REWIND_ST_FLAG_INIT_ATTEMPTED)
|
||||
|| rewind_st->state)
|
||||
if (!rewind_st)
|
||||
return;
|
||||
rewind_st->flags &= ~STATE_MGR_REWIND_ST_FLAG_INIT_PENDING;
|
||||
if ( (rewind_st->flags & STATE_MGR_REWIND_ST_FLAG_INIT_ATTEMPTED)
|
||||
|| rewind_st->state)
|
||||
return;
|
||||
|
||||
rewind_st->size = 0;
|
||||
@@ -862,6 +864,7 @@ void state_manager_event_deinit(
|
||||
| STATE_MGR_REWIND_ST_FLAG_HOTKEY_WAS_CHECKED
|
||||
| STATE_MGR_REWIND_ST_FLAG_HOTKEY_WAS_PRESSED
|
||||
| STATE_MGR_REWIND_ST_FLAG_INIT_ATTEMPTED
|
||||
| STATE_MGR_REWIND_ST_FLAG_INIT_PENDING
|
||||
);
|
||||
|
||||
/* Restore regular (non-rewind) core audio
|
||||
|
||||
+4
-1
@@ -34,7 +34,10 @@ enum state_manager_rewind_st_flags
|
||||
STATE_MGR_REWIND_ST_FLAG_FRAME_IS_REVERSED = (1 << 0),
|
||||
STATE_MGR_REWIND_ST_FLAG_INIT_ATTEMPTED = (1 << 1),
|
||||
STATE_MGR_REWIND_ST_FLAG_HOTKEY_WAS_CHECKED = (1 << 2),
|
||||
STATE_MGR_REWIND_ST_FLAG_HOTKEY_WAS_PRESSED = (1 << 3)
|
||||
STATE_MGR_REWIND_ST_FLAG_HOTKEY_WAS_PRESSED = (1 << 3),
|
||||
/* A load wants the buffer: it is set up on the frame after,
|
||||
* before the core runs, rather than inside the load */
|
||||
STATE_MGR_REWIND_ST_FLAG_INIT_PENDING = (1 << 4)
|
||||
};
|
||||
|
||||
struct state_manager
|
||||
|
||||
Reference in new issue
Block a user