all repos — mgba @ 0019cb69d8bb7588f7e9e50344e3d4bd2eca2aeb

mGBA Game Boy Advance Emulator

src/platform/libretro/libretro_core_options.h (view raw)

  1#ifndef LIBRETRO_CORE_OPTIONS_H__
  2#define LIBRETRO_CORE_OPTIONS_H__
  3
  4#include <stdlib.h>
  5#include <string.h>
  6
  7#include "libretro.h"
  8#include "retro_inline.h"
  9
 10#ifndef HAVE_NO_LANGEXTRA
 11#include "libretro_core_options_intl.h"
 12#endif
 13
 14/*
 15 ********************************
 16 * VERSION: 1.3
 17 ********************************
 18 *
 19 * - 1.3: Move translations to libretro_core_options_intl.h
 20 *        - libretro_core_options_intl.h includes BOM and utf-8
 21 *          fix for MSVC 2010-2013
 22 *        - Added HAVE_NO_LANGEXTRA flag to disable translations
 23 *          on platforms/compilers without BOM support
 24 * - 1.2: Use core options v1 interface when
 25 *        RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION is >= 1
 26 *        (previously required RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION == 1)
 27 * - 1.1: Support generation of core options v0 retro_core_option_value
 28 *        arrays containing options with a single value
 29 * - 1.0: First commit
 30*/
 31
 32#ifdef __cplusplus
 33extern "C" {
 34#endif
 35
 36/*
 37 ********************************
 38 * Core Option Definitions
 39 ********************************
 40*/
 41
 42/* RETRO_LANGUAGE_ENGLISH */
 43
 44/* Default language:
 45 * - All other languages must include the same keys and values
 46 * - Will be used as a fallback in the event that frontend language
 47 *   is not available
 48 * - Will be used as a fallback for any missing entries in
 49 *   frontend language definition */
 50
 51struct retro_core_option_definition option_defs_us[] = {
 52   {
 53      "mgba_solar_sensor_level",
 54      "Solar Sensor Level",
 55      "Sets ambient sunlight intensity. Can be used by games that included a solar sensor in their cartridges, e.g: the Boktai series.",
 56      {
 57         { "0",  NULL },
 58         { "1",  NULL },
 59         { "2",  NULL },
 60         { "3",  NULL },
 61         { "4",  NULL },
 62         { "5",  NULL },
 63         { "6",  NULL },
 64         { "7",  NULL },
 65         { "8",  NULL },
 66         { "9",  NULL },
 67         { "10", NULL },
 68         { NULL, NULL },
 69      },
 70      "0"
 71   },
 72   {
 73      "mgba_allow_opposing_directions",
 74      "Allow Opposing Directional Input",
 75      "Enabling this will allow pressing / quickly alternating / holding both left and right (or up and down) directions at the same time. This may cause movement-based glitches.",
 76      {
 77         { "no",  "disabled" },
 78         { "yes", "enabled" },
 79         { NULL, NULL },
 80      },
 81      "no"
 82   },
 83   {
 84      "mgba_gb_model",
 85      "Game Boy Model (requires restart)",
 86      "Runs loaded content with a specific Game Boy model. 'Autodetect' will select the most appropriate model for the current game.",
 87      {
 88         { "Autodetect",       NULL },
 89         { "Game Boy",         NULL },
 90         { "Super Game Boy",   NULL },
 91         { "Game Boy Color",   NULL },
 92         { "Game Boy Advance", NULL },
 93         { NULL, NULL },
 94      },
 95      "Autodetect"
 96   },
 97   {
 98      "mgba_use_bios",
 99      "Use BIOS File if Found (requires restart)",
100      "Use official BIOS/bootloader for emulated hardware, if present in RetroArch's system directory.",
101      {
102         { "ON",  NULL },
103         { "OFF", NULL },
104         { NULL, NULL },
105      },
106      "ON"
107   },
108   {
109      "mgba_skip_bios",
110      "Skip BIOS Intro (requires restart)",
111      "When using an official BIOS/bootloader, skip the start-up logo animation. This setting is ignored when 'Use BIOS File if Found' is disabled.",
112      {
113         { "OFF", NULL },
114         { "ON",  NULL },
115         { NULL, NULL },
116      },
117      "OFF"
118   },
119   {
120      "mgba_sgb_borders",
121      "Use Super Game Boy Borders (requires restart)",
122      "Display Super Game Boy borders when running Super Game Boy enhanced games.",
123      {
124         { "ON",  NULL },
125         { "OFF", NULL },
126         { NULL, NULL },
127      },
128      "ON"
129   },
130   {
131      "mgba_idle_optimization",
132      "Idle Loop Removal",
133      "Reduce system load by optimizing so-called 'idle-loops' - sections in the code where nothing happens, but the CPU runs at full speed (like a car revving in neutral). Improves performance, and should be enabled on low-end hardware.",
134      {
135         { "Remove Known",      NULL },
136         { "Detect and Remove", NULL },
137         { "Don't Remove",      NULL },
138         { NULL, NULL },
139      },
140      "Remove Known"
141   },
142   {
143      "mgba_frameskip",
144      "Frameskip",
145      "Skip frames to improve performance at the expense of visual smoothness. Value set here is the number of frames omitted after a frame is rendered - i.e. '0' = 60fps, '1' = 30fps, '2' = 15fps, etc.",
146      {
147         { "0",  NULL },
148         { "1",  NULL },
149         { "2",  NULL },
150         { "3",  NULL },
151         { "4",  NULL },
152         { "5",  NULL },
153         { "6",  NULL },
154         { "7",  NULL },
155         { "8",  NULL },
156         { "9",  NULL },
157         { "10", NULL },
158         { NULL, NULL },
159      },
160      "0"
161   },
162#if defined(COLOR_16_BIT) && defined(COLOR_5_6_5)
163   {
164      "mgba_color_correction",
165      "Color Correction",
166      "Adjusts output colors to match the display of real GBA/GBC hardware.",
167      {
168         { "OFF",  NULL },
169         { "GBA",  "Game Boy Advance" },
170         { "GBC",  "Game Boy Color" },
171         { "Auto", NULL },
172         { NULL, NULL },
173      },
174      "OFF"
175   },
176#endif
177   { NULL, NULL, NULL, {{0}}, NULL },
178};
179
180/*
181 ********************************
182 * Language Mapping
183 ********************************
184*/
185
186#ifndef HAVE_NO_LANGEXTRA
187struct retro_core_option_definition *option_defs_intl[RETRO_LANGUAGE_LAST] = {
188   option_defs_us, /* RETRO_LANGUAGE_ENGLISH */
189   NULL,           /* RETRO_LANGUAGE_JAPANESE */
190   NULL,           /* RETRO_LANGUAGE_FRENCH */
191   NULL,           /* RETRO_LANGUAGE_SPANISH */
192   NULL,           /* RETRO_LANGUAGE_GERMAN */
193   option_defs_it, /* RETRO_LANGUAGE_ITALIAN */
194   NULL,           /* RETRO_LANGUAGE_DUTCH */
195   NULL,           /* RETRO_LANGUAGE_PORTUGUESE_BRAZIL */
196   NULL,           /* RETRO_LANGUAGE_PORTUGUESE_PORTUGAL */
197   NULL,           /* RETRO_LANGUAGE_RUSSIAN */
198   NULL,           /* RETRO_LANGUAGE_KOREAN */
199   NULL,           /* RETRO_LANGUAGE_CHINESE_TRADITIONAL */
200   NULL,           /* RETRO_LANGUAGE_CHINESE_SIMPLIFIED */
201   NULL,           /* RETRO_LANGUAGE_ESPERANTO */
202   NULL,           /* RETRO_LANGUAGE_POLISH */
203   NULL,           /* RETRO_LANGUAGE_VIETNAMESE */
204   NULL,           /* RETRO_LANGUAGE_ARABIC */
205   NULL,           /* RETRO_LANGUAGE_GREEK */
206   option_defs_tr, /* RETRO_LANGUAGE_TURKISH */
207};
208#endif
209
210/*
211 ********************************
212 * Functions
213 ********************************
214*/
215
216/* Handles configuration/setting of core options.
217 * Should be called as early as possible - ideally inside
218 * retro_set_environment(), and no later than retro_load_game()
219 * > We place the function body in the header to avoid the
220 *   necessity of adding more .c files (i.e. want this to
221 *   be as painless as possible for core devs)
222 */
223
224static INLINE void libretro_set_core_options(retro_environment_t environ_cb)
225{
226   unsigned version = 0;
227
228   if (!environ_cb)
229      return;
230
231   if (environ_cb(RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION, &version) && (version >= 1))
232   {
233#ifndef HAVE_NO_LANGEXTRA
234      struct retro_core_options_intl core_options_intl;
235      unsigned language = 0;
236
237      core_options_intl.us    = option_defs_us;
238      core_options_intl.local = NULL;
239
240      if (environ_cb(RETRO_ENVIRONMENT_GET_LANGUAGE, &language) &&
241          (language < RETRO_LANGUAGE_LAST) && (language != RETRO_LANGUAGE_ENGLISH))
242         core_options_intl.local = option_defs_intl[language];
243
244      environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL, &core_options_intl);
245#else
246      environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS, &option_defs_us);
247#endif
248   }
249   else
250   {
251      size_t i;
252      size_t num_options               = 0;
253      struct retro_variable *variables = NULL;
254      char **values_buf                = NULL;
255
256      /* Determine number of options */
257      while (true)
258      {
259         if (option_defs_us[num_options].key)
260            num_options++;
261         else
262            break;
263      }
264
265      /* Allocate arrays */
266      variables  = (struct retro_variable *)calloc(num_options + 1, sizeof(struct retro_variable));
267      values_buf = (char **)calloc(num_options, sizeof(char *));
268
269      if (!variables || !values_buf)
270         goto error;
271
272      /* Copy parameters from option_defs_us array */
273      for (i = 0; i < num_options; i++)
274      {
275         const char *key                        = option_defs_us[i].key;
276         const char *desc                       = option_defs_us[i].desc;
277         const char *default_value              = option_defs_us[i].default_value;
278         struct retro_core_option_value *values = option_defs_us[i].values;
279         size_t buf_len                         = 3;
280         size_t default_index                   = 0;
281
282         values_buf[i] = NULL;
283
284         if (desc)
285         {
286            size_t num_values = 0;
287
288            /* Determine number of values */
289            while (true)
290            {
291               if (values[num_values].value)
292               {
293                  /* Check if this is the default value */
294                  if (default_value)
295                     if (strcmp(values[num_values].value, default_value) == 0)
296                        default_index = num_values;
297
298                  buf_len += strlen(values[num_values].value);
299                  num_values++;
300               }
301               else
302                  break;
303            }
304
305            /* Build values string */
306            if (num_values > 0)
307            {
308               size_t j;
309
310               buf_len += num_values - 1;
311               buf_len += strlen(desc);
312
313               values_buf[i] = (char *)calloc(buf_len, sizeof(char));
314               if (!values_buf[i])
315                  goto error;
316
317               strcpy(values_buf[i], desc);
318               strcat(values_buf[i], "; ");
319
320               /* Default value goes first */
321               strcat(values_buf[i], values[default_index].value);
322
323               /* Add remaining values */
324               for (j = 0; j < num_values; j++)
325               {
326                  if (j != default_index)
327                  {
328                     strcat(values_buf[i], "|");
329                     strcat(values_buf[i], values[j].value);
330                  }
331               }
332            }
333         }
334
335         variables[i].key   = key;
336         variables[i].value = values_buf[i];
337      }
338
339      /* Set variables */
340      environ_cb(RETRO_ENVIRONMENT_SET_VARIABLES, variables);
341
342error:
343
344      /* Clean up */
345      if (values_buf)
346      {
347         for (i = 0; i < num_options; i++)
348         {
349            if (values_buf[i])
350            {
351               free(values_buf[i]);
352               values_buf[i] = NULL;
353            }
354         }
355
356         free(values_buf);
357         values_buf = NULL;
358      }
359
360      if (variables)
361      {
362         free(variables);
363         variables = NULL;
364      }
365   }
366}
367
368#ifdef __cplusplus
369}
370#endif
371
372#endif