diff --git a/command_event.c b/command_event.c index 27c568d8f9..c0085570e0 100644 --- a/command_event.c +++ b/command_event.c @@ -599,6 +599,7 @@ static bool event_init_core(void) if (!event_init_content()) return false; + core.poll_type = POLL_TYPE_LATE; retro_init_libretro_cbs(&retro_ctx); rarch_ctl(RARCH_CTL_INIT_SYSTEM_AV_INFO, NULL); diff --git a/dynamic.h b/dynamic.h index fbc3c8c3da..0d3f0f6040 100644 --- a/dynamic.h +++ b/dynamic.h @@ -123,6 +123,7 @@ bool rarch_environment_cb(unsigned cmd, void *data); struct retro_core_t { + unsigned poll_type; void (*retro_init)(void); void (*retro_deinit)(void); unsigned (*retro_api_version)(void); diff --git a/libretro_version_1.c b/libretro_version_1.c index 192d14249e..e92b5cd597 100644 --- a/libretro_version_1.c +++ b/libretro_version_1.c @@ -37,6 +37,21 @@ struct retro_callbacks retro_ctx; +static bool input_polled; + +static int16_t input_state_poll(unsigned port, + unsigned device, unsigned idx, unsigned id) +{ + if (core.poll_type == POLL_TYPE_LATE) + { + if (!input_polled) + input_poll(); + + input_polled = true; + } + return input_state(port, device, idx, id); +} + /** * retro_set_default_callbacks: * @data : pointer to retro_callbacks object @@ -53,7 +68,7 @@ void retro_set_default_callbacks(void *data) cbs->frame_cb = video_driver_frame; cbs->sample_cb = audio_driver_sample; cbs->sample_batch_cb = audio_driver_sample_batch; - cbs->state_cb = input_state; + cbs->state_cb = input_state_poll; cbs->poll_cb = input_poll; } @@ -68,6 +83,27 @@ void retro_uninit_libretro_cbs(void) cbs->poll_cb = NULL; } + +void retro_run_core(void) +{ + switch (core.poll_type) + { + case POLL_TYPE_EARLY: + input_poll(); + break; + case POLL_TYPE_LATE: + input_polled = false; + break; + } + core.retro_run(); +} + +static void input_poll_maybe(void) +{ + if (core.poll_type == POLL_TYPE_NORMAL) + input_poll(); +} + /** * retro_init_libretro_cbs: * @data : pointer to retro_callbacks object @@ -88,8 +124,8 @@ void retro_init_libretro_cbs(void *data) core.retro_set_video_refresh(video_driver_frame); core.retro_set_audio_sample(audio_driver_sample); core.retro_set_audio_sample_batch(audio_driver_sample_batch); - core.retro_set_input_state(input_state); - core.retro_set_input_poll(input_poll); + core.retro_set_input_state(input_state_poll); + core.retro_set_input_poll(input_poll_maybe); retro_set_default_callbacks(cbs); @@ -97,6 +133,9 @@ void retro_init_libretro_cbs(void *data) if (!netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_DATA_INITED, NULL)) return; + /* Force normal poll type for netplay. */ + core.poll_type = POLL_TYPE_NORMAL; + if (global->netplay.is_spectate) { core.retro_set_input_state( diff --git a/libretro_version_1.h b/libretro_version_1.h index 5daaaf2bb6..4b71319bee 100644 --- a/libretro_version_1.h +++ b/libretro_version_1.h @@ -24,6 +24,17 @@ extern "C" { #include "libretro.h" +enum +{ + /* Polling is performed before call to retro_run */ + POLL_TYPE_EARLY = 0, + /* Polling is performed when requested. */ + POLL_TYPE_NORMAL, + /* Polling is performed on first call to retro_input_state + * per frame. */ + POLL_TYPE_LATE +}; + typedef struct retro_callbacks { retro_video_refresh_t frame_cb; @@ -60,6 +71,9 @@ void retro_set_default_callbacks(void *data); **/ void retro_set_rewind_callbacks(void); +/* Runs the core for one frame. Use instead of core.retro_run(). */ +void retro_run_core(void); + /** * retro_flush_audio: * @data : pointer to audio buffer. diff --git a/menu/menu_display.c b/menu/menu_display.c index 7b776d3232..98ff96af8a 100644 --- a/menu/menu_display.c +++ b/menu/menu_display.c @@ -321,7 +321,7 @@ bool menu_display_ctl(enum menu_display_ctl_state state, void *data) if (!libretro_input_is_blocked) input_driver_ctl(RARCH_INPUT_CTL_SET_LIBRETRO_INPUT_BLOCKED, NULL); - core.retro_run(); + retro_run_core(); input_driver_ctl(RARCH_INPUT_CTL_UNSET_LIBRETRO_INPUT_BLOCKED, NULL); return true; diff --git a/menu/menu_display.h b/menu/menu_display.h index ebd9d99fee..a422a93313 100644 --- a/menu/menu_display.h +++ b/menu/menu_display.h @@ -25,6 +25,7 @@ #include "../gfx/video_context_driver.h" #include "../gfx/font_driver.h" #include "../gfx/video_common.h" +#include "../libretro_version_1.h" #ifdef __cplusplus extern "C" { diff --git a/netplay/netplay_net.c b/netplay/netplay_net.c index b27b6cc907..92018b6ff8 100644 --- a/netplay/netplay_net.c +++ b/netplay/netplay_net.c @@ -77,7 +77,7 @@ static void netplay_net_post_frame(netplay_t *netplay) #if defined(HAVE_THREADS) && !defined(RARCH_CONSOLE) lock_autosave(); #endif - core.retro_run(); + retro_run_core(); #if defined(HAVE_THREADS) && !defined(RARCH_CONSOLE) unlock_autosave(); #endif diff --git a/runloop.c b/runloop.c index 9d1cbfc4e7..4fa1f27492 100644 --- a/runloop.c +++ b/runloop.c @@ -1424,7 +1424,7 @@ int runloop_iterate(unsigned *sleep_ms) retro_sleep(settings->video.frame_delay); /* Run libretro for one frame. */ - core.retro_run(); + retro_run_core(); #ifdef HAVE_CHEEVOS /* Test the achievements. */