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