#ifndef LIBRETRO_CORE_OPTIONS_H__ #define LIBRETRO_CORE_OPTIONS_H__ #include #include #include #include #ifndef HAVE_NO_LANGEXTRA #include "libretro_core_options_intl.h" #endif /* ******************************** * VERSION: 1.3 ******************************** * * - 1.3: Move translations to libretro_core_options_intl.h * - libretro_core_options_intl.h includes BOM and utf-8 * fix for MSVC 2010-2013 * - Added HAVE_NO_LANGEXTRA flag to disable translations * on platforms/compilers without BOM support * - 1.2: Use core options v1 interface when * RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION is >= 1 * (previously required RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION == 1) * - 1.1: Support generation of core options v0 retro_core_option_value * arrays containing options with a single value * - 1.0: First commit */ #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 */ struct retro_core_option_definition option_defs_us[] = { { "picodrive_input1", "Input device 1", "Choose which kind of controller is plugged in slot 1.", { { "3 button pad", NULL }, { "6 button pad", NULL }, { "None", NULL }, { NULL, NULL }, }, "3 button pad" }, { "picodrive_input2", "Input device 2", "Choose which kind of controller is plugged in slot 2.", { { "3 button pad", NULL }, { "6 button pad", NULL }, { "None", NULL }, { NULL, NULL }, }, "3 button pad" }, { "picodrive_sprlim", "No sprite limit", "Enable this to remove the sprite limit.", { { "disabled", NULL }, { "enabled", NULL }, { NULL, NULL }, }, "disabled" }, { "picodrive_ramcart", "MegaCD RAM cart", "Emulate a MegaCD RAM cart, used for save game data.", { { "disabled", NULL }, { "enabled", NULL }, { NULL, NULL }, }, "disabled" }, { "picodrive_region", "Region", "Force a specific region.", { { "Auto", NULL }, { "Japan NTSC", NULL }, { "Japan PAL", NULL }, { "US", NULL }, { "Europe", NULL }, { NULL, NULL }, }, "Auto" }, { "picodrive_aspect", "Core-provided aspect ratio", "Choose the core-provided aspect ratio. RetroArch's aspect ratio must be set to Core provided in the Video settings.", { { "PAR", NULL }, { "4/3", NULL }, { "CRT", NULL }, { NULL, NULL }, }, "PAR" }, { "picodrive_overscan", "Show Overscan", "Crop out the potentially random glitchy video output that would have been hidden by the bezel around the edge of a standard-definition television screen.", { { "disabled", NULL }, { "enabled", NULL }, { NULL, NULL }, }, "disabled" }, { "picodrive_overclk68k", "68K Overclock", "Overclock the emulated 68K chip.", { { "disabled", NULL }, { "+25%", NULL }, { "+50%", NULL }, { "+75%", NULL }, { "+100%", NULL }, { "+200%", NULL }, { "+400%", NULL }, { NULL, NULL }, }, "disabled" }, #ifdef DRC_SH2 { "picodrive_drc", "Dynamic recompilers", "Enable dynamic recompilers which help to improve performance. Less accurate than interpreter CPU cores, but much faster.", { { "enabled", NULL }, { "disabled", NULL }, { NULL, NULL }, }, "enabled" }, #endif { "picodrive_audio_filter", "Audio filter", "Enable a low pass audio filter to better simulate the characteristic sound of a Model 1 Genesis. This option is ignored when running Master System and PICO titles. Only the Genesis and its add-on hardware (Sega CD, 32X) employed a physical low pass filter.", { { "disabled", NULL }, { "low-pass", NULL }, { NULL, NULL }, }, "disabled" }, { "picodrive_lowpass_range", "Low-pass filter %", "Specify the cut-off frequency of the audio low pass filter. A higher value increases the perceived 'strength' of the filter, since a wider range of the high frequency spectrum is attenuated.", { { "5", NULL }, { "10", NULL }, { "15", NULL }, { "20", NULL }, { "25", NULL }, { "30", NULL }, { "35", NULL }, { "40", NULL }, { "45", NULL }, { "50", NULL }, { "55", NULL }, { "60", NULL }, { "65", NULL }, { "70", NULL }, { "75", NULL }, { "80", NULL }, { "85", NULL }, { "90", NULL }, { "95", NULL }, { NULL, NULL }, }, "60" }, #if !defined(RENDER_GSKIT_PS2) { "picodrive_renderer", "Renderer", "Fast renderer can't render any mid-frame image changes so it is useful only for some games.", { { "accurate", NULL }, { "fast", NULL }, { NULL, NULL }, }, "accurate" }, #endif { "picodrive_sound_rate", "Sound quality", "Sound quality (in Hz). A lower value may increase performance.", { { "16000", NULL }, { "22050", NULL }, { "32000", NULL }, { "44100", NULL }, { NULL, NULL }, }, "44100" }, { NULL, NULL, NULL, {{0}}, NULL }, }; /* ******************************** * Language Mapping ******************************** */ #ifndef HAVE_NO_LANGEXTRA 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 */ option_defs_tr, /* RETRO_LANGUAGE_TURKISH */ }; #endif /* ******************************** * Functions ******************************** */ /* Handles configuration/setting of core options. * Should be called as early as possible - ideally inside * retro_set_environment(), and no later than retro_load_game() * > 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)) { #ifndef HAVE_NO_LANGEXTRA 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 environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS, &option_defs_us); #endif } else { size_t i; size_t num_options = 0; struct retro_variable *variables = NULL; char **values_buf = NULL; /* Determine number of options */ 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; 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 > 0) { 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[i].key = key; variables[i].value = values_buf[i]; } /* 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