1
0
mirror of https://github.com/libretro/RetroArch synced 2024-07-03 00:38:44 +00:00

Move run_ahead.c to retroarch.c - most of the runloop

should now be self-contained in one file. Allows us to
turn more functions static, remove more extraneous functions
that just consisted of a single line (mostly getters/setters), etc.
This commit is contained in:
twinaphex 2019-06-20 09:30:44 +02:00
parent 2cad59092c
commit 6bc1802914
8 changed files with 476 additions and 570 deletions

View File

@ -268,7 +268,6 @@ ifeq ($(HAVE_RUNAHEAD), 1)
runahead/dirty_input.o \
runahead/mem_util.o \
runahead/mylist.o \
runahead/run_ahead.o \
runahead/secondary_core.o
endif

3
core.h
View File

@ -172,9 +172,6 @@ bool core_set_poll_type(unsigned *type);
/* Runs the core for one frame. */
bool core_run(void);
/* Runs the core for one frame, but does not trigger any input polling */
bool core_run_no_input_polling(void);
bool core_init(void);
bool core_deinit(void *data);

View File

@ -1368,7 +1368,6 @@ MENU
#ifdef HAVE_RUNAHEAD
#include "../runahead/mem_util.c"
#include "../runahead/secondary_core.c"
#include "../runahead/run_ahead.c"
#include "../runahead/copy_load_info.c"
#include "../runahead/dirty_input.c"
#include "../runahead/mylist.c"

View File

@ -294,13 +294,6 @@ float input_sensor_get_input(unsigned port, unsigned id);
} \
}
/**
* input_poll:
*
* Input polling callback function.
**/
void input_poll(void);
/**
* input_state:
* @port : user number.

View File

@ -163,7 +163,9 @@
#include "retroarch.h"
#ifdef HAVE_RUNAHEAD
#include "runahead/dirty_input.h"
#include "runahead/copy_load_info.h"
#include "runahead/mylist.h"
#include "runahead/secondary_core.h"
#include "runahead/run_ahead.h"
#endif
@ -1488,6 +1490,20 @@ void streaming_set_state(bool state)
streaming_enable = state;
}
bool video_driver_gpu_record_init(unsigned size)
{
video_driver_record_gpu_buffer = (uint8_t*)malloc(size);
if (!video_driver_record_gpu_buffer)
return false;
return true;
}
void video_driver_gpu_record_deinit(void)
{
free(video_driver_record_gpu_buffer);
video_driver_record_gpu_buffer = NULL;
}
/**
* recording_init:
*
@ -2405,7 +2421,7 @@ float input_sensor_get_input(unsigned port, unsigned id)
*
* Input polling callback function.
**/
void input_poll(void)
static void input_poll(void)
{
size_t i;
settings_t *settings = configuration_settings;
@ -7236,26 +7252,11 @@ void audio_driver_frame_is_reverse(void)
runloop_slowmotion);
}
void audio_driver_suspend(void)
{
audio_suspended = true;
}
bool audio_driver_is_suspended(void)
{
return audio_suspended;
}
void audio_driver_resume(void)
{
audio_suspended = false;
}
void audio_driver_set_active(void)
{
audio_driver_active = true;
}
bool audio_driver_is_active(void)
{
return audio_driver_active;
@ -8956,35 +8957,11 @@ bool video_driver_is_video_cache_context_ack(void)
return video_driver_cache_context_ack;
}
void video_driver_set_active(void)
{
video_driver_active = true;
}
void video_driver_unset_active(void)
{
video_driver_active = false;
}
bool video_driver_is_active(void)
{
return video_driver_active;
}
bool video_driver_gpu_record_init(unsigned size)
{
video_driver_record_gpu_buffer = (uint8_t*)malloc(size);
if (!video_driver_record_gpu_buffer)
return false;
return true;
}
void video_driver_gpu_record_deinit(void)
{
free(video_driver_record_gpu_buffer);
video_driver_record_gpu_buffer = NULL;
}
bool video_driver_get_current_software_framebuffer(
struct retro_framebuffer *fb)
{
@ -11672,6 +11649,447 @@ bool driver_ctl(enum driver_ctl_state state, void *data)
return true;
}
/* Runahead */
static size_t runahead_save_state_size = 0;
static bool runahead_save_state_size_known = false;
static bool request_fast_savestate = false;
static bool hard_disable_audio = false;
/* Save State List for Run Ahead */
static MyList *runahead_save_state_list = NULL;
static void *runahead_save_state_alloc(void)
{
retro_ctx_serialize_info_t *savestate = (retro_ctx_serialize_info_t*)
malloc(sizeof(retro_ctx_serialize_info_t));
if (!savestate)
return NULL;
savestate->data = NULL;
savestate->data_const = NULL;
savestate->size = 0;
if (runahead_save_state_size > 0 && runahead_save_state_size_known)
{
savestate->data = malloc(runahead_save_state_size);
savestate->data_const = savestate->data;
savestate->size = runahead_save_state_size;
}
return savestate;
}
static void runahead_save_state_free(void *data)
{
retro_ctx_serialize_info_t *savestate = (retro_ctx_serialize_info_t*)data;
if (!savestate)
return;
free(savestate->data);
free(savestate);
}
static void runahead_save_state_list_init(size_t saveStateSize)
{
runahead_save_state_size = saveStateSize;
runahead_save_state_size_known = true;
mylist_create(&runahead_save_state_list, 16,
runahead_save_state_alloc, runahead_save_state_free);
}
static void runahead_save_state_list_destroy(void)
{
mylist_destroy(&runahead_save_state_list);
}
#if 0
static void runahead_save_state_list_rotate(void)
{
unsigned i;
void *element;
void *firstElement = runahead_save_state_list->data[0];
for (i = 1; i < runahead_save_state_list->size; i++)
runahead_save_state_list->data[i - 1] =
runahead_save_state_list->data[i];
runahead_save_state_list->data[runahead_save_state_list->size - 1] =
firstElement;
}
#endif
/* Hooks - Hooks to cleanup, and add dirty input hooks */
static function_t originalRetroDeinit = NULL;
static function_t originalRetroUnload = NULL;
extern struct retro_core_t current_core;
extern struct retro_callbacks retro_ctx;
static void runahead_remove_hooks(void)
{
if (originalRetroDeinit)
{
current_core.retro_deinit = originalRetroDeinit;
originalRetroDeinit = NULL;
}
if (originalRetroUnload)
{
current_core.retro_unload_game = originalRetroUnload;
originalRetroUnload = NULL;
}
remove_input_state_hook();
}
static bool runahead_video_driver_is_active = true;
static bool runahead_available = true;
static bool runahead_secondary_core_available = true;
static bool runahead_force_input_dirty = true;
static uint64_t runahead_last_frame_count = 0;
static void runahead_clear_variables(void)
{
runahead_save_state_size = 0;
runahead_save_state_size_known = false;
runahead_video_driver_is_active = true;
runahead_available = true;
runahead_secondary_core_available = true;
runahead_force_input_dirty = true;
runahead_last_frame_count = 0;
}
static void runahead_destroy(void)
{
runahead_save_state_list_destroy();
runahead_remove_hooks();
runahead_clear_variables();
}
static void unload_hook(void)
{
runahead_remove_hooks();
runahead_destroy();
secondary_core_destroy();
if (current_core.retro_unload_game)
current_core.retro_unload_game();
}
static void runahead_deinit_hook(void)
{
runahead_remove_hooks();
runahead_destroy();
secondary_core_destroy();
if (current_core.retro_deinit)
current_core.retro_deinit();
}
static void runahead_add_hooks(void)
{
if (!originalRetroDeinit)
{
originalRetroDeinit = current_core.retro_deinit;
current_core.retro_deinit = runahead_deinit_hook;
}
if (!originalRetroUnload)
{
originalRetroUnload = current_core.retro_unload_game;
current_core.retro_unload_game = unload_hook;
}
add_input_state_hook();
}
/* Runahead Code */
static void runahead_error(void)
{
runahead_available = false;
runahead_save_state_list_destroy();
runahead_remove_hooks();
runahead_save_state_size = 0;
runahead_save_state_size_known = true;
}
static bool runahead_create(void)
{
/* get savestate size and allocate buffer */
retro_ctx_size_info_t info;
request_fast_savestate = true;
core_serialize_size(&info);
request_fast_savestate = false;
runahead_save_state_list_init(info.size);
runahead_video_driver_is_active = video_driver_is_active();
if (runahead_save_state_size == 0 || !runahead_save_state_size_known)
{
runahead_error();
return false;
}
runahead_add_hooks();
runahead_force_input_dirty = true;
mylist_resize(runahead_save_state_list, 1, true);
return true;
}
static bool runahead_save_state(void)
{
bool okay = false;
retro_ctx_serialize_info_t *serialize_info;
if (!runahead_save_state_list)
return false;
serialize_info =
(retro_ctx_serialize_info_t*)runahead_save_state_list->data[0];
request_fast_savestate = true;
okay = core_serialize(serialize_info);
request_fast_savestate = false;
if (okay)
return true;
runahead_error();
return false;
}
static bool runahead_load_state(void)
{
bool okay = false;
retro_ctx_serialize_info_t *serialize_info = (retro_ctx_serialize_info_t*)
runahead_save_state_list->data[0];
bool last_dirty = input_is_dirty;
request_fast_savestate = true;
/* calling core_unserialize has side effects with
* netplay (it triggers transmitting your save state)
call retro_unserialize directly from the core instead */
okay = current_core.retro_unserialize(
serialize_info->data_const, serialize_info->size);
request_fast_savestate = false;
input_is_dirty = last_dirty;
if (!okay)
runahead_error();
return okay;
}
#if HAVE_DYNAMIC
static bool runahead_load_state_secondary(void)
{
bool okay = false;
retro_ctx_serialize_info_t *serialize_info =
(retro_ctx_serialize_info_t*)runahead_save_state_list->data[0];
request_fast_savestate = true;
okay = secondary_core_deserialize(
serialize_info->data_const, (int)serialize_info->size);
request_fast_savestate = false;
if (!okay)
{
runahead_secondary_core_available = false;
runahead_error();
return false;
}
return true;
}
static bool runahead_run_secondary(void)
{
if (!secondary_core_run_use_last_input())
{
runahead_secondary_core_available = false;
return false;
}
return true;
}
#endif
static void runahead_resume_video(void)
{
if (runahead_video_driver_is_active)
video_driver_active = true;
else
video_driver_active = false;
}
static void retro_input_poll_null(void);
static bool runahead_core_run_use_last_input(void)
{
retro_input_poll_t old_poll_function = retro_ctx.poll_cb;
retro_input_state_t old_input_function = retro_ctx.state_cb;
retro_ctx.poll_cb = retro_input_poll_null;
retro_ctx.state_cb = input_state_get_last;
current_core.retro_set_input_poll(retro_ctx.poll_cb);
current_core.retro_set_input_state(retro_ctx.state_cb);
current_core.retro_run();
retro_ctx.poll_cb = old_poll_function;
retro_ctx.state_cb = old_input_function;
current_core.retro_set_input_poll(retro_ctx.poll_cb);
current_core.retro_set_input_state(retro_ctx.state_cb);
return true;
}
static void run_ahead(int runahead_count, bool useSecondary)
{
int frame_number = 0;
bool last_frame = false;
bool suspended_frame = false;
#if defined(HAVE_DYNAMIC) || defined(HAVE_DYLIB)
const bool have_dynamic = true;
#else
const bool have_dynamic = false;
#endif
uint64_t frame_count = video_driver_frame_count;
if (runahead_count <= 0 || !runahead_available)
{
core_run();
runahead_force_input_dirty = true;
return;
}
if (!runahead_save_state_size_known)
{
if (!runahead_create())
{
settings_t *settings = config_get_ptr();
if (!settings->bools.run_ahead_hide_warnings)
runloop_msg_queue_push(msg_hash_to_str(MSG_RUNAHEAD_CORE_DOES_NOT_SUPPORT_SAVESTATES), 0, 2 * 60, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
core_run();
runahead_force_input_dirty = true;
return;
}
}
/* Check for GUI */
/* Hack: If we were in the GUI, force a resync. */
if (frame_count != runahead_last_frame_count + 1)
runahead_force_input_dirty = true;
runahead_last_frame_count = frame_count;
if (!useSecondary || !have_dynamic || !runahead_secondary_core_available)
{
/* TODO: multiple savestates for higher performance
* when not using secondary core */
for (frame_number = 0; frame_number <= runahead_count; frame_number++)
{
last_frame = frame_number == runahead_count;
suspended_frame = !last_frame;
if (suspended_frame)
{
audio_suspended = true;
video_driver_active = false;
}
if (frame_number == 0)
core_run();
else
runahead_core_run_use_last_input();
if (suspended_frame)
{
runahead_resume_video();
audio_suspended = false;
}
if (frame_number == 0)
{
if (!runahead_save_state())
{
runloop_msg_queue_push(msg_hash_to_str(MSG_RUNAHEAD_FAILED_TO_SAVE_STATE), 0, 3 * 60, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
return;
}
}
if (last_frame)
{
if (!runahead_load_state())
{
runloop_msg_queue_push(msg_hash_to_str(MSG_RUNAHEAD_FAILED_TO_LOAD_STATE), 0, 3 * 60, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
return;
}
}
}
}
else
{
#if HAVE_DYNAMIC
if (!secondary_core_ensure_exists())
{
runahead_secondary_core_available = false;
runloop_msg_queue_push(msg_hash_to_str(MSG_RUNAHEAD_FAILED_TO_CREATE_SECONDARY_INSTANCE), 0, 3 * 60, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
core_run();
runahead_force_input_dirty = true;
return;
}
/* run main core with video suspended */
video_driver_active = false;
core_run();
runahead_resume_video();
if (input_is_dirty || runahead_force_input_dirty)
{
input_is_dirty = false;
if (!runahead_save_state())
{
runloop_msg_queue_push(msg_hash_to_str(MSG_RUNAHEAD_FAILED_TO_SAVE_STATE), 0, 3 * 60, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
return;
}
if (!runahead_load_state_secondary())
{
runloop_msg_queue_push(msg_hash_to_str(MSG_RUNAHEAD_FAILED_TO_LOAD_STATE), 0, 3 * 60, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
return;
}
for (frame_number = 0; frame_number < runahead_count - 1; frame_number++)
{
video_driver_active = false;
audio_suspended = true;
hard_disable_audio = true;
runahead_run_secondary();
hard_disable_audio = false;
audio_suspended = false;
runahead_resume_video();
}
}
audio_suspended = true;
hard_disable_audio = true;
runahead_run_secondary();
hard_disable_audio = false;
audio_suspended = false;
#endif
}
runahead_force_input_dirty = false;
}
bool want_fast_savestate(void)
{
return request_fast_savestate;
}
bool get_hard_disable_audio(void)
{
return hard_disable_audio;
}
void rarch_core_runtime_tick(void)
{
struct retro_system_av_info *av_info = &video_driver_av_info;
@ -12750,7 +13168,7 @@ bool retroarch_main_init(int argc, char *argv[])
char log_file_name[128];
#endif
video_driver_set_active();
video_driver_active = true;
audio_driver_active = true;
if (setjmp(error_sjlj_context) > 0)
@ -13021,7 +13439,6 @@ static void runloop_task_msg_queue_push(
runloop_msg_queue_push(msg, prio, duration, flush, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
}
bool rarch_ctl(enum rarch_ctl_state state, void *data)
{
static bool has_set_username = false;
@ -13140,7 +13557,7 @@ bool rarch_ctl(enum rarch_ctl_state state, void *data)
sthread_tls_create(&rarch_tls);
sthread_tls_set(&rarch_tls, MAGIC_POINTER);
#endif
video_driver_set_active();
video_driver_active = true;
audio_driver_active = true;
{
uint8_t i;
@ -16712,12 +17129,6 @@ bool core_run(void)
return true;
}
bool core_run_no_input_polling(void)
{
current_core.retro_run();
return true;
}
static bool core_verify_api_version(void)
{
unsigned api_version = current_core.retro_api_version();

View File

@ -556,14 +556,8 @@ typedef struct audio_driver
size_t (*buffer_size)(void *data);
} audio_driver_t;
void audio_driver_suspend(void);
bool audio_driver_is_suspended(void);
void audio_driver_resume(void);
void audio_driver_set_active(void);
bool audio_driver_is_active(void);
bool audio_driver_enable_callback(void);
@ -1669,23 +1663,33 @@ void video_driver_load_settings(config_file_t *conf);
void video_driver_save_settings(config_file_t *conf);
bool video_driver_is_hw_context(void);
struct retro_hw_render_callback *video_driver_get_hw_context(void);
const struct retro_hw_render_context_negotiation_interface
*video_driver_get_context_negotiation_interface(void);
void video_driver_set_context_negotiation_interface(const struct
retro_hw_render_context_negotiation_interface *iface);
bool video_driver_is_video_cache_context(void);
void video_driver_set_video_cache_context_ack(void);
bool video_driver_is_video_cache_context_ack(void);
void video_driver_set_active(void);
void video_driver_unset_active(void);
bool video_driver_is_active(void);
bool video_driver_gpu_record_init(unsigned size);
void video_driver_gpu_record_deinit(void);
bool video_driver_is_video_cache_context(void);
void video_driver_set_video_cache_context_ack(void);
bool video_driver_is_video_cache_context_ack(void);
bool video_driver_is_active(void);
bool video_driver_get_current_software_framebuffer(struct
retro_framebuffer *fb);
bool video_driver_get_hw_render_interface(const struct
retro_hw_render_interface **iface);
bool video_driver_get_viewport_info(struct video_viewport *viewport);
void video_driver_set_title_buf(void);
#if defined(HAVE_MENU) && defined(HAVE_MENU_WIDGETS)
@ -1917,9 +1921,6 @@ bool *video_driver_get_threaded(void);
void video_driver_set_threaded(bool val);
void video_driver_get_status(uint64_t *frame_count, bool * is_alive,
bool *is_focused);
/**
* video_context_driver_init_first:
* @data : Input data.

View File

@ -1,490 +0,0 @@
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <boolean.h>
#include "dirty_input.h"
#include "mylist.h"
#include "secondary_core.h"
#include "run_ahead.h"
#include "../core.h"
#include "../dynamic.h"
#include "../configuration.h"
#include "../retroarch.h"
static size_t runahead_save_state_size = 0;
static bool runahead_save_state_size_known = false;
static bool request_fast_savestate = false;
static bool hard_disable_audio = false;
/* Save State List for Run Ahead */
static MyList *runahead_save_state_list = NULL;
static void *runahead_save_state_alloc(void)
{
retro_ctx_serialize_info_t *savestate = (retro_ctx_serialize_info_t*)
malloc(sizeof(retro_ctx_serialize_info_t));
if (!savestate)
return NULL;
savestate->data = NULL;
savestate->data_const = NULL;
savestate->size = 0;
if (runahead_save_state_size > 0 && runahead_save_state_size_known)
{
savestate->data = malloc(runahead_save_state_size);
savestate->data_const = savestate->data;
savestate->size = runahead_save_state_size;
}
return savestate;
}
static void runahead_save_state_free(void *data)
{
retro_ctx_serialize_info_t *savestate = (retro_ctx_serialize_info_t*)data;
if (!savestate)
return;
free(savestate->data);
free(savestate);
}
static void runahead_save_state_list_init(size_t saveStateSize)
{
runahead_save_state_size = saveStateSize;
runahead_save_state_size_known = true;
mylist_create(&runahead_save_state_list, 16,
runahead_save_state_alloc, runahead_save_state_free);
}
static void runahead_save_state_list_destroy(void)
{
mylist_destroy(&runahead_save_state_list);
}
#if 0
static void runahead_save_state_list_rotate(void)
{
int i;
void *element;
void *firstElement;
firstElement = runahead_save_state_list->data[0];
for (i = 1; i < runahead_save_state_list->size; i++)
runahead_save_state_list->data[i - 1] =
runahead_save_state_list->data[i];
runahead_save_state_list->data[runahead_save_state_list->size - 1] =
firstElement;
}
#endif
/* Hooks - Hooks to cleanup, and add dirty input hooks */
static function_t originalRetroDeinit = NULL;
static function_t originalRetroUnload = NULL;
extern struct retro_core_t current_core;
extern struct retro_callbacks retro_ctx;
static void runahead_remove_hooks(void)
{
if (originalRetroDeinit)
{
current_core.retro_deinit = originalRetroDeinit;
originalRetroDeinit = NULL;
}
if (originalRetroUnload)
{
current_core.retro_unload_game = originalRetroUnload;
originalRetroUnload = NULL;
}
remove_input_state_hook();
}
static void unload_hook(void)
{
runahead_remove_hooks();
runahead_destroy();
secondary_core_destroy();
if (current_core.retro_unload_game)
current_core.retro_unload_game();
}
static void deinit_hook(void)
{
runahead_remove_hooks();
runahead_destroy();
secondary_core_destroy();
if (current_core.retro_deinit)
current_core.retro_deinit();
}
static void add_hooks(void)
{
if (!originalRetroDeinit)
{
originalRetroDeinit = current_core.retro_deinit;
current_core.retro_deinit = deinit_hook;
}
if (!originalRetroUnload)
{
originalRetroUnload = current_core.retro_unload_game;
current_core.retro_unload_game = unload_hook;
}
add_input_state_hook();
}
/* Runahead Code */
static bool runahead_video_driver_is_active = true;
static bool runahead_available = true;
static bool runahead_secondary_core_available = true;
static bool runahead_force_input_dirty = true;
static uint64_t runahead_last_frame_count = 0;
static void runahead_clear_variables(void)
{
runahead_save_state_size = 0;
runahead_save_state_size_known = false;
runahead_video_driver_is_active = true;
runahead_available = true;
runahead_secondary_core_available = true;
runahead_force_input_dirty = true;
runahead_last_frame_count = 0;
}
static uint64_t runahead_get_frame_count(void)
{
bool is_alive, is_focused = false;
uint64_t frame_count = 0;
video_driver_get_status(&frame_count, &is_alive, &is_focused);
return frame_count;
}
static void runahead_check_for_gui(void)
{
/* Hack: If we were in the GUI, force a resync. */
uint64_t frame_count = runahead_get_frame_count();
if (frame_count != runahead_last_frame_count + 1)
runahead_force_input_dirty = true;
runahead_last_frame_count = frame_count;
}
static void runahead_error(void)
{
runahead_available = false;
runahead_save_state_list_destroy();
runahead_remove_hooks();
runahead_save_state_size = 0;
runahead_save_state_size_known = true;
}
static bool runahead_create(void)
{
/* get savestate size and allocate buffer */
retro_ctx_size_info_t info;
request_fast_savestate = true;
core_serialize_size(&info);
request_fast_savestate = false;
runahead_save_state_list_init(info.size);
runahead_video_driver_is_active = video_driver_is_active();
if (runahead_save_state_size == 0 || !runahead_save_state_size_known)
{
runahead_error();
return false;
}
add_hooks();
runahead_force_input_dirty = true;
mylist_resize(runahead_save_state_list, 1, true);
return true;
}
static bool runahead_save_state(void)
{
bool okay = false;
retro_ctx_serialize_info_t *serialize_info;
if (!runahead_save_state_list)
return false;
serialize_info =
(retro_ctx_serialize_info_t*)runahead_save_state_list->data[0];
request_fast_savestate = true;
okay = core_serialize(serialize_info);
request_fast_savestate = false;
if (okay)
return true;
runahead_error();
return false;
}
static bool runahead_load_state(void)
{
bool okay = false;
retro_ctx_serialize_info_t *serialize_info = (retro_ctx_serialize_info_t*)
runahead_save_state_list->data[0];
bool last_dirty = input_is_dirty;
request_fast_savestate = true;
/* calling core_unserialize has side effects with
* netplay (it triggers transmitting your save state)
call retro_unserialize directly from the core instead */
okay = current_core.retro_unserialize(
serialize_info->data_const, serialize_info->size);
request_fast_savestate = false;
input_is_dirty = last_dirty;
if (!okay)
runahead_error();
return okay;
}
#if HAVE_DYNAMIC
static bool runahead_load_state_secondary(void)
{
bool okay = false;
retro_ctx_serialize_info_t *serialize_info =
(retro_ctx_serialize_info_t*)runahead_save_state_list->data[0];
request_fast_savestate = true;
okay = secondary_core_deserialize(
serialize_info->data_const, (int)serialize_info->size);
request_fast_savestate = false;
if (!okay)
{
runahead_secondary_core_available = false;
runahead_error();
return false;
}
return true;
}
static bool runahead_run_secondary(void)
{
if (!secondary_core_run_use_last_input())
{
runahead_secondary_core_available = false;
return false;
}
return true;
}
#endif
static void runahead_suspend_audio(void)
{
audio_driver_suspend();
}
static void runahead_resume_audio(void)
{
audio_driver_resume();
}
static void runahead_suspend_video(void)
{
video_driver_unset_active();
}
static void runahead_resume_video(void)
{
if (runahead_video_driver_is_active)
video_driver_set_active();
else
video_driver_unset_active();
}
static void runahead_input_poll_null(void)
{
}
static bool runahead_core_run_use_last_input(void)
{
extern struct retro_callbacks retro_ctx;
extern struct retro_core_t current_core;
retro_input_poll_t old_poll_function = retro_ctx.poll_cb;
retro_input_state_t old_input_function = retro_ctx.state_cb;
retro_ctx.poll_cb = runahead_input_poll_null;
retro_ctx.state_cb = input_state_get_last;
current_core.retro_set_input_poll(retro_ctx.poll_cb);
current_core.retro_set_input_state(retro_ctx.state_cb);
current_core.retro_run();
retro_ctx.poll_cb = old_poll_function;
retro_ctx.state_cb = old_input_function;
current_core.retro_set_input_poll(retro_ctx.poll_cb);
current_core.retro_set_input_state(retro_ctx.state_cb);
return true;
}
void run_ahead(int runahead_count, bool useSecondary)
{
int frame_number = 0;
bool last_frame = false;
bool suspended_frame = false;
#if defined(HAVE_DYNAMIC) || defined(HAVE_DYLIB)
const bool have_dynamic = true;
#else
const bool have_dynamic = false;
#endif
if (runahead_count <= 0 || !runahead_available)
{
core_run();
runahead_force_input_dirty = true;
return;
}
if (!runahead_save_state_size_known)
{
if (!runahead_create())
{
settings_t *settings = config_get_ptr();
if (!settings->bools.run_ahead_hide_warnings)
{
runloop_msg_queue_push(msg_hash_to_str(MSG_RUNAHEAD_CORE_DOES_NOT_SUPPORT_SAVESTATES), 0, 2 * 60, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
}
core_run();
runahead_force_input_dirty = true;
return;
}
}
runahead_check_for_gui();
if (!useSecondary || !have_dynamic || !runahead_secondary_core_available)
{
/* TODO: multiple savestates for higher performance
* when not using secondary core */
for (frame_number = 0; frame_number <= runahead_count; frame_number++)
{
last_frame = frame_number == runahead_count;
suspended_frame = !last_frame;
if (suspended_frame)
{
runahead_suspend_audio();
runahead_suspend_video();
}
if (frame_number == 0)
core_run();
else
runahead_core_run_use_last_input();
if (suspended_frame)
{
runahead_resume_video();
runahead_resume_audio();
}
if (frame_number == 0)
{
if (!runahead_save_state())
{
runloop_msg_queue_push(msg_hash_to_str(MSG_RUNAHEAD_FAILED_TO_SAVE_STATE), 0, 3 * 60, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
return;
}
}
if (last_frame)
{
if (!runahead_load_state())
{
runloop_msg_queue_push(msg_hash_to_str(MSG_RUNAHEAD_FAILED_TO_LOAD_STATE), 0, 3 * 60, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
return;
}
}
}
}
else
{
#if HAVE_DYNAMIC
if (!secondary_core_ensure_exists())
{
runahead_secondary_core_available = false;
runloop_msg_queue_push(msg_hash_to_str(MSG_RUNAHEAD_FAILED_TO_CREATE_SECONDARY_INSTANCE), 0, 3 * 60, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
core_run();
runahead_force_input_dirty = true;
return;
}
/* run main core with video suspended */
runahead_suspend_video();
core_run();
runahead_resume_video();
if (input_is_dirty || runahead_force_input_dirty)
{
input_is_dirty = false;
if (!runahead_save_state())
{
runloop_msg_queue_push(msg_hash_to_str(MSG_RUNAHEAD_FAILED_TO_SAVE_STATE), 0, 3 * 60, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
return;
}
if (!runahead_load_state_secondary())
{
runloop_msg_queue_push(msg_hash_to_str(MSG_RUNAHEAD_FAILED_TO_LOAD_STATE), 0, 3 * 60, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
return;
}
for (frame_number = 0; frame_number < runahead_count - 1; frame_number++)
{
runahead_suspend_video();
runahead_suspend_audio();
hard_disable_audio = true;
runahead_run_secondary();
hard_disable_audio = false;
runahead_resume_audio();
runahead_resume_video();
}
}
runahead_suspend_audio();
hard_disable_audio = true;
runahead_run_secondary();
hard_disable_audio = false;
runahead_resume_audio();
#endif
}
runahead_force_input_dirty = false;
}
void runahead_destroy(void)
{
runahead_save_state_list_destroy();
runahead_remove_hooks();
runahead_clear_variables();
}
bool want_fast_savestate(void)
{
return request_fast_savestate;
}
bool get_hard_disable_audio(void)
{
return hard_disable_audio;
}

View File

@ -8,10 +8,6 @@
RETRO_BEGIN_DECLS
void runahead_destroy(void);
void run_ahead(int runAheadCount, bool useSecondary);
bool want_fast_savestate(void);
bool get_hard_disable_audio(void);