diff --git a/Makefile.common b/Makefile.common index 2ca5dacddb..ee7b3303e2 100644 --- a/Makefile.common +++ b/Makefile.common @@ -265,7 +265,6 @@ OBJ += frontend/frontend.o \ ifeq ($(HAVE_RUNAHEAD), 1) DEFINES += -DHAVE_RUNAHEAD OBJ += runahead/copy_load_info.o \ - runahead/dirty_input.o \ runahead/mem_util.o \ runahead/mylist.o \ runahead/secondary_core.o diff --git a/core.h b/core.h index c7e47b7740..75e5482f9a 100644 --- a/core.h +++ b/core.h @@ -234,8 +234,6 @@ bool core_is_game_loaded(void); void core_free_retro_game_info(struct retro_game_info *dest); -extern struct retro_callbacks retro_ctx; - RETRO_END_DECLS #endif diff --git a/griffin/griffin.c b/griffin/griffin.c index fd28cc9a1d..89432403f5 100644 --- a/griffin/griffin.c +++ b/griffin/griffin.c @@ -1369,7 +1369,6 @@ MENU #include "../runahead/mem_util.c" #include "../runahead/secondary_core.c" #include "../runahead/copy_load_info.c" -#include "../runahead/dirty_input.c" #include "../runahead/mylist.c" #endif diff --git a/retroarch.c b/retroarch.c index 2817fa5e71..2b9d971895 100644 --- a/retroarch.c +++ b/retroarch.c @@ -240,6 +240,9 @@ typedef struct runloop_ctx_msg_info static struct global g_extern; +static struct retro_callbacks retro_ctx; +static struct retro_core_t current_core; + static jmp_buf error_sjlj_context; static enum rarch_core_type current_core_type = CORE_TYPE_PLAIN; static enum rarch_core_type explicit_current_core_type = CORE_TYPE_PLAIN; @@ -11651,6 +11654,212 @@ static bool hard_disable_audio = false; /* Save State List for Run Ahead */ static MyList *runahead_save_state_list = NULL; +static bool input_is_dirty = false; +static MyList *input_state_list = NULL; + +typedef struct InputListElement_t +{ + unsigned port; + unsigned device; + unsigned index; + int16_t *state; + unsigned int state_size; +} InputListElement; + +typedef bool(*LoadStateFunction)(const void*, size_t); + +static function_t retro_reset_callback_original = NULL; +static LoadStateFunction retro_unserialize_callback_original = NULL; +static retro_input_state_t input_state_callback_original; + +static void* InputListElementConstructor(void) +{ + const int size = sizeof(InputListElement); + const int initial_state_array_size = 256; + void *ptr = calloc(1, size); + InputListElement *element = (InputListElement*)ptr; + element->state_size = initial_state_array_size; + element->state = (int16_t*)calloc(element->state_size, sizeof(int16_t)); + return ptr; +} + +static void InputListElementRealloc(InputListElement *element, + unsigned int new_size) +{ + if (new_size > element->state_size) + { + element->state = (int16_t*)realloc(element->state, + new_size * sizeof(int16_t)); + memset(&element->state[element->state_size], 0, + (new_size - element->state_size) * sizeof(int16_t)); + element->state_size = new_size; + } +} + +static void InputListElementExpand( + InputListElement *element, unsigned int newIndex) +{ + unsigned int new_size = element->state_size; + if (new_size == 0) + new_size = 32; + while (newIndex >= new_size) + new_size *= 2; + InputListElementRealloc(element, new_size); +} + +static void InputListElementDestructor(void* element_ptr) +{ + InputListElement *element = (InputListElement*)element_ptr; + free(element->state); + free(element_ptr); +} + +static void input_state_destroy(void) +{ + mylist_destroy(&input_state_list); +} + +static void input_state_set_last(unsigned port, unsigned device, + unsigned index, unsigned id, int16_t value) +{ + unsigned i; + InputListElement *element = NULL; + if (id >= 65536) + return; + /*arbitrary limit of up to 65536 elements in state array*/ + + if (!input_state_list) + mylist_create(&input_state_list, 16, + InputListElementConstructor, InputListElementDestructor); + + /* find list item */ + for (i = 0; i < (unsigned)input_state_list->size; i++) + { + element = (InputListElement*)input_state_list->data[i]; + if ( (element->port == port) && + (element->device == device) && + (element->index == index) + ) + { + if (id >= element->state_size) + InputListElementExpand(element, id); + element->state[id] = value; + return; + } + } + + element = (InputListElement*) + mylist_add_element(input_state_list); + element->port = port; + element->device = device; + element->index = index; + if (id >= element->state_size) + InputListElementExpand(element, id); + element->state[id] = value; +} + +int16_t input_state_get_last(unsigned port, + unsigned device, unsigned index, unsigned id) +{ + unsigned i; + + if (!input_state_list) + return 0; + + /* find list item */ + for (i = 0; i < (unsigned)input_state_list->size; i++) + { + InputListElement *element = + (InputListElement*)input_state_list->data[i]; + + if ( (element->port == port) && + (element->device == device) && + (element->index == index)) + { + if (id < element->state_size) + return element->state[id]; + return 0; + } + } + return 0; +} + +static int16_t input_state_with_logging(unsigned port, + unsigned device, unsigned index, unsigned id) +{ + if (input_state_callback_original) + { + int16_t result = input_state_callback_original( + port, device, index, id); + int16_t last_input = input_state_get_last(port, device, index, id); + if (result != last_input) + input_is_dirty = true; + input_state_set_last(port, device, index, id, result); + return result; + } + return 0; +} + +static void reset_hook(void) +{ + input_is_dirty = true; + if (retro_reset_callback_original) + retro_reset_callback_original(); +} + +static bool unserialze_hook(const void *buf, size_t size) +{ + input_is_dirty = true; + if (retro_unserialize_callback_original) + return retro_unserialize_callback_original(buf, size); + return false; +} + +static void add_input_state_hook(void) +{ + if (!input_state_callback_original) + { + input_state_callback_original = retro_ctx.state_cb; + retro_ctx.state_cb = input_state_with_logging; + current_core.retro_set_input_state(retro_ctx.state_cb); + } + + if (!retro_reset_callback_original) + { + retro_reset_callback_original = current_core.retro_reset; + current_core.retro_reset = reset_hook; + } + + if (!retro_unserialize_callback_original) + { + retro_unserialize_callback_original = current_core.retro_unserialize; + current_core.retro_unserialize = unserialze_hook; + } +} + +static void remove_input_state_hook(void) +{ + if (input_state_callback_original) + { + retro_ctx.state_cb = input_state_callback_original; + current_core.retro_set_input_state(retro_ctx.state_cb); + input_state_callback_original = NULL; + input_state_destroy(); + } + + if (retro_reset_callback_original) + { + current_core.retro_reset = retro_reset_callback_original; + retro_reset_callback_original = NULL; + } + + if (retro_unserialize_callback_original) + { + current_core.retro_unserialize = retro_unserialize_callback_original; + retro_unserialize_callback_original = NULL; + } +} + static void *runahead_save_state_alloc(void) { retro_ctx_serialize_info_t *savestate = (retro_ctx_serialize_info_t*) @@ -11714,9 +11923,6 @@ static void runahead_save_state_list_rotate(void) 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) @@ -11916,8 +12122,8 @@ 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; + 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); @@ -16715,9 +16921,6 @@ enum retro_language rarch_get_language_from_iso(const char *iso639) /* Libretro core loader */ -struct retro_callbacks retro_ctx; -struct retro_core_t current_core; - static void retro_run_null(void) { } diff --git a/runahead/dirty_input.c b/runahead/dirty_input.c deleted file mode 100644 index 6602d9223e..0000000000 --- a/runahead/dirty_input.c +++ /dev/null @@ -1,223 +0,0 @@ -#include - -#include -#include - -#include "../core.h" -#include "../dynamic.h" - -#include "mylist.h" -#include "mem_util.h" -#include "dirty_input.h" - -bool input_is_dirty = false; -static MyList *input_state_list = NULL; - -typedef struct InputListElement_t -{ - unsigned port; - unsigned device; - unsigned index; - int16_t *state; - unsigned int state_size; -} InputListElement; - -extern struct retro_core_t current_core; -extern struct retro_callbacks retro_ctx; - -typedef bool(*LoadStateFunction)(const void*, size_t); - -static function_t retro_reset_callback_original = NULL; -static LoadStateFunction retro_unserialize_callback_original = NULL; -static retro_input_state_t input_state_callback_original; - -static void reset_hook(void); -static bool unserialze_hook(const void *buf, size_t size); - -static void* InputListElementConstructor(void) -{ - const int size = sizeof(InputListElement); - const int initial_state_array_size = 256; - void *ptr = calloc(1, size); - InputListElement *element = (InputListElement*)ptr; - element->state_size = initial_state_array_size; - element->state = (int16_t*)calloc(element->state_size, sizeof(int16_t)); - return ptr; -} - -static void InputListElementRealloc(InputListElement *element, - unsigned int new_size) -{ - if (new_size > element->state_size) - { - element->state = (int16_t*)realloc(element->state, - new_size * sizeof(int16_t)); - memset(&element->state[element->state_size], 0, - (new_size - element->state_size) * sizeof(int16_t)); - element->state_size = new_size; - } -} - -static void InputListElementExpand( - InputListElement *element, unsigned int newIndex) -{ - unsigned int new_size = element->state_size; - if (new_size == 0) - new_size = 32; - while (newIndex >= new_size) - new_size *= 2; - InputListElementRealloc(element, new_size); -} - -static void InputListElementDestructor(void* element_ptr) -{ - InputListElement *element = (InputListElement*)element_ptr; - free(element->state); - free(element_ptr); -} - -static void input_state_destroy(void) -{ - mylist_destroy(&input_state_list); -} - -static void input_state_set_last(unsigned port, unsigned device, - unsigned index, unsigned id, int16_t value) -{ - unsigned i; - InputListElement *element = NULL; - if (id >= 65536) - return; - /*arbitrary limit of up to 65536 elements in state array*/ - - if (!input_state_list) - mylist_create(&input_state_list, 16, - InputListElementConstructor, InputListElementDestructor); - - /* find list item */ - for (i = 0; i < (unsigned)input_state_list->size; i++) - { - element = (InputListElement*)input_state_list->data[i]; - if ( (element->port == port) && - (element->device == device) && - (element->index == index) - ) - { - if (id >= element->state_size) - InputListElementExpand(element, id); - element->state[id] = value; - return; - } - } - - element = (InputListElement*) - mylist_add_element(input_state_list); - element->port = port; - element->device = device; - element->index = index; - if (id >= element->state_size) - InputListElementExpand(element, id); - element->state[id] = value; -} - -int16_t input_state_get_last(unsigned port, - unsigned device, unsigned index, unsigned id) -{ - unsigned i; - - if (!input_state_list) - return 0; - - /* find list item */ - for (i = 0; i < (unsigned)input_state_list->size; i++) - { - InputListElement *element = - (InputListElement*)input_state_list->data[i]; - - if ( (element->port == port) && - (element->device == device) && - (element->index == index)) - { - if (id < element->state_size) - return element->state[id]; - return 0; - } - } - return 0; -} - -static int16_t input_state_with_logging(unsigned port, - unsigned device, unsigned index, unsigned id) -{ - if (input_state_callback_original) - { - int16_t result = input_state_callback_original( - port, device, index, id); - int16_t last_input = input_state_get_last(port, device, index, id); - if (result != last_input) - input_is_dirty = true; - input_state_set_last(port, device, index, id, result); - return result; - } - return 0; -} - -static void reset_hook(void) -{ - input_is_dirty = true; - if (retro_reset_callback_original) - retro_reset_callback_original(); -} - -static bool unserialze_hook(const void *buf, size_t size) -{ - input_is_dirty = true; - if (retro_unserialize_callback_original) - return retro_unserialize_callback_original(buf, size); - return false; -} - -void add_input_state_hook(void) -{ - if (!input_state_callback_original) - { - input_state_callback_original = retro_ctx.state_cb; - retro_ctx.state_cb = input_state_with_logging; - current_core.retro_set_input_state(retro_ctx.state_cb); - } - - if (!retro_reset_callback_original) - { - retro_reset_callback_original = current_core.retro_reset; - current_core.retro_reset = reset_hook; - } - - if (!retro_unserialize_callback_original) - { - retro_unserialize_callback_original = current_core.retro_unserialize; - current_core.retro_unserialize = unserialze_hook; - } -} - -void remove_input_state_hook(void) -{ - if (input_state_callback_original) - { - retro_ctx.state_cb = input_state_callback_original; - current_core.retro_set_input_state(retro_ctx.state_cb); - input_state_callback_original = NULL; - input_state_destroy(); - } - - if (retro_reset_callback_original) - { - current_core.retro_reset = retro_reset_callback_original; - retro_reset_callback_original = NULL; - } - - if (retro_unserialize_callback_original) - { - current_core.retro_unserialize = retro_unserialize_callback_original; - retro_unserialize_callback_original = NULL; - } -} diff --git a/runahead/dirty_input.h b/runahead/dirty_input.h index 1aa935cc1b..6428fe45ba 100644 --- a/runahead/dirty_input.h +++ b/runahead/dirty_input.h @@ -6,9 +6,6 @@ RETRO_BEGIN_DECLS -extern bool input_is_dirty; -void add_input_state_hook(void); -void remove_input_state_hook(void); int16_t input_state_get_last(unsigned port, unsigned device, unsigned index, unsigned id);