From f58130bb6468a4689f1943d2fb8f54e3cc8108b4 Mon Sep 17 00:00:00 2001 From: Jamiras Date: Tue, 20 Oct 2020 10:37:05 -0600 Subject: [PATCH] disable achievement hardcore mode when certain core options are enabled --- cheevos/cheevos.c | 141 ++++++++++++++++++++++++++++++++++++++++++++++ cheevos/cheevos.h | 2 + retroarch.c | 51 ++++++++--------- 3 files changed, 168 insertions(+), 26 deletions(-) diff --git a/cheevos/cheevos.c b/cheevos/cheevos.c index d4676b9077..3a3e47bddc 100644 --- a/cheevos/cheevos.c +++ b/cheevos/cheevos.c @@ -65,6 +65,7 @@ #include "../msg_hash.h" #include "../retroarch.h" #include "../core.h" +#include "../core_option_manager.h" #include "../version.h" #include "../frontend/frontend_driver.h" @@ -1429,6 +1430,11 @@ static void rcheevos_toggle_hardcore_active(rcheevos_locals_t* locals) /* activate hardcore */ locals->hardcore_active = true; + /* if one or more invalid settings is enabled, abort*/ + rcheevos_validate_config_settings(); + if (!locals->hardcore_active) + return; + if (locals->loaded) { const char* msg = msg_hash_to_str(MSG_CHEEVOS_HARDCORE_MODE_ENABLE); @@ -1500,6 +1506,140 @@ void rcheevos_hardcore_enabled_changed(void) } } +typedef struct rc_disallowed_setting_t +{ + const char* setting; + const char* value; +} rc_disallowed_setting_t; + +typedef struct rc_disallowed_core_settings_t +{ + const char* library_name; + const rc_disallowed_setting_t* disallowed_settings; +} rc_disallowed_core_settings_t; + +static const rc_disallowed_setting_t _rc_disallowed_dolphin_settings[] = { + { "dolphin_cheats_enabled", "enabled" }, + { NULL, NULL } +}; + +static const rc_disallowed_setting_t _rc_disallowed_ecwolf_settings[] = { + { "ecwolf-invulnerability", "enabled" }, + { NULL, NULL } +}; + +static const rc_disallowed_setting_t _rc_disallowed_fbneo_settings[] = { + { "fbneo-allow-patched-romsets", "enabled" }, + { "fbneo-cheat-*", "!Disabled" }, + { NULL, NULL } +}; + +static const rc_disallowed_setting_t _rc_disallowed_gpgx_settings[] = { + { "genesis_plus_gx_lock_on", "action replay (pro)" }, + { "genesis_plus_gx_lock_on", "game genie" }, + { NULL, NULL } +}; + +static const rc_disallowed_setting_t _rc_disallowed_ppsspp_settings[] = { + { "ppsspp_cheats", "enabled" }, + { NULL, NULL } +}; + +static const rc_disallowed_core_settings_t rc_disallowed_core_settings[] = { + { "dolphin-emu", _rc_disallowed_dolphin_settings }, + { "ecwolf", _rc_disallowed_ecwolf_settings }, + { "FinalBurn Neo", _rc_disallowed_fbneo_settings }, + { "Genesis Plus GX", _rc_disallowed_gpgx_settings }, + { "PPSSPP", _rc_disallowed_ppsspp_settings }, + { NULL, NULL } +}; + +static int rcheevos_match_value(const char* val, const char* match) +{ + if (*match == '!') + return !string_is_equal_case_insensitive(val, &match[1]); + + return string_is_equal_case_insensitive(val, match); +} + +void rcheevos_validate_config_settings(void) +{ + const rc_disallowed_core_settings_t* core_filter = rc_disallowed_core_settings; + struct retro_system_info* system = runloop_get_libretro_system_info(); + if (!system->library_name || !rcheevos_hardcore_active()) + return; + + while (core_filter->library_name) + { + if (string_is_equal(core_filter->library_name, system->library_name)) + { + core_option_manager_t* coreopts = NULL; + + if (rarch_ctl(RARCH_CTL_CORE_OPTIONS_LIST_GET, &coreopts)) + { + const rc_disallowed_setting_t* disallowed_setting = core_filter->disallowed_settings; + const char* key; + const char* val; + int i; + int allowed = 1; + size_t key_len; + + for (; disallowed_setting->setting; ++disallowed_setting) + { + key = disallowed_setting->setting; + key_len = strlen(key); + if (key[key_len - 1] == '*') + { + for (i = 0; i < coreopts->size; i++) + { + if (string_starts_with_size(coreopts->opts[i].key, key, key_len - 1)) + { + val = core_option_manager_get_val(coreopts, i); + if (rcheevos_match_value(val, disallowed_setting->value)) + { + key = coreopts->opts[i].key; + allowed = 0; + break; + } + } + } + } + else + { + for (i = 0; i < coreopts->size; i++) + { + if (string_is_equal(coreopts->opts[i].key, key)) + { + val = core_option_manager_get_val(coreopts, i); + if (rcheevos_match_value(val, disallowed_setting->value)) + { + allowed = 0; + break; + } + } + } + } + } + + if (!allowed) + { + char buffer[256]; + snprintf(buffer, sizeof(buffer), "Hardcore paused. Setting not allowed: %s=%s", key, val); + CHEEVOS_LOG(RCHEEVOS_TAG "%s\n", buffer); + rcheevos_pause_hardcore(); + + runloop_msg_queue_push(buffer, 0, 4 * 60, false, NULL, + MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_WARNING); + } + } + + break; + } + + ++core_filter; + } +} + static void rcheevos_runtime_event_handler(const rc_runtime_event_t* runtime_event) { switch (runtime_event->type) @@ -2417,6 +2557,7 @@ bool rcheevos_load(const void *data) /* reset hardcore mode and leaderboard settings based on configs */ rcheevos_hardcore_enabled_changed(); + rcheevos_validate_config_settings(); rcheevos_leaderboards_enabled_changed(); coro = (rcheevos_coro_t*)calloc(1, sizeof(*coro)); diff --git a/cheevos/cheevos.h b/cheevos/cheevos.h index 6496e4e8ee..3298dd892a 100644 --- a/cheevos/cheevos.h +++ b/cheevos/cheevos.h @@ -57,6 +57,8 @@ bool rcheevos_unload(void); void rcheevos_hardcore_enabled_changed(void); void rcheevos_toggle_hardcore_paused(void); +void rcheevos_validate_config_settings(void); + void rcheevos_leaderboards_enabled_changed(void); void rcheevos_test(void); diff --git a/retroarch.c b/retroarch.c index 95430401af..96c79bed76 100644 --- a/retroarch.c +++ b/retroarch.c @@ -18511,7 +18511,7 @@ bool core_option_manager_get_visible(core_option_manager_t *opt, void core_option_manager_set_val(core_option_manager_t *opt, size_t idx, size_t val_idx) { - struct core_option *option= NULL; + struct core_option *option = NULL; if (!opt) return; @@ -18522,6 +18522,24 @@ void core_option_manager_set_val(core_option_manager_t *opt, option->index = val_idx % option->vals->size; opt->updated = true; + rcheevos_validate_config_settings(); +} + +static void core_option_manager_adjust_val(core_option_manager_t* opt, + size_t idx, int adjustment) +{ + struct core_option* option = NULL; + + if (!opt) + return; + if (idx >= opt->size) + return; + + option = (struct core_option*)&opt->opts[idx]; + option->index = (option->index + option->vals->size + adjustment) % option->vals->size; + + opt->updated = true; + rcheevos_validate_config_settings(); } /** @@ -18540,6 +18558,8 @@ void core_option_manager_set_default(core_option_manager_t *opt, size_t idx) opt->opts[idx].index = opt->opts[idx].default_index; opt->updated = true; + + rcheevos_validate_config_settings(); } static struct retro_core_option_definition *core_option_manager_get_definitions( @@ -38099,20 +38119,10 @@ bool rarch_ctl(enum rarch_ctl_state state, void *data) * Options wrap around. */ { - struct core_option *option = NULL; - unsigned *idx = (unsigned*)data; + unsigned *idx = (unsigned*)data; if (!idx || !p_rarch->runloop_core_options) return false; - option = (struct core_option*) - &p_rarch->runloop_core_options->opts[*idx]; - - if (option) - { - option->index = - (option->index + option->vals->size - 1) % - option->vals->size; - p_rarch->runloop_core_options->updated = true; - } + core_option_manager_adjust_val(p_rarch->runloop_core_options, *idx, -1); } break; case RARCH_CTL_CORE_OPTION_NEXT: @@ -38121,21 +38131,10 @@ bool rarch_ctl(enum rarch_ctl_state state, void *data) * Options wrap around. */ { - struct core_option *option = NULL; - unsigned *idx = (unsigned*)data; - + unsigned* idx = (unsigned*)data; if (!idx || !p_rarch->runloop_core_options) return false; - - option = - (struct core_option*)&p_rarch->runloop_core_options->opts[*idx]; - - if (option) - { - option->index = - (option->index + 1) % option->vals->size; - p_rarch->runloop_core_options->updated = true; - } + core_option_manager_adjust_val(p_rarch->runloop_core_options, *idx, 1); } break;