diff --git a/src/drivers/libretro/dipswitch.c b/src/drivers/libretro/dipswitch.c index 610dde2..b30b318 100644 --- a/src/drivers/libretro/dipswitch.c +++ b/src/drivers/libretro/dipswitch.c @@ -944,9 +944,14 @@ static VSUNIGAME dipswitch_topgun = { } }; +typedef struct { + char value[100]; + char label[100]; +} VSUNIGAMEOPT_VALUE; + typedef struct { char key[64]; - char val[150]; + VSUNIGAMEOPT_VALUE val[10]; } VSUNIGAMEOPT; static VSUNIGAME *vsgame = NULL; @@ -967,34 +972,32 @@ static void str_to_corekey_label(char *str) static void make_core_options(void) { - unsigned i, dipswitch_size; - char core_prefix[32]; + unsigned i, j, num_dipswitch; + char *romname_short = NULL; - dipswitch_size = vsgame->dipswitch_size; - sprintf(core_prefix, "fceumm_dipswitch_%s", vsgame->romname_short); - for (i = 0; i < dipswitch_size; i++) + num_dipswitch = vsgame->dipswitch_size; + romname_short = vsgame->romname_short; + for (i = 0; i < num_dipswitch; i++) { - unsigned x; char core_key[64], core_values[150]; - DIPSWITCH *coreoptions = &vsgame->dipswitch_core_options[i]; + unsigned num_values = vsgame->dipswitch_core_options[i].settings_size; + const char *option_name = vsgame->dipswitch_core_options[i].option_name; - /* make var key string from list */ - sprintf(core_key, "%s%c%s", core_prefix, '-', coreoptions->option_name); + memset(core_key, 0 , sizeof(core_key)); + memset(core_values, 0 , sizeof(core_values)); + + /* Create core key string */ + sprintf(core_key, "fceumm_dipswitch_%s-%s", romname_short, option_name); + /* sanitize core key string */ str_to_corekey_label(core_key); - - /* make var values string from lists of values */ - sprintf(core_values, "%s; ", coreoptions->option_name); - for (x = 0; x < coreoptions->settings_size; x++) - { - SETTING *corevalues = &coreoptions->settings[x]; - - strcat(core_values, corevalues->name); - if ((coreoptions->settings_size - 1) > x) - strcat(core_values, "|"); - } - sprintf(vscoreopt[i].key, "%s", core_key); - sprintf(vscoreopt[i].val, "%s", core_values); + + /* Create core values */ + for (j = 0; j < num_values; j++) + { + const char *var_value = vsgame->dipswitch_core_options[i].settings[j].name; + sprintf(vscoreopt[i].val[j].value, "%s", var_value); + } } } @@ -1067,25 +1070,25 @@ static void update_dipswitch_vsuni(void) { struct retro_variable var = {0}; unsigned idx_dips, idx_var; - uint8 vsdip_new = 0x00; + uint8 vsdip_new = FCEUI_VSUniGetDIPs(); - if (vsgame == NULL) - return; - - vsdip_new = FCEUI_VSUniGetDIPs(); for (idx_dips = 0; idx_dips < vsgame->dipswitch_size; idx_dips++) { - DIPSWITCH *core_option = &vsgame->dipswitch_core_options[idx_dips]; - var.key = vscoreopt[idx_dips].key; + const char *key = vscoreopt[idx_dips].key; + unsigned num_options = vsgame->dipswitch_core_options[idx_dips].settings_size; + + var.key = key; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) == 0) continue; - for (idx_var = 0; idx_var < core_option->settings_size; idx_var++) + for (idx_var = 0; idx_var < num_options; idx_var++) { - SETTING *vs_settings = &core_option->settings[idx_var]; - if (strcmp(var.value, vs_settings->name) != 0) + const char *var_value = vsgame->dipswitch_core_options[idx_dips].settings[idx_var].name; + uint8 value = vsgame->dipswitch_core_options[idx_dips].settings[idx_var].value; + uint8 mask = vsgame->dipswitch_core_options[idx_dips].mask; + if (strcmp(var.value, var_value) != 0) continue; - vsdip_new &= ~core_option->mask; - vsdip_new |= vs_settings->value; + vsdip_new &= ~mask; + vsdip_new |= value; } } @@ -1101,28 +1104,67 @@ static void update_dipswitch_vsuni(void) } /* Nintendo World Championship */ -static struct retro_variable dipswitch_nwc[] = { - { "fceumm_dipswitch_nwc_swa", "Dipswitch SW1 (18.7s); disabled|enabled" }, - { "fceumm_dipswitch_nwc_swb", "Dipswitch SW2 (37.5s); disabled|enabled" }, - { "fceumm_dipswitch_nwc_swc", "Dipswitch SW3 (1m 15s); enabled|disabled" }, - { "fceumm_dipswitch_nwc_swd", "Dipswitch SW4 (2m 30s); disabled|enabled" }, - { NULL, NULL } +static struct retro_core_option_definition dipswitch_nwc[] = { + { + "fceumm_dipswitch_nwc_swa", + "Dipswitch SW1 (+18.7secs)", + "Adds 18.7 seconds to total time. Total time = 5 mins + enabled dipswitches.", + { + { "disabled", NULL }, + { "enabled", NULL }, + { NULL, NULL}, + }, + "disabled", + }, + { + "fceumm_dipswitch_nwc_swb", + "Dipswitch SW1 (+37.5s)", + "Adds 37.5 seconds to total time. Total time = 5 mins + enabled dipswitches.", + { + { "disabled", NULL }, + { "enabled", NULL }, + { NULL, NULL}, + }, + "disabled", + }, + { + "fceumm_dipswitch_nwc_swc", + "Dipswitch SW1 (+1m 15s)", + "Adds 1 minute and 15 seconds to total time. Total time = 5 mins + enabled dipswitches.", + { + { "disabled", NULL }, + { "enabled", NULL }, + { NULL, NULL}, + }, + "enabled", + }, + { + "fceumm_dipswitch_nwc_swd", + "Dipswitch SW1 (+2m 30s)", + "Adds 2 minutes and 30 seconds to total time. Total time = 5 mins + time of enabled dipswitches.", + { + { "disabled", NULL }, + { "enabled", NULL }, + { NULL, NULL}, + }, + "disabled", + }, }; static void update_dipswitch_nwc(void) { struct retro_variable var = {0}; unsigned dips = 0x00; - unsigned index; + unsigned i; - for (index = 0; index < 4; index++) + for (i = 0; i < 4; i++) { - struct retro_variable *nwc = &dipswitch_nwc[index]; - var.key = nwc->key; + const char *key = dipswitch_nwc[i].key; + var.key = key; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { if (strcmp(var.value, "enabled") == 0) - dips |= (1 << index); + dips |= (1 << i); } } @@ -1136,9 +1178,9 @@ static void update_dipswitch_nwc(void) } } -void set_dipswitch_variables(unsigned *index, struct retro_variable *vars) +void set_dipswitch_variables(unsigned *index, struct retro_core_option_definition *vars) { - unsigned i, idx = *index; + unsigned idx = *index; /* VSUNI Dipswitch */ if (GameInfo->type == GIT_VSUNI) @@ -1146,10 +1188,25 @@ void set_dipswitch_variables(unsigned *index, struct retro_variable *vars) vsgame = get_vsuni_dipswitch(GameInfo->gameid); if (vsgame) { + unsigned i, j; + unsigned num_options = vsgame->dipswitch_size; + make_core_options(); - for (i = 0; i < vsgame->dipswitch_size; i++, idx++) { - vars[idx].key = vscoreopt[i].key; - vars[idx].value = vscoreopt[i].val; + + for (i = 0; i < num_options; i++) { + const char *key = vscoreopt[i].key; + const char *desc = vsgame->dipswitch_core_options[i].option_name; + unsigned num_values = vsgame->dipswitch_core_options[i].settings_size; + + vars[idx].key = key; + vars[idx].desc = desc; + + for (j = 0; j < num_values; j++) { + char *value = vscoreopt[i].val[j].value; + vars[idx].values[j].value = value; + } + + idx++; } } } @@ -1157,7 +1214,8 @@ void set_dipswitch_variables(unsigned *index, struct retro_variable *vars) /* Nintendo World Championship cart (Mapper 105)*/ if (iNESCart.mapper == 105) { - i = 0; + unsigned i = 0; + while (dipswitch_nwc[i].key) { vars[idx] = dipswitch_nwc[i]; idx++; @@ -1165,7 +1223,7 @@ void set_dipswitch_variables(unsigned *index, struct retro_variable *vars) } } - *index = idx; + *index = idx; } void update_dipswitch(void) diff --git a/src/drivers/libretro/dipswitch.h b/src/drivers/libretro/dipswitch.h index 8b03006..d5a1d8a 100644 --- a/src/drivers/libretro/dipswitch.h +++ b/src/drivers/libretro/dipswitch.h @@ -3,7 +3,7 @@ #include -void set_dipswitch_variables(unsigned *index, struct retro_variable *vars); +void set_dipswitch_variables(unsigned *index, struct retro_core_option_definition *vars); void update_dipswitch(void); extern retro_environment_t environ_cb; diff --git a/src/drivers/libretro/libretro-common/compat/compat_snprintf.c b/src/drivers/libretro/libretro-common/compat/compat_snprintf.c index 40734a6..b69ad04 100644 --- a/src/drivers/libretro/libretro-common/compat/compat_snprintf.c +++ b/src/drivers/libretro/libretro-common/compat/compat_snprintf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (compat_snprintf.c). @@ -23,9 +23,7 @@ /* THIS FILE HAS NOT BEEN VALIDATED ON PLATFORMS BESIDES MSVC */ #ifdef _MSC_VER -#include - -#include /* added for _vsnprintf_s and _vscprintf on VS2015 and VS2017 */ +#include #include #if _MSC_VER < 1800 @@ -53,14 +51,23 @@ int c99_vsnprintf_retro__(char *outBuf, size_t size, const char *format, va_list int count = -1; if (size != 0) + { #if (_MSC_VER <= 1310) - count = _vsnprintf(outBuf, size, format, ap); + count = _vsnprintf(outBuf, size - 1, format, ap); #else - count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap); + count = _vsnprintf_s(outBuf, size, size - 1, format, ap); #endif + } + if (count == -1) count = _vscprintf(format, ap); + if (count == size) + { + /* there was no room for a NULL, so truncate the last character */ + outBuf[size - 1] = '\0'; + } + return count; } diff --git a/src/drivers/libretro/libretro-common/include/compat/msvc.h b/src/drivers/libretro/libretro-common/include/compat/msvc.h index fea4b53..4681b12 100644 --- a/src/drivers/libretro/libretro-common/include/compat/msvc.h +++ b/src/drivers/libretro/libretro-common/include/compat/msvc.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (msvc.h). @@ -39,8 +39,8 @@ extern "C" { int c99_snprintf_retro__(char *outBuf, size_t size, const char *format, ...); #endif -/* Pre-MSVC 2010 compilers don't implement vsnprintf in a cross-platform manner? Not sure about this one. */ -#if _MSC_VER < 1600 +/* Pre-MSVC 2008 compilers don't implement vsnprintf in a cross-platform manner? Not sure about this one. */ +#if _MSC_VER < 1500 #include #include #ifndef vsnprintf @@ -56,6 +56,8 @@ extern "C" { #undef UNICODE /* Do not bother with UNICODE at this time. */ #include #include + +#define _USE_MATH_DEFINES #include /* Python headers defines ssize_t and sets HAVE_SSIZE_T. @@ -125,4 +127,3 @@ typedef int ssize_t; #endif #endif - diff --git a/src/drivers/libretro/libretro-common/include/compat/msvc/stdint.h b/src/drivers/libretro/libretro-common/include/compat/msvc/stdint.h index c791176..7c91a68 100644 --- a/src/drivers/libretro/libretro-common/include/compat/msvc/stdint.h +++ b/src/drivers/libretro/libretro-common/include/compat/msvc/stdint.h @@ -67,7 +67,6 @@ extern "C" { # endif #endif - /* 7.18.1 Integer types. */ /* 7.18.1.1 Exact-width integer types. */ @@ -94,7 +93,6 @@ extern "C" { typedef signed __int64 int64_t; typedef unsigned __int64 uint64_t; - /* 7.18.1.2 Minimum-width integer types. */ typedef int8_t int_least8_t; typedef int16_t int_least16_t; @@ -255,4 +253,3 @@ typedef uint64_t uintmax_t; #endif #endif - diff --git a/src/drivers/libretro/libretro-common/include/libretro.h b/src/drivers/libretro/libretro-common/include/libretro.h index 8daec83..1fd2f5b 100644 --- a/src/drivers/libretro/libretro-common/include/libretro.h +++ b/src/drivers/libretro/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/src/drivers/libretro/libretro-common/include/retro_common.h b/src/drivers/libretro/libretro-common/include/retro_common.h index 5938bea..9a1fd5f 100644 --- a/src/drivers/libretro/libretro-common/include/retro_common.h +++ b/src/drivers/libretro/libretro-common/include/retro_common.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (retro_common.h). @@ -34,4 +34,3 @@ in a public API, you may need this. #include #endif - diff --git a/src/drivers/libretro/libretro-common/include/retro_common_api.h b/src/drivers/libretro/libretro-common/include/retro_common_api.h index ff38f98..fc4f745 100644 --- a/src/drivers/libretro/libretro-common/include/retro_common_api.h +++ b/src/drivers/libretro/libretro-common/include/retro_common_api.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (retro_common_api.h). @@ -113,6 +113,5 @@ Of course, another school of thought is that you should do as little damage as p in as few places as possible... */ - /* _LIBRETRO_COMMON_RETRO_COMMON_API_H */ #endif diff --git a/src/drivers/libretro/libretro-common/include/retro_inline.h b/src/drivers/libretro/libretro-common/include/retro_inline.h new file mode 100644 index 0000000..e4a21f6 --- /dev/null +++ b/src/drivers/libretro/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 diff --git a/src/drivers/libretro/libretro-common/include/streams/memory_stream.h b/src/drivers/libretro/libretro-common/include/streams/memory_stream.h index fba8783..c594808 100644 --- a/src/drivers/libretro/libretro-common/include/streams/memory_stream.h +++ b/src/drivers/libretro/libretro-common/include/streams/memory_stream.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (memory_stream.h). diff --git a/src/drivers/libretro/libretro-common/streams/memory_stream.c b/src/drivers/libretro/libretro-common/streams/memory_stream.c index 784d0fe..77a2c00 100644 --- a/src/drivers/libretro/libretro-common/streams/memory_stream.c +++ b/src/drivers/libretro/libretro-common/streams/memory_stream.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2017 The RetroArch team +/* Copyright (C) 2010-2018 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (memory_stream.c). diff --git a/src/drivers/libretro/libretro.c b/src/drivers/libretro/libretro.c index 077790d..7c40219 100644 --- a/src/drivers/libretro/libretro.c +++ b/src/drivers/libretro/libretro.c @@ -30,6 +30,7 @@ #include "libretro-common/include/streams/memory_stream.h" #include "dipswitch.h" +#include "libretro_core_options.h" #define MAX_PLAYERS 4 /* max supported players */ #define MAX_PORTS 2 /* max controller ports, @@ -80,6 +81,7 @@ static unsigned turbo_delay = 0; static unsigned input_type[MAX_PLAYERS + 1] = {0}; /* 4-players + famicom expansion */ enum RetroZapperInputModes{RetroLightgun, RetroMouse, RetroPointer}; static enum RetroZapperInputModes zappermode = RetroLightgun; +static unsigned show_advance_sound_options; /* emulator-specific variables */ @@ -744,63 +746,22 @@ void retro_set_controller_port_device(unsigned port, unsigned device) static void set_variables(void) { - static const struct retro_variable vars[] = { - { "fceumm_region", "Region Override; Auto|NTSC|PAL|Dendy" }, - { "fceumm_aspect", "Preferred aspect ratio; 8:7 PAR|4:3" }, - { "fceumm_palette", "Color Palette; default|asqrealc|nintendo-vc|rgb|yuv-v3|unsaturated-final|sony-cxa2025as-us|pal|bmf-final2|bmf-final3|smooth-fbx|composite-direct-fbx|pvm-style-d93-fbx|ntsc-hardware-fbx|nes-classic-fbx-fs|nescap|wavebeam|raw|custom" }, - { "fceumm_up_down_allowed", "Allow Opposing Directions; disabled|enabled" }, -#ifdef PSP - { "fceumm_overscan", "Crop Overscan; enabled|disabled" }, -#else - { "fceumm_overscan_h", "Crop Overscan (Horizontal); disabled|enabled" }, - { "fceumm_overscan_v", "Crop Overscan (Vertical); enabled|disabled" }, -#endif - { "fceumm_nospritelimit", "No Sprite Limit; disabled|enabled" }, - { "fceumm_sndvolume", "Sound Volume; 150|160|170|180|190|200|210|220|230|240|250|0|10|20|30|40|50|60|70|80|90|100|110|120|130|140" }, - { "fceumm_sndquality", "Sound Quality; Low|High|Very High" }, - { "fceumm_swapduty", "Swap Duty Cycles; disabled|enabled" }, -#ifdef DEBUG - { "fceumm_apu_1", "Enable Sound Channel 1 (Square 1); enabled|disabled" }, - { "fceumm_apu_2", "Enable Sound Channel 2 (Square 2); enabled|disabled" }, - { "fceumm_apu_3", "Enable Sound Channel 3 (Triangle); enabled|disabled" }, - { "fceumm_apu_4", "Enable Sound Channel 4 (Noise); enabled|disabled" }, - { "fceumm_apu_5", "Enable Sound Channel 5 (PCM); enabled|disabled" }, -#endif - { "fceumm_turbo_enable", "Turbo Enable; None|Player 1|Player 2|Both" }, - { "fceumm_turbo_delay", "Turbo Delay (in frames); 3|5|10|15|30|60|1|2" }, - { "fceumm_zapper_mode", "Zapper Mode; lightgun|touchscreen|mouse" }, - { "fceumm_show_crosshair", "Show Crosshair; enabled|disabled" }, - { "fceumm_overclocking", "Overclocking; disabled|2x-Postrender|2x-VBlank" }, - { "fceumm_ramstate", "RAM power up state (Restart); fill $ff|fill $00|random" }, - { NULL, NULL } - }; + unsigned i = 0, index = 0; - static struct retro_variable vars_empty = { NULL, NULL }; - static struct retro_variable retro_vars[32]; - unsigned i = 0, index_core = 0; + /* Initialize main core option struct */ + for (i = 0; i < MAX_CORE_OPTIONS; i++) + option_defs_us[i] = option_defs_empty; - while (vars[index_core].key != NULL) - { - retro_vars[index_core].key = vars[index_core].key; - retro_vars[index_core].value = vars[index_core].value; - index_core++; + /* Write common core options to main struct */ + while (option_defs_common[index].key) { + option_defs_us[index] = option_defs_common[index]; + index++; } - /* append dipswitches to core options if available */ - set_dipswitch_variables(&index_core, retro_vars); + /* Append dipswitch settings to core options if available */ + set_dipswitch_variables(&index, option_defs_us); - /* NULL terminate */ - retro_vars[index_core] = vars_empty; - environ_cb(RETRO_ENVIRONMENT_SET_VARIABLES, (void*)retro_vars); - -#ifdef DEBUG - /* list core options */ - i = 0; - while (retro_vars[i].key) { - FCEU_printf(" { '%s', '%s' }\n", retro_vars[i].key, retro_vars[i].value); - i++; - } -#endif + libretro_set_core_options(environ_cb); } void retro_set_environment(retro_environment_t cb) @@ -1316,7 +1277,8 @@ static void check_variables(bool startup) if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { - sndvolume = atoi(var.value); + int val = (int)(atof(var.value) * 25.6); + sndvolume = val; FCEUD_SoundToggle(); } diff --git a/src/drivers/libretro/libretro_core_options.h b/src/drivers/libretro/libretro_core_options.h new file mode 100644 index 0000000..877c05f --- /dev/null +++ b/src/drivers/libretro/libretro_core_options.h @@ -0,0 +1,563 @@ +#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 */ + +#define MAX_CORE_OPTIONS 32 + +struct retro_core_option_definition option_defs_common[] = { + { + "fceumm_region", + "Region Override", + "Force core to use NTSC, PAL or Dendy region timings.", + { + { "Auto", NULL }, + { "NTSC", NULL }, + { "PAL", NULL }, + { "Dendy", NULL }, + { NULL, NULL}, + }, + "Auto", + }, + { + "fceumm_aspect", + "Preferred aspect ratio", + "Choose prefered aspect ratio.", + { + { "8:7 PAR", NULL }, + { "4:3", NULL }, + { NULL, NULL}, + }, + "8:7 PAR", + }, + { + "fceumm_palette", + "Color Palette", + "Choose from pre-generted palettes, a custom 64x3 palette from file or raw format (needs to use a nes-decoder shader).", + { + { "default", NULL }, + { "asqrealc", NULL }, + { "nintendo-vc", NULL }, + { "rgb", NULL }, + { "yuv-v3", NULL }, + { "unsaturated-final", NULL }, + { "sony-cxa2025as-us", NULL }, + { "pal", NULL }, + { "bmf-final2", NULL }, + { "bmf-final3", NULL }, + { "smooth-fbx", NULL }, + { "composite-direct-fbx", NULL }, + { "pvm-style-d93-fbx", NULL }, + { "ntsc-hardware-fbx", NULL }, + { "nes-classic-fbx-fs", NULL }, + { "nescap", NULL }, + { "wavebeam", NULL }, + { "raw", NULL }, + { "custom", NULL }, + { NULL, NULL}, + }, + "default", + }, + { + "fceumm_up_down_allowed", + "Allow Opposing Directions", + "Allows simultaneous UP+DOWN or LEFT+RIGHT button combination which can create different effects in some games.", + { + { "disabled", NULL }, + { "enabled", NULL }, + { NULL, NULL}, + }, + "disabled", + }, + +#ifdef PSP + { + "fceumm_overscan", + "Crop Overscan", + "Removes 8 pixel overscan from all sides", + { + { "enabled", NULL }, + { "disabled", NULL }, + { NULL, NULL}, + }, + "enabled", + }, +#else + { + "fceumm_overscan_h", + "Crop Overscan (Horizontal)", + "Removes 8 pixel from left and right of screen to simulates overscans seen on standard CRT television.", + { + { "disabled", NULL }, + { "enabled", NULL }, + { NULL, NULL}, + }, + "disabled", + }, + { + "fceumm_overscan_v", + "Crop Overscan (Vertical)", + "Removes 8 pixel from top and bottom of screen to simulates overscans seen on standard CRT television.", + { + { "disabled", NULL }, + { "enabled", NULL }, + { NULL, NULL}, + }, + "enabled", + }, +#endif + { + "fceumm_nospritelimit", + "No Sprite Limit", + "Removes the 8-per-scanline hardware limit. This reduces sprite flickering but can cause some games to glitch since some use this for effects.", + { + { "disabled", NULL }, + { "enabled", NULL }, + { NULL, NULL}, + }, + "disabled", + }, + { + "fceumm_sndvolume", + "Sound Volume", + "Change master volume level", + { + { "0", NULL }, + { "1", NULL }, + { "2", NULL }, + { "3", NULL }, + { "4", NULL }, + { "5", NULL }, + { "6", NULL }, + { "7", NULL }, + { "8", NULL }, + { "9", NULL }, + { "10", NULL }, + { NULL, NULL}, + }, + "7", + }, + { + "fceumm_sndquality", + "Sound Quality", + "Enable higher quality sounds in exchange for more processing power required", + { + { "Low", NULL }, + { "High", NULL }, + { "Very High", NULL }, + { NULL, NULL}, + }, + "Low", + }, + { + "fceumm_swapduty", + "Swap Duty Cycles", + "Simulates the sound from famiclones has the pulse wave channels duty cycle bits reversed.", + { + { "disabled", NULL }, + { "enabled", NULL }, + { NULL, NULL}, + }, + "disabled", + }, + { + "fceumm_turbo_enable", + "Turbo Enable", + "Enables or disables turbo buttons.", + { + { "None", NULL }, + { "Player 1", NULL }, + { "Player 2", NULL }, + { "Both", NULL }, + { NULL, NULL}, + }, + "None", + }, + { + "fceumm_turbo_delay", + "Turbo Delay (in frames)", + "Repeat rate of turbo buttons in frames.", + { + { "1", NULL }, + { "2", NULL }, + { "3", NULL }, + { "5", NULL }, + { "10", NULL }, + { "15", NULL }, + { "30", NULL }, + { "60", NULL }, + { NULL, NULL}, + }, + "3", + }, + { + "fceumm_zapper_mode", + "Zapper Mode", + "Selects device to use for zapper games.", + { + { "lightgun", NULL }, + { "touchscreen", NULL }, + { "mouse", NULL }, + { NULL, NULL}, + }, + "lightgun", + }, + { + "fceumm_show_crosshair", + "Show Crosshair", + "Shows or hides on-screen crosshairs when using a zapper.", + { + { "enabled", NULL }, + { "disabled", NULL }, + { NULL, NULL}, + }, + "enabled", + }, + { + "fceumm_overclocking", + "Overclocking", + "Enables or disables overclocking which can reduce slowdowns in some games. Postrender method is more compatible with every game with Vblank more effective for games like Contra Force.", + { + { "disabled", NULL }, + { "2x-Postrender", NULL }, + { "2x-VBlank", NULL }, + { NULL, NULL}, + }, + "disabled", + }, + { + "fceumm_ramstate", + "RAM power up state (Restart)", + "Choose RAM startup during power up. Some games rely on initial ram values for random generator as an example.", + { + { "fill $ff", NULL }, + { "fill $00", NULL }, + { "random", NULL }, + { NULL, NULL}, + }, + "fill $ff", + }, +#ifdef DEBUG + { + "fceumm_apu_1", + "Channel 1 (Square 1)", + "Enables or disables pulse wave generator audio output 1.", + { + { "enabled", NULL }, + { "disabled", NULL }, + { NULL, NULL}, + }, + "enabled", + }, + { + "fceumm_apu_2", + "Channel 2 (Square 2)", + "Enables or disables pulse wave generator audio output 2.", + { + { "enabled", NULL }, + { "disabled", NULL }, + { NULL, NULL}, + }, + "enabled", + }, + { + "fceumm_apu_3", + "Channel 3 (Triangle)", + "Enables or disables triangle wave generator audio output.", + { + { "enabled", NULL }, + { "disabled", NULL }, + { NULL, NULL}, + }, + "enabled", + }, + { + "fceumm_apu_4", + "Channel 4 (Noise)", + "Enables or disables noise generator audio output.", + { + { "enabled", NULL }, + { "disabled", NULL }, + { NULL, NULL}, + }, + "enabled", + }, + { + "fceumm_apu_5", + "Channel 5 (PCM)", + "Enables or disables delta modulation channel audio output.", + { + { "enabled", NULL }, + { "disabled", NULL }, + { NULL, NULL}, + }, + "enabled", + }, +#endif + + { NULL, NULL, NULL, { NULL, NULL }, NULL }, +}; + +struct retro_core_option_definition option_defs_empty = { + NULL, NULL, NULL, { NULL, NULL }, NULL +}; + +struct retro_core_option_definition option_defs_us[MAX_CORE_OPTIONS]; + +/* 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