From 919cac880fbd25c537a1cbca01112e4634dba88e Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Mon, 29 Jul 2019 21:00:29 +0800 Subject: [PATCH] Add enhanced core options --- Makefile | 1 + frontend/libretro.c | 65 +- frontend/libretro_core_options.h | 787 ++++++++++++++++++ .../include}/libretro.h | 202 ++++- libretro-common/include/retro_inline.h | 39 + 5 files changed, 1035 insertions(+), 59 deletions(-) create mode 100644 frontend/libretro_core_options.h rename {frontend => libretro-common/include}/libretro.h (90%) mode change 100755 => 100644 create mode 100644 libretro-common/include/retro_inline.h diff --git a/Makefile b/Makefile index a2785194..7f8356b1 100644 --- a/Makefile +++ b/Makefile @@ -274,6 +274,7 @@ LDFLAGS += `pkg-config --libs glib-2.0 libosso dbus-1 hildon-fm-2` endif ifeq "$(PLATFORM)" "libretro" OBJS += frontend/libretro.o +CFLAGS += -Ilibretro-common/include CFLAGS += -DFRONTEND_SUPPORTS_RGB565 CFLAGS += -DHAVE_LIBRETRO diff --git a/frontend/libretro.c b/frontend/libretro.c index 992da60f..f5522a3d 100644 --- a/frontend/libretro.c +++ b/frontend/libretro.c @@ -33,7 +33,9 @@ #include "plugin_lib.h" #include "arm_features.h" #include "revision.h" -#include "libretro.h" + +#include +#include "libretro_core_options.h" #ifdef _3DS #include "3ds/3ds_utils.h" @@ -485,65 +487,12 @@ void out_register_libretro(struct out_driver *drv) /* libretro */ void retro_set_environment(retro_environment_t cb) { - static const struct retro_variable vars[] = { - { "pcsx_rearmed_frameskip", "Frameskip; 0|1|2|3" }, - { "pcsx_rearmed_bios", "Use BIOS; auto|HLE" }, - { "pcsx_rearmed_region", "Region; auto|NTSC|PAL" }, - { "pcsx_rearmed_memcard2", "Enable second memory card; disabled|enabled" }, - { "pcsx_rearmed_pad1type", "Pad 1 Type; standard|analog|dualshock|negcon|none" }, - { "pcsx_rearmed_pad2type", "Pad 2 Type; standard|analog|dualshock|negcon|none" }, - { "pcsx_rearmed_pad3type", "Pad 3 Type; none|standard|analog|dualshock|negcon" }, - { "pcsx_rearmed_pad4type", "Pad 4 Type; none|standard|analog|dualshock|negcon" }, - { "pcsx_rearmed_pad5type", "Pad 5 Type; none|standard|analog|dualshock|negcon" }, - { "pcsx_rearmed_pad6type", "Pad 6 Type; none|standard|analog|dualshock|negcon" }, - { "pcsx_rearmed_pad7type", "Pad 7 Type; none|standard|analog|dualshock|negcon" }, - { "pcsx_rearmed_pad8type", "Pad 8 Type; none|standard|analog|dualshock|negcon" }, - { "pcsx_rearmed_multitap1", "Multitap 1; auto|disabled|enabled" }, - { "pcsx_rearmed_multitap2", "Multitap 2; auto|disabled|enabled" }, - { "pcsx_rearmed_negcon_deadzone", "NegCon Twist Deadzone (percent); 0|5|10|15|20|25|30" }, - { "pcsx_rearmed_negcon_response", "NegCon Twist Response; linear|quadratic|cubic" }, - { "pcsx_rearmed_vibration", "Enable Vibration; enabled|disabled" }, - { "pcsx_rearmed_dithering", "Enable Dithering; enabled|disabled" }, -#ifndef DRC_DISABLE - { "pcsx_rearmed_drc", "Dynamic recompiler; enabled|disabled" }, -#ifdef HAVE_PRE_ARMV7 - { "pcsx_rearmed_psxclock", "PSX cpu clock (default 50); 50|51|52|53|54|55|5657|58|59|60|61|62|63|64|65|66|67|68|69|70|71|72|73|74|75|76|77|78|79|80|81|82|83|84|85|86|87|88|89|90|91|92|93|94|95|96|97|98|99|100|30|31|32|33|34|35|36|37|38|39|40|41|42|43|44|45|46|47|48|49" }, -#else - { "pcsx_rearmed_psxclock", "PSX cpu clock (default 57); 57|58|59|60|61|62|63|64|65|66|67|68|69|70|71|72|73|74|75|76|77|78|79|80|81|82|83|84|85|86|87|88|89|90|91|92|93|94|95|96|97|98|99|100|30|31|32|33|34|35|36|37|38|39|40|41|42|43|44|45|46|47|48|49|50|51|52|53|54|55|56" }, -#endif -#endif -#ifdef __ARM_NEON__ - { "pcsx_rearmed_neon_interlace_enable", "Enable interlacing mode(s); disabled|enabled" }, - { "pcsx_rearmed_neon_enhancement_enable", "Enhanced resolution (slow); disabled|enabled" }, - { "pcsx_rearmed_neon_enhancement_no_main", "Enhanced resolution speed hack; disabled|enabled" }, -#endif - { "pcsx_rearmed_duping_enable", "Frame duping; enabled|disabled" }, - { "pcsx_rearmed_display_internal_fps", "Display Internal FPS; disabled|enabled" }, - { "pcsx_rearmed_show_bios_bootlogo", "Show Bios Bootlogo(Breaks some games); disabled|enabled" }, - { "pcsx_rearmed_spu_reverb", "Sound: Reverb; enabled|disabled" }, - { "pcsx_rearmed_spu_interpolation", "Sound: Interpolation; simple|gaussian|cubic|off" }, - { "pcsx_rearmed_idiablofix", "Diablo Music Fix; disabled|enabled" }, - { "pcsx_rearmed_pe2_fix", "Parasite Eve 2/Vandal Hearts 1/2 Fix; disabled|enabled" }, - { "pcsx_rearmed_inuyasha_fix", "InuYasha Sengoku Battle Fix; disabled|enabled" }, - - /* Advance options */ - { "pcsx_rearmed_noxadecoding", "XA Decoding; enabled|disabled" }, - { "pcsx_rearmed_nocdaudio", "CD Audio; enabled|disabled" }, -#ifndef DRC_DISABLE - { "pcsx_rearmed_nosmccheck", "(Speed Hack) Disable SMC Checks; disabled|enabled" }, - { "pcsx_rearmed_gteregsunneeded", "(Speed Hack) Assume GTE Regs Unneeded; disabled|enabled" }, - { "pcsx_rearmed_nogteflags", "(Speed Hack) Disable GTE Flags; disabled|enabled" }, -#endif - - { NULL, NULL } - }; - - if (cb(RETRO_ENVIRONMENT_GET_LOG_INTERFACE, &logging)) - log_cb = logging.log; - environ_cb = cb; - cb(RETRO_ENVIRONMENT_SET_VARIABLES, (void*)vars); + if (cb(RETRO_ENVIRONMENT_GET_LOG_INTERFACE, &logging)) + log_cb = logging.log; + + libretro_set_core_options(environ_cb); } void retro_set_video_refresh(retro_video_refresh_t cb) { video_cb = cb; } diff --git a/frontend/libretro_core_options.h b/frontend/libretro_core_options.h new file mode 100644 index 00000000..66f1b0cd --- /dev/null +++ b/frontend/libretro_core_options.h @@ -0,0 +1,787 @@ +#ifndef LIBRETRO_CORE_OPTIONS_H__ +#define LIBRETRO_CORE_OPTIONS_H__ + +#include +#include + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + ******************************** + * Core Option Definitions + ******************************** +*/ + +/* RETRO_LANGUAGE_ENGLISH */ + +/* Default language: + * - All other languages must include the same keys and values + * - Will be used as a fallback in the event that frontend language + * is not available + * - Will be used as a fallback for any missing entries in + * frontend language definition + */ + +#ifdef HAVE_PRE_ARMV7 +#define PSX_CLOCK_DEFAULT "50" +#define PSX_CLOCK_LABEL "Overclock or underclock the PSX clock. Default is 50" +#else +#define PSX_CLOCK_DEFAULT "57" +#define PSX_CLOCK_LABEL "Overclock or underclock the PSX clock. Default is 57" +#endif + +struct retro_core_option_definition option_defs_us[] = { + { + "pcsx_rearmed_frameskip", + "Frameskip", + "Choose how much frames should be skipped to improve performance at the expense of visual smoothness.", + { + { "0", NULL }, + { "1", NULL }, + { "2", NULL }, + { "3", NULL }, + { NULL, NULL}, + }, + "0", + }, + { + "pcsx_rearmed_bios", + "Use BIOS", + "Allows you to use real bios file (if available) or emulated bios (HLE). Its recommended to use official bios file for better compatibility.", + { + { "auto", "auto" }, + { "HLE", "hle" }, + { NULL, NULL}, + }, + "auto", + }, + { + "pcsx_rearmed_region", + "Region", + "Choose what region the system is from. 60 Hz for NTSC, 50 Hz for PAL.", + { + { "auto", "auto" }, + { "NTSC", "ntsc" }, + { "PAL", "pal" }, + { NULL, NULL}, + }, + "auto", + }, + { + "pcsx_rearmed_memcard2", + "Enable second memory card (shared)", + "Enabled the memory card slot 2. This is shared amongs all games.", + { + { "disable", NULL }, + { "enabled", NULL }, + { NULL, NULL}, + }, + "disable", + }, + { + "pcsx_rearmed_pad1type", + "Pad 1 Type", + "Pad type for player 1", + { + { "standard", NULL }, + { "analog", NULL }, + { "dualshock", NULL }, + { "negcon", NULL }, + { "none", NULL }, + { NULL, NULL}, + }, + "standard", + }, + { + "pcsx_rearmed_pad2type", + "Pad 2 Type", + "Pad type for player 2", + { + { "standard", NULL }, + { "analog", NULL }, + { "dualshock", NULL }, + { "negcon", NULL }, + { "none", NULL }, + { NULL, NULL}, + }, + "standard", + }, + { + "pcsx_rearmed_pad3type", + "Pad 3 Type", + "Pad type for player 3", + { + { "standard", NULL }, + { "analog", NULL }, + { "dualshock", NULL }, + { "negcon", NULL }, + { "none", NULL }, + { NULL, NULL}, + }, + "none", + }, + { + "pcsx_rearmed_pad4type", + "Pad 4 Type", + "Pad type for player 4", + { + { "standard", NULL }, + { "analog", NULL }, + { "dualshock", NULL }, + { "negcon", NULL }, + { "none", NULL }, + { NULL, NULL}, + }, + "none", + }, + { + "pcsx_rearmed_pad5type", + "Pad 5 Type", + "Pad type for player 5", + { + { "standard", NULL }, + { "analog", NULL }, + { "dualshock", NULL }, + { "negcon", NULL }, + { "none", NULL }, + { NULL, NULL}, + }, + "none", + },{ + "pcsx_rearmed_pad6type", + "Pad 6 Type", + "Pad type for player 6", + { + { "standard", NULL }, + { "analog", NULL }, + { "dualshock", NULL }, + { "negcon", NULL }, + { "none", NULL }, + { NULL, NULL}, + }, + "none", + },{ + "pcsx_rearmed_pad7type", + "Pad 7 Type", + "Pad type for player 7", + { + { "standard", NULL }, + { "analog", NULL }, + { "dualshock", NULL }, + { "negcon", NULL }, + { "none", NULL }, + { NULL, NULL}, + }, + "none", + },{ + "pcsx_rearmed_pad8type", + "Pad 8 Type", + "Pad type for player 8", + { + { "standard", NULL }, + { "analog", NULL }, + { "dualshock", NULL }, + { "negcon", NULL }, + { "none", NULL }, + { NULL, NULL}, + }, + "none", + }, + { + "pcsx_rearmed_multitap1", + "Multitap 1", + "Enables/Disables multitap on port 1, allowing upto 5 players in games that permit it.", + { + { "auto", NULL }, + { "disabled", NULL }, + { "enabled", NULL }, + { NULL, NULL}, + }, + "auto", + }, + { + "pcsx_rearmed_multitap2", + "Multitap 2", + "Enables/Disables multitap on port 2, allowing upto 8 players in games that permit it. Multitap 1 has to be enabled for this to work.", + { + { "auto", NULL }, + { "disabled", NULL }, + { "enabled", NULL }, + { NULL, NULL}, + }, + "auto", + }, + { + "pcsx_rearmed_negcon_deadzone", + "NegCon Twist Deadzone (percent)", + "Sets the deadzone of the RetroPad left analog stick when simulating the 'twist' action of emulated neGcon Controllers. Used to eliminate drift/unwanted input.", + { + { "0", NULL }, + { "5", NULL }, + { "10", NULL }, + { "15", NULL }, + { "20", NULL }, + { "25", NULL }, + { "30", NULL }, + { NULL, NULL}, + }, + "0", + }, + { + "pcsx_rearmed_negcon_response", + "NegCon Twist Response", + "Specifies the analog response when using a RetroPad left analog stick to simulate the 'twist' action of emulated neGcon Controllers.", + { + { "linear", NULL }, + { "quadratic", NULL }, + { "cubic", NULL }, + { NULL, NULL}, + }, + "linear", + }, + { + "pcsx_rearmed_vibration", + "Enable Vibration", + "Enables Vibration feedback for controllers that supports vibration features.", + { + { "disabled", NULL }, + { "enabled", NULL }, + { NULL, NULL}, + }, + "enabled", + }, + { + "pcsx_rearmed_dithering", + "Enable Dithering", + "If Off, disables the dithering pattern the PSX applies to combat color banding.", + { + { "disabled", NULL }, + { "enabled", NULL }, + { NULL, NULL}, + }, + "enabled", + }, + +#ifndef DRC_DISABLE + { + "pcsx_rearmed_drc", + "Dynamic recompiler", + "Enables core to use dynamic recompiler or interpreter (slower) cpu instructions.", + { + { "disabled", NULL }, + { "enabled", NULL }, + { NULL, NULL}, + }, + "enabled", + }, + { + "pcsx_rearmed_psxclock", + "PSX CPU clock", + PSX_CLOCK_LABEL, + { + { "30", NULL }, + { "31", NULL }, + { "32", NULL }, + { "33", NULL }, + { "34", NULL }, + { "35", NULL }, + { "36", NULL }, + { "37", NULL }, + { "38", NULL }, + { "39", NULL }, + { "40", NULL }, + { "41", NULL }, + { "42", NULL }, + { "43", NULL }, + { "44", NULL }, + { "45", NULL }, + { "46", NULL }, + { "47", NULL }, + { "48", NULL }, + { "49", NULL }, + { "50", NULL }, + { "51", NULL }, + { "52", NULL }, + { "53", NULL }, + { "54", NULL }, + { "55", NULL }, + { "56", NULL }, + { "57", NULL }, + { "58", NULL }, + { "59", NULL }, + { "60", NULL }, + { "61", NULL }, + { "62", NULL }, + { "63", NULL }, + { "64", NULL }, + { "65", NULL }, + { "66", NULL }, + { "67", NULL }, + { "68", NULL }, + { "69", NULL }, + { "70", NULL }, + { "71", NULL }, + { "72", NULL }, + { "73", NULL }, + { "74", NULL }, + { "75", NULL }, + { "76", NULL }, + { "77", NULL }, + { "78", NULL }, + { "79", NULL }, + { "80", NULL }, + { "81", NULL }, + { "82", NULL }, + { "83", NULL }, + { "84", NULL }, + { "85", NULL }, + { "86", NULL }, + { "87", NULL }, + { "88", NULL }, + { "89", NULL }, + { "90", NULL }, + { "91", NULL }, + { "92", NULL }, + { "93", NULL }, + { "94", NULL }, + { "95", NULL }, + { "96", NULL }, + { "97", NULL }, + { "98", NULL }, + { "99", NULL }, + { "100", NULL }, + { NULL, NULL}, + }, + PSX_CLOCK_DEFAULT, + }, +#endif /* DRC_DISABLE */ + +#ifdef __ARM_NEON__ + { + "pcsx_rearmed_neon_interlace_enable", + "Enable interlacing mode(s)", + "Enables fake scanlines effect.", + { + { "disabled", NULL }, + { "enabled", NULL }, + { NULL, NULL}, + }, + "disabled", + }, + { + "pcsx_rearmed_neon_enhancement_enable", + "Enhanced resolution (slow)", + "Renders in double resolution at the cost of lower performance", + { + { "disabled", NULL }, + { "enabled", NULL }, + { NULL, NULL}, + }, + "disabled", + }, + { + "pcsx_rearmed_neon_enhancement_no_main", + "Enhanced resolution speed hack", + "Speed hack for Enhanced resolution option (glitches some games).", + { + { "disabled", NULL }, + { "enabled", NULL }, + { NULL, NULL}, + }, + "disabled", + }, +#endif /* __ARM_NEON__ */ + + { + "pcsx_rearmed_duping_enable", + "Frame duping", + "A speedup, redraws/reuses the last frame if there was no new data.", + { + { "disabled", NULL }, + { "enabled", NULL }, + { NULL, NULL}, + }, + "enabled", + }, + { + "pcsx_rearmed_display_internal_fps", + "Display Internal FPS", + "Shows an on-screen frames per second counter when enabled.", + { + { "disabled", NULL }, + { "enabled", NULL }, + { NULL, NULL}, + }, + "disabled", + }, + { + "pcsx_rearmed_show_bios_bootlogo", + "Show Bios Bootlogo", + "When enabled, shows the playstation logo when starting or resetting. (Breaks some games).", + { + { "disabled", NULL }, + { "enabled", NULL }, + { NULL, NULL}, + }, + "disabled", + }, + { + "pcsx_rearmed_spu_reverb", + "Sound Reverb", + "Enables or disables audio reverb effect.", + { + { "disabled", NULL }, + { "enabled", NULL }, + { NULL, NULL}, + }, + "enabled", + }, + { + "pcsx_rearmed_spu_interpolation", + "Sound: Interpolation", + NULL, + { + { "simple", NULL }, + { "gaussian", NULL }, + { "cubic", NULL }, + { "off", NULL }, + { NULL, NULL}, + }, + "simple", + }, + { + "pcsx_rearmed_idiablofix", + "Diablo Music Fix", + NULL, + { + { "disabled", NULL }, + { "enabled", NULL }, + { NULL, NULL}, + }, + "disabled", + }, + { + "pcsx_rearmed_pe2_fix", + "Parasite Eve 2/Vandal Hearts 1/2 Fix", + NULL, + { + { "disabled", NULL }, + { "enabled", NULL }, + { NULL, NULL}, + }, + "disabled", + }, + { + "pcsx_rearmed_inuyasha_fix", + "InuYasha Sengoku Battle Fix", + NULL, + { + { "disabled", NULL }, + { "enabled", NULL }, + { NULL, NULL}, + }, + "disabled", + }, + + /* ADVANCED OPTIONS */ + { + "pcsx_rearmed_noxadecoding", + "XA Decoding", + NULL, + { + { "disabled", NULL }, + { "enabled", NULL }, + { NULL, NULL}, + }, + "enabled", + }, + { + "pcsx_rearmed_nocdaudio", + "CD Audio", + NULL, + { + { "disabled", NULL }, + { "enabled", NULL }, + { NULL, NULL}, + }, + "enabled", + }, + +#ifndef DRC_DISABLE + { + "pcsx_rearmed_nosmccheck", + "(Speed Hack) Disable SMC Checks", + "Will cause crashes when loading, break memcards.", + { + { "disabled", NULL }, + { "enabled", NULL }, + { NULL, NULL}, + }, + "disabled", + }, + { + "pcsx_rearmed_gteregsunneeded", + "(Speed Hack) Assume GTE Regs Unneeded", + "May cause graphical glitches.", + { + { "disabled", NULL }, + { "enabled", NULL }, + { NULL, NULL}, + }, + "disabled", + }, + { + "pcsx_rearmed_nogteflags", + "(Speed Hack) Disable GTE Flags", + "Will cause graphical glitches.", + { + { "disabled", NULL }, + { "enabled", NULL }, + { NULL, NULL}, + }, + "disabled", + }, +#endif /* DRC_DISABLE */ + + { NULL, NULL, NULL, { NULL, NULL }, NULL }, +}; + +/* RETRO_LANGUAGE_JAPANESE */ + +/* RETRO_LANGUAGE_FRENCH */ + +/* RETRO_LANGUAGE_SPANISH */ + +/* RETRO_LANGUAGE_GERMAN */ + +/* RETRO_LANGUAGE_ITALIAN */ + +/* RETRO_LANGUAGE_DUTCH */ + +/* RETRO_LANGUAGE_PORTUGUESE_BRAZIL */ + +/* RETRO_LANGUAGE_PORTUGUESE_PORTUGAL */ + +/* RETRO_LANGUAGE_RUSSIAN */ + +/* RETRO_LANGUAGE_KOREAN */ + +/* RETRO_LANGUAGE_CHINESE_TRADITIONAL */ + +/* RETRO_LANGUAGE_CHINESE_SIMPLIFIED */ + +/* RETRO_LANGUAGE_ESPERANTO */ + +/* RETRO_LANGUAGE_POLISH */ + +/* RETRO_LANGUAGE_VIETNAMESE */ + +/* RETRO_LANGUAGE_ARABIC */ + +/* RETRO_LANGUAGE_GREEK */ + +/* RETRO_LANGUAGE_TURKISH */ + +/* + ******************************** + * Language Mapping + ******************************** +*/ + +struct retro_core_option_definition *option_defs_intl[RETRO_LANGUAGE_LAST] = { + option_defs_us, /* RETRO_LANGUAGE_ENGLISH */ + NULL, /* RETRO_LANGUAGE_JAPANESE */ + NULL, /* RETRO_LANGUAGE_FRENCH */ + NULL, /* RETRO_LANGUAGE_SPANISH */ + NULL, /* RETRO_LANGUAGE_GERMAN */ + NULL, /* RETRO_LANGUAGE_ITALIAN */ + NULL, /* RETRO_LANGUAGE_DUTCH */ + NULL, /* RETRO_LANGUAGE_PORTUGUESE_BRAZIL */ + NULL, /* RETRO_LANGUAGE_PORTUGUESE_PORTUGAL */ + NULL, /* RETRO_LANGUAGE_RUSSIAN */ + NULL, /* RETRO_LANGUAGE_KOREAN */ + NULL, /* RETRO_LANGUAGE_CHINESE_TRADITIONAL */ + NULL, /* RETRO_LANGUAGE_CHINESE_SIMPLIFIED */ + NULL, /* RETRO_LANGUAGE_ESPERANTO */ + NULL, /* RETRO_LANGUAGE_POLISH */ + NULL, /* RETRO_LANGUAGE_VIETNAMESE */ + NULL, /* RETRO_LANGUAGE_ARABIC */ + NULL, /* RETRO_LANGUAGE_GREEK */ + NULL, /* RETRO_LANGUAGE_TURKISH */ +}; + +/* + ******************************** + * Functions + ******************************** +*/ + +/* Handles configuration/setting of core options. + * Should only be called inside retro_set_environment(). + * > We place the function body in the header to avoid the + * necessity of adding more .c files (i.e. want this to + * be as painless as possible for core devs) + */ + +static INLINE void libretro_set_core_options(retro_environment_t environ_cb) +{ + unsigned version = 0; + + if (!environ_cb) + return; + + if (environ_cb(RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION, &version) && (version == 1)) + { + struct retro_core_options_intl core_options_intl; + unsigned language = 0; + + core_options_intl.us = option_defs_us; + core_options_intl.local = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_LANGUAGE, &language) && + (language < RETRO_LANGUAGE_LAST) && (language != RETRO_LANGUAGE_ENGLISH)) + core_options_intl.local = option_defs_intl[language]; + + environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL, &core_options_intl); + } + else + { + size_t i; + size_t option_index = 0; + size_t num_options = 0; + struct retro_variable *variables = NULL; + char **values_buf = NULL; + + /* Determine number of options + * > Note: We are going to skip a number of irrelevant + * core options when building the retro_variable array, + * but we'll allocate space for all of them. The difference + * in resource usage is negligible, and this allows us to + * keep the code 'cleaner' */ + while (true) + { + if (option_defs_us[num_options].key) + num_options++; + else + break; + } + + /* Allocate arrays */ + variables = (struct retro_variable *)calloc(num_options + 1, sizeof(struct retro_variable)); + values_buf = (char **)calloc(num_options, sizeof(char *)); + + if (!variables || !values_buf) + goto error; + + /* Copy parameters from option_defs_us array */ + for (i = 0; i < num_options; i++) + { + const char *key = option_defs_us[i].key; + const char *desc = option_defs_us[i].desc; + const char *default_value = option_defs_us[i].default_value; + struct retro_core_option_value *values = option_defs_us[i].values; + size_t buf_len = 3; + size_t default_index = 0; + + values_buf[i] = NULL; + + /* Skip options that are irrelevant when using the + * old style core options interface */ + if ((strcmp(key, "fceumm_advance_sound_options") == 0)) + continue; + + if (desc) + { + size_t num_values = 0; + + /* Determine number of values */ + while (true) + { + if (values[num_values].value) + { + /* Check if this is the default value */ + if (default_value) + if (strcmp(values[num_values].value, default_value) == 0) + default_index = num_values; + + buf_len += strlen(values[num_values].value); + num_values++; + } + else + break; + } + + /* Build values string */ + if (num_values > 1) + { + size_t j; + + buf_len += num_values - 1; + buf_len += strlen(desc); + + values_buf[i] = (char *)calloc(buf_len, sizeof(char)); + if (!values_buf[i]) + goto error; + + strcpy(values_buf[i], desc); + strcat(values_buf[i], "; "); + + /* Default value goes first */ + strcat(values_buf[i], values[default_index].value); + + /* Add remaining values */ + for (j = 0; j < num_values; j++) + { + if (j != default_index) + { + strcat(values_buf[i], "|"); + strcat(values_buf[i], values[j].value); + } + } + } + } + + variables[option_index].key = key; + variables[option_index].value = values_buf[i]; + option_index++; + } + + /* Set variables */ + environ_cb(RETRO_ENVIRONMENT_SET_VARIABLES, variables); + +error: + + /* Clean up */ + if (values_buf) + { + for (i = 0; i < num_options; i++) + { + if (values_buf[i]) + { + free(values_buf[i]); + values_buf[i] = NULL; + } + } + + free(values_buf); + values_buf = NULL; + } + + if (variables) + { + free(variables); + variables = NULL; + } + } +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/frontend/libretro.h b/libretro-common/include/libretro.h old mode 100755 new mode 100644 similarity index 90% rename from frontend/libretro.h rename to libretro-common/include/libretro.h index 8daec836..1fd2f5b7 --- a/frontend/libretro.h +++ b/libretro-common/include/libretro.h @@ -614,7 +614,7 @@ enum retro_mod * Afterward it may be called again for the core to communicate * updated options to the frontend, but the number of core * options must not change from the number in the initial call. - * + * * 'data' points to an array of retro_variable structs * terminated by a { NULL, NULL } element. * retro_variable::key should be namespaced to not collide @@ -1106,6 +1106,148 @@ enum retro_mod * It will return a bitmask of all the digital buttons. */ +#define RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION 52 + /* unsigned * -- + * Unsigned value is the API version number of the core options + * interface supported by the frontend. If callback return false, + * API version is assumed to be 0. + * + * In legacy code, core options are set by passing an array of + * retro_variable structs to RETRO_ENVIRONMENT_SET_VARIABLES. + * This may be still be done regardless of the core options + * interface version. + * + * If version is 1 however, core options may instead be set by + * passing an array of retro_core_option_definition structs to + * RETRO_ENVIRONMENT_SET_CORE_OPTIONS, or a 2D array of + * retro_core_option_definition structs to RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL. + * This allows the core to additionally set option sublabel information + * and/or provide localisation support. + */ + +#define RETRO_ENVIRONMENT_SET_CORE_OPTIONS 53 + /* const struct retro_core_option_definition ** -- + * Allows an implementation to signal the environment + * which variables it might want to check for later using + * GET_VARIABLE. + * This allows the frontend to present these variables to + * a user dynamically. + * This should only be called if RETRO_ENVIRONMENT_GET_ENHANCED_CORE_OPTIONS + * returns an API version of 1. + * This should be called instead of RETRO_ENVIRONMENT_SET_VARIABLES. + * This should be called the first time as early as + * possible (ideally in retro_set_environment). + * Afterwards it may be called again for the core to communicate + * updated options to the frontend, but the number of core + * options must not change from the number in the initial call. + * + * 'data' points to an array of retro_core_option_definition structs + * terminated by a { NULL, NULL, NULL, {{0}}, NULL } element. + * retro_core_option_definition::key should be namespaced to not collide + * with other implementations' keys. e.g. A core called + * 'foo' should use keys named as 'foo_option'. + * retro_core_option_definition::desc should contain a human readable + * description of the key. + * retro_core_option_definition::info should contain any additional human + * readable information text that a typical user may need to + * understand the functionality of the option. + * retro_core_option_definition::values is an array of retro_core_option_value + * structs terminated by a { NULL, NULL } element. + * > retro_core_option_definition::values[index].value is an expected option + * value. + * > retro_core_option_definition::values[index].label is a human readable + * label used when displaying the value on screen. If NULL, + * the value itself is used. + * retro_core_option_definition::default_value is the default core option + * setting. It must match one of the expected option values in the + * retro_core_option_definition::values array. If it does not, or the + * default value is NULL, the first entry in the + * retro_core_option_definition::values array is treated as the default. + * + * The number of possible options should be very limited, + * and must be less than RETRO_NUM_CORE_OPTION_VALUES_MAX. + * i.e. it should be feasible to cycle through options + * without a keyboard. + * + * First entry should be treated as a default. + * + * Example entry: + * { + * "foo_option", + * "Speed hack coprocessor X", + * "Provides increased performance at the expense of reduced accuracy", + * { + * { "false", NULL }, + * { "true", NULL }, + * { "unstable", "Turbo (Unstable)" }, + * { NULL, NULL }, + * }, + * "false" + * } + * + * Only strings are operated on. The possible values will + * generally be displayed and stored as-is by the frontend. + */ + +#define RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL 54 + /* const struct retro_core_options_intl * -- + * Allows an implementation to signal the environment + * which variables it might want to check for later using + * GET_VARIABLE. + * This allows the frontend to present these variables to + * a user dynamically. + * This should only be called if RETRO_ENVIRONMENT_GET_ENHANCED_CORE_OPTIONS + * returns an API version of 1. + * This should be called instead of RETRO_ENVIRONMENT_SET_VARIABLES. + * This should be called the first time as early as + * possible (ideally in retro_set_environment). + * Afterwards it may be called again for the core to communicate + * updated options to the frontend, but the number of core + * options must not change from the number in the initial call. + * + * This is fundamentally the same as RETRO_ENVIRONMENT_SET_CORE_OPTIONS, + * with the addition of localisation support. The description of the + * RETRO_ENVIRONMENT_SET_CORE_OPTIONS callback should be consulted + * for further details. + * + * 'data' points to a retro_core_options_intl struct. + * + * retro_core_options_intl::us is a pointer to an array of + * retro_core_option_definition structs defining the US English + * core options implementation. It must point to a valid array. + * + * retro_core_options_intl::local is a pointer to an array of + * retro_core_option_definition structs defining core options for + * the current frontend language. It may be NULL (in which case + * retro_core_options_intl::us is used by the frontend). Any items + * missing from this array will be read from retro_core_options_intl::us + * instead. + * + * NOTE: Default core option values are always taken from the + * retro_core_options_intl::us array. Any default values in + * retro_core_options_intl::local array will be ignored. + */ + +#define RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY 55 + /* struct retro_core_option_display * -- + * + * Allows an implementation to signal the environment to show + * or hide a variable when displaying core options. This is + * considered a *suggestion*. The frontend is free to ignore + * this callback, and its implementation not considered mandatory. + * + * 'data' points to a retro_core_option_display struct + * + * retro_core_option_display::key is a variable identifier + * which has already been set by SET_VARIABLES/SET_CORE_OPTIONS. + * + * retro_core_option_display::visible is a boolean, specifying + * whether variable should be displayed + * + * Note that all core option variables will be set visible by + * default when calling SET_VARIABLES/SET_CORE_OPTIONS. + */ + /* VFS functionality */ /* File paths: @@ -2351,6 +2493,64 @@ struct retro_variable const char *value; }; +struct retro_core_option_display +{ + /* Variable to configure in RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY */ + const char *key; + + /* Specifies whether variable should be displayed + * when presenting core options to the user */ + bool visible; +}; + +/* Maximum number of values permitted for a core option + * NOTE: This may be increased on a core-by-core basis + * if required (doing so has no effect on the frontend) */ +#define RETRO_NUM_CORE_OPTION_VALUES_MAX 128 + +struct retro_core_option_value +{ + /* Expected option value */ + const char *value; + + /* Human-readable value label. If NULL, value itself + * will be displayed by the frontend */ + const char *label; +}; + +struct retro_core_option_definition +{ + /* Variable to query in RETRO_ENVIRONMENT_GET_VARIABLE. */ + const char *key; + + /* Human-readable core option description (used as menu label) */ + const char *desc; + + /* Human-readable core option information (used as menu sublabel) */ + const char *info; + + /* Array of retro_core_option_value structs, terminated by NULL */ + struct retro_core_option_value values[RETRO_NUM_CORE_OPTION_VALUES_MAX]; + + /* Default core option value. Must match one of the values + * in the retro_core_option_value array, otherwise will be + * ignored */ + const char *default_value; +}; + +struct retro_core_options_intl +{ + /* Pointer to an array of retro_core_option_definition structs + * - US English implementation + * - Must point to a valid array */ + struct retro_core_option_definition *us; + + /* Pointer to an array of retro_core_option_definition structs + * - Implementation for current frontend language + * - May be NULL */ + struct retro_core_option_definition *local; +}; + struct retro_game_info { const char *path; /* Path to game, UTF-8 encoded. diff --git a/libretro-common/include/retro_inline.h b/libretro-common/include/retro_inline.h new file mode 100644 index 00000000..e4a21f6c --- /dev/null +++ b/libretro-common/include/retro_inline.h @@ -0,0 +1,39 @@ +/* Copyright (C) 2010-2018 The RetroArch team + * + * --------------------------------------------------------------------------------------- + * The following license statement only applies to this file (retro_inline.h). + * --------------------------------------------------------------------------------------- + * + * Permission is hereby granted, free of charge, + * to any person obtaining a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __LIBRETRO_SDK_INLINE_H +#define __LIBRETRO_SDK_INLINE_H + +#ifndef INLINE + +#if defined(_WIN32) || defined(__INTEL_COMPILER) +#define INLINE __inline +#elif defined(__STDC_VERSION__) && __STDC_VERSION__>=199901L +#define INLINE inline +#elif defined(__GNUC__) +#define INLINE __inline__ +#else +#define INLINE +#endif + +#endif +#endif -- 2.39.2