diff --git a/cheats.c b/cheats.c index 62abe00e6c..5de7692e88 100644 --- a/cheats.c +++ b/cheats.c @@ -35,21 +35,6 @@ #include "compat/rxml/rxml.h" #endif -struct cheat -{ - char *desc; - bool state; - char *code; -}; - -struct cheat_manager -{ - struct cheat *cheats; - unsigned ptr; - unsigned size; - unsigned buf_size; -}; - static char *strcat_alloc(char *dest, const char *input) { size_t dest_len = dest ? strlen(dest) : 0; @@ -68,13 +53,13 @@ static char *strcat_alloc(char *dest, const char *input) return output; } -static bool xml_grab_cheat(struct cheat *cht, xmlNodePtr ptr) +static bool xml_grab_cheat(struct item_cheat *cht, xmlNodePtr ptr) { bool first; if (!ptr) return false; - memset(cht, 0, sizeof(struct cheat)); + memset(cht, 0, sizeof(struct item_cheat)); first = true; for (; ptr; ptr = ptr->next) @@ -124,10 +109,7 @@ static bool xml_grab_cheats(cheat_manager_t *handle, xmlNodePtr ptr) { if (handle->size == handle->buf_size) { - handle->buf_size *= 2; - handle->cheats = (struct cheat*) - realloc(handle->cheats, handle->buf_size * sizeof(struct cheat)); - if (!handle->cheats) + if (!cheat_manager_realloc(handle, handle->buf_size * 2)) return false; } @@ -139,7 +121,7 @@ static bool xml_grab_cheats(cheat_manager_t *handle, xmlNodePtr ptr) return true; } -static void cheat_manager_apply_cheats(cheat_manager_t *handle) +void cheat_manager_apply_cheats(cheat_manager_t *handle) { unsigned i; unsigned idx = 0; @@ -231,7 +213,68 @@ static void cheat_manager_save_config(cheat_manager_t *handle, config_file_free(conf); } -cheat_manager_t *cheat_manager_new(const char *path) +cheat_manager_t *cheat_manager_new(void) +{ + unsigned i; + cheat_manager_t *handle = NULL; + handle = (cheat_manager_t*)calloc(1, sizeof(struct cheat_manager)); + if (!handle) + return NULL; + + handle->buf_size = handle->size = 0; + handle->cheats = (struct item_cheat*) + calloc(handle->buf_size, sizeof(struct item_cheat)); + + if (!handle->cheats) + { + handle->buf_size = 0; + handle->size = 0; + handle->cheats = NULL; + return handle; + } + + for (i = 0; i < handle->size; i++) + { + handle->cheats[i].desc = NULL; + handle->cheats[i].code = NULL; + handle->cheats[i].state = false; + } + + return handle; +} + +bool cheat_manager_realloc(cheat_manager_t *handle, unsigned new_size) +{ + unsigned i; + + if (!handle->cheats) + handle->cheats = (struct item_cheat*) + calloc(new_size, sizeof(struct item_cheat)); + else + handle->cheats = (struct item_cheat*) + realloc(handle->cheats, new_size * sizeof(struct item_cheat)); + + if (!handle->cheats) + { + handle->buf_size = handle->size = 0; + handle->cheats = NULL; + return false; + } + + handle->buf_size = new_size; + handle->size = new_size; + + for (i = 0; i < handle->size; i++) + { + handle->cheats[i].desc = NULL; + handle->cheats[i].code = NULL; + handle->cheats[i].state = false; + } + + return true; +} + +cheat_manager_t *cheat_manager_new_from_xml(const char *path) { xmlParserCtxtPtr ctx; xmlNodePtr head, cur; @@ -252,8 +295,8 @@ cheat_manager_t *cheat_manager_new(const char *path) cur = NULL; handle->buf_size = 1; - handle->cheats = (struct cheat*) - calloc(handle->buf_size, sizeof(struct cheat)); + handle->cheats = (struct item_cheat*) + calloc(handle->buf_size, sizeof(struct item_cheat)); if (!handle->cheats) { handle->buf_size = 0; diff --git a/cheats.h b/cheats.h index 0eee59fb23..88c29dab74 100644 --- a/cheats.h +++ b/cheats.h @@ -16,13 +16,34 @@ #ifndef __RARCH_CHEATS_H #define __RARCH_CHEATS_H +#include + #ifdef __cplusplus extern "C" { #endif +struct item_cheat +{ + char *desc; + bool state; + char *code; +}; + +struct cheat_manager +{ + struct item_cheat *cheats; + unsigned ptr; + unsigned size; + unsigned buf_size; +}; + typedef struct cheat_manager cheat_manager_t; -cheat_manager_t* cheat_manager_new(const char *path); +cheat_manager_t *cheat_manager_new(void); + +cheat_manager_t* cheat_manager_new_from_xml(const char *path); + +bool cheat_manager_realloc(cheat_manager_t *handle, unsigned new_size); void cheat_manager_free(cheat_manager_t *handle); @@ -32,6 +53,8 @@ void cheat_manager_index_prev(cheat_manager_t *handle); void cheat_manager_toggle(cheat_manager_t *handle); +void cheat_manager_apply_cheats(cheat_manager_t *handle); + #ifdef __cplusplus } #endif diff --git a/menu/disp/shared.h b/menu/disp/shared.h index 8fc30929f7..68faaf6002 100644 --- a/menu/disp/shared.h +++ b/menu/disp/shared.h @@ -58,6 +58,8 @@ static void get_title(const char *label, const char *dir, strlcpy(title, "DISK OPTIONS", sizeof_title); else if (!strcmp(label, "core_options")) strlcpy(title, "CORE OPTIONS", sizeof_title); + else if (!strcmp(label, "core_cheat_options")) + strlcpy(title, "CORE CHEAT OPTIONS", sizeof_title); else if (!strcmp(label, "core_information")) strlcpy(title, "CORE INFO", sizeof_title); else if (!strcmp(label, "Privacy Options")) diff --git a/menu/menu_common.c b/menu/menu_common.c index f89922c22b..db4f84d82b 100644 --- a/menu/menu_common.c +++ b/menu/menu_common.c @@ -166,6 +166,7 @@ void *menu_init(const void *data) #ifdef HAVE_SHADER_MANAGER menu->shader = (struct gfx_shader*)calloc(1, sizeof(struct gfx_shader)); #endif + menu->cheats = cheat_manager_new(); menu->push_start_screen = g_settings.menu_show_start_screen; g_settings.menu_show_start_screen = false; @@ -218,6 +219,10 @@ void menu_free(void *data) menu->shader = NULL; #endif + if (menu->cheats) + cheat_manager_free(menu->cheats); + menu->cheats = NULL; + if (driver.menu_ctx && driver.menu_ctx->free) driver.menu_ctx->free(menu); diff --git a/menu/menu_common.h b/menu/menu_common.h index b1ded080b7..ea4980cf29 100644 --- a/menu/menu_common.h +++ b/menu/menu_common.h @@ -45,6 +45,10 @@ #define MAX_COUNTERS 64 #endif +#ifndef MAX_CHEAT_COUNTERS +#define MAX_CHEAT_COUNTERS 100 +#endif + #define MENU_SETTINGS_CORE_INFO_NONE 0xffff #define MENU_SETTINGS_CORE_OPTION_NONE 0xffff #define MENU_SETTINGS_CORE_OPTION_START 0x10000 @@ -141,7 +145,9 @@ typedef enum MENU_SETTINGS_LIBRETRO_PERF_COUNTERS_BEGIN, MENU_SETTINGS_LIBRETRO_PERF_COUNTERS_END = MENU_SETTINGS_LIBRETRO_PERF_COUNTERS_BEGIN + (MAX_COUNTERS - 1), MENU_SETTINGS_PERF_COUNTERS_BEGIN, - MENU_SETTINGS_PERF_COUNTERS_END = MENU_SETTINGS_PERF_COUNTERS_BEGIN + (MAX_COUNTERS - 1) + MENU_SETTINGS_PERF_COUNTERS_END = MENU_SETTINGS_PERF_COUNTERS_BEGIN + (MAX_COUNTERS - 1), + MENU_SETTINGS_CHEAT_BEGIN, + MENU_SETTINGS_CHEAT_END = MENU_SETTINGS_CHEAT_BEGIN + (MAX_CHEAT_COUNTERS - 1), } menu_settings_t; void *menu_init(const void *data); diff --git a/menu/menu_driver.h b/menu/menu_driver.h index 6d1dc430bf..490d54e392 100644 --- a/menu/menu_driver.h +++ b/menu/menu_driver.h @@ -21,6 +21,7 @@ #include #include #include "menu_list.h" +#include "../cheats.h" #include "../settings_list.h" #ifdef __cplusplus @@ -108,6 +109,7 @@ typedef struct bool load_no_content; struct gfx_shader *shader; + cheat_manager_t *cheats; struct menu_bind_state binds; @@ -133,6 +135,8 @@ typedef struct const char *label; const char *label_setting; bool display; + unsigned type; + unsigned idx; } keyboard; rarch_setting_t *list_mainmenu; diff --git a/menu/menu_entries_cbs.c b/menu/menu_entries_cbs.c index e47e5c7342..4b18f2f3f1 100644 --- a/menu/menu_entries_cbs.c +++ b/menu/menu_entries_cbs.c @@ -24,6 +24,7 @@ #include "../file_ext.h" #include "../config.def.h" +#include "../cheats.h" #include @@ -164,6 +165,14 @@ static int action_ok_load_state(const char *path, return 0; } +static int action_ok_cheat(const char *path, + const char *label, unsigned type, size_t idx) +{ + menu_key_start_line(driver.menu, "Input Cheat", + label, type, idx, st_cheat_callback); + return 0; +} + static int action_ok_save_state(const char *path, const char *label, unsigned type, size_t idx) { @@ -261,6 +270,19 @@ static int action_ok_shader_apply_changes(const char *path, return 0; } +static int action_ok_cheat_apply_changes(const char *path, + const char *label, unsigned type, size_t idx) +{ + cheat_manager_t *cheat = (cheat_manager_t*)driver.menu->cheats; + + if (!cheat) + return -1; + + cheat_manager_apply_cheats(cheat); + + return 0; +} + /* FIXME: Ugly hack, need to be refactored badly. */ size_t hack_shader_pass = 0; @@ -321,7 +343,7 @@ static int action_ok_shader_preset_save_as(const char *path, return -1; menu_key_start_line(driver.menu, "Preset Filename", - label, st_string_callback); + label, type, idx, st_string_callback); return 0; } @@ -1130,7 +1152,7 @@ static int action_start_shader_num_passes(unsigned type, const char *label, if (!shader) return -1; - if (shader && shader->passes) + if (shader->passes) shader->passes = 0; driver.menu->need_refresh = true; @@ -1139,6 +1161,52 @@ static int action_start_shader_num_passes(unsigned type, const char *label, return 0; } +static int action_start_cheat_num_passes(unsigned type, const char *label, + unsigned action) +{ + cheat_manager_t *cheat = (cheat_manager_t*)driver.menu->cheats; + + if (!cheat) + return -1; + + if (cheat->size) + { + cheat_manager_realloc(cheat, 0); + driver.menu->need_refresh = true; + } + + return 0; +} + +static int action_toggle_cheat_num_passes(unsigned type, const char *label, + unsigned action) +{ + unsigned new_size = 0; + cheat_manager_t *cheat = (cheat_manager_t*)driver.menu->cheats; + + if (!cheat) + return -1; + + switch (action) + { + case MENU_ACTION_LEFT: + if (cheat->size) + new_size = cheat->size - 1; + driver.menu->need_refresh = true; + break; + + case MENU_ACTION_RIGHT: + new_size = cheat->size + 1; + driver.menu->need_refresh = true; + break; + } + + if (driver.menu->need_refresh) + cheat_manager_realloc(cheat, new_size); + + return 0; +} + static int action_toggle_shader_num_passes(unsigned type, const char *label, unsigned action) { @@ -1151,13 +1219,13 @@ static int action_toggle_shader_num_passes(unsigned type, const char *label, switch (action) { case MENU_ACTION_LEFT: - if (shader && shader->passes) + if (shader->passes) shader->passes--; driver.menu->need_refresh = true; break; case MENU_ACTION_RIGHT: - if (shader && (shader->passes < GFX_MAX_SHADERS)) + if ((shader->passes < GFX_MAX_SHADERS)) shader->passes++; driver.menu->need_refresh = true; break; @@ -1761,6 +1829,36 @@ static int deferred_push_frontend_counters(void *data, void *userdata, return 0; } +static int deferred_push_core_cheat_options(void *data, void *userdata, + const char *path, const char *label, unsigned type) +{ + unsigned i; + size_t opts = 100; + file_list_t *list = (file_list_t*)data; + cheat_manager_t *cheat = (cheat_manager_t*)driver.menu->cheats; + + if (!list || !cheat) + return -1; + + menu_list_clear(list); + menu_list_push(list, "Cheat Passes", "cheat_num_passes", + 0, 0); + menu_list_push(list, "Apply Cheat Changes", "cheat_apply_changes", + MENU_SETTING_ACTION, 0); + + for (i = 0; i < cheat->size; i++) + { + char label[64]; + snprintf(label, sizeof(label), "Cheat #%d: ", i); + menu_list_push(list, label, "", MENU_SETTINGS_CHEAT_BEGIN + i, 0); + } + + if (driver.menu_ctx && driver.menu_ctx->populate_entries) + driver.menu_ctx->populate_entries(driver.menu, path, label, type); + + return 0; +} + static int deferred_push_core_options(void *data, void *userdata, const char *path, const char *label, unsigned type) { @@ -2106,6 +2204,9 @@ static int menu_entries_cbs_init_bind_ok_first(menu_file_list_cbs_t *cbs, else if (type >= MENU_SETTINGS_SHADER_PRESET_PARAMETER_0 && type <= MENU_SETTINGS_SHADER_PRESET_PARAMETER_LAST) cbs->action_ok = NULL; + else if (type >= MENU_SETTINGS_CHEAT_BEGIN + && type <= MENU_SETTINGS_CHEAT_END) + cbs->action_ok = action_ok_cheat; else if (!strcmp(label, "savestate")) cbs->action_ok = action_ok_save_state; else if (!strcmp(label, "loadstate")) @@ -2210,6 +2311,8 @@ static void menu_entries_cbs_init_bind_start(menu_file_list_cbs_t *cbs, cbs->action_start = action_start_shader_filter_pass; else if (!strcmp(label, "video_shader_num_passes")) cbs->action_start = action_start_shader_num_passes; + else if (!strcmp(label, "cheat_num_passes")) + cbs->action_start = action_start_cheat_num_passes; else if (type >= MENU_SETTINGS_SHADER_PARAMETER_0 && type <= MENU_SETTINGS_SHADER_PARAMETER_LAST) cbs->action_start = action_start_shader_action_parameter; @@ -2263,6 +2366,7 @@ static void menu_entries_cbs_init_bind_ok(menu_file_list_cbs_t *cbs, !strcmp(label, "Shader Options") || !strcmp(label, "Input Options") || !strcmp(label, "core_options") || + !strcmp(label, "core_cheat_options") || !strcmp(label, "core_information") || !strcmp(label, "disk_options") || !strcmp(label, "settings") || @@ -2282,6 +2386,8 @@ static void menu_entries_cbs_init_bind_ok(menu_file_list_cbs_t *cbs, cbs->action_ok = action_ok_push_path_list; else if (!strcmp(label, "shader_apply_changes")) cbs->action_ok = action_ok_shader_apply_changes; + else if (!strcmp(label, "cheat_apply_changes")) + cbs->action_ok = action_ok_cheat_apply_changes; else if (!strcmp(label, "video_shader_preset_save_as")) cbs->action_ok = action_ok_shader_preset_save_as; else if (!strcmp(label, "core_list")) @@ -2334,6 +2440,8 @@ static void menu_entries_cbs_init_bind_toggle(menu_file_list_cbs_t *cbs, cbs->action_toggle = action_toggle_shader_filter_default; else if (!strcmp(label, "video_shader_num_passes")) cbs->action_toggle = action_toggle_shader_num_passes; + else if (!strcmp(label, "cheat_num_passes")) + cbs->action_toggle = action_toggle_cheat_num_passes; else if (type == MENU_SETTINGS_VIDEO_RESOLUTION) cbs->action_toggle = action_toggle_video_resolution; else if ((type >= MENU_SETTINGS_CORE_OPTION_START)) @@ -2401,6 +2509,8 @@ static void menu_entries_cbs_init_bind_deferred_push(menu_file_list_cbs_t *cbs, cbs->action_deferred_push = deferred_push_frontend_counters; else if (!strcmp(label, "core_options")) cbs->action_deferred_push = deferred_push_core_options; + else if (!strcmp(label, "core_cheat_options")) + cbs->action_deferred_push = deferred_push_core_cheat_options; else if (!strcmp(label, "disk_options")) cbs->action_deferred_push = deferred_push_disk_options; else if (!strcmp(label, "core_list")) diff --git a/menu/menu_input_line_cb.c b/menu/menu_input_line_cb.c index 0198ed734f..8195714a5e 100644 --- a/menu/menu_input_line_cb.c +++ b/menu/menu_input_line_cb.c @@ -33,7 +33,8 @@ #include "../settings_data.h" void menu_key_start_line(void *data, const char *label, - const char *label_setting, input_keyboard_line_complete_t cb) + const char *label_setting, unsigned type, unsigned idx, + input_keyboard_line_complete_t cb) { menu_handle_t *menu = (menu_handle_t*)data; @@ -43,6 +44,8 @@ void menu_key_start_line(void *data, const char *label, menu->keyboard.display = true; menu->keyboard.label = label; menu->keyboard.label_setting = label_setting; + menu->keyboard.type = type; + menu->keyboard.idx = idx; menu->keyboard.buffer = input_keyboard_start_line(menu, cb); } @@ -107,6 +110,22 @@ void st_string_callback(void *userdata, const char *str) menu_key_end_line(menu); } +void st_cheat_callback(void *userdata, const char *str) +{ + menu_handle_t *menu = (menu_handle_t*)userdata; + cheat_manager_t *cheat = (cheat_manager_t*)menu->cheats; + + if (cheat && str && *str) + { + unsigned cheat_index = menu->keyboard.type - MENU_SETTINGS_CHEAT_BEGIN; + RARCH_LOG("cheat_index is: %d\n", cheat_index); + + cheat->cheats[cheat_index].code = strdup(str); + cheat->cheats[cheat_index].state = true; + } + menu_key_end_line(menu); +} + void menu_key_event(bool down, unsigned keycode, uint32_t character, uint16_t mod) { diff --git a/menu/menu_input_line_cb.h b/menu/menu_input_line_cb.h index 4a375889c4..9adb73dd2a 100644 --- a/menu/menu_input_line_cb.h +++ b/menu/menu_input_line_cb.h @@ -27,12 +27,15 @@ void menu_key_event(bool down, unsigned keycode, uint32_t character, uint16_t key_modifiers); void menu_key_start_line(void *data, const char *label, - const char *label_setting, input_keyboard_line_complete_t cb); + const char *label_setting, unsigned type, unsigned idx, + input_keyboard_line_complete_t cb); void st_uint_callback(void *userdata, const char *str); void st_string_callback(void *userdata, const char *str); +void st_cheat_callback(void *userdata, const char *str); + void menu_poll_bind_get_rested_axes(struct menu_bind_state *state); void menu_poll_bind_state(struct menu_bind_state *state); diff --git a/retroarch.c b/retroarch.c index 2ceac10f9a..ee24332830 100644 --- a/retroarch.c +++ b/retroarch.c @@ -1118,7 +1118,7 @@ static void init_cheats(void) return; if (*g_settings.cheat_database) - g_extern.cheat = cheat_manager_new(g_settings.cheat_database); + g_extern.cheat = cheat_manager_new_from_xml(g_settings.cheat_database); } static void init_rewind(void) diff --git a/settings_data.c b/settings_data.c index 143ce7ec78..2b14b2925a 100644 --- a/settings_data.c +++ b/settings_data.c @@ -989,7 +989,7 @@ static int setting_data_uint_action_ok_linefeed(void *data, unsigned action) return -1; menu_key_start_line(driver.menu, setting->short_description, - setting->name, st_uint_callback); + setting->name, 0, 0, st_uint_callback); return 0; } @@ -2400,7 +2400,19 @@ void setting_data_get_label(char *type_str, } else #endif - if (type >= MENU_SETTINGS_PERF_COUNTERS_BEGIN + if (!strcmp(label, "cheat_num_passes")) + snprintf(type_str, type_str_size, "%u", driver.menu->cheats->buf_size); + else if (type >= MENU_SETTINGS_CHEAT_BEGIN + && type <= MENU_SETTINGS_CHEAT_END) + { + unsigned cheat_index = type - MENU_SETTINGS_CHEAT_BEGIN; + if (cheat_index < driver.menu->cheats->buf_size) + snprintf(type_str, type_str_size, "%s", + ( + (driver.menu->cheats->cheats[cheat_index].code != NULL) + ) ? driver.menu->cheats->cheats[cheat_index].code : "N/A"); + } + else if (type >= MENU_SETTINGS_PERF_COUNTERS_BEGIN && type <= MENU_SETTINGS_PERF_COUNTERS_END) menu_common_setting_set_label_perf(type_str, type_str_size, w, type, perf_counters_rarch, @@ -2747,7 +2759,7 @@ static int setting_data_string_action_ok_allow_input(void *data, return -1; menu_key_start_line(driver.menu, setting->short_description, - setting->name, st_string_callback); + setting->name, 0, 0, st_string_callback); return 0; } @@ -2859,22 +2871,32 @@ static bool setting_data_append_list_main_menu_options( group_info.name, subgroup_info.name); + CONFIG_ACTION( "core_information", "Core Information", group_info.name, subgroup_info.name); - if (g_extern.main_is_init - && !g_extern.libretro_dummy - && g_extern.system.disk_control.get_num_images) + if (g_extern.main_is_init) { CONFIG_ACTION( - "disk_options", - "Core Disk Options", + "core_cheat_options", + "Core Cheat Options", group_info.name, subgroup_info.name); + + if ( !g_extern.libretro_dummy + && g_extern.system.disk_control.get_num_images) + { + CONFIG_ACTION( + "disk_options", + "Core Disk Options", + group_info.name, + subgroup_info.name); + } } + CONFIG_ACTION( "settings", "Settings",