all repos — mgba @ 33098926577f52a74730de1708a427e275a9bc88

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         { "sensor",  "Use device sensor if available" },
 58         { "0",       NULL },
 59         { "1",       NULL },
 60         { "2",       NULL },
 61         { "3",       NULL },
 62         { "4",       NULL },
 63         { "5",       NULL },
 64         { "6",       NULL },
 65         { "7",       NULL },
 66         { "8",       NULL },
 67         { "9",       NULL },
 68         { "10",      NULL },
 69         { NULL,      NULL },
 70      },
 71      "0"
 72   },
 73   {
 74      "mgba_allow_opposing_directions",
 75      "Allow Opposing Directional Input",
 76      "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.",
 77      {
 78         { "no",  "disabled" },
 79         { "yes", "enabled" },
 80         { NULL, NULL },
 81      },
 82      "no"
 83   },
 84   {
 85      "mgba_gb_model",
 86      "Game Boy Model (requires restart)",
 87      "Runs loaded content with a specific Game Boy model. 'Autodetect' will select the most appropriate model for the current game.",
 88      {
 89         { "Autodetect",       NULL },
 90         { "Game Boy",         NULL },
 91         { "Super Game Boy",   NULL },
 92         { "Game Boy Color",   NULL },
 93         { "Game Boy Advance", NULL },
 94         { NULL, NULL },
 95      },
 96      "Autodetect"
 97   },
 98   {
 99      "mgba_use_bios",
100      "Use BIOS File if Found (requires restart)",
101      "Use official BIOS/bootloader for emulated hardware, if present in RetroArch's system directory.",
102      {
103         { "ON",  NULL },
104         { "OFF", NULL },
105         { NULL, NULL },
106      },
107      "ON"
108   },
109   {
110      "mgba_skip_bios",
111      "Skip BIOS Intro (requires restart)",
112      "When using an official BIOS/bootloader, skip the start-up logo animation. This setting is ignored when 'Use BIOS File if Found' is disabled.",
113      {
114         { "OFF", NULL },
115         { "ON",  NULL },
116         { NULL, NULL },
117      },
118      "OFF"
119   },
120   {
121      "mgba_sgb_borders",
122      "Use Super Game Boy Borders (requires restart)",
123      "Display Super Game Boy borders when running Super Game Boy enhanced games.",
124      {
125         { "ON",  NULL },
126         { "OFF", NULL },
127         { NULL, NULL },
128      },
129      "ON"
130   },
131   {
132      "mgba_idle_optimization",
133      "Idle Loop Removal",
134      "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.",
135      {
136         { "Remove Known",      NULL },
137         { "Detect and Remove", NULL },
138         { "Don't Remove",      NULL },
139         { NULL, NULL },
140      },
141      "Remove Known"
142   },
143   {
144      "mgba_frameskip",
145      "Frameskip",
146      "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.",
147      {
148         { "0",  NULL },
149         { "1",  NULL },
150         { "2",  NULL },
151         { "3",  NULL },
152         { "4",  NULL },
153         { "5",  NULL },
154         { "6",  NULL },
155         { "7",  NULL },
156         { "8",  NULL },
157         { "9",  NULL },
158         { "10", NULL },
159         { NULL, NULL },
160      },
161      "0"
162   },
163#if defined(COLOR_16_BIT) && defined(COLOR_5_6_5)
164   {
165      "mgba_color_correction",
166      "Color Correction",
167      "Adjusts output colors to match the display of real GBA/GBC hardware.",
168      {
169         { "OFF",  NULL },
170         { "GBA",  "Game Boy Advance" },
171         { "GBC",  "Game Boy Color" },
172         { "Auto", NULL },
173         { NULL, NULL },
174      },
175      "OFF"
176   },
177#endif
178   {
179      "mgba_force_gbp",
180      "Enable Game Boy Player Rumble (requires restart)",
181      "Enabling this will allow compatible games with the Game Boy Player boot logo to make the controller rumble. Due to how Nintendo decided this feature should work, it may cause glitches such as flickering or lag in some of these games.",
182      {
183         { "OFF", NULL },
184         { "ON",  NULL },
185         { NULL, NULL },
186      },
187      "OFF"
188   },
189   { NULL, NULL, NULL, {{0}}, NULL },
190};
191
192/*
193 ********************************
194 * Language Mapping
195 ********************************
196*/
197
198#ifndef HAVE_NO_LANGEXTRA
199struct retro_core_option_definition *option_defs_intl[RETRO_LANGUAGE_LAST] = {
200   option_defs_us, /* RETRO_LANGUAGE_ENGLISH */
201   NULL,           /* RETRO_LANGUAGE_JAPANESE */
202   NULL,           /* RETRO_LANGUAGE_FRENCH */
203   NULL,           /* RETRO_LANGUAGE_SPANISH */
204   NULL,           /* RETRO_LANGUAGE_GERMAN */
205   option_defs_it, /* RETRO_LANGUAGE_ITALIAN */
206   NULL,           /* RETRO_LANGUAGE_DUTCH */
207   NULL,           /* RETRO_LANGUAGE_PORTUGUESE_BRAZIL */
208   NULL,           /* RETRO_LANGUAGE_PORTUGUESE_PORTUGAL */
209   NULL,           /* RETRO_LANGUAGE_RUSSIAN */
210   NULL,           /* RETRO_LANGUAGE_KOREAN */
211   NULL,           /* RETRO_LANGUAGE_CHINESE_TRADITIONAL */
212   NULL,           /* RETRO_LANGUAGE_CHINESE_SIMPLIFIED */
213   NULL,           /* RETRO_LANGUAGE_ESPERANTO */
214   NULL,           /* RETRO_LANGUAGE_POLISH */
215   NULL,           /* RETRO_LANGUAGE_VIETNAMESE */
216   NULL,           /* RETRO_LANGUAGE_ARABIC */
217   NULL,           /* RETRO_LANGUAGE_GREEK */
218   option_defs_tr, /* RETRO_LANGUAGE_TURKISH */
219};
220#endif
221
222/*
223 ********************************
224 * Functions
225 ********************************
226*/
227
228/* Handles configuration/setting of core options.
229 * Should be called as early as possible - ideally inside
230 * retro_set_environment(), and no later than retro_load_game()
231 * > We place the function body in the header to avoid the
232 *   necessity of adding more .c files (i.e. want this to
233 *   be as painless as possible for core devs)
234 */
235
236static INLINE void libretro_set_core_options(retro_environment_t environ_cb)
237{
238   unsigned version = 0;
239
240   if (!environ_cb)
241      return;
242
243   if (environ_cb(RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION, &version) && (version >= 1))
244   {
245#ifndef HAVE_NO_LANGEXTRA
246      struct retro_core_options_intl core_options_intl;
247      unsigned language = 0;
248
249      core_options_intl.us    = option_defs_us;
250      core_options_intl.local = NULL;
251
252      if (environ_cb(RETRO_ENVIRONMENT_GET_LANGUAGE, &language) &&
253          (language < RETRO_LANGUAGE_LAST) && (language != RETRO_LANGUAGE_ENGLISH))
254         core_options_intl.local = option_defs_intl[language];
255
256      environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL, &core_options_intl);
257#else
258      environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS, &option_defs_us);
259#endif
260   }
261   else
262   {
263      size_t i;
264      size_t num_options               = 0;
265      struct retro_variable *variables = NULL;
266      char **values_buf                = NULL;
267
268      /* Determine number of options */
269      while (true)
270      {
271         if (option_defs_us[num_options].key)
272            num_options++;
273         else
274            break;
275      }
276
277      /* Allocate arrays */
278      variables  = (struct retro_variable *)calloc(num_options + 1, sizeof(struct retro_variable));
279      values_buf = (char **)calloc(num_options, sizeof(char *));
280
281      if (!variables || !values_buf)
282         goto error;
283
284      /* Copy parameters from option_defs_us array */
285      for (i = 0; i < num_options; i++)
286      {
287         const char *key                        = option_defs_us[i].key;
288         const char *desc                       = option_defs_us[i].desc;
289         const char *default_value              = option_defs_us[i].default_value;
290         struct retro_core_option_value *values = option_defs_us[i].values;
291         size_t buf_len                         = 3;
292         size_t default_index                   = 0;
293
294         values_buf[i] = NULL;
295
296         if (desc)
297         {
298            size_t num_values = 0;
299
300            /* Determine number of values */
301            while (true)
302            {
303               if (values[num_values].value)
304               {
305                  /* Check if this is the default value */
306                  if (default_value)
307                     if (strcmp(values[num_values].value, default_value) == 0)
308                        default_index = num_values;
309
310                  buf_len += strlen(values[num_values].value);
311                  num_values++;
312               }
313               else
314                  break;
315            }
316
317            /* Build values string */
318            if (num_values > 0)
319            {
320               size_t j;
321
322               buf_len += num_values - 1;
323               buf_len += strlen(desc);
324
325               values_buf[i] = (char *)calloc(buf_len, sizeof(char));
326               if (!values_buf[i])
327                  goto error;
328
329               strcpy(values_buf[i], desc);
330               strcat(values_buf[i], "; ");
331
332               /* Default value goes first */
333               strcat(values_buf[i], values[default_index].value);
334
335               /* Add remaining values */
336               for (j = 0; j < num_values; j++)
337               {
338                  if (j != default_index)
339                  {
340                     strcat(values_buf[i], "|");
341                     strcat(values_buf[i], values[j].value);
342                  }
343               }
344            }
345         }
346
347         variables[i].key   = key;
348         variables[i].value = values_buf[i];
349      }
350
351      /* Set variables */
352      environ_cb(RETRO_ENVIRONMENT_SET_VARIABLES, variables);
353
354error:
355
356      /* Clean up */
357      if (values_buf)
358      {
359         for (i = 0; i < num_options; i++)
360         {
361            if (values_buf[i])
362            {
363               free(values_buf[i]);
364               values_buf[i] = NULL;
365            }
366         }
367
368         free(values_buf);
369         values_buf = NULL;
370      }
371
372      if (variables)
373      {
374         free(variables);
375         variables = NULL;
376      }
377   }
378}
379
380#ifdef __cplusplus
381}
382#endif
383
384#endif