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
33 extern "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
51 struct retro_core_option_definition option_defs_us[] = {
52 {
53 "wswan_rotate_keymap",
54 "Rotate button mappings",
55 "",
56 {
57 { "auto", NULL },
58 { "disabled", NULL },
59 { "enabled", NULL },
60 { NULL, NULL},
61 },
62 "auto",
63 },
64 {
65 "wswan_sound_sample_rate",
66 "Sound Output Sample Rate",
67 "Slightly higher quality or higher performance.",
68 {
69 { "11025", NULL },
70 { "22050", NULL },
71 { "44100", NULL },
72 { "48000", NULL },
73 { "96000", NULL },
74 { "192000", NULL },
75 { "384000", NULL },
76 { NULL, NULL },
77 },
78 "44100",
79 },
80 {
81 "wswan_gfx_colors",
82 "Color Depth",
83 "24-bit is slower and not available on all platforms.",
84 {
85 { "16bit", "Thousands (16-bit)" },
86 { "24bit", "Millions (24-bit)" },
87 { NULL, NULL },
88 },
89 "16bit"
90 },
91 { NULL, NULL, NULL, { NULL, NULL }, NULL },
92 };
93
94 /*
95 ********************************
96 * Language Mapping
97 ********************************
98 */
99
100 #ifndef HAVE_NO_LANGEXTRA
101 struct retro_core_option_definition *option_defs_intl[RETRO_LANGUAGE_LAST] = {
102 option_defs_us, /* RETRO_LANGUAGE_ENGLISH */
103 NULL, /* RETRO_LANGUAGE_JAPANESE */
104 NULL, /* RETRO_LANGUAGE_FRENCH */
105 NULL, /* RETRO_LANGUAGE_SPANISH */
106 NULL, /* RETRO_LANGUAGE_GERMAN */
107 NULL, /* RETRO_LANGUAGE_ITALIAN */
108 NULL, /* RETRO_LANGUAGE_DUTCH */
109 NULL, /* RETRO_LANGUAGE_PORTUGUESE_BRAZIL */
110 NULL, /* RETRO_LANGUAGE_PORTUGUESE_PORTUGAL */
111 NULL, /* RETRO_LANGUAGE_RUSSIAN */
112 NULL, /* RETRO_LANGUAGE_KOREAN */
113 NULL, /* RETRO_LANGUAGE_CHINESE_TRADITIONAL */
114 NULL, /* RETRO_LANGUAGE_CHINESE_SIMPLIFIED */
115 NULL, /* RETRO_LANGUAGE_ESPERANTO */
116 NULL, /* RETRO_LANGUAGE_POLISH */
117 NULL, /* RETRO_LANGUAGE_VIETNAMESE */
118 NULL, /* RETRO_LANGUAGE_ARABIC */
119 NULL, /* RETRO_LANGUAGE_GREEK */
120 option_defs_tr, /* RETRO_LANGUAGE_TURKISH */
121 };
122 #endif
123
124 /*
125 ********************************
126 * Functions
127 ********************************
128 */
129
130 /* Handles configuration/setting of core options.
131 * Should be called as early as possible - ideally inside
132 * retro_set_environment(), and no later than retro_load_game()
133 * > We place the function body in the header to avoid the
134 * necessity of adding more .c files (i.e. want this to
135 * be as painless as possible for core devs)
136 */
137
libretro_set_core_options(retro_environment_t environ_cb)138 static INLINE void libretro_set_core_options(retro_environment_t environ_cb)
139 {
140 unsigned version = 0;
141
142 if (!environ_cb)
143 return;
144
145 if (environ_cb(RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION, &version) && (version >= 1))
146 {
147 #ifndef HAVE_NO_LANGEXTRA
148 struct retro_core_options_intl core_options_intl;
149 unsigned language = 0;
150
151 core_options_intl.us = option_defs_us;
152 core_options_intl.local = NULL;
153
154 if (environ_cb(RETRO_ENVIRONMENT_GET_LANGUAGE, &language) &&
155 (language < RETRO_LANGUAGE_LAST) && (language != RETRO_LANGUAGE_ENGLISH))
156 core_options_intl.local = option_defs_intl[language];
157
158 environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL, &core_options_intl);
159 #else
160 environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS, &option_defs_us);
161 #endif
162 }
163 else
164 {
165 size_t i;
166 size_t num_options = 0;
167 struct retro_variable *variables = NULL;
168 char **values_buf = NULL;
169
170 /* Determine number of options */
171 while (true)
172 {
173 if (option_defs_us[num_options].key)
174 num_options++;
175 else
176 break;
177 }
178
179 /* Allocate arrays */
180 variables = (struct retro_variable *)calloc(num_options + 1, sizeof(struct retro_variable));
181 values_buf = (char **)calloc(num_options, sizeof(char *));
182
183 if (!variables || !values_buf)
184 goto error;
185
186 /* Copy parameters from option_defs_us array */
187 for (i = 0; i < num_options; i++)
188 {
189 const char *key = option_defs_us[i].key;
190 const char *desc = option_defs_us[i].desc;
191 const char *default_value = option_defs_us[i].default_value;
192 struct retro_core_option_value *values = option_defs_us[i].values;
193 size_t buf_len = 3;
194 size_t default_index = 0;
195
196 values_buf[i] = NULL;
197
198 if (desc)
199 {
200 size_t num_values = 0;
201
202 /* Determine number of values */
203 while (true)
204 {
205 if (values[num_values].value)
206 {
207 /* Check if this is the default value */
208 if (default_value)
209 if (strcmp(values[num_values].value, default_value) == 0)
210 default_index = num_values;
211
212 buf_len += strlen(values[num_values].value);
213 num_values++;
214 }
215 else
216 break;
217 }
218
219 /* Build values string */
220 if (num_values > 0)
221 {
222 size_t j;
223
224 buf_len += num_values - 1;
225 buf_len += strlen(desc);
226
227 values_buf[i] = (char *)calloc(buf_len, sizeof(char));
228 if (!values_buf[i])
229 goto error;
230
231 strcpy(values_buf[i], desc);
232 strcat(values_buf[i], "; ");
233
234 /* Default value goes first */
235 strcat(values_buf[i], values[default_index].value);
236
237 /* Add remaining values */
238 for (j = 0; j < num_values; j++)
239 {
240 if (j != default_index)
241 {
242 strcat(values_buf[i], "|");
243 strcat(values_buf[i], values[j].value);
244 }
245 }
246 }
247 }
248
249 variables[i].key = key;
250 variables[i].value = values_buf[i];
251 }
252
253 /* Set variables */
254 environ_cb(RETRO_ENVIRONMENT_SET_VARIABLES, variables);
255
256 error:
257
258 /* Clean up */
259 if (values_buf)
260 {
261 for (i = 0; i < num_options; i++)
262 {
263 if (values_buf[i])
264 {
265 free(values_buf[i]);
266 values_buf[i] = NULL;
267 }
268 }
269
270 free(values_buf);
271 values_buf = NULL;
272 }
273
274 if (variables)
275 {
276 free(variables);
277 variables = NULL;
278 }
279 }
280 }
281
282 #ifdef __cplusplus
283 }
284 #endif
285
286 #endif
287