From e39e6418029a34cf999513ecc832c07dfee8162f Mon Sep 17 00:00:00 2001 From: LibretroAdmin Date: Tue, 29 Sep 2026 18:13:12 +0000 Subject: [PATCH] runloop: put cheats, presence, camera and BSV behind frame_work bits The post-core_run product block called into four translation units every frame to find out nothing needed doing: cheat_manager_apply_ retro_cheats() loads a cold global to see there is no cheat list, presence_update() calls discord_update() and steam_update_presence() which each compare a status word and return, the camera poll reads settings_t for camera_allow before the caps check, and bsv_movie_next_frame() pulled two settings through config_get_ptr() before checking whether a movie handle exists at all. Give each an up/down owner and a bit on runloop_state_t::frame_work, raised and dropped by the product itself through runloop_frame_work_set(): RUNLOOP_WORK_CHEATS - cheat_manager_new/realloc raise it when a list is allocated, cheat_manager_free drops it RUNLOOP_WORK_PRESENCE - raised with Discord init and with Steam (mist) init; dropped with whichever of the two is the last compiled-in sink RUNLOOP_WORK_CAMERA - driver_camera_start raises it when the core's start succeeds, driver_camera_stop and the driver teardown drop it. The remaining camera_allow/caps/driver checks stay behind the bit; a camera the core registered but never started is no longer polled. BSV needs no bit: the movie handles live on input_st, which the frame already has in cache, so the iterate tests the pointers directly and bsv_movie_next_frame() checks its handle before touching settings. --- camera/camera_driver.c | 7 ++++++- cheat_manager.c | 5 +++++ input/bsv/bsvmovie.c | 6 ++++-- retroarch.c | 6 +++++- runloop.c | 33 +++++++++++++++++++++++++-------- runloop.h | 8 +++++++- steam/steam.c | 8 ++++++++ 7 files changed, 60 insertions(+), 13 deletions(-) diff --git a/camera/camera_driver.c b/camera/camera_driver.c index 4bb10c19e2..3aaf5d4fdf 100644 --- a/camera/camera_driver.c +++ b/camera/camera_driver.c @@ -110,7 +110,11 @@ bool driver_camera_start(void) settings_t *settings = config_get_ptr(); bool camera_allow = settings->bools.camera_allow; if (camera_allow) - return camera_st->driver->start(camera_st->data); + { + bool ok = camera_st->driver->start(camera_st->data); + runloop_frame_work_set(RUNLOOP_WORK_CAMERA, ok); + return ok; + } runloop_msg_queue_push( "Camera is explicitly disabled.\n", @@ -128,6 +132,7 @@ void driver_camera_stop(void) && camera_st->driver->stop && camera_st->data) camera_st->driver->stop(camera_st->data); + runloop_frame_work_set(RUNLOOP_WORK_CAMERA, false); } bool camera_driver_find_driver(const char *prefix, diff --git a/cheat_manager.c b/cheat_manager.c index e28b38ed78..a74892976a 100644 --- a/cheat_manager.c +++ b/cheat_manager.c @@ -411,6 +411,7 @@ static void cheat_manager_free(void) cheat_st->num_memory_buffers = 0; cheat_st->total_memory_size = 0; cheat_st->memory_initialized = false; + runloop_frame_work_set(RUNLOOP_WORK_CHEATS, false); } static void cheat_manager_new(unsigned size) @@ -431,8 +432,10 @@ static void cheat_manager_new(unsigned size) cheat_st->buf_size = 0; cheat_st->size = 0; cheat_st->cheats = NULL; + runloop_frame_work_set(RUNLOOP_WORK_CHEATS, false); return; } + runloop_frame_work_set(RUNLOOP_WORK_CHEATS, true); for (i = 0; i < cheat_st->size; i++) { @@ -674,8 +677,10 @@ bool cheat_manager_realloc(unsigned new_size, unsigned default_handler) { cheat_st->buf_size = cheat_st->size = 0; cheat_st->cheats = NULL; + runloop_frame_work_set(RUNLOOP_WORK_CHEATS, false); return false; } + runloop_frame_work_set(RUNLOOP_WORK_CHEATS, true); cheat_st->buf_size = new_size; cheat_st->size = new_size; diff --git a/input/bsv/bsvmovie.c b/input/bsv/bsvmovie.c index a3afd3a970..45a18c1c5a 100644 --- a/input/bsv/bsvmovie.c +++ b/input/bsv/bsvmovie.c @@ -1015,8 +1015,8 @@ void bsv_movie_scan_from_start(bsv_movie_t *movie, int32_t len) void bsv_movie_next_frame(input_driver_state_t *input_st) { - unsigned checkpoint_interval = config_get_ptr()->uints.replay_checkpoint_interval; - unsigned checkpoint_deserialize= config_get_ptr()->bools.replay_checkpoint_deserialize; + unsigned checkpoint_interval; + unsigned checkpoint_deserialize; /* If bsv_movie_state_next_handle is not NULL, deinit and set bsv_movie_state_handle to bsv_movie_state_next_handle and clear next_handle */ @@ -1024,6 +1024,8 @@ void bsv_movie_next_frame(input_driver_state_t *input_st) if (!handle) return; + checkpoint_interval = config_get_ptr()->uints.replay_checkpoint_interval; + checkpoint_deserialize = config_get_ptr()->bools.replay_checkpoint_deserialize; #ifdef HAVE_REWIND if (state_manager_frame_is_reversed()) { diff --git a/retroarch.c b/retroarch.c index 7dab20476d..ffbb357c9c 100644 --- a/retroarch.c +++ b/retroarch.c @@ -1989,6 +1989,7 @@ void driver_uninit(int flags, enum driver_lifetime_flags lifetime_flags) } camera_st->data = NULL; + runloop_frame_work_set(RUNLOOP_WORK_CAMERA, false); } #ifdef HAVE_BLUETOOTH @@ -8998,7 +8999,7 @@ bool retroarch_main_init(int argc, char *argv[]) if (command_event(CMD_EVENT_DISCORD_INIT, NULL)) { discord_st->inited = true; - runloop_st->frame_work |= RUNLOOP_WORK_DISCORD; + runloop_st->frame_work |= RUNLOOP_WORK_DISCORD | RUNLOOP_WORK_PRESENCE; } } #endif @@ -9695,6 +9696,9 @@ bool retroarch_main_quit(void) } discord_st->inited = false; runloop_st->frame_work &= ~RUNLOOP_WORK_DISCORD; +#ifndef HAVE_MIST + runloop_st->frame_work &= ~RUNLOOP_WORK_PRESENCE; +#endif } #endif diff --git a/runloop.c b/runloop.c index a9a6c64f15..d663309d26 100644 --- a/runloop.c +++ b/runloop.c @@ -455,6 +455,14 @@ runloop_state_t *runloop_state_get_ptr(void) return &runloop_state; } +void runloop_frame_work_set(unsigned bit, bool on) +{ + if (on) + runloop_state.frame_work |= bit; + else + runloop_state.frame_work &= ~bit; +} + bool runloop_is_content_closing(void) { return runloop_state.content_closing; @@ -8362,7 +8370,8 @@ int runloop_iterate(void) #endif #ifdef HAVE_BSV_MOVIE - bsv_movie_dequeue_next(input_st); + if (input_st->bsv_movie_state_next_handle) + bsv_movie_dequeue_next(input_st); #endif #ifdef ANDROID @@ -8614,7 +8623,8 @@ int runloop_iterate(void) autosave_lock(); #endif - if ( settings->bools.camera_allow + if ( (runloop_st->frame_work & RUNLOOP_WORK_CAMERA) + && settings->bools.camera_allow && camera_st->cb.caps && camera_st->driver && camera_st->driver->poll @@ -8663,17 +8673,24 @@ int runloop_iterate(void) rcheevos_test(); #endif #ifdef HAVE_CHEATS - cheat_manager_apply_retro_cheats(); + if (runloop_st->frame_work & RUNLOOP_WORK_CHEATS) + cheat_manager_apply_retro_cheats(); #endif #ifdef HAVE_PRESENCE - presence_update(PRESENCE_GAME); + if (runloop_st->frame_work & RUNLOOP_WORK_PRESENCE) + presence_update(PRESENCE_GAME); #endif #ifdef HAVE_BSV_MOVIE - bsv_movie_next_frame(input_st); - if (input_st->bsv_movie_state.flags & BSV_FLAG_MOVIE_END) + /* The movie handle lives on input_st, which this frame already + * has in cache; no bit needed. */ + if (input_st->bsv_movie_state_handle) { - movie_stop(input_st); - command_event(CMD_EVENT_PAUSE, NULL); + bsv_movie_next_frame(input_st); + if (input_st->bsv_movie_state.flags & BSV_FLAG_MOVIE_END) + { + movie_stop(input_st); + command_event(CMD_EVENT_PAUSE, NULL); + } } #endif diff --git a/runloop.h b/runloop.h index f420640b51..25cb7a1a73 100644 --- a/runloop.h +++ b/runloop.h @@ -748,9 +748,15 @@ typedef struct runloop runloop_state_t; /* runloop_state_t::frame_work bits */ enum runloop_frame_work { - RUNLOOP_WORK_DISCORD = (1 << 0) /* Discord RPC is up: pump it */ + RUNLOOP_WORK_DISCORD = (1 << 0), /* Discord RPC is up: pump it */ + RUNLOOP_WORK_PRESENCE = (1 << 1), /* a rich-presence sink is up */ + RUNLOOP_WORK_CHEATS = (1 << 2), /* a cheat list is loaded */ + RUNLOOP_WORK_CAMERA = (1 << 3) /* the core started the camera */ }; +/* Raise or drop one frame_work bit from the product that owns it. */ +void runloop_frame_work_set(unsigned bit, bool on); + /* Runs deferred off-main message pushes; the main thread, once per * iterate. */ void runloop_msg_queue_drain_deferred(void); diff --git a/steam/steam.c b/steam/steam.c index 3fce19f442..574c27651e 100644 --- a/steam/steam.c +++ b/steam/steam.c @@ -28,7 +28,10 @@ void steam_init(void) MistResult result = mist_subprocess_init(); if (MIST_IS_SUCCESS(result)) + { mist_initialized = true; + runloop_frame_work_set(RUNLOOP_WORK_PRESENCE, true); + } else RARCH_ERR("[Steam] Failed to initialize mist subprocess (%d-%d).\n", MIST_UNPACK_RESULT(result)); } @@ -520,7 +523,12 @@ void steam_deinit(void) steam_core_dlc_list_free(mist_dlc_list); if (MIST_IS_SUCCESS(result)) + { mist_initialized = false; +#ifndef HAVE_DISCORD + runloop_frame_work_set(RUNLOOP_WORK_PRESENCE, false); +#endif + } else RARCH_ERR("[Steam] Failed to deinitialize mist subprocess (%d-%d).\n", MIST_UNPACK_RESULT(result)); }