919cac88 |
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 | #ifdef __cplusplus |
11 | extern "C" { |
12 | #endif |
13 | |
14 | /* |
15 | ******************************** |
16 | * Core Option Definitions |
17 | ******************************** |
18 | */ |
19 | |
20 | /* RETRO_LANGUAGE_ENGLISH */ |
21 | |
22 | /* Default language: |
23 | * - All other languages must include the same keys and values |
24 | * - Will be used as a fallback in the event that frontend language |
25 | * is not available |
26 | * - Will be used as a fallback for any missing entries in |
27 | * frontend language definition |
28 | */ |
29 | |
30 | #ifdef HAVE_PRE_ARMV7 |
31 | #define PSX_CLOCK_DEFAULT "50" |
32 | #define PSX_CLOCK_LABEL "Overclock or underclock the PSX clock. Default is 50" |
33 | #else |
34 | #define PSX_CLOCK_DEFAULT "57" |
35 | #define PSX_CLOCK_LABEL "Overclock or underclock the PSX clock. Default is 57" |
36 | #endif |
37 | |
38 | struct retro_core_option_definition option_defs_us[] = { |
39 | { |
40 | "pcsx_rearmed_frameskip", |
41 | "Frameskip", |
42 | "Choose how much frames should be skipped to improve performance at the expense of visual smoothness.", |
43 | { |
44 | { "0", NULL }, |
45 | { "1", NULL }, |
46 | { "2", NULL }, |
47 | { "3", NULL }, |
48 | { NULL, NULL}, |
49 | }, |
50 | "0", |
51 | }, |
52 | { |
53 | "pcsx_rearmed_bios", |
54 | "Use BIOS", |
55 | "Allows you to use real bios file (if available) or emulated bios (HLE). Its recommended to use official bios file for better compatibility.", |
56 | { |
57 | { "auto", "auto" }, |
58 | { "HLE", "hle" }, |
59 | { NULL, NULL}, |
60 | }, |
61 | "auto", |
62 | }, |
63 | { |
64 | "pcsx_rearmed_region", |
65 | "Region", |
66 | "Choose what region the system is from. 60 Hz for NTSC, 50 Hz for PAL.", |
67 | { |
68 | { "auto", "auto" }, |
69 | { "NTSC", "ntsc" }, |
70 | { "PAL", "pal" }, |
71 | { NULL, NULL}, |
72 | }, |
73 | "auto", |
74 | }, |
75 | { |
76 | "pcsx_rearmed_memcard2", |
77 | "Enable second memory card (shared)", |
78 | "Enabled the memory card slot 2. This is shared amongs all games.", |
79 | { |
80 | { "disable", NULL }, |
81 | { "enabled", NULL }, |
82 | { NULL, NULL}, |
83 | }, |
84 | "disable", |
85 | }, |
86 | { |
87 | "pcsx_rearmed_pad1type", |
88 | "Pad 1 Type", |
89 | "Pad type for player 1", |
90 | { |
91 | { "standard", NULL }, |
92 | { "analog", NULL }, |
93 | { "dualshock", NULL }, |
94 | { "negcon", NULL }, |
95 | { "none", NULL }, |
96 | { NULL, NULL}, |
97 | }, |
98 | "standard", |
99 | }, |
100 | { |
101 | "pcsx_rearmed_pad2type", |
102 | "Pad 2 Type", |
103 | "Pad type for player 2", |
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_pad3type", |
116 | "Pad 3 Type", |
117 | "Pad type for player 3", |
118 | { |
119 | { "standard", NULL }, |
120 | { "analog", NULL }, |
121 | { "dualshock", NULL }, |
122 | { "negcon", NULL }, |
123 | { "none", NULL }, |
124 | { NULL, NULL}, |
125 | }, |
126 | "none", |
127 | }, |
128 | { |
129 | "pcsx_rearmed_pad4type", |
130 | "Pad 4 Type", |
131 | "Pad type for player 4", |
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_pad5type", |
144 | "Pad 5 Type", |
145 | "Pad type for player 5", |
146 | { |
147 | { "standard", NULL }, |
148 | { "analog", NULL }, |
149 | { "dualshock", NULL }, |
150 | { "negcon", NULL }, |
151 | { "none", NULL }, |
152 | { NULL, NULL}, |
153 | }, |
154 | "none", |
155 | },{ |
156 | "pcsx_rearmed_pad6type", |
157 | "Pad 6 Type", |
158 | "Pad type for player 6", |
159 | { |
160 | { "standard", NULL }, |
161 | { "analog", NULL }, |
162 | { "dualshock", NULL }, |
163 | { "negcon", NULL }, |
164 | { "none", NULL }, |
165 | { NULL, NULL}, |
166 | }, |
167 | "none", |
168 | },{ |
169 | "pcsx_rearmed_pad7type", |
170 | "Pad 7 Type", |
171 | "Pad type for player 7", |
172 | { |
173 | { "standard", NULL }, |
174 | { "analog", NULL }, |
175 | { "dualshock", NULL }, |
176 | { "negcon", NULL }, |
177 | { "none", NULL }, |
178 | { NULL, NULL}, |
179 | }, |
180 | "none", |
181 | },{ |
182 | "pcsx_rearmed_pad8type", |
183 | "Pad 8 Type", |
184 | "Pad type for player 8", |
185 | { |
186 | { "standard", NULL }, |
187 | { "analog", NULL }, |
188 | { "dualshock", NULL }, |
189 | { "negcon", NULL }, |
190 | { "none", NULL }, |
191 | { NULL, NULL}, |
192 | }, |
193 | "none", |
194 | }, |
195 | { |
196 | "pcsx_rearmed_multitap1", |
197 | "Multitap 1", |
198 | "Enables/Disables multitap on port 1, allowing upto 5 players in games that permit it.", |
199 | { |
200 | { "auto", NULL }, |
201 | { "disabled", NULL }, |
202 | { "enabled", NULL }, |
203 | { NULL, NULL}, |
204 | }, |
205 | "auto", |
206 | }, |
207 | { |
208 | "pcsx_rearmed_multitap2", |
209 | "Multitap 2", |
210 | "Enables/Disables multitap on port 2, allowing upto 8 players in games that permit it. Multitap 1 has to be enabled for this to work.", |
211 | { |
212 | { "auto", NULL }, |
213 | { "disabled", NULL }, |
214 | { "enabled", NULL }, |
215 | { NULL, NULL}, |
216 | }, |
217 | "auto", |
218 | }, |
219 | { |
220 | "pcsx_rearmed_negcon_deadzone", |
221 | "NegCon Twist Deadzone (percent)", |
222 | "Sets the deadzone of the RetroPad left analog stick when simulating the 'twist' action of emulated neGcon Controllers. Used to eliminate drift/unwanted input.", |
223 | { |
224 | { "0", NULL }, |
225 | { "5", NULL }, |
226 | { "10", NULL }, |
227 | { "15", NULL }, |
228 | { "20", NULL }, |
229 | { "25", NULL }, |
230 | { "30", NULL }, |
231 | { NULL, NULL}, |
232 | }, |
233 | "0", |
234 | }, |
235 | { |
236 | "pcsx_rearmed_negcon_response", |
237 | "NegCon Twist Response", |
238 | "Specifies the analog response when using a RetroPad left analog stick to simulate the 'twist' action of emulated neGcon Controllers.", |
239 | { |
240 | { "linear", NULL }, |
241 | { "quadratic", NULL }, |
242 | { "cubic", NULL }, |
243 | { NULL, NULL}, |
244 | }, |
245 | "linear", |
246 | }, |
247 | { |
248 | "pcsx_rearmed_vibration", |
249 | "Enable Vibration", |
250 | "Enables Vibration feedback for controllers that supports vibration features.", |
251 | { |
252 | { "disabled", NULL }, |
253 | { "enabled", NULL }, |
254 | { NULL, NULL}, |
255 | }, |
256 | "enabled", |
257 | }, |
258 | { |
259 | "pcsx_rearmed_dithering", |
260 | "Enable Dithering", |
261 | "If Off, disables the dithering pattern the PSX applies to combat color banding.", |
262 | { |
263 | { "disabled", NULL }, |
264 | { "enabled", NULL }, |
265 | { NULL, NULL}, |
266 | }, |
267 | "enabled", |
268 | }, |
269 | |
270 | #ifndef DRC_DISABLE |
271 | { |
272 | "pcsx_rearmed_drc", |
273 | "Dynamic recompiler", |
274 | "Enables core to use dynamic recompiler or interpreter (slower) cpu instructions.", |
275 | { |
276 | { "disabled", NULL }, |
277 | { "enabled", NULL }, |
278 | { NULL, NULL}, |
279 | }, |
280 | "enabled", |
281 | }, |
282 | { |
283 | "pcsx_rearmed_psxclock", |
284 | "PSX CPU clock", |
285 | PSX_CLOCK_LABEL, |
286 | { |
287 | { "30", NULL }, |
288 | { "31", NULL }, |
289 | { "32", NULL }, |
290 | { "33", NULL }, |
291 | { "34", NULL }, |
292 | { "35", NULL }, |
293 | { "36", NULL }, |
294 | { "37", NULL }, |
295 | { "38", NULL }, |
296 | { "39", NULL }, |
297 | { "40", NULL }, |
298 | { "41", NULL }, |
299 | { "42", NULL }, |
300 | { "43", NULL }, |
301 | { "44", NULL }, |
302 | { "45", NULL }, |
303 | { "46", NULL }, |
304 | { "47", NULL }, |
305 | { "48", NULL }, |
306 | { "49", NULL }, |
307 | { "50", NULL }, |
308 | { "51", NULL }, |
309 | { "52", NULL }, |
310 | { "53", NULL }, |
311 | { "54", NULL }, |
312 | { "55", NULL }, |
313 | { "56", NULL }, |
314 | { "57", NULL }, |
315 | { "58", NULL }, |
316 | { "59", NULL }, |
317 | { "60", NULL }, |
318 | { "61", NULL }, |
319 | { "62", NULL }, |
320 | { "63", NULL }, |
321 | { "64", NULL }, |
322 | { "65", NULL }, |
323 | { "66", NULL }, |
324 | { "67", NULL }, |
325 | { "68", NULL }, |
326 | { "69", NULL }, |
327 | { "70", NULL }, |
328 | { "71", NULL }, |
329 | { "72", NULL }, |
330 | { "73", NULL }, |
331 | { "74", NULL }, |
332 | { "75", NULL }, |
333 | { "76", NULL }, |
334 | { "77", NULL }, |
335 | { "78", NULL }, |
336 | { "79", NULL }, |
337 | { "80", NULL }, |
338 | { "81", NULL }, |
339 | { "82", NULL }, |
340 | { "83", NULL }, |
341 | { "84", NULL }, |
342 | { "85", NULL }, |
343 | { "86", NULL }, |
344 | { "87", NULL }, |
345 | { "88", NULL }, |
346 | { "89", NULL }, |
347 | { "90", NULL }, |
348 | { "91", NULL }, |
349 | { "92", NULL }, |
350 | { "93", NULL }, |
351 | { "94", NULL }, |
352 | { "95", NULL }, |
353 | { "96", NULL }, |
354 | { "97", NULL }, |
355 | { "98", NULL }, |
356 | { "99", NULL }, |
357 | { "100", NULL }, |
358 | { NULL, NULL}, |
359 | }, |
360 | PSX_CLOCK_DEFAULT, |
361 | }, |
362 | #endif /* DRC_DISABLE */ |
363 | |
364 | #ifdef __ARM_NEON__ |
365 | { |
366 | "pcsx_rearmed_neon_interlace_enable", |
367 | "Enable interlacing mode(s)", |
368 | "Enables fake scanlines effect.", |
369 | { |
370 | { "disabled", NULL }, |
371 | { "enabled", NULL }, |
372 | { NULL, NULL}, |
373 | }, |
374 | "disabled", |
375 | }, |
376 | { |
377 | "pcsx_rearmed_neon_enhancement_enable", |
378 | "Enhanced resolution (slow)", |
379 | "Renders in double resolution at the cost of lower performance", |
380 | { |
381 | { "disabled", NULL }, |
382 | { "enabled", NULL }, |
383 | { NULL, NULL}, |
384 | }, |
385 | "disabled", |
386 | }, |
387 | { |
388 | "pcsx_rearmed_neon_enhancement_no_main", |
389 | "Enhanced resolution speed hack", |
390 | "Speed hack for Enhanced resolution option (glitches some games).", |
391 | { |
392 | { "disabled", NULL }, |
393 | { "enabled", NULL }, |
394 | { NULL, NULL}, |
395 | }, |
396 | "disabled", |
397 | }, |
398 | #endif /* __ARM_NEON__ */ |
399 | |
400 | { |
401 | "pcsx_rearmed_duping_enable", |
402 | "Frame duping", |
403 | "A speedup, redraws/reuses the last frame if there was no new data.", |
404 | { |
405 | { "disabled", NULL }, |
406 | { "enabled", NULL }, |
407 | { NULL, NULL}, |
408 | }, |
409 | "enabled", |
410 | }, |
411 | { |
412 | "pcsx_rearmed_display_internal_fps", |
413 | "Display Internal FPS", |
414 | "Shows an on-screen frames per second counter when enabled.", |
415 | { |
416 | { "disabled", NULL }, |
417 | { "enabled", NULL }, |
418 | { NULL, NULL}, |
419 | }, |
420 | "disabled", |
421 | }, |
422 | { |
423 | "pcsx_rearmed_show_bios_bootlogo", |
424 | "Show Bios Bootlogo", |
425 | "When enabled, shows the playstation logo when starting or resetting. (Breaks some games).", |
426 | { |
427 | { "disabled", NULL }, |
428 | { "enabled", NULL }, |
429 | { NULL, NULL}, |
430 | }, |
431 | "disabled", |
432 | }, |
433 | { |
434 | "pcsx_rearmed_spu_reverb", |
435 | "Sound Reverb", |
436 | "Enables or disables audio reverb effect.", |
437 | { |
438 | { "disabled", NULL }, |
439 | { "enabled", NULL }, |
440 | { NULL, NULL}, |
441 | }, |
442 | "enabled", |
443 | }, |
444 | { |
445 | "pcsx_rearmed_spu_interpolation", |
446 | "Sound: Interpolation", |
447 | NULL, |
448 | { |
449 | { "simple", NULL }, |
450 | { "gaussian", NULL }, |
451 | { "cubic", NULL }, |
452 | { "off", NULL }, |
453 | { NULL, NULL}, |
454 | }, |
455 | "simple", |
456 | }, |
457 | { |
458 | "pcsx_rearmed_idiablofix", |
459 | "Diablo Music Fix", |
460 | NULL, |
461 | { |
462 | { "disabled", NULL }, |
463 | { "enabled", NULL }, |
464 | { NULL, NULL}, |
465 | }, |
466 | "disabled", |
467 | }, |
468 | { |
469 | "pcsx_rearmed_pe2_fix", |
470 | "Parasite Eve 2/Vandal Hearts 1/2 Fix", |
471 | NULL, |
472 | { |
473 | { "disabled", NULL }, |
474 | { "enabled", NULL }, |
475 | { NULL, NULL}, |
476 | }, |
477 | "disabled", |
478 | }, |
479 | { |
480 | "pcsx_rearmed_inuyasha_fix", |
481 | "InuYasha Sengoku Battle Fix", |
482 | NULL, |
483 | { |
484 | { "disabled", NULL }, |
485 | { "enabled", NULL }, |
486 | { NULL, NULL}, |
487 | }, |
488 | "disabled", |
489 | }, |
490 | |
491 | /* ADVANCED OPTIONS */ |
492 | { |
493 | "pcsx_rearmed_noxadecoding", |
494 | "XA Decoding", |
495 | NULL, |
496 | { |
497 | { "disabled", NULL }, |
498 | { "enabled", NULL }, |
499 | { NULL, NULL}, |
500 | }, |
501 | "enabled", |
502 | }, |
503 | { |
504 | "pcsx_rearmed_nocdaudio", |
505 | "CD Audio", |
506 | NULL, |
507 | { |
508 | { "disabled", NULL }, |
509 | { "enabled", NULL }, |
510 | { NULL, NULL}, |
511 | }, |
512 | "enabled", |
513 | }, |
514 | |
515 | #ifndef DRC_DISABLE |
516 | { |
517 | "pcsx_rearmed_nosmccheck", |
518 | "(Speed Hack) Disable SMC Checks", |
519 | "Will cause crashes when loading, break memcards.", |
520 | { |
521 | { "disabled", NULL }, |
522 | { "enabled", NULL }, |
523 | { NULL, NULL}, |
524 | }, |
525 | "disabled", |
526 | }, |
527 | { |
528 | "pcsx_rearmed_gteregsunneeded", |
529 | "(Speed Hack) Assume GTE Regs Unneeded", |
530 | "May cause graphical glitches.", |
531 | { |
532 | { "disabled", NULL }, |
533 | { "enabled", NULL }, |
534 | { NULL, NULL}, |
535 | }, |
536 | "disabled", |
537 | }, |
538 | { |
539 | "pcsx_rearmed_nogteflags", |
540 | "(Speed Hack) Disable GTE Flags", |
541 | "Will cause graphical glitches.", |
542 | { |
543 | { "disabled", NULL }, |
544 | { "enabled", NULL }, |
545 | { NULL, NULL}, |
546 | }, |
547 | "disabled", |
548 | }, |
549 | #endif /* DRC_DISABLE */ |
550 | |
551 | { NULL, NULL, NULL, { NULL, NULL }, NULL }, |
552 | }; |
553 | |
554 | /* RETRO_LANGUAGE_JAPANESE */ |
555 | |
556 | /* RETRO_LANGUAGE_FRENCH */ |
557 | |
558 | /* RETRO_LANGUAGE_SPANISH */ |
559 | |
560 | /* RETRO_LANGUAGE_GERMAN */ |
561 | |
562 | /* RETRO_LANGUAGE_ITALIAN */ |
563 | |
564 | /* RETRO_LANGUAGE_DUTCH */ |
565 | |
566 | /* RETRO_LANGUAGE_PORTUGUESE_BRAZIL */ |
567 | |
568 | /* RETRO_LANGUAGE_PORTUGUESE_PORTUGAL */ |
569 | |
570 | /* RETRO_LANGUAGE_RUSSIAN */ |
571 | |
572 | /* RETRO_LANGUAGE_KOREAN */ |
573 | |
574 | /* RETRO_LANGUAGE_CHINESE_TRADITIONAL */ |
575 | |
576 | /* RETRO_LANGUAGE_CHINESE_SIMPLIFIED */ |
577 | |
578 | /* RETRO_LANGUAGE_ESPERANTO */ |
579 | |
580 | /* RETRO_LANGUAGE_POLISH */ |
581 | |
582 | /* RETRO_LANGUAGE_VIETNAMESE */ |
583 | |
584 | /* RETRO_LANGUAGE_ARABIC */ |
585 | |
586 | /* RETRO_LANGUAGE_GREEK */ |
587 | |
588 | /* RETRO_LANGUAGE_TURKISH */ |
589 | |
590 | /* |
591 | ******************************** |
592 | * Language Mapping |
593 | ******************************** |
594 | */ |
595 | |
596 | struct retro_core_option_definition *option_defs_intl[RETRO_LANGUAGE_LAST] = { |
597 | option_defs_us, /* RETRO_LANGUAGE_ENGLISH */ |
598 | NULL, /* RETRO_LANGUAGE_JAPANESE */ |
599 | NULL, /* RETRO_LANGUAGE_FRENCH */ |
600 | NULL, /* RETRO_LANGUAGE_SPANISH */ |
601 | NULL, /* RETRO_LANGUAGE_GERMAN */ |
602 | NULL, /* RETRO_LANGUAGE_ITALIAN */ |
603 | NULL, /* RETRO_LANGUAGE_DUTCH */ |
604 | NULL, /* RETRO_LANGUAGE_PORTUGUESE_BRAZIL */ |
605 | NULL, /* RETRO_LANGUAGE_PORTUGUESE_PORTUGAL */ |
606 | NULL, /* RETRO_LANGUAGE_RUSSIAN */ |
607 | NULL, /* RETRO_LANGUAGE_KOREAN */ |
608 | NULL, /* RETRO_LANGUAGE_CHINESE_TRADITIONAL */ |
609 | NULL, /* RETRO_LANGUAGE_CHINESE_SIMPLIFIED */ |
610 | NULL, /* RETRO_LANGUAGE_ESPERANTO */ |
611 | NULL, /* RETRO_LANGUAGE_POLISH */ |
612 | NULL, /* RETRO_LANGUAGE_VIETNAMESE */ |
613 | NULL, /* RETRO_LANGUAGE_ARABIC */ |
614 | NULL, /* RETRO_LANGUAGE_GREEK */ |
615 | NULL, /* RETRO_LANGUAGE_TURKISH */ |
616 | }; |
617 | |
618 | /* |
619 | ******************************** |
620 | * Functions |
621 | ******************************** |
622 | */ |
623 | |
624 | /* Handles configuration/setting of core options. |
625 | * Should only be called inside retro_set_environment(). |
626 | * > We place the function body in the header to avoid the |
627 | * necessity of adding more .c files (i.e. want this to |
628 | * be as painless as possible for core devs) |
629 | */ |
630 | |
631 | static INLINE void libretro_set_core_options(retro_environment_t environ_cb) |
632 | { |
633 | unsigned version = 0; |
634 | |
635 | if (!environ_cb) |
636 | return; |
637 | |
638 | if (environ_cb(RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION, &version) && (version == 1)) |
639 | { |
640 | struct retro_core_options_intl core_options_intl; |
641 | unsigned language = 0; |
642 | |
643 | core_options_intl.us = option_defs_us; |
644 | core_options_intl.local = NULL; |
645 | |
646 | if (environ_cb(RETRO_ENVIRONMENT_GET_LANGUAGE, &language) && |
647 | (language < RETRO_LANGUAGE_LAST) && (language != RETRO_LANGUAGE_ENGLISH)) |
648 | core_options_intl.local = option_defs_intl[language]; |
649 | |
650 | environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL, &core_options_intl); |
651 | } |
652 | else |
653 | { |
654 | size_t i; |
655 | size_t option_index = 0; |
656 | size_t num_options = 0; |
657 | struct retro_variable *variables = NULL; |
658 | char **values_buf = NULL; |
659 | |
660 | /* Determine number of options |
661 | * > Note: We are going to skip a number of irrelevant |
662 | * core options when building the retro_variable array, |
663 | * but we'll allocate space for all of them. The difference |
664 | * in resource usage is negligible, and this allows us to |
665 | * keep the code 'cleaner' */ |
666 | while (true) |
667 | { |
668 | if (option_defs_us[num_options].key) |
669 | num_options++; |
670 | else |
671 | break; |
672 | } |
673 | |
674 | /* Allocate arrays */ |
675 | variables = (struct retro_variable *)calloc(num_options + 1, sizeof(struct retro_variable)); |
676 | values_buf = (char **)calloc(num_options, sizeof(char *)); |
677 | |
678 | if (!variables || !values_buf) |
679 | goto error; |
680 | |
681 | /* Copy parameters from option_defs_us array */ |
682 | for (i = 0; i < num_options; i++) |
683 | { |
684 | const char *key = option_defs_us[i].key; |
685 | const char *desc = option_defs_us[i].desc; |
686 | const char *default_value = option_defs_us[i].default_value; |
687 | struct retro_core_option_value *values = option_defs_us[i].values; |
688 | size_t buf_len = 3; |
689 | size_t default_index = 0; |
690 | |
691 | values_buf[i] = NULL; |
692 | |
693 | /* Skip options that are irrelevant when using the |
694 | * old style core options interface */ |
695 | if ((strcmp(key, "fceumm_advance_sound_options") == 0)) |
696 | continue; |
697 | |
698 | if (desc) |
699 | { |
700 | size_t num_values = 0; |
701 | |
702 | /* Determine number of values */ |
703 | while (true) |
704 | { |
705 | if (values[num_values].value) |
706 | { |
707 | /* Check if this is the default value */ |
708 | if (default_value) |
709 | if (strcmp(values[num_values].value, default_value) == 0) |
710 | default_index = num_values; |
711 | |
712 | buf_len += strlen(values[num_values].value); |
713 | num_values++; |
714 | } |
715 | else |
716 | break; |
717 | } |
718 | |
719 | /* Build values string */ |
720 | if (num_values > 1) |
721 | { |
722 | size_t j; |
723 | |
724 | buf_len += num_values - 1; |
725 | buf_len += strlen(desc); |
726 | |
727 | values_buf[i] = (char *)calloc(buf_len, sizeof(char)); |
728 | if (!values_buf[i]) |
729 | goto error; |
730 | |
731 | strcpy(values_buf[i], desc); |
732 | strcat(values_buf[i], "; "); |
733 | |
734 | /* Default value goes first */ |
735 | strcat(values_buf[i], values[default_index].value); |
736 | |
737 | /* Add remaining values */ |
738 | for (j = 0; j < num_values; j++) |
739 | { |
740 | if (j != default_index) |
741 | { |
742 | strcat(values_buf[i], "|"); |
743 | strcat(values_buf[i], values[j].value); |
744 | } |
745 | } |
746 | } |
747 | } |
748 | |
749 | variables[option_index].key = key; |
750 | variables[option_index].value = values_buf[i]; |
751 | option_index++; |
752 | } |
753 | |
754 | /* Set variables */ |
755 | environ_cb(RETRO_ENVIRONMENT_SET_VARIABLES, variables); |
756 | |
757 | error: |
758 | |
759 | /* Clean up */ |
760 | if (values_buf) |
761 | { |
762 | for (i = 0; i < num_options; i++) |
763 | { |
764 | if (values_buf[i]) |
765 | { |
766 | free(values_buf[i]); |
767 | values_buf[i] = NULL; |
768 | } |
769 | } |
770 | |
771 | free(values_buf); |
772 | values_buf = NULL; |
773 | } |
774 | |
775 | if (variables) |
776 | { |
777 | free(variables); |
778 | variables = NULL; |
779 | } |
780 | } |
781 | } |
782 | |
783 | #ifdef __cplusplus |
784 | } |
785 | #endif |
786 | |
787 | #endif |