Commit | Line | Data |
---|---|---|
3719602c PC |
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 | "mycore_region", /* key (option name) */ | |
54 | "Console Region", /* description (label) */ | |
55 | "Specify which region the system is from.", /* sublabel */ | |
56 | { | |
57 | { "auto", "Auto" }, /* value_1, value_1_label */ | |
58 | { "ntsc-j", "Japan" }, /* value_2, value_2_label */ | |
59 | { "ntsc-u", "America" }, /* value_3, value_3_label */ | |
60 | { "pal", "Europe" }, /* value_4, value_4_label */ | |
61 | { NULL, NULL }, | |
62 | }, | |
63 | "auto" /* default_value */ | |
64 | }, | |
65 | { | |
66 | "mycore_video_scale", | |
67 | "Video Scale", | |
68 | "Set internal video scale factor.", | |
69 | { | |
70 | { "1x", NULL }, /* If value itself is human-readable (e.g. a number) */ | |
71 | { "2x", NULL }, /* and can displayed directly, the value_label should */ | |
72 | { "3x", NULL }, /* be set to NULL */ | |
73 | { "4x", NULL }, | |
74 | { NULL, NULL }, | |
75 | }, | |
76 | "3x" | |
77 | }, | |
78 | /* This 'mycore_show_speedhacks' option will only be shown | |
79 | * if the frontend supports core options API v1. | |
80 | * It will be hidden on older frontends. | |
81 | * See line 227 */ | |
82 | { | |
83 | "mycore_show_speedhacks", | |
84 | "Show Unsafe Settings", | |
85 | "Enable configuration of emulation speed hacks.", | |
86 | { | |
87 | { "enabled", NULL }, | |
88 | { "disabled", NULL }, | |
89 | { NULL, NULL}, | |
90 | }, | |
91 | "disabled" | |
92 | }, | |
93 | { | |
94 | "mycore_overclock", | |
95 | "Reduce Slowdown", | |
96 | "Enable CPU overclock (unsafe).", | |
97 | { | |
98 | { "enabled", NULL }, /* If value is equal to 'enabled' or 'disabled', */ | |
99 | { "disabled", NULL }, /* value_label should be set to NULL */ | |
100 | { NULL, NULL }, | |
101 | }, | |
102 | "disabled" | |
103 | }, | |
104 | { NULL, NULL, NULL, {{0}}, NULL }, | |
105 | }; | |
106 | ||
107 | /* | |
108 | ******************************** | |
109 | * Language Mapping | |
110 | ******************************** | |
111 | */ | |
112 | ||
113 | #ifndef HAVE_NO_LANGEXTRA | |
114 | struct retro_core_option_definition *option_defs_intl[RETRO_LANGUAGE_LAST] = { | |
115 | option_defs_us, /* RETRO_LANGUAGE_ENGLISH */ | |
116 | NULL, /* RETRO_LANGUAGE_JAPANESE */ | |
117 | NULL, /* RETRO_LANGUAGE_FRENCH */ | |
118 | NULL, /* RETRO_LANGUAGE_SPANISH */ | |
119 | NULL, /* RETRO_LANGUAGE_GERMAN */ | |
120 | NULL, /* RETRO_LANGUAGE_ITALIAN */ | |
121 | NULL, /* RETRO_LANGUAGE_DUTCH */ | |
122 | NULL, /* RETRO_LANGUAGE_PORTUGUESE_BRAZIL */ | |
123 | NULL, /* RETRO_LANGUAGE_PORTUGUESE_PORTUGAL */ | |
124 | NULL, /* RETRO_LANGUAGE_RUSSIAN */ | |
125 | NULL, /* RETRO_LANGUAGE_KOREAN */ | |
126 | NULL, /* RETRO_LANGUAGE_CHINESE_TRADITIONAL */ | |
127 | NULL, /* RETRO_LANGUAGE_CHINESE_SIMPLIFIED */ | |
128 | NULL, /* RETRO_LANGUAGE_ESPERANTO */ | |
129 | NULL, /* RETRO_LANGUAGE_POLISH */ | |
130 | NULL, /* RETRO_LANGUAGE_VIETNAMESE */ | |
131 | NULL, /* RETRO_LANGUAGE_ARABIC */ | |
132 | NULL, /* RETRO_LANGUAGE_GREEK */ | |
133 | NULL, /* RETRO_LANGUAGE_TURKISH */ | |
134 | NULL, /* RETRO_LANGUAGE_SLOVAK */ | |
135 | NULL, /* RETRO_LANGUAGE_PERSIAN */ | |
136 | NULL, /* RETRO_LANGUAGE_HEBREW */ | |
137 | NULL, /* RETRO_LANGUAGE_ASTURIAN */ | |
138 | NULL, /* RETRO_LANGUAGE_FINNISH */ | |
139 | NULL, /* RETRO_LANGUAGE_INDONESIAN */ | |
140 | NULL, /* RETRO_LANGUAGE_SWEDISH */ | |
141 | NULL, /* RETRO_LANGUAGE_UKRAINIAN */ | |
142 | NULL, /* RETRO_LANGUAGE_CZECH */ | |
143 | }; | |
144 | #endif | |
145 | ||
146 | /* | |
147 | ******************************** | |
148 | * Functions | |
149 | ******************************** | |
150 | */ | |
151 | ||
152 | /* Handles configuration/setting of core options. | |
153 | * Should be called as early as possible - ideally inside | |
154 | * retro_set_environment(), and no later than retro_load_game() | |
155 | * > We place the function body in the header to avoid the | |
156 | * necessity of adding more .c files (i.e. want this to | |
157 | * be as painless as possible for core devs) | |
158 | */ | |
159 | ||
160 | static INLINE void libretro_set_core_options(retro_environment_t environ_cb) | |
161 | { | |
162 | unsigned version = 0; | |
163 | ||
164 | if (!environ_cb) | |
165 | return; | |
166 | ||
167 | if (environ_cb(RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION, &version) && (version >= 1)) | |
168 | { | |
169 | #ifndef HAVE_NO_LANGEXTRA | |
170 | struct retro_core_options_intl core_options_intl; | |
171 | unsigned language = 0; | |
172 | ||
173 | core_options_intl.us = option_defs_us; | |
174 | core_options_intl.local = NULL; | |
175 | ||
176 | if (environ_cb(RETRO_ENVIRONMENT_GET_LANGUAGE, &language) && | |
177 | (language < RETRO_LANGUAGE_LAST) && (language != RETRO_LANGUAGE_ENGLISH)) | |
178 | core_options_intl.local = option_defs_intl[language]; | |
179 | ||
180 | environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL, &core_options_intl); | |
181 | #else | |
182 | environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS, &option_defs_us); | |
183 | #endif | |
184 | } | |
185 | else | |
186 | { | |
187 | size_t i; | |
188 | size_t option_index = 0; | |
189 | size_t num_options = 0; | |
190 | struct retro_variable *variables = NULL; | |
191 | char **values_buf = NULL; | |
192 | ||
193 | /* Determine number of options | |
194 | * > Note: We are going to skip a number of irrelevant | |
195 | * core options when building the retro_variable array, | |
196 | * but we'll allocate space for all of them. The difference | |
197 | * in resource usage is negligible, and this allows us to | |
198 | * keep the code 'cleaner' */ | |
199 | for (;;) | |
200 | { | |
201 | if (!option_defs_us[num_options].key) | |
202 | break; | |
203 | num_options++; | |
204 | } | |
205 | ||
206 | /* Allocate arrays */ | |
207 | variables = (struct retro_variable *)calloc(num_options + 1, sizeof(struct retro_variable)); | |
208 | values_buf = (char **)calloc(num_options, sizeof(char *)); | |
209 | ||
210 | if (!variables || !values_buf) | |
211 | goto error; | |
212 | ||
213 | /* Copy parameters from option_defs_us array */ | |
214 | for (i = 0; i < num_options; i++) | |
215 | { | |
216 | const char *key = option_defs_us[i].key; | |
217 | const char *desc = option_defs_us[i].desc; | |
218 | const char *default_value = option_defs_us[i].default_value; | |
219 | struct retro_core_option_value *values = option_defs_us[i].values; | |
220 | size_t buf_len = 3; | |
221 | size_t default_index = 0; | |
222 | ||
223 | values_buf[i] = NULL; | |
224 | ||
225 | /* Skip options that are irrelevant when using the | |
226 | * old style core options interface */ | |
227 | if (strcmp(key, "mycore_show_speedhacks") == 0) | |
228 | continue; | |
229 | ||
230 | if (desc) | |
231 | { | |
232 | size_t num_values = 0; | |
233 | ||
234 | /* Determine number of values */ | |
235 | for (;;) | |
236 | { | |
237 | if (!values[num_values].value) | |
238 | break; | |
239 | ||
240 | /* Check if this is the default value */ | |
241 | if (default_value) | |
242 | if (strcmp(values[num_values].value, default_value) == 0) | |
243 | default_index = num_values; | |
244 | ||
245 | buf_len += strlen(values[num_values].value); | |
246 | num_values++; | |
247 | } | |
248 | ||
249 | /* Build values string */ | |
250 | if (num_values > 0) | |
251 | { | |
252 | size_t j; | |
253 | ||
254 | buf_len += num_values - 1; | |
255 | buf_len += strlen(desc); | |
256 | ||
257 | values_buf[i] = (char *)calloc(buf_len, sizeof(char)); | |
258 | if (!values_buf[i]) | |
259 | goto error; | |
260 | ||
261 | strcpy(values_buf[i], desc); | |
262 | strcat(values_buf[i], "; "); | |
263 | ||
264 | /* Default value goes first */ | |
265 | strcat(values_buf[i], values[default_index].value); | |
266 | ||
267 | /* Add remaining values */ | |
268 | for (j = 0; j < num_values; j++) | |
269 | { | |
270 | if (j != default_index) | |
271 | { | |
272 | strcat(values_buf[i], "|"); | |
273 | strcat(values_buf[i], values[j].value); | |
274 | } | |
275 | } | |
276 | } | |
277 | } | |
278 | ||
279 | variables[option_index].key = key; | |
280 | variables[option_index].value = values_buf[i]; | |
281 | option_index++; | |
282 | } | |
283 | ||
284 | /* Set variables */ | |
285 | environ_cb(RETRO_ENVIRONMENT_SET_VARIABLES, variables); | |
286 | ||
287 | error: | |
288 | ||
289 | /* Clean up */ | |
290 | if (values_buf) | |
291 | { | |
292 | for (i = 0; i < num_options; i++) | |
293 | { | |
294 | if (values_buf[i]) | |
295 | { | |
296 | free(values_buf[i]); | |
297 | values_buf[i] = NULL; | |
298 | } | |
299 | } | |
300 | ||
301 | free(values_buf); | |
302 | values_buf = NULL; | |
303 | } | |
304 | ||
305 | if (variables) | |
306 | { | |
307 | free(variables); | |
308 | variables = NULL; | |
309 | } | |
310 | } | |
311 | } | |
312 | ||
313 | #ifdef __cplusplus | |
314 | } | |
315 | #endif | |
316 | ||
317 | #endif |