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