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