#ifndef LIBRETRO_CORE_OPTIONS_H__ #define LIBRETRO_CORE_OPTIONS_H__ #include #include #include #include #ifdef __cplusplus extern "C" { #endif /* ******************************** * Core Option Definitions ******************************** */ #define MAX_CORE_OPTIONS 34 /* 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[] = { { "video", "Video", #ifdef HAVE_NTSC_FILTER "Configure aspect ratio / display cropping / color palette / video filter options." #else "Configure aspect ratio / display cropping / color palette options." #endif }, { "audio", "Audio", "Configure sound quality / volume / channel enable settings." }, { "input", "Input", "Configure turbo / light gun parameters." }, { "hacks", "Emulation Hacks", "Configure processor overclocking and emulation accuracy parameters affecting low-level performance and compatibility." }, { "dip_switch", "DIP Switches", "Configure arcade game settings." }, { NULL, NULL, NULL }, }; struct retro_core_option_v2_definition option_defs_us_common[] = { { "fceumm_region", "Region", NULL, "Force core to use NTSC, PAL or Dendy region timings.", NULL, NULL, { { "Auto", NULL }, { "NTSC", NULL }, { "PAL", NULL }, { "Dendy", NULL }, { NULL, NULL}, }, "Auto", }, { "fceumm_show_adv_system_options", "Show Advanced System Options", NULL, "Show advanced system options and tweaks.", NULL, NULL, { { "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}, }, "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", }, { "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 FS" }, { "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, "Enable blargg NTSC filters.", NULL, "video", { { "disabled", NULL }, { "composite", "Composite" }, { "svideo", "S-Video" }, { "rgb", "RGB" }, { "monochrome", "Monochrome" }, { NULL, NULL }, }, "disabled" }, #endif { "fceumm_sndquality", "Sound Quality", NULL, "Enable higher quality sound. Increases performance requirements.", NULL, "audio", { { "Low", NULL }, { "High", NULL }, { "Very High", NULL }, { NULL, NULL}, }, "Low", }, { "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", { { "disabled", NULL }, { "enabled", NULL }, { NULL, NULL}, }, "disabled", }, { "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", { { "enabled", NULL }, { "disabled", NULL }, { NULL, NULL}, }, "enabled", }, { "fceumm_apu_2", "Audio Channel 2 (Square 2)", "Channel 2 (Square 2)", "Enables or disables pulse wave generator audio output 2.", NULL, "audio", { { "enabled", NULL }, { "disabled", NULL }, { NULL, NULL}, }, "enabled", }, { "fceumm_apu_3", "Audio Channel 3 (Triangle)", "Channel 3 (Triangle)", "Enables or disables triangle wave generator audio output.", NULL, "audio", { { "enabled", NULL }, { "disabled", NULL }, { NULL, NULL}, }, "enabled", }, { "fceumm_apu_4", "Audio Channel 4 (Noise)", "Channel 4 (Noise)", "Enables or disables noise generator audio output.", NULL, "audio", { { "enabled", NULL }, { "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", { { "enabled", NULL }, { "disabled", NULL }, { NULL, NULL}, }, "enabled", }, { "fceumm_turbo_enable", "Turbo Enable", NULL, "Enables or disables turbo buttons.", NULL, "input", { { "None", NULL }, { "Player 1", NULL }, { "Player 2", NULL }, { "Both", NULL }, { NULL, NULL}, }, "None", }, { "fceumm_turbo_delay", "Turbo Delay (in frames)", NULL, "Repeat rate of turbo buttons in frames.", NULL, "input", { { "1", NULL }, { "2", NULL }, { "3", NULL }, { "5", NULL }, { "10", NULL }, { "15", NULL }, { "30", NULL }, { "60", NULL }, { NULL, NULL}, }, "3", }, { "fceumm_zapper_mode", "Zapper Mode", NULL, "Selects device to use for zapper games.", NULL, "input", { { "lightgun", "Lightgun" }, { "touchscreen", "Touchscreen" }, { "mouse", "Mouse" }, { NULL, NULL}, }, "lightgun", }, { "fceumm_show_crosshair", "Show Zapper Crosshair", NULL, "Shows or hides on-screen crosshairs when using a zapper.", NULL, "input", { { "enabled", NULL }, { "disabled", NULL }, { NULL, NULL}, }, "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", }, { "fceumm_up_down_allowed", "Allow Opposing Directions", NULL, "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}, }, "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", { { "disabled", NULL }, { "enabled", NULL }, { NULL, NULL}, }, "disabled", }, { "fceumm_overclocking", "Overclock", NULL, "Enables or disables overclocking which can reduce slowdowns in some games. Postrender method is more compatible with every game with Vblank more effective for games like Contra Force.", NULL, "hacks", { { "disabled", NULL }, { "2x-Postrender", NULL }, { "2x-VBlank", NULL }, { NULL, NULL}, }, "disabled", }, { "fceumm_ramstate", "RAM Power-On Fill (Restart)", NULL, "Choose RAM startup during power up. Some games rely on initial ram values for random generator as an example.", NULL, "hacks", { { "fill $ff", "$FF" }, { "fill $00", "$00" }, { "random", "Random" }, { NULL, NULL}, }, "fill $ff", }, { NULL, NULL, NULL, NULL, NULL, NULL, {{0}}, NULL }, }; struct retro_core_option_v2_definition option_defs_us[MAX_CORE_OPTIONS]; struct retro_core_options_v2 options_us = { option_cats_us, option_defs_us }; /* ******************************** * Language Mapping ******************************** */ #ifndef HAVE_NO_LANGEXTRA struct retro_core_options_v2 *options_intl[RETRO_LANGUAGE_LAST] = { &options_us, /* RETRO_LANGUAGE_ENGLISH */ NULL, /* RETRO_LANGUAGE_JAPANESE */ NULL, /* RETRO_LANGUAGE_FRENCH */ NULL, /* RETRO_LANGUAGE_SPANISH */ NULL, /* RETRO_LANGUAGE_GERMAN */ NULL, /* RETRO_LANGUAGE_ITALIAN */ NULL, /* RETRO_LANGUAGE_DUTCH */ NULL, /* RETRO_LANGUAGE_PORTUGUESE_BRAZIL */ NULL, /* RETRO_LANGUAGE_PORTUGUESE_PORTUGAL */ NULL, /* RETRO_LANGUAGE_RUSSIAN */ NULL, /* RETRO_LANGUAGE_KOREAN */ NULL, /* RETRO_LANGUAGE_CHINESE_TRADITIONAL */ NULL, /* RETRO_LANGUAGE_CHINESE_SIMPLIFIED */ NULL, /* RETRO_LANGUAGE_ESPERANTO */ NULL, /* RETRO_LANGUAGE_POLISH */ NULL, /* RETRO_LANGUAGE_VIETNAMESE */ NULL, /* RETRO_LANGUAGE_ARABIC */ NULL, /* RETRO_LANGUAGE_GREEK */ NULL, /* RETRO_LANGUAGE_TURKISH */ }; #endif /* ******************************** * 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) { unsigned version = 0; #ifndef HAVE_NO_LANGEXTRA unsigned language = 0; #endif if (!environ_cb || !categories_supported) return; *categories_supported = false; if (!environ_cb(RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION, &version)) version = 0; if (version >= 2) { #ifndef HAVE_NO_LANGEXTRA struct retro_core_options_v2_intl core_options_intl; core_options_intl.us = &options_us; 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]; *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 } else { size_t i, j; 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 struct retro_variable *variables = NULL; char **values_buf = NULL; /* Determine total number of options */ while (true) { if (option_defs_us[num_options].key) num_options++; else break; } if (version >= 1) { /* 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; option_values++; option_v1_values++; } } #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; if (option_defs_intl) { /* Determine number of intl options */ while (true) { if (option_defs_intl[num_options_intl].key) num_options_intl++; 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++) { 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; option_values++; option_v1_values++; } } } core_options_v1_intl.us = option_v1_defs_us; core_options_v1_intl.local = option_v1_defs_intl; 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; /* 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; /* Determine number of values */ while (true) { if (values[num_values].value) { /* 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); } } } } variables[option_index].key = key; variables[option_index].value = values_buf[i]; option_index++; } /* Set variables */ environ_cb(RETRO_ENVIRONMENT_SET_VARIABLES, variables); } 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 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