drc: handle upto 64k page size
[pcsx_rearmed.git] / deps / libretro-common / samples / core_options / example_hide_option / libretro_core_options.h
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