Update
[pcsx_rearmed.git] / frontend / 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
52 struct retro_core_option_definition option_defs_us[] = {
53    {
54       "pcsx_rearmed_frameskip",
55       "Frameskip",
56       "Choose how much frames should be skipped to improve performance at the expense of visual smoothness.",
57       {
58          { "0", NULL },
59          { "1", NULL },
60          { "2", NULL },
61          { "3", NULL },
62          { NULL, NULL },
63       },
64       "0",
65    },
66    {
67       "pcsx_rearmed_bios",
68       "Use BIOS",
69       "Allows you to use real bios file (if available) or emulated bios (HLE). Its recommended to use official bios file for better compatibility.",
70       {
71          { "auto", "auto" },
72          { "HLE",  "hle" },
73          { NULL, NULL },
74       },
75       "auto",
76    },
77    {
78       "pcsx_rearmed_region",
79       "Region",
80       "Choose what region the system is from. 60 Hz for NTSC, 50 Hz for PAL.",
81       {
82          { "auto", "auto" },
83          { "NTSC", "ntsc" },
84          { "PAL",  "pal" },
85          { NULL, NULL },
86       },
87       "auto",
88    },
89    {
90       "pcsx_rearmed_memcard2",
91       "Enable Second Memory Card (Shared)",
92       "Enabled the memory card slot 2. This memory card is shared amongst all games.",
93       {
94          { "disabled", NULL },
95          { "enabled",  NULL },
96          { NULL, NULL },
97       },
98       "disabled",
99    },
100    {
101       "pcsx_rearmed_pad1type",
102       "Pad 1 Type",
103       "Pad type for player 1",
104       {
105          { "standard",  NULL },
106          { "analog",    NULL },
107          { "dualshock", NULL },
108          { "negcon",    NULL },
109          { "none",      NULL },
110          { NULL, NULL },
111       },
112       "standard",
113    },
114    {
115       "pcsx_rearmed_pad2type",
116       "Pad 2 Type",
117       "Pad type for player 2",
118       {
119          { "standard",  NULL },
120          { "analog",    NULL },
121          { "dualshock", NULL },
122          { "negcon",    NULL },
123          { "none",      NULL },
124          { NULL, NULL },
125       },
126       "standard",
127    },
128    {
129       "pcsx_rearmed_pad3type",
130       "Pad 3 Type",
131       "Pad type for player 3",
132       {
133          { "standard",  NULL },
134          { "analog",    NULL },
135          { "dualshock", NULL },
136          { "negcon",    NULL },
137          { "none",      NULL },
138          { NULL, NULL },
139       },
140       "none",
141    },
142    {
143       "pcsx_rearmed_pad4type",
144       "Pad 4 Type",
145       "Pad type for player 4",
146       {
147          { "standard",  NULL },
148          { "analog",    NULL },
149          { "dualshock", NULL },
150          { "negcon",    NULL },
151          { "none",      NULL },
152          { NULL, NULL },
153       },
154       "none",
155    },
156    {
157       "pcsx_rearmed_pad5type",
158       "Pad 5 Type",
159       "Pad type for player 5",
160       {
161          { "standard",  NULL },
162          { "analog",    NULL },
163          { "dualshock", NULL },
164          { "negcon",    NULL },
165          { "none",      NULL },
166          { NULL, NULL },
167       },
168       "none",
169    },{
170       "pcsx_rearmed_pad6type",
171       "Pad 6 Type",
172       "Pad type for player 6",
173       {
174          { "standard",  NULL },
175          { "analog",    NULL },
176          { "dualshock", NULL },
177          { "negcon",    NULL },
178          { "none",      NULL },
179          { NULL, NULL },
180       },
181       "none",
182    },{
183       "pcsx_rearmed_pad7type",
184       "Pad 7 Type",
185       "Pad type for player 7",
186       {
187          { "standard",  NULL },
188          { "analog",    NULL },
189          { "dualshock", NULL },
190          { "negcon",    NULL },
191          { "none",      NULL },
192          { NULL, NULL },
193       },
194       "none",
195    },{
196       "pcsx_rearmed_pad8type",
197       "Pad 8 Type",
198       "Pad type for player 8",
199       {
200          { "standard",  NULL },
201          { "analog",    NULL },
202          { "dualshock", NULL },
203          { "negcon",    NULL },
204          { "none",      NULL },
205          { NULL, NULL },
206       },
207       "none",
208    },
209    {
210       "pcsx_rearmed_multitap1",
211       "Multitap 1",
212       "Enables/Disables multitap on port 1, allowing upto 5 players in games that permit it.",
213       {
214          { "auto",     NULL },
215          { "disabled", NULL },
216          { "enabled",  NULL },
217          { NULL, NULL },
218       },
219       "auto",
220    },
221    {
222       "pcsx_rearmed_multitap2",
223       "Multitap 2",
224       "Enables/Disables multitap on port 2, allowing up to 8 players in games that permit it. Multitap 1 has to be enabled for this to work.",
225       {
226          { "auto",     NULL },
227          { "disabled", NULL },
228          { "enabled",  NULL },
229          { NULL, NULL },
230       },
231       "auto",
232    },
233    {
234       "pcsx_rearmed_negcon_deadzone",
235       "NegCon Twist Deadzone (Percent)",
236       "Sets the deadzone of the RetroPad left analog stick when simulating the 'twist' action of emulated neGcon Controllers. Used to eliminate drift/unwanted input.",
237       {
238          { "0",  NULL },
239          { "5",  NULL },
240          { "10", NULL },
241          { "15", NULL },
242          { "20", NULL },
243          { "25", NULL },
244          { "30", NULL },
245          { NULL, NULL },
246       },
247       "0",
248    },
249    {
250       "pcsx_rearmed_negcon_response",
251       "NegCon Twist Response",
252       "Specifies the analog response when using a RetroPad left analog stick to simulate the 'twist' action of emulated neGcon Controllers.",
253       {
254          { "linear",    NULL },
255          { "quadratic", NULL },
256          { "cubic",     NULL },
257          { NULL, NULL },
258       },
259       "linear",
260    },
261    {
262       "pcsx_rearmed_vibration",
263       "Enable Vibration",
264       "Enables vibration feedback for controllers that supports vibration features.",
265       {
266          { "disabled", NULL },
267          { "enabled",  NULL },
268          { NULL, NULL },
269       },
270       "enabled",
271    },
272    {
273       "pcsx_rearmed_dithering",
274       "Enable Dithering",
275       "If Off, disables the dithering pattern the PSX applies to combat color banding.",
276       {
277          { "disabled", NULL },
278          { "enabled",  NULL },
279          { NULL, NULL },
280       },
281 #ifdef HAVE_LIBNX
282           "disabled",
283 #else
284       "enabled",
285 #endif
286    },
287
288 #ifndef DRC_DISABLE
289    {
290       "pcsx_rearmed_drc",
291       "Dynamic Recompiler",
292       "Enables core to use dynamic recompiler or interpreter (slower) CPU instructions.",
293       {
294          { "disabled", NULL },
295          { "enabled",  NULL },
296          { NULL, NULL },
297       },
298       "enabled",
299    },
300    {
301       "pcsx_rearmed_psxclock",
302       "PSX CPU Clock",
303 #ifdef HAVE_PRE_ARMV7
304       "Overclock or underclock the PSX clock. Default is 50",
305 #else
306       "Overclock or underclock the PSX clock. Default is 57",
307 #endif
308       {
309          { "30",  NULL },
310          { "31",  NULL },
311          { "32",  NULL },
312          { "33",  NULL },
313          { "34",  NULL },
314          { "35",  NULL },
315          { "36",  NULL },
316          { "37",  NULL },
317          { "38",  NULL },
318          { "39",  NULL },
319          { "40",  NULL },
320          { "41",  NULL },
321          { "42",  NULL },
322          { "43",  NULL },
323          { "44",  NULL },
324          { "45",  NULL },
325          { "46",  NULL },
326          { "47",  NULL },
327          { "48",  NULL },
328          { "49",  NULL },
329          { "50",  NULL },
330          { "51",  NULL },
331          { "52",  NULL },
332          { "53",  NULL },
333          { "54",  NULL },
334          { "55",  NULL },
335          { "56",  NULL },
336          { "57",  NULL },
337          { "58",  NULL },
338          { "59",  NULL },
339          { "60",  NULL },
340          { "61",  NULL },
341          { "62",  NULL },
342          { "63",  NULL },
343          { "64",  NULL },
344          { "65",  NULL },
345          { "66",  NULL },
346          { "67",  NULL },
347          { "68",  NULL },
348          { "69",  NULL },
349          { "70",  NULL },
350          { "71",  NULL },
351          { "72",  NULL },
352          { "73",  NULL },
353          { "74",  NULL },
354          { "75",  NULL },
355          { "76",  NULL },
356          { "77",  NULL },
357          { "78",  NULL },
358          { "79",  NULL },
359          { "80",  NULL },
360          { "81",  NULL },
361          { "82",  NULL },
362          { "83",  NULL },
363          { "84",  NULL },
364          { "85",  NULL },
365          { "86",  NULL },
366          { "87",  NULL },
367          { "88",  NULL },
368          { "89",  NULL },
369          { "90",  NULL },
370          { "91",  NULL },
371          { "92",  NULL },
372          { "93",  NULL },
373          { "94",  NULL },
374          { "95",  NULL },
375          { "96",  NULL },
376          { "97",  NULL },
377          { "98",  NULL },
378          { "99",  NULL },
379          { "100", NULL },
380          { NULL, NULL },
381       },
382 #ifdef HAVE_PRE_ARMV7
383       "50",
384 #else
385       "57",
386 #endif
387    },
388 #endif /* DRC_DISABLE */
389
390 #ifdef __ARM_NEON__
391    {
392       "pcsx_rearmed_neon_interlace_enable",
393       "Enable Interlacing Mode",
394       "Enables fake scanlines effect.",
395       {
396          { "disabled", NULL },
397          { "enabled",  NULL },
398          { NULL, NULL },
399       },
400       "disabled",
401    },
402    {
403       "pcsx_rearmed_neon_enhancement_enable",
404       "Enhanced Resolution (Slow)",
405       "Renders in double resolution at the cost of lower performance.",
406       {
407          { "disabled", NULL },
408          { "enabled",  NULL },
409          { NULL, NULL },
410       },
411       "disabled",
412    },
413    {
414       "pcsx_rearmed_neon_enhancement_no_main",
415       "Enhanced Resolution (Speed Hack)",
416       "Speed hack for Enhanced resolution option (glitches some games).",
417       {
418          { "disabled", NULL },
419          { "enabled",  NULL },
420          { NULL, NULL },
421       },
422       "disabled",
423    },
424 #endif /* __ARM_NEON__ */
425
426    {
427       "pcsx_rearmed_duping_enable",
428       "Frame Duping",
429       "A speedup, redraws/reuses the last frame if there was no new data.",
430       {
431          { "disabled", NULL },
432          { "enabled",  NULL },
433          { NULL, NULL },
434       },
435       "enabled",
436    },
437    {
438       "pcsx_rearmed_display_internal_fps",
439       "Display Internal FPS",
440       "Shows an on-screen frames per second counter when enabled.",
441       {
442          { "disabled", NULL },
443          { "enabled",  NULL },
444          { NULL, NULL },
445       },
446       "disabled",
447    },
448
449    /* GPU PEOPS OPTIONS */
450 #ifdef GPU_PEOPS
451    {
452       "pcsx_rearmed_show_gpu_peops_settings",
453       "Advanced GPU P.E.Op.S. Settings",
454       "Shows or hides advanced GPU plugin settings. NOTE: Quick Menu must be toggled for this setting to take effect.",
455       {
456          { "disabled", NULL },
457          { "enabled",  NULL },
458          { NULL, NULL },
459       },
460       "disabled",
461    },
462    {
463       "pcsx_rearmed_gpu_peops_odd_even_bit",
464       "(GPU) Odd/Even Bit Hack",
465       "Needed for Chrono Cross.",
466       {
467          { "disabled", NULL },
468          { "enabled",  NULL },
469          { NULL, NULL },
470       },
471       "disabled",
472    },
473    {
474       "pcsx_rearmed_gpu_peops_expand_screen_width",
475       "(GPU) Expand Screen Width",
476       "Capcom fighting games",
477       {
478          { "disabled", NULL },
479          { "enabled",  NULL },
480          { NULL, NULL },
481       },
482       "disabled",
483    },
484    {
485       "pcsx_rearmed_gpu_peops_ignore_brightness",
486       "(GPU) Ignore Brightness Color",
487       "Black screens in Lunar Silver Star Story games",
488       {
489          { "disabled", NULL },
490          { "enabled",  NULL },
491          { NULL, NULL },
492       },
493       "disabled",
494    },
495    {
496       "pcsx_rearmed_gpu_peops_disable_coord_check",
497       "(GPU) Disable Coordinate Check",
498       "Compatibility mode",
499       {
500          { "disabled", NULL },
501          { "enabled",  NULL },
502          { NULL, NULL },
503       },
504       "disabled",
505    },
506    {
507       "pcsx_rearmed_gpu_peops_lazy_screen_update",
508       "(GPU) Lazy Screen Update",
509       "Pandemonium 2",
510       {
511          { "disabled", NULL },
512          { "enabled",  NULL },
513          { NULL, NULL },
514       },
515       "disabled",
516    },
517    {
518       "pcsx_rearmed_gpu_peops_old_frame_skip",
519       "(GPU) Old Frame Skipping",
520       "Skip every second frame",
521       {
522          { "disabled", NULL },
523          { "enabled",  NULL },
524          { NULL, NULL },
525       },
526       "enabled",
527    },
528    {
529       "pcsx_rearmed_gpu_peops_repeated_triangles",
530       "(GPU) Repeated Flat Tex Triangles",
531       "Needed by Star Wars: Dark Forces",
532       {
533          { "disabled", NULL },
534          { "enabled",  NULL },
535          { NULL, NULL },
536       },
537       "disabled",
538    },
539    {
540       "pcsx_rearmed_gpu_peops_quads_with_triangles",
541       "(GPU) Draw Quads with Triangles",
542       "Better g-colors, worse textures",
543       {
544          { "disabled", NULL },
545          { "enabled",  NULL },
546          { NULL, NULL },
547       },
548       "disabled",
549    },
550    {
551       "pcsx_rearmed_gpu_peops_fake_busy_state",
552       "(GPU) Fake 'Gpu Busy' States",
553       "Toggle busy flags after drawing",
554       {
555          { "disabled", NULL },
556          { "enabled",  NULL },
557          { NULL, NULL },
558       },
559       "disabled",
560    },
561 #endif
562
563     /* GPU UNAI Advanced Options */
564 #ifdef GPU_UNAI
565    {
566       "pcsx_rearmed_show_gpu_unai_settings",
567       "Advance GPU UNAI/PCSX4All Settings",
568       "Shows or hides advanced gpu settings. A core restart might be needed for settings to take effect. NOTE: Quick Menu must be toggled for this setting to take effect.",
569       {
570          { "disabled", NULL },
571          { "enabled",  NULL },
572          { NULL, NULL},
573       },
574       "disabled",
575    },
576    {
577       "pcsx_rearmed_gpu_unai_blending",
578       "(GPU) Enable Blending",
579       NULL,
580       {
581          { "disabled", NULL },
582          { "enabled",  NULL },
583          { NULL, NULL},
584       },
585       "enabled",
586    },
587    {
588       "pcsx_rearmed_gpu_unai_lighting",
589       "(GPU) Enable Lighting",
590       NULL,
591       {
592          { "disabled", NULL },
593          { "enabled",  NULL },
594          { NULL, NULL},
595       },
596       "enabled",
597    },
598    {
599       "pcsx_rearmed_gpu_unai_fast_lighting",
600       "(GPU) Enable Fast Lighting",
601       NULL,
602       {
603          { "disabled", NULL },
604          { "enabled",  NULL },
605          { NULL, NULL},
606       },
607       "enabled",
608    },
609    {
610       "pcsx_rearmed_gpu_unai_ilace_force",
611       "(GPU) Enable Forced Interlace",
612       NULL,
613       {
614          { "disabled", NULL },
615          { "enabled",  NULL },
616          { NULL, NULL},
617       },
618       "disabled",
619    },
620    {
621       "pcsx_rearmed_gpu_unai_pixel_skip",
622       "(GPU) Enable Pixel Skip",
623       NULL,
624       {
625          { "disabled", NULL },
626          { "enabled",  NULL },
627          { NULL, NULL},
628       },
629       "disabled",
630    },
631 #endif /* GPU UNAI Advanced Settings */
632
633    {
634       "pcsx_rearmed_show_bios_bootlogo",
635       "Show Bios Bootlogo",
636       "When enabled, shows the PlayStation logo when starting or resetting. (Breaks some games).",
637       {
638          { "disabled", NULL },
639          { "enabled",  NULL },
640          { NULL, NULL },
641       },
642       "disabled",
643    },
644    {
645       "pcsx_rearmed_spu_reverb",
646       "Sound Reverb",
647       "Enables or disables audio reverb effect.",
648       {
649          { "disabled", NULL },
650          { "enabled",  NULL },
651          { NULL, NULL },
652       },
653       "enabled",
654    },
655    {
656       "pcsx_rearmed_spu_interpolation",
657       "Sound Interpolation",
658       NULL,
659       {
660          { "simple",   "Simple" },
661          { "gaussian", "Gaussian" },
662          { "cubic",    "Cubic" },
663          { "off",      "disabled" },
664          { NULL, NULL },
665       },
666       "simple",
667    },
668    {
669       "pcsx_rearmed_idiablofix",
670       "Diablo Music Fix",
671       NULL,
672       {
673          { "disabled", NULL },
674          { "enabled",  NULL },
675          { NULL, NULL },
676       },
677       "disabled",
678    },
679    {
680       "pcsx_rearmed_pe2_fix",
681       "Parasite Eve 2/Vandal Hearts 1/2 Fix",
682       NULL,
683       {
684          { "disabled", NULL },
685          { "enabled",  NULL },
686          { NULL, NULL },
687       },
688       "disabled",
689    },
690    {
691       "pcsx_rearmed_inuyasha_fix",
692       "InuYasha Sengoku Battle Fix",
693       NULL,
694       {
695          { "disabled", NULL },
696          { "enabled",  NULL },
697          { NULL, NULL },
698       },
699       "disabled",
700    },
701
702    /* ADVANCED OPTIONS */
703    {
704       "pcsx_rearmed_noxadecoding",
705       "XA Decoding",
706       NULL,
707       {
708          { "disabled", NULL },
709          { "enabled",  NULL },
710          { NULL, NULL },
711       },
712       "enabled",
713    },
714    {
715       "pcsx_rearmed_nocdaudio",
716       "CD Audio",
717       NULL,
718       {
719          { "disabled", NULL },
720          { "enabled",  NULL },
721          { NULL, NULL },
722       },
723       "enabled",
724    },
725
726 #ifndef DRC_DISABLE
727    {
728       "pcsx_rearmed_nosmccheck",
729       "(Speed Hack) Disable SMC Checks",
730       "Will cause crashes when loading, break memcards.",
731       {
732          { "disabled", NULL },
733          { "enabled",  NULL },
734          { NULL, NULL },
735       },
736       "disabled",
737    },
738    {
739       "pcsx_rearmed_gteregsunneeded",
740       "(Speed Hack) Assume GTE Regs Unneeded",
741       "May cause graphical glitches.",
742       {
743          { "disabled", NULL },
744          { "enabled",  NULL },
745          { NULL, NULL },
746       },
747       "disabled",
748    },
749    {
750       "pcsx_rearmed_nogteflags",
751       "(Speed Hack) Disable GTE Flags",
752       "Will cause graphical glitches.",
753       {
754          { "disabled", NULL },
755          { "enabled",  NULL },
756          { NULL, NULL },
757       },
758       "disabled",
759    },
760 #endif /* DRC_DISABLE */
761
762    { NULL, NULL, NULL, {{0}}, NULL },
763 };
764
765 /*
766  ********************************
767  * Language Mapping
768  ********************************
769 */
770
771 #ifndef HAVE_NO_LANGEXTRA
772 struct retro_core_option_definition *option_defs_intl[RETRO_LANGUAGE_LAST] = {
773    option_defs_us, /* RETRO_LANGUAGE_ENGLISH */
774    NULL,           /* RETRO_LANGUAGE_JAPANESE */
775    NULL,           /* RETRO_LANGUAGE_FRENCH */
776    NULL,           /* RETRO_LANGUAGE_SPANISH */
777    NULL,           /* RETRO_LANGUAGE_GERMAN */
778    NULL,           /* RETRO_LANGUAGE_ITALIAN */
779    NULL,           /* RETRO_LANGUAGE_DUTCH */
780    NULL,           /* RETRO_LANGUAGE_PORTUGUESE_BRAZIL */
781    NULL,           /* RETRO_LANGUAGE_PORTUGUESE_PORTUGAL */
782    NULL,           /* RETRO_LANGUAGE_RUSSIAN */
783    NULL,           /* RETRO_LANGUAGE_KOREAN */
784    NULL,           /* RETRO_LANGUAGE_CHINESE_TRADITIONAL */
785    NULL,           /* RETRO_LANGUAGE_CHINESE_SIMPLIFIED */
786    NULL,           /* RETRO_LANGUAGE_ESPERANTO */
787    NULL,           /* RETRO_LANGUAGE_POLISH */
788    NULL,           /* RETRO_LANGUAGE_VIETNAMESE */
789    NULL,           /* RETRO_LANGUAGE_ARABIC */
790    NULL,           /* RETRO_LANGUAGE_GREEK */
791    option_defs_tr, /* RETRO_LANGUAGE_TURKISH */
792 };
793 #endif
794
795 /*
796  ********************************
797  * Functions
798  ********************************
799 */
800
801 /* Handles configuration/setting of core options.
802  * Should be called as early as possible - ideally inside
803  * retro_set_environment(), and no later than retro_load_game()
804  * > We place the function body in the header to avoid the
805  *   necessity of adding more .c files (i.e. want this to
806  *   be as painless as possible for core devs)
807  */
808
809 static INLINE void libretro_set_core_options(retro_environment_t environ_cb)
810 {
811    unsigned version = 0;
812
813    if (!environ_cb)
814       return;
815
816    if (environ_cb(RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION, &version) && (version >= 1))
817    {
818 #ifndef HAVE_NO_LANGEXTRA
819       struct retro_core_options_intl core_options_intl;
820       unsigned language = 0;
821
822       core_options_intl.us    = option_defs_us;
823       core_options_intl.local = NULL;
824
825       if (environ_cb(RETRO_ENVIRONMENT_GET_LANGUAGE, &language) &&
826           (language < RETRO_LANGUAGE_LAST) && (language != RETRO_LANGUAGE_ENGLISH))
827          core_options_intl.local = option_defs_intl[language];
828
829       environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL, &core_options_intl);
830 #else
831       environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS, &option_defs_us);
832 #endif
833    }
834    else
835    {
836       size_t i;
837       size_t option_index              = 0;
838       size_t num_options               = 0;
839       struct retro_variable *variables = NULL;
840       char **values_buf                = NULL;
841
842       /* Determine number of options
843        * > Note: We are going to skip a number of irrelevant
844        *   core options when building the retro_variable array,
845        *   but we'll allocate space for all of them. The difference
846        *   in resource usage is negligible, and this allows us to
847        *   keep the code 'cleaner' */
848       while (true)
849       {
850          if (option_defs_us[num_options].key)
851             num_options++;
852          else
853             break;
854       }
855
856       /* Allocate arrays */
857       variables  = (struct retro_variable *)calloc(num_options + 1, sizeof(struct retro_variable));
858       values_buf = (char **)calloc(num_options, sizeof(char *));
859
860       if (!variables || !values_buf)
861          goto error;
862
863       /* Copy parameters from option_defs_us array */
864       for (i = 0; i < num_options; i++)
865       {
866          const char *key                        = option_defs_us[i].key;
867          const char *desc                       = option_defs_us[i].desc;
868          const char *default_value              = option_defs_us[i].default_value;
869          struct retro_core_option_value *values = option_defs_us[i].values;
870          size_t buf_len                         = 3;
871          size_t default_index                   = 0;
872
873          values_buf[i] = NULL;
874
875          /* Skip options that are irrelevant when using the
876           * old style core options interface */
877          if ((strcmp(key, "pcsx_rearmed_show_gpu_peops_settings") == 0))
878             continue;
879
880          if (desc)
881          {
882             size_t num_values = 0;
883
884             /* Determine number of values */
885             while (true)
886             {
887                if (values[num_values].value)
888                {
889                   /* Check if this is the default value */
890                   if (default_value)
891                      if (strcmp(values[num_values].value, default_value) == 0)
892                         default_index = num_values;
893
894                   buf_len += strlen(values[num_values].value);
895                   num_values++;
896                }
897                else
898                   break;
899             }
900
901             /* Build values string */
902             if (num_values > 0)
903             {
904                size_t j;
905
906                buf_len += num_values - 1;
907                buf_len += strlen(desc);
908
909                values_buf[i] = (char *)calloc(buf_len, sizeof(char));
910                if (!values_buf[i])
911                   goto error;
912
913                strcpy(values_buf[i], desc);
914                strcat(values_buf[i], "; ");
915
916                /* Default value goes first */
917                strcat(values_buf[i], values[default_index].value);
918
919                /* Add remaining values */
920                for (j = 0; j < num_values; j++)
921                {
922                   if (j != default_index)
923                   {
924                      strcat(values_buf[i], "|");
925                      strcat(values_buf[i], values[j].value);
926                   }
927                }
928             }
929          }
930
931          variables[option_index].key   = key;
932          variables[option_index].value = values_buf[i];
933          option_index++;
934       }
935
936       /* Set variables */
937       environ_cb(RETRO_ENVIRONMENT_SET_VARIABLES, variables);
938
939 error:
940
941       /* Clean up */
942       if (values_buf)
943       {
944          for (i = 0; i < num_options; i++)
945          {
946             if (values_buf[i])
947             {
948                free(values_buf[i]);
949                values_buf[i] = NULL;
950             }
951          }
952
953          free(values_buf);
954          values_buf = NULL;
955       }
956
957       if (variables)
958       {
959          free(variables);
960          variables = NULL;
961       }
962    }
963 }
964
965 #ifdef __cplusplus
966 }
967 #endif
968
969 #endif