all repos — mgba @ 70f581162fe47d260fcf5946858054328188b808

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   {
178      "mgba_force_gbp",
179      "Enable Game Boy Player Rumble (requires restart)",
180      "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.",
181      {
182         { "OFF", NULL },
183         { "ON",  NULL },
184         { NULL, NULL },
185      },
186      "OFF"
187   },
188   { NULL, NULL, NULL, {{0}}, NULL },
189};
190
191/*
192 ********************************
193 * Language Mapping
194 ********************************
195*/
196
197#ifndef HAVE_NO_LANGEXTRA
198struct retro_core_option_definition *option_defs_intl[RETRO_LANGUAGE_LAST] = {
199   option_defs_us, /* RETRO_LANGUAGE_ENGLISH */
200   NULL,           /* RETRO_LANGUAGE_JAPANESE */
201   NULL,           /* RETRO_LANGUAGE_FRENCH */
202   NULL,           /* RETRO_LANGUAGE_SPANISH */
203   NULL,           /* RETRO_LANGUAGE_GERMAN */
204   option_defs_it, /* RETRO_LANGUAGE_ITALIAN */
205   NULL,           /* RETRO_LANGUAGE_DUTCH */
206   NULL,           /* RETRO_LANGUAGE_PORTUGUESE_BRAZIL */
207   NULL,           /* RETRO_LANGUAGE_PORTUGUESE_PORTUGAL */
208   NULL,           /* RETRO_LANGUAGE_RUSSIAN */
209   NULL,           /* RETRO_LANGUAGE_KOREAN */
210   NULL,           /* RETRO_LANGUAGE_CHINESE_TRADITIONAL */
211   NULL,           /* RETRO_LANGUAGE_CHINESE_SIMPLIFIED */
212   NULL,           /* RETRO_LANGUAGE_ESPERANTO */
213   NULL,           /* RETRO_LANGUAGE_POLISH */
214   NULL,           /* RETRO_LANGUAGE_VIETNAMESE */
215   NULL,           /* RETRO_LANGUAGE_ARABIC */
216   NULL,           /* RETRO_LANGUAGE_GREEK */
217   option_defs_tr, /* RETRO_LANGUAGE_TURKISH */
218};
219#endif
220
221/*
222 ********************************
223 * Functions
224 ********************************
225*/
226
227/* Handles configuration/setting of core options.
228 * Should be called as early as possible - ideally inside
229 * retro_set_environment(), and no later than retro_load_game()
230 * > We place the function body in the header to avoid the
231 *   necessity of adding more .c files (i.e. want this to
232 *   be as painless as possible for core devs)
233 */
234
235static INLINE void libretro_set_core_options(retro_environment_t environ_cb)
236{
237   unsigned version = 0;
238
239   if (!environ_cb)
240      return;
241
242   if (environ_cb(RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION, &version) && (version >= 1))
243   {
244#ifndef HAVE_NO_LANGEXTRA
245      struct retro_core_options_intl core_options_intl;
246      unsigned language = 0;
247
248      core_options_intl.us    = option_defs_us;
249      core_options_intl.local = NULL;
250
251      if (environ_cb(RETRO_ENVIRONMENT_GET_LANGUAGE, &language) &&
252          (language < RETRO_LANGUAGE_LAST) && (language != RETRO_LANGUAGE_ENGLISH))
253         core_options_intl.local = option_defs_intl[language];
254
255      environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL, &core_options_intl);
256#else
257      environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS, &option_defs_us);
258#endif
259   }
260   else
261   {
262      size_t i;
263      size_t num_options               = 0;
264      struct retro_variable *variables = NULL;
265      char **values_buf                = NULL;
266
267      /* Determine number of options */
268      while (true)
269      {
270         if (option_defs_us[num_options].key)
271            num_options++;
272         else
273            break;
274      }
275
276      /* Allocate arrays */
277      variables  = (struct retro_variable *)calloc(num_options + 1, sizeof(struct retro_variable));
278      values_buf = (char **)calloc(num_options, sizeof(char *));
279
280      if (!variables || !values_buf)
281         goto error;
282
283      /* Copy parameters from option_defs_us array */
284      for (i = 0; i < num_options; i++)
285      {
286         const char *key                        = option_defs_us[i].key;
287         const char *desc                       = option_defs_us[i].desc;
288         const char *default_value              = option_defs_us[i].default_value;
289         struct retro_core_option_value *values = option_defs_us[i].values;
290         size_t buf_len                         = 3;
291         size_t default_index                   = 0;
292
293         values_buf[i] = NULL;
294
295         if (desc)
296         {
297            size_t num_values = 0;
298
299            /* Determine number of values */
300            while (true)
301            {
302               if (values[num_values].value)
303               {
304                  /* Check if this is the default value */
305                  if (default_value)
306                     if (strcmp(values[num_values].value, default_value) == 0)
307                        default_index = num_values;
308
309                  buf_len += strlen(values[num_values].value);
310                  num_values++;
311               }
312               else
313                  break;
314            }
315
316            /* Build values string */
317            if (num_values > 0)
318            {
319               size_t j;
320
321               buf_len += num_values - 1;
322               buf_len += strlen(desc);
323
324               values_buf[i] = (char *)calloc(buf_len, sizeof(char));
325               if (!values_buf[i])
326                  goto error;
327
328               strcpy(values_buf[i], desc);
329               strcat(values_buf[i], "; ");
330
331               /* Default value goes first */
332               strcat(values_buf[i], values[default_index].value);
333
334               /* Add remaining values */
335               for (j = 0; j < num_values; j++)
336               {
337                  if (j != default_index)
338                  {
339                     strcat(values_buf[i], "|");
340                     strcat(values_buf[i], values[j].value);
341                  }
342               }
343            }
344         }
345
346         variables[i].key   = key;
347         variables[i].value = values_buf[i];
348      }
349
350      /* Set variables */
351      environ_cb(RETRO_ENVIRONMENT_SET_VARIABLES, variables);
352
353error:
354
355      /* Clean up */
356      if (values_buf)
357      {
358         for (i = 0; i < num_options; i++)
359         {
360            if (values_buf[i])
361            {
362               free(values_buf[i]);
363               values_buf[i] = NULL;
364            }
365         }
366
367         free(values_buf);
368         values_buf = NULL;
369      }
370
371      if (variables)
372      {
373         free(variables);
374         variables = NULL;
375      }
376   }
377}
378
379#ifdef __cplusplus
380}
381#endif
382
383#endif