endif
ifeq "$(PLATFORM)" "libretro"
OBJS += frontend/libretro.o
+CFLAGS += -Ilibretro-common/include
CFLAGS += -DFRONTEND_SUPPORTS_RGB565
CFLAGS += -DHAVE_LIBRETRO
#include "plugin_lib.h"
#include "arm_features.h"
#include "revision.h"
-#include "libretro.h"
+
+#include <libretro.h>
+#include "libretro_core_options.h"
#ifdef _3DS
#include "3ds/3ds_utils.h"
/* 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; }
--- /dev/null
+#ifndef LIBRETRO_CORE_OPTIONS_H__
+#define LIBRETRO_CORE_OPTIONS_H__
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <libretro.h>
+#include <retro_inline.h>
+
+#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
* 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
* 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:
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.
--- /dev/null
+/* 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