Files
ci-libretro-fceumm/src/drivers/libretro/libretro_core_options.h

856 lines
23 KiB
C
Raw Normal View History

2019-07-20 00:12:02 +08:00
#ifndef LIBRETRO_CORE_OPTIONS_H__
#define LIBRETRO_CORE_OPTIONS_H__
#include <stdlib.h>
#include <string.h>
#include <libretro.h>
#include <retro_inline.h>
2021-12-04 14:41:07 +01:00
#ifndef HAVE_NO_LANGEXTRA
#include "libretro_core_options_intl.h"
#endif
2019-07-20 00:12:02 +08:00
#ifdef __cplusplus
extern "C" {
#endif
/*
********************************
* Core Option Definitions
********************************
*/
#define MAX_CORE_OPTIONS 35
2019-07-20 00:12:02 +08:00
/* RETRO_LANGUAGE_ENGLISH */
/* Default language:
* - All other languages must include the same keys and values
* - Will be used as a fallback in the event that frontend language
* is not available
* - Will be used as a fallback for any missing entries in
* frontend language definition */
struct retro_core_option_v2_category option_cats_us[] = {
{
"system",
"System",
"Change region and hardware add-on settings."
},
{
"video",
"Video",
#ifdef HAVE_NTSC_FILTER
"Change aspect ratio, display cropping, color palette and video filter options."
#else
"Change aspect ratio, display cropping and color palette options."
#endif
},
{
"audio",
"Audio",
"Change sound quality, volume, channel enable settings."
},
{
"input",
"Input",
"Change turbo and light gun settings."
},
{
"hacks",
"Emulation Hacks",
"Change processor overclocking and emulation accuracy settings affecting low-level performance and compatibility."
},
{
"dip_switch",
"DIP Switches",
"Change arcade game settings."
},
{ NULL, NULL, NULL },
};
2019-07-20 00:12:02 +08:00
2021-12-04 14:41:07 +01:00
struct retro_core_option_v2_definition option_defs[] = {
2019-07-20 00:12:02 +08:00
{
"fceumm_region",
"Region",
NULL,
2019-07-20 00:12:02 +08:00
"Force core to use NTSC, PAL or Dendy region timings.",
NULL,
"system",
2019-07-20 00:12:02 +08:00
{
{ "Auto", NULL },
{ "NTSC", NULL },
{ "PAL", NULL },
{ "Dendy", NULL },
{ NULL, NULL },
2019-07-20 00:12:02 +08:00
},
"Auto",
},
{
"fceumm_game_genie",
2021-12-04 14:41:07 +01:00
"Game Genie Add-On (Restart Required)",
NULL,
"Enable emulation of a Game Genie add-on cartridge, allowing cheat codes to be entered when launching games. The Game Genie ROM file 'gamegenie.nes' must be present in the frontend's system directory. Does not apply to FDS or arcade content.",
NULL,
"system",
{
{ "disabled", NULL },
{ "enabled", NULL },
{ NULL, NULL },
},
"disabled",
},
2019-07-20 00:12:02 +08:00
{
"fceumm_show_adv_system_options",
"Show Advanced System Options",
NULL,
"Show advanced system options and tweaks.",
NULL,
NULL,
2019-07-20 00:12:02 +08:00
{
{ "disabled", NULL },
{ "enabled", NULL },
{ NULL, NULL },
},
"disabled"
},
{
"fceumm_show_adv_sound_options",
"Show Advanced Sound Options",
NULL,
"Show advanced sound options and tweaks.",
NULL,
NULL,
{
{ "disabled", NULL },
{ "enabled", NULL },
{ NULL, NULL },
},
"disabled"
},
{
"fceumm_aspect",
"Aspect Ratio",
NULL,
"Choose preferred aspect ratio.",
NULL,
"video",
{
{ "8:7 PAR", NULL },
{ "4:3", NULL },
{ "PP", "Pixel Perfect" },
{ NULL, NULL },
2019-07-20 00:12:02 +08:00
},
"8:7 PAR",
},
#ifdef PSP /* overscan options */
{
"fceumm_overscan",
"Crop Overscan",
NULL,
"Removes 8 pixel overscan from all sides of the screen.",
NULL,
"video",
{
{ "enabled", NULL },
{ "disabled", NULL },
{ NULL, NULL },
},
"enabled",
},
#else
{
"fceumm_overscan_h",
"Crop Horizontal Overscan",
NULL,
"Removes 8 pixels from left and right sides of the screen to simulate overscan seen on standard CRT televisions.",
NULL,
"video",
{
{ "disabled", NULL },
{ "enabled", NULL },
{ NULL, NULL },
},
"disabled",
2019-07-20 00:12:02 +08:00
},
{
"fceumm_overscan_v",
"Crop Vertical Overscan",
NULL,
"Removes 8 pixels from the top and bottom of the screen to simulate overscan seen on standard CRT televisions.",
NULL,
"video",
{
{ "disabled", NULL },
{ "enabled", NULL },
{ NULL, NULL },
},
"enabled",
},
#endif /* overscan options */
{
"fceumm_palette",
"Color Palette",
NULL,
"Choose from pre-generated palettes, a custom 64x3 palette from file or raw format (needs to use a nes-decoder shader).",
NULL,
"video",
{
{ "default", "Default" },
{ "asqrealc", "AspiringSquire's Real" },
{ "nintendo-vc", "Nintendo Virtual Console" },
{ "rgb", "Nintendo RGB PPU" },
{ "yuv-v3", "FBX's YUV-V3" },
{ "unsaturated-final", "FBX's Unsaturated-Final" },
{ "sony-cxa2025as-us", "Sony CXA2025AS US" },
{ "pal", "PAL" },
{ "bmf-final2", "BMF's Final 2" },
{ "bmf-final3", "BMF's Final 3" },
{ "smooth-fbx", "FBX's Smooth" },
{ "composite-direct-fbx", "FBX's Composite Direct" },
{ "pvm-style-d93-fbx", "FBX's PVM Style D93" },
{ "ntsc-hardware-fbx", "FBX's NTSC Hardware" },
{ "nes-classic-fbx-fs", "FBX's NES Classic (fixed)" },
{ "nescap", "RGBSource's NESCAP" },
{ "wavebeam", "nakedarthur's Wavebeam" },
{ "raw", "Raw" },
{ "custom", "Custom" },
{ NULL, NULL },
},
"default",
},
#ifdef HAVE_NTSC_FILTER
{
"fceumm_ntsc_filter",
"NTSC Filter",
NULL,
"Blargg's NTSC filters are used to replicate RF, Composite, S-Video, and RGB cable signals.",
NULL,
"video",
{
{ "disabled", NULL },
{ "composite", "Composite" },
{ "svideo", "S-Video" },
{ "rgb", "RGB" },
{ "monochrome", "Monochrome" },
{ NULL, NULL },
},
"disabled"
},
#endif
2019-07-20 00:12:02 +08:00
{
"fceumm_sndquality",
"Sound Quality",
NULL,
"Enable higher quality sound. Increases performance requirements.",
NULL,
"audio",
2019-07-20 00:12:02 +08:00
{
{ "Low", NULL },
{ "High", NULL },
{ "Very High", NULL },
{ NULL, NULL },
2019-07-20 00:12:02 +08:00
},
"Low",
2019-07-20 00:12:02 +08:00
},
{
"fceumm_swapduty",
"Swap Audio Duty Cycles",
"Swap Duty Cycles",
"Simulates the sound from famiclones that have the pulse wave channels duty cycle bits reversed.",
NULL,
"audio",
2019-07-20 00:12:02 +08:00
{
{ "disabled", NULL },
{ "enabled", NULL },
{ NULL, NULL },
2019-07-20 00:12:02 +08:00
},
"disabled",
2019-07-20 00:12:02 +08:00
},
{
"fceumm_sndvolume",
"Master Volume",
NULL,
"Change master volume level.",
NULL,
"audio",
{
{ "0", "0%" },
{ "1", "10%" },
{ "2", "20%" },
{ "3", "30%" },
{ "4", "40%" },
{ "5", "50%" },
{ "6", "60%" },
{ "7", "70%" },
{ "8", "80%" },
{ "9", "90%" },
{ "10", "100%" },
{ NULL, NULL },
},
"7",
},
{
"fceumm_apu_1",
"Audio Channel 1 (Square 1)",
"Channel 1 (Square 1)",
"Enables or disables pulse wave generator audio output 1.",
NULL,
"audio",
2019-07-20 00:12:02 +08:00
{
{ "enabled", NULL },
{ "disabled", NULL },
{ NULL, NULL },
2019-07-20 00:12:02 +08:00
},
"enabled",
},
{
"fceumm_apu_2",
"Audio Channel 2 (Square 2)",
"Channel 2 (Square 2)",
"Enables or disables pulse wave generator audio output 2.",
NULL,
"audio",
2019-07-20 00:12:02 +08:00
{
{ "enabled", NULL },
{ "disabled", NULL },
{ NULL, NULL },
2019-07-20 00:12:02 +08:00
},
"enabled",
2019-07-20 00:12:02 +08:00
},
{
"fceumm_apu_3",
"Audio Channel 3 (Triangle)",
"Channel 3 (Triangle)",
"Enables or disables triangle wave generator audio output.",
NULL,
"audio",
2019-07-20 00:12:02 +08:00
{
{ "enabled", NULL },
{ "disabled", NULL },
{ NULL, NULL },
2019-07-20 00:12:02 +08:00
},
"enabled",
},
{
"fceumm_apu_4",
"Audio Channel 4 (Noise)",
"Channel 4 (Noise)",
"Enables or disables noise generator audio output.",
NULL,
"audio",
2019-07-20 00:12:02 +08:00
{
{ "enabled", NULL },
2019-07-20 00:12:02 +08:00
{ "disabled", NULL },
{ NULL, NULL },
},
"enabled",
},
{
"fceumm_apu_5",
"Audio Channel 5 (PCM)",
"Channel 5 (PCM)",
"Enables or disables delta modulation channel audio output.",
NULL,
"audio",
{
2019-07-20 00:12:02 +08:00
{ "enabled", NULL },
{ "disabled", NULL },
{ NULL, NULL },
2019-07-20 00:12:02 +08:00
},
"enabled",
2019-07-20 00:12:02 +08:00
},
{
"fceumm_turbo_enable",
"Turbo Enable",
NULL,
2019-07-20 00:12:02 +08:00
"Enables or disables turbo buttons.",
NULL,
"input",
2019-07-20 00:12:02 +08:00
{
{ "None", NULL },
{ "Player 1", NULL },
{ "Player 2", NULL },
{ "Both", NULL },
{ NULL, NULL },
2019-07-20 00:12:02 +08:00
},
"None",
},
{
"fceumm_turbo_delay",
"Turbo Delay (in frames)",
NULL,
2019-07-20 00:12:02 +08:00
"Repeat rate of turbo buttons in frames.",
NULL,
"input",
2019-07-20 00:12:02 +08:00
{
{ "1", NULL },
{ "2", NULL },
{ "3", NULL },
{ "5", NULL },
{ "10", NULL },
{ "15", NULL },
{ "30", NULL },
{ "60", NULL },
{ NULL, NULL },
2019-07-20 00:12:02 +08:00
},
"3",
},
{
"fceumm_zapper_mode",
"Zapper Mode",
NULL,
"Selects device to use for Zapper games.",
NULL,
"input",
2019-07-20 00:12:02 +08:00
{
2021-12-04 14:41:07 +01:00
{ "lightgun", "Light gun" },
{ "touchscreen", "Touchscreen" },
{ "mouse", "Mouse" },
{ NULL, NULL },
2019-07-20 00:12:02 +08:00
},
"lightgun",
},
{
"fceumm_show_crosshair",
"Show Zapper Crosshair",
NULL,
"Shows or hides on-screen crosshairs when using a Zapper.",
NULL,
"input",
2019-07-20 00:12:02 +08:00
{
{ "enabled", NULL },
{ "disabled", NULL },
{ NULL, NULL },
2019-07-20 00:12:02 +08:00
},
"enabled",
},
{
"fceumm_zapper_tolerance",
"Zapper Tolerance",
NULL,
"Sets how many pixels from target area is on target.",
NULL,
"input",
{
{ "0", NULL },
{ "1", NULL },
{ "2", NULL },
{ "3", NULL },
{ "4", NULL },
{ "5", NULL },
{ "6", NULL },
{ "7", NULL },
{ "8", NULL },
{ "9", NULL },
{ "10", NULL },
{ "11", NULL },
{ "12", NULL },
{ "13", NULL },
{ "14", NULL },
{ "15", NULL },
{ "16", NULL },
{ "17", NULL },
{ "18", NULL },
{ "19", NULL },
{ "20", NULL },
{ NULL, NULL },
},
"6",
},
2019-07-20 00:12:02 +08:00
{
"fceumm_up_down_allowed",
"Allow Opposing Directions",
NULL,
2021-12-04 14:41:07 +01:00
"Allows simultaneous UP+DOWN or LEFT+RIGHT button combinations, which can create different effects in some games.",
NULL,
"input",
{
{ "disabled", NULL },
{ "enabled", NULL },
{ NULL, NULL },
2019-07-20 00:12:02 +08:00
},
"disabled",
},
{
"fceumm_nospritelimit",
"No Sprite Limit",
NULL,
"Removes the 8-per-scanline hardware limit. This reduces sprite flickering but can cause some games to glitch since some use this for effects.",
NULL,
"hacks",
2019-07-20 00:12:02 +08:00
{
{ "disabled", NULL },
{ "enabled", NULL },
{ NULL, NULL },
2019-07-20 00:12:02 +08:00
},
"disabled",
2019-07-20 00:12:02 +08:00
},
{
"fceumm_overclocking",
"Overclock",
NULL,
2021-12-04 14:41:07 +01:00
"Enables or disables overclocking, which can reduce slowdowns in some games. Postrender method is more compatible with every game, Vblank is more effective for games like Contra Force.",
NULL,
"hacks",
2019-07-20 00:12:02 +08:00
{
{ "disabled", NULL },
{ "2x-Postrender", NULL },
{ "2x-VBlank", NULL },
{ NULL, NULL },
2019-07-20 00:12:02 +08:00
},
"disabled",
2019-07-20 00:12:02 +08:00
},
{
"fceumm_ramstate",
2021-12-04 14:41:07 +01:00
"RAM Power-On Fill (Restart Required)",
NULL,
2021-12-04 14:41:07 +01:00
"RAM values on power up. Some games rely on initial RAM values for random number generation as an example.",
NULL,
"hacks",
2019-07-20 00:12:02 +08:00
{
{ "fill $ff", "$FF" },
{ "fill $00", "$00" },
{ "random", "Random" },
{ NULL, NULL },
2019-07-20 00:12:02 +08:00
},
"fill $ff",
},
{ NULL, NULL, NULL, NULL, NULL, NULL, {{0}}, NULL },
2019-07-20 00:12:02 +08:00
};
struct retro_core_option_v2_definition option_defs_us[MAX_CORE_OPTIONS];
2019-07-20 00:12:02 +08:00
struct retro_core_options_v2 options_us = {
option_cats_us,
option_defs_us
};
2019-07-20 00:12:02 +08:00
/*
********************************
* Language Mapping
********************************
*/
#ifndef HAVE_NO_LANGEXTRA
struct retro_core_options_v2 *options_intl[RETRO_LANGUAGE_LAST] = {
&options_us, /* RETRO_LANGUAGE_ENGLISH */
2021-12-04 14:41:07 +01:00
&options_ja, /* RETRO_LANGUAGE_JAPANESE */
&options_fr, /* RETRO_LANGUAGE_FRENCH */
&options_es, /* RETRO_LANGUAGE_SPANISH */
&options_de, /* RETRO_LANGUAGE_GERMAN */
&options_it, /* RETRO_LANGUAGE_ITALIAN */
&options_nl, /* RETRO_LANGUAGE_DUTCH */
&options_pt_br, /* RETRO_LANGUAGE_PORTUGUESE_BRAZIL */
&options_pt_pt, /* RETRO_LANGUAGE_PORTUGUESE_PORTUGAL */
&options_ru, /* RETRO_LANGUAGE_RUSSIAN */
&options_ko, /* RETRO_LANGUAGE_KOREAN */
&options_cht, /* RETRO_LANGUAGE_CHINESE_TRADITIONAL */
&options_chs, /* RETRO_LANGUAGE_CHINESE_SIMPLIFIED */
&options_eo, /* RETRO_LANGUAGE_ESPERANTO */
&options_pl, /* RETRO_LANGUAGE_POLISH */
&options_vn, /* RETRO_LANGUAGE_VIETNAMESE */
&options_ar, /* RETRO_LANGUAGE_ARABIC */
&options_el, /* RETRO_LANGUAGE_GREEK */
&options_tr, /* RETRO_LANGUAGE_TURKISH */
&options_sv, /* RETRO_LANGUAGE_SLOVAK */
&options_fa, /* RETRO_LANGUAGE_PERSIAN */
&options_he, /* RETRO_LANGUAGE_HEBREW */
&options_ast, /* RETRO_LANGUAGE_ASTURIAN */
&options_fi, /* RETRO_LANGUAGE_FINNISH */
2019-07-20 00:12:02 +08:00
};
#endif
2019-07-20 00:12:02 +08:00
/*
********************************
* Functions
********************************
*/
/* Handles configuration/setting of core options.
* Should only be called inside retro_set_environment().
* > We place the function body in the header to avoid the
* necessity of adding more .c files (i.e. want this to
* be as painless as possible for core devs)
*/
static INLINE void libretro_set_core_options(retro_environment_t environ_cb,
bool *categories_supported)
2019-07-20 00:12:02 +08:00
{
unsigned version = 0;
#ifndef HAVE_NO_LANGEXTRA
unsigned language = 0;
#endif
2019-07-20 00:12:02 +08:00
if (!environ_cb || !categories_supported)
2019-07-20 00:12:02 +08:00
return;
*categories_supported = false;
if (!environ_cb(RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION, &version))
version = 0;
if (version >= 2)
2019-07-20 00:12:02 +08:00
{
#ifndef HAVE_NO_LANGEXTRA
struct retro_core_options_v2_intl core_options_intl;
2019-07-20 00:12:02 +08:00
core_options_intl.us = &options_us;
2019-07-20 00:12:02 +08:00
core_options_intl.local = NULL;
if (environ_cb(RETRO_ENVIRONMENT_GET_LANGUAGE, &language) &&
(language < RETRO_LANGUAGE_LAST) && (language != RETRO_LANGUAGE_ENGLISH))
core_options_intl.local = options_intl[language];
2019-07-20 00:12:02 +08:00
*categories_supported = environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2_INTL,
&core_options_intl);
#else
*categories_supported = environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2,
&options_us);
#endif
2019-07-20 00:12:02 +08:00
}
else
{
size_t i, j;
2019-07-20 00:12:02 +08:00
size_t option_index = 0;
size_t num_options = 0;
struct retro_core_option_definition
*option_v1_defs_us = NULL;
#ifndef HAVE_NO_LANGEXTRA
size_t num_options_intl = 0;
struct retro_core_option_v2_definition
*option_defs_intl = NULL;
struct retro_core_option_definition
*option_v1_defs_intl = NULL;
struct retro_core_options_intl
core_options_v1_intl;
#endif
2019-07-20 00:12:02 +08:00
struct retro_variable *variables = NULL;
char **values_buf = NULL;
/* Determine total number of options */
2019-07-20 00:12:02 +08:00
while (true)
{
if (option_defs_us[num_options].key)
num_options++;
else
break;
}
if (version >= 1)
2019-07-20 00:12:02 +08:00
{
/* Allocate US array */
option_v1_defs_us = (struct retro_core_option_definition *)
calloc(num_options + 1, sizeof(struct retro_core_option_definition));
/* Copy parameters from option_defs_us array */
for (i = 0; i < num_options; i++)
{
struct retro_core_option_v2_definition *option_def_us = &option_defs_us[i];
struct retro_core_option_value *option_values = option_def_us->values;
struct retro_core_option_definition *option_v1_def_us = &option_v1_defs_us[i];
struct retro_core_option_value *option_v1_values = option_v1_def_us->values;
option_v1_def_us->key = option_def_us->key;
option_v1_def_us->desc = option_def_us->desc;
option_v1_def_us->info = option_def_us->info;
option_v1_def_us->default_value = option_def_us->default_value;
/* Values must be copied individually... */
while (option_values->value)
{
option_v1_values->value = option_values->value;
option_v1_values->label = option_values->label;
2019-07-20 00:12:02 +08:00
option_values++;
option_v1_values++;
}
}
2019-07-20 00:12:02 +08:00
#ifndef HAVE_NO_LANGEXTRA
if (environ_cb(RETRO_ENVIRONMENT_GET_LANGUAGE, &language) &&
(language < RETRO_LANGUAGE_LAST) && (language != RETRO_LANGUAGE_ENGLISH) &&
options_intl[language])
option_defs_intl = options_intl[language]->definitions;
2019-07-20 00:12:02 +08:00
if (option_defs_intl)
2019-07-20 00:12:02 +08:00
{
/* Determine number of intl options */
2019-07-20 00:12:02 +08:00
while (true)
{
if (option_defs_intl[num_options_intl].key)
num_options_intl++;
2019-07-20 00:12:02 +08:00
else
break;
}
/* Allocate intl array */
option_v1_defs_intl = (struct retro_core_option_definition *)
calloc(num_options_intl + 1, sizeof(struct retro_core_option_definition));
/* Copy parameters from option_defs_intl array */
for (i = 0; i < num_options_intl; i++)
2019-07-20 00:12:02 +08:00
{
struct retro_core_option_v2_definition *option_def_intl = &option_defs_intl[i];
struct retro_core_option_value *option_values = option_def_intl->values;
struct retro_core_option_definition *option_v1_def_intl = &option_v1_defs_intl[i];
struct retro_core_option_value *option_v1_values = option_v1_def_intl->values;
option_v1_def_intl->key = option_def_intl->key;
option_v1_def_intl->desc = option_def_intl->desc;
option_v1_def_intl->info = option_def_intl->info;
option_v1_def_intl->default_value = option_def_intl->default_value;
/* Values must be copied individually... */
while (option_values->value)
{
option_v1_values->value = option_values->value;
option_v1_values->label = option_values->label;
2019-07-20 00:12:02 +08:00
option_values++;
option_v1_values++;
}
}
}
2019-07-20 00:12:02 +08:00
core_options_v1_intl.us = option_v1_defs_us;
core_options_v1_intl.local = option_v1_defs_intl;
2019-07-20 00:12:02 +08:00
environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL, &core_options_v1_intl);
#else
environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS, option_v1_defs_us);
#endif
}
else
{
/* Allocate arrays */
variables = (struct retro_variable *)calloc(num_options + 1,
sizeof(struct retro_variable));
values_buf = (char **)calloc(num_options, sizeof(char *));
if (!variables || !values_buf)
goto error;
2019-07-20 00:12:02 +08:00
/* Copy parameters from option_defs_us array */
for (i = 0; i < num_options; i++)
{
const char *key = option_defs_us[i].key;
const char *desc = option_defs_us[i].desc;
const char *default_value = option_defs_us[i].default_value;
struct retro_core_option_value *values = option_defs_us[i].values;
size_t buf_len = 3;
size_t default_index = 0;
values_buf[i] = NULL;
/* Skip options that are irrelevant when using the
* old style core options interface */
if ((strcmp(key, "fceumm_show_adv_system_options") == 0) ||
(strcmp(key, "fceumm_advance_sound_options") == 0))
continue;
if (desc)
{
size_t num_values = 0;
2019-07-20 00:12:02 +08:00
/* Determine number of values */
while (true)
2019-07-20 00:12:02 +08:00
{
if (values[num_values].value)
2019-07-20 00:12:02 +08:00
{
/* Check if this is the default value */
if (default_value)
if (strcmp(values[num_values].value, default_value) == 0)
default_index = num_values;
buf_len += strlen(values[num_values].value);
num_values++;
}
else
break;
}
/* Build values string */
if (num_values > 0)
{
buf_len += num_values - 1;
buf_len += strlen(desc);
values_buf[i] = (char *)calloc(buf_len, sizeof(char));
if (!values_buf[i])
goto error;
strcpy(values_buf[i], desc);
strcat(values_buf[i], "; ");
/* Default value goes first */
strcat(values_buf[i], values[default_index].value);
/* Add remaining values */
for (j = 0; j < num_values; j++)
{
if (j != default_index)
{
strcat(values_buf[i], "|");
strcat(values_buf[i], values[j].value);
}
2019-07-20 00:12:02 +08:00
}
}
}
variables[option_index].key = key;
variables[option_index].value = values_buf[i];
option_index++;
2019-07-20 00:12:02 +08:00
}
/* Set variables */
environ_cb(RETRO_ENVIRONMENT_SET_VARIABLES, variables);
2019-07-20 00:12:02 +08:00
}
error:
/* Clean up */
if (option_v1_defs_us)
{
free(option_v1_defs_us);
option_v1_defs_us = NULL;
}
#ifndef HAVE_NO_LANGEXTRA
if (option_v1_defs_intl)
{
free(option_v1_defs_intl);
option_v1_defs_intl = NULL;
}
#endif
2019-07-20 00:12:02 +08:00
if (values_buf)
{
for (i = 0; i < num_options; i++)
{
if (values_buf[i])
{
free(values_buf[i]);
values_buf[i] = NULL;
}
}
free(values_buf);
values_buf = NULL;
}
if (variables)
{
free(variables);
variables = NULL;
}
}
}
#ifdef __cplusplus
}
#endif
#endif