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