Add core option sublabels

This commit is contained in:
jdgleaver 2019-07-23 16:04:01 +01:00
parent b469051259
commit 2a474b39b0
3 changed files with 1012 additions and 90 deletions

View File

@ -614,7 +614,7 @@ enum retro_mod
* Afterward it may be called again for the core to communicate
* updated options to the frontend, but the number of core
* options must not change from the number in the initial call.
*
*
* 'data' points to an array of retro_variable structs
* terminated by a { NULL, NULL } element.
* retro_variable::key should be namespaced to not collide
@ -1106,6 +1106,148 @@ enum retro_mod
* It will return a bitmask of all the digital buttons.
*/
#define RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION 52
/* unsigned * --
* Unsigned value is the API version number of the core options
* interface supported by the frontend. If callback return false,
* API version is assumed to be 0.
*
* In legacy code, core options are set by passing an array of
* retro_variable structs to RETRO_ENVIRONMENT_SET_VARIABLES.
* This may be still be done regardless of the core options
* interface version.
*
* If version is 1 however, core options may instead be set by
* passing an array of retro_core_option_definition structs to
* RETRO_ENVIRONMENT_SET_CORE_OPTIONS, or a 2D array of
* retro_core_option_definition structs to RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL.
* This allows the core to additionally set option sublabel information
* and/or provide localisation support.
*/
#define RETRO_ENVIRONMENT_SET_CORE_OPTIONS 53
/* const struct retro_core_option_definition ** --
* Allows an implementation to signal the environment
* which variables it might want to check for later using
* GET_VARIABLE.
* This allows the frontend to present these variables to
* a user dynamically.
* This should only be called if RETRO_ENVIRONMENT_GET_ENHANCED_CORE_OPTIONS
* returns an API version of 1.
* This should be called instead of RETRO_ENVIRONMENT_SET_VARIABLES.
* This should be called the first time as early as
* possible (ideally in retro_set_environment).
* Afterwards it may be called again for the core to communicate
* updated options to the frontend, but the number of core
* options must not change from the number in the initial call.
*
* 'data' points to an array of retro_core_option_definition structs
* terminated by a { NULL, NULL, NULL, {{0}}, NULL } element.
* retro_core_option_definition::key should be namespaced to not collide
* with other implementations' keys. e.g. A core called
* 'foo' should use keys named as 'foo_option'.
* retro_core_option_definition::desc should contain a human readable
* description of the key.
* retro_core_option_definition::info should contain any additional human
* readable information text that a typical user may need to
* understand the functionality of the option.
* retro_core_option_definition::values is an array of retro_core_option_value
* structs terminated by a { NULL, NULL } element.
* > retro_core_option_definition::values[index].value is an expected option
* value.
* > retro_core_option_definition::values[index].label is a human readable
* label used when displaying the value on screen. If NULL,
* the value itself is used.
* retro_core_option_definition::default_value is the default core option
* setting. It must match one of the expected option values in the
* retro_core_option_definition::values array. If it does not, or the
* default value is NULL, the first entry in the
* retro_core_option_definition::values array is treated as the default.
*
* The number of possible options should be very limited,
* and must be less than RETRO_NUM_CORE_OPTION_VALUES_MAX.
* i.e. it should be feasible to cycle through options
* without a keyboard.
*
* First entry should be treated as a default.
*
* Example entry:
* {
* "foo_option",
* "Speed hack coprocessor X",
* "Provides increased performance at the expense of reduced accuracy",
* {
* { "false", NULL },
* { "true", NULL },
* { "unstable", "Turbo (Unstable)" },
* { NULL, NULL },
* },
* "false"
* }
*
* Only strings are operated on. The possible values will
* generally be displayed and stored as-is by the frontend.
*/
#define RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL 54
/* const struct retro_core_options_intl * --
* Allows an implementation to signal the environment
* which variables it might want to check for later using
* GET_VARIABLE.
* This allows the frontend to present these variables to
* a user dynamically.
* This should only be called if RETRO_ENVIRONMENT_GET_ENHANCED_CORE_OPTIONS
* returns an API version of 1.
* This should be called instead of RETRO_ENVIRONMENT_SET_VARIABLES.
* This should be called the first time as early as
* possible (ideally in retro_set_environment).
* Afterwards it may be called again for the core to communicate
* updated options to the frontend, but the number of core
* options must not change from the number in the initial call.
*
* This is fundamentally the same as RETRO_ENVIRONMENT_SET_CORE_OPTIONS,
* with the addition of localisation support. The description of the
* RETRO_ENVIRONMENT_SET_CORE_OPTIONS callback should be consulted
* for further details.
*
* 'data' points to a retro_core_options_intl struct.
*
* retro_core_options_intl::us is a pointer to an array of
* retro_core_option_definition structs defining the US English
* core options implementation. It must point to a valid array.
*
* retro_core_options_intl::local is a pointer to an array of
* retro_core_option_definition structs defining core options for
* the current frontend language. It may be NULL (in which case
* retro_core_options_intl::us is used by the frontend). Any items
* missing from this array will be read from retro_core_options_intl::us
* instead.
*
* NOTE: Default core option values are always taken from the
* retro_core_options_intl::us array. Any default values in
* retro_core_options_intl::local array will be ignored.
*/
#define RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY 55
/* struct retro_core_option_display * --
*
* Allows an implementation to signal the environment to show
* or hide a variable when displaying core options. This is
* considered a *suggestion*. The frontend is free to ignore
* this callback, and its implementation not considered mandatory.
*
* 'data' points to a retro_core_option_display struct
*
* retro_core_option_display::key is a variable identifier
* which has already been set by SET_VARIABLES/SET_CORE_OPTIONS.
*
* retro_core_option_display::visible is a boolean, specifying
* whether variable should be displayed
*
* Note that all core option variables will be set visible by
* default when calling SET_VARIABLES/SET_CORE_OPTIONS.
*/
/* VFS functionality */
/* File paths:
@ -2351,6 +2493,64 @@ struct retro_variable
const char *value;
};
struct retro_core_option_display
{
/* Variable to configure in RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY */
const char *key;
/* Specifies whether variable should be displayed
* when presenting core options to the user */
bool visible;
};
/* Maximum number of values permitted for a core option
* NOTE: This may be increased on a core-by-core basis
* if required (doing so has no effect on the frontend) */
#define RETRO_NUM_CORE_OPTION_VALUES_MAX 128
struct retro_core_option_value
{
/* Expected option value */
const char *value;
/* Human-readable value label. If NULL, value itself
* will be displayed by the frontend */
const char *label;
};
struct retro_core_option_definition
{
/* Variable to query in RETRO_ENVIRONMENT_GET_VARIABLE. */
const char *key;
/* Human-readable core option description (used as menu label) */
const char *desc;
/* Human-readable core option information (used as menu sublabel) */
const char *info;
/* Array of retro_core_option_value structs, terminated by NULL */
struct retro_core_option_value values[RETRO_NUM_CORE_OPTION_VALUES_MAX];
/* Default core option value. Must match one of the values
* in the retro_core_option_value array, otherwise will be
* ignored */
const char *default_value;
};
struct retro_core_options_intl
{
/* Pointer to an array of retro_core_option_definition structs
* - US English implementation
* - Must point to a valid array */
struct retro_core_option_definition *us;
/* Pointer to an array of retro_core_option_definition structs
* - Implementation for current frontend language
* - May be NULL */
struct retro_core_option_definition *local;
};
struct retro_game_info
{
const char *path; /* Path to game, UTF-8 encoded.

View File

@ -1,6 +1,7 @@
#include <stdlib.h>
#include <libretro.h>
#include <libretro_core_options.h>
#include "blipper.h"
#include "gambatte.h"
#include "gbcpalettes.h"
@ -42,6 +43,8 @@ static gambatte::GB gb;
static bool libretro_supports_bitmasks = false;
static bool show_gb_link_settings = true;
static bool up_down_allowed = false;
static bool rom_loaded = false;
@ -326,80 +329,7 @@ void retro_set_environment(retro_environment_t cb)
struct retro_vfs_interface_info vfs_iface_info;
environ_cb = cb;
static const struct retro_variable vars[] = {
{ "gambatte_up_down_allowed", "Allow Opposing Directions; disabled|enabled" },
{ "gambatte_gb_colorization", "GB Colorization; disabled|auto|GBC|SGB|internal|custom" },
{ "gambatte_gb_internal_palette", "Internal Palette; \
GB - DMG|\
GB - Pocket|\
GB - Light|\
GBC - Blue|\
GBC - Brown|\
GBC - Dark Blue|\
GBC - Dark Brown|\
GBC - Dark Green|\
GBC - Grayscale|\
GBC - Green|\
GBC - Inverted|\
GBC - Orange|\
GBC - Pastel Mix|\
GBC - Red|\
GBC - Yellow|\
SGB - 1A|\
SGB - 1B|\
SGB - 1C|\
SGB - 1D|\
SGB - 1E|\
SGB - 1F|\
SGB - 1G|\
SGB - 1H|\
SGB - 2A|\
SGB - 2B|\
SGB - 2C|\
SGB - 2D|\
SGB - 2E|\
SGB - 2F|\
SGB - 2G|\
SGB - 2H|\
SGB - 3A|\
SGB - 3B|\
SGB - 3C|\
SGB - 3D|\
SGB - 3E|\
SGB - 3F|\
SGB - 3G|\
SGB - 3H|\
SGB - 4A|\
SGB - 4B|\
SGB - 4C|\
SGB - 4D|\
SGB - 4E|\
SGB - 4F|\
SGB - 4G|\
SGB - 4H|\
Special 1|\
Special 2|\
Special 3"
}, // So many... place on seperate lines for readability...
{ "gambatte_gbc_color_correction", "Color correction; GBC only|always|disabled" },
{ "gambatte_gbc_color_correction_mode", "Color correction mode; accurate|fast" },
{ "gambatte_gbc_frontlight_position", "Color correction - frontlight position; central|above screen|below screen" },
{ "gambatte_dark_filter_level", "Dark Filter Level (percent); 0|5|10|15|20|25|30|35|40|45|50" },
{ "gambatte_gb_hwmode", "Emulated hardware (restart); Auto|GB|GBC|GBA" },
{ "gambatte_gb_bootloader", "Use official bootloader (restart); enabled|disabled" },
{ "gambatte_mix_frames", "Mix frames; disabled|accurate|fast" },
#ifdef HAVE_NETWORK
{ "gambatte_gb_link_mode", "GameBoy Link Mode; Not Connected|Network Server|Network Client" },
{ "gambatte_gb_link_network_port", "Network Link Port; 56400|56401|56402|56403|56404|56405|56406|56407|56408|56409|56410|56411|56412|56413|56414|56415|56416|56417|56418|56419|56420" },
{ "gambatte_gb_link_network_server_ip_octet1", "Network link server address part 1 (client only); 0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|32|33|34|35|36|37|38|39|40|41|42|43|44|45|46|47|48|49|50|51|52|53|54|55|56|57|58|59|60|61|62|63|64|65|66|67|68|69|70|71|72|73|74|75|76|77|78|79|80|81|82|83|84|85|86|87|88|89|90|91|92|93|94|95|96|97|98|99|100|101|102|103|104|105|106|107|108|109|110|111|112|113|114|115|116|117|118|119|120|121|122|123|124|125|126|127|128|129|130|131|132|133|134|135|136|137|138|139|140|141|142|143|144|145|146|147|148|149|150|151|152|153|154|155|156|157|158|159|160|161|162|163|164|165|166|167|168|169|170|171|172|173|174|175|176|177|178|179|180|181|182|183|184|185|186|187|188|189|190|191|192|193|194|195|196|197|198|199|200|201|202|203|204|205|206|207|208|209|210|211|212|213|214|215|216|217|218|219|220|221|222|223|224|225|226|227|228|229|230|231|232|233|234|235|236|237|238|239|240|241|242|243|244|245|246|247|248|249|250|251|252|253|254|255" },
{ "gambatte_gb_link_network_server_ip_octet2", "Network link server address part 2 (client only); 0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|32|33|34|35|36|37|38|39|40|41|42|43|44|45|46|47|48|49|50|51|52|53|54|55|56|57|58|59|60|61|62|63|64|65|66|67|68|69|70|71|72|73|74|75|76|77|78|79|80|81|82|83|84|85|86|87|88|89|90|91|92|93|94|95|96|97|98|99|100|101|102|103|104|105|106|107|108|109|110|111|112|113|114|115|116|117|118|119|120|121|122|123|124|125|126|127|128|129|130|131|132|133|134|135|136|137|138|139|140|141|142|143|144|145|146|147|148|149|150|151|152|153|154|155|156|157|158|159|160|161|162|163|164|165|166|167|168|169|170|171|172|173|174|175|176|177|178|179|180|181|182|183|184|185|186|187|188|189|190|191|192|193|194|195|196|197|198|199|200|201|202|203|204|205|206|207|208|209|210|211|212|213|214|215|216|217|218|219|220|221|222|223|224|225|226|227|228|229|230|231|232|233|234|235|236|237|238|239|240|241|242|243|244|245|246|247|248|249|250|251|252|253|254|255" },
{ "gambatte_gb_link_network_server_ip_octet3", "Network link server address part 3 (client only); 0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|32|33|34|35|36|37|38|39|40|41|42|43|44|45|46|47|48|49|50|51|52|53|54|55|56|57|58|59|60|61|62|63|64|65|66|67|68|69|70|71|72|73|74|75|76|77|78|79|80|81|82|83|84|85|86|87|88|89|90|91|92|93|94|95|96|97|98|99|100|101|102|103|104|105|106|107|108|109|110|111|112|113|114|115|116|117|118|119|120|121|122|123|124|125|126|127|128|129|130|131|132|133|134|135|136|137|138|139|140|141|142|143|144|145|146|147|148|149|150|151|152|153|154|155|156|157|158|159|160|161|162|163|164|165|166|167|168|169|170|171|172|173|174|175|176|177|178|179|180|181|182|183|184|185|186|187|188|189|190|191|192|193|194|195|196|197|198|199|200|201|202|203|204|205|206|207|208|209|210|211|212|213|214|215|216|217|218|219|220|221|222|223|224|225|226|227|228|229|230|231|232|233|234|235|236|237|238|239|240|241|242|243|244|245|246|247|248|249|250|251|252|253|254|255" },
{ "gambatte_gb_link_network_server_ip_octet4", "Network link server address part 4 (client only); 0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|32|33|34|35|36|37|38|39|40|41|42|43|44|45|46|47|48|49|50|51|52|53|54|55|56|57|58|59|60|61|62|63|64|65|66|67|68|69|70|71|72|73|74|75|76|77|78|79|80|81|82|83|84|85|86|87|88|89|90|91|92|93|94|95|96|97|98|99|100|101|102|103|104|105|106|107|108|109|110|111|112|113|114|115|116|117|118|119|120|121|122|123|124|125|126|127|128|129|130|131|132|133|134|135|136|137|138|139|140|141|142|143|144|145|146|147|148|149|150|151|152|153|154|155|156|157|158|159|160|161|162|163|164|165|166|167|168|169|170|171|172|173|174|175|176|177|178|179|180|181|182|183|184|185|186|187|188|189|190|191|192|193|194|195|196|197|198|199|200|201|202|203|204|205|206|207|208|209|210|211|212|213|214|215|216|217|218|219|220|221|222|223|224|225|226|227|228|229|230|231|232|233|234|235|236|237|238|239|240|241|242|243|244|245|246|247|248|249|250|251|252|253|254|255" },
#endif
{ NULL, NULL },
};
cb(RETRO_ENVIRONMENT_SET_VARIABLES, (void*)vars);
libretro_set_core_options(environ_cb);
vfs_iface_info.required_interface_version = 1;
vfs_iface_info.iface = NULL;
@ -629,6 +559,8 @@ static void load_custom_palette(void)
static void check_variables(void)
{
unsigned i, j;
unsigned colorCorrection = 0;
struct retro_variable var = {0};
var.key = "gambatte_gbc_color_correction";
@ -700,8 +632,10 @@ static void check_variables(void)
}
#ifdef HAVE_NETWORK
gb_serialMode = SERIAL_NONE;
var.key = "gambatte_gb_link_mode";
var.value = NULL;
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
if (!strcmp(var.value, "Network Server")) {
gb_serialMode = SERIAL_SERVER;
@ -711,26 +645,47 @@ static void check_variables(void)
}
var.key = "gambatte_gb_link_network_port";
var.value = NULL;
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
gb_NetworkPort=atoi(var.value);
}
unsigned ip_index = 1;
gb_NetworkClientAddr = "";
var.key = "gambatte_gb_link_network_server_ip_octet1";
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
gb_NetworkClientAddr += std::string(var.value);
}
var.key = "gambatte_gb_link_network_server_ip_octet2";
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
gb_NetworkClientAddr += "." + std::string(var.value);
}
var.key = "gambatte_gb_link_network_server_ip_octet3";
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
gb_NetworkClientAddr += "." + std::string(var.value);
}
var.key = "gambatte_gb_link_network_server_ip_octet4";
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
gb_NetworkClientAddr += "." + std::string(var.value);
for (i = 0; i < 4; i++)
{
std::string octet = "0";
char tmp[8] = {0};
for (j = 0; j < 3; j++)
{
char key[64] = {0};
/* Should be using std::to_string() here, but some
* compilers don't support it... */
sprintf(key, "%s%u",
"gambatte_gb_link_network_server_ip_", ip_index);
var.key = key;
var.value = NULL;
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
octet += std::string(var.value);
ip_index++;
}
/* Remove leading zeros
* Should be using std::stoul() here, but some compilers
* don't support it... */
sprintf(tmp, "%u", atoi(octet.c_str()));
octet = std::string(tmp);
if (i < 3)
octet += ".";
gb_NetworkClientAddr += octet;
}
switch(gb_serialMode)
@ -748,6 +703,48 @@ static void check_variables(void)
gb.setSerialIO(NULL);
break;
}
/* Show/hide core options */
var.key = "gambatte_show_gb_link_settings";
var.value = NULL;
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
{
bool show_gb_link_settings_prev = show_gb_link_settings;
show_gb_link_settings = true;
if (strcmp(var.value, "disabled") == 0)
show_gb_link_settings = false;
if (show_gb_link_settings != show_gb_link_settings_prev)
{
struct retro_core_option_display option_display;
option_display.visible = show_gb_link_settings;
option_display.key = "gambatte_gb_link_mode";
environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY, &option_display);
option_display.key = "gambatte_gb_link_network_port";
environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY, &option_display);
for (i = 0; i < 12; i++)
{
char key[64] = {0};
/* Should be using std::to_string() here, but some
* compilers don't support it... */
sprintf(key, "%s%u",
"gambatte_gb_link_network_server_ip_", i + 1);
option_display.key = key;
environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY, &option_display);
}
}
}
#endif
var.key = "gambatte_gb_colorization";

View File

@ -0,0 +1,725 @@
#ifndef LIBRETRO_CORE_OPTIONS_H__
#define LIBRETRO_CORE_OPTIONS_H__
#include <stdlib.h>
#include <string.h>
#include <libretro.h>
#include <retro_inline.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
********************************
* Core Option Definitions
********************************
*/
/* 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_definition option_defs_us[] = {
{
"gambatte_up_down_allowed",
"Allow Opposing Directions",
"Enabling this will allow pressing / quickly alternating / holding both left and right (or up and down) directions at the same time. This may cause movement-based glitches.",
{
{ "disabled", NULL },
{ "enabled", NULL },
{ NULL, NULL },
},
"disabled"
},
{
"gambatte_gb_colorization",
"GB Colorization",
"Enables colorization of Game Boy games. 'Auto' selects the 'best' (most colorful/appropriate) palette. 'GBC' selects game-specific Game Boy Color palette if defined, otherwise 'GBC - Dark Green'. 'SGB' selects game-specific Super Game Boy palette if defined, otherwise 'SGB - 1A', 'Internal' uses 'Internal Palette' core option. 'Custom' loads user-created palette from system directory.",
{
{ "disabled", NULL },
{ "auto", "Auto" },
{ "GBC", "GBC" },
{ "SGB", "SGB" },
{ "internal", "Internal" },
{ "custom", "Custom" },
{ NULL, NULL },
},
"disabled"
},
{
"gambatte_gb_internal_palette",
"Internal Palette",
"Selects palette used for colorizing Game Boy games when 'GB Colorization' is set to 'Internal', or when 'GB Colorization' is set to 'Auto' and game has no pre-defined SGB/GBC palette. 'GB' palettes mimic the display of original Game Boy hardware. 'GBC' palettes are identical to the built-in presets of the Game Boy Color. 'SGB' palettes are identical to the built-in presets of the Super Game Boy.",
{
{ "GB - DMG", NULL },
{ "GB - Pocket", NULL },
{ "GB - Light", NULL },
{ "GBC - Blue", NULL },
{ "GBC - Brown", NULL },
{ "GBC - Dark Blue", NULL },
{ "GBC - Dark Brown", NULL },
{ "GBC - Dark Green", NULL },
{ "GBC - Grayscale", NULL },
{ "GBC - Green", NULL },
{ "GBC - Inverted", NULL },
{ "GBC - Orange", NULL },
{ "GBC - Pastel Mix", NULL },
{ "GBC - Red", NULL },
{ "GBC - Yellow", NULL },
{ "SGB - 1A", NULL },
{ "SGB - 1B", NULL },
{ "SGB - 1C", NULL },
{ "SGB - 1D", NULL },
{ "SGB - 1E", NULL },
{ "SGB - 1F", NULL },
{ "SGB - 1G", NULL },
{ "SGB - 1H", NULL },
{ "SGB - 2A", NULL },
{ "SGB - 2B", NULL },
{ "SGB - 2C", NULL },
{ "SGB - 2D", NULL },
{ "SGB - 2E", NULL },
{ "SGB - 2F", NULL },
{ "SGB - 2G", NULL },
{ "SGB - 2H", NULL },
{ "SGB - 3A", NULL },
{ "SGB - 3B", NULL },
{ "SGB - 3C", NULL },
{ "SGB - 3D", NULL },
{ "SGB - 3E", NULL },
{ "SGB - 3F", NULL },
{ "SGB - 3G", NULL },
{ "SGB - 3H", NULL },
{ "SGB - 4A", NULL },
{ "SGB - 4B", NULL },
{ "SGB - 4C", NULL },
{ "SGB - 4D", NULL },
{ "SGB - 4E", NULL },
{ "SGB - 4F", NULL },
{ "SGB - 4G", NULL },
{ "SGB - 4H", NULL },
{ "Special 1", NULL },
{ "Special 2", NULL },
{ "Special 3", NULL },
{ NULL, NULL },
},
"GB - DMG"
},
{
"gambatte_gbc_color_correction",
"Color Correction",
"Adjusts output colors to match the display of real Game Boy Color hardware. 'GBC Only' ensures that correction will only be applied when playing Game Boy Color games, or when using a Game Boy Color palette to colorize a Game Boy game. 'Always' applies color correction to all content, and will produce unexpected/suboptimal results when using 'GB' or 'SGB' internal color palettes.",
{
{ "GBC only", "GBC Only" },
{ "always", "Always" },
{ "disabled", NULL },
{ NULL, NULL },
},
"GBC only"
},
{
"gambatte_gbc_color_correction_mode",
"Color Correction Mode",
"Specifies method used when performing color correction. 'Accurate' produces output almost indistinguishable from a real Game Boy Color LCD panel. 'Fast' merely darkens colors and reduces saturation, and may be used on low-end hardware if the 'Accurate' method is too slow.",
{
{ "accurate", "Accurate" },
{ "fast", "Fast" },
{ NULL, NULL },
},
"accurate"
},
{
"gambatte_gbc_frontlight_position",
"Color Correction - Frontlight Position",
"Simulates the physical response of the Game Boy Color LCD panel when illuminated from different angles. 'Central' represents standard color reproduction. 'Above Screen' increases brightness. 'Below Screen' reduces brightness. This setting only applies when 'Color Correction Mode' is set to 'Accurate'.",
{
{ "central", "Central" },
{ "above screen", "Above Screen" },
{ "below screen", "Below Screen" },
{ NULL, NULL },
},
"central"
},
{
"gambatte_dark_filter_level",
"Dark Filter Level (percent)",
"Enable luminosity-based brightness reduction. May be used to avoid glare/eye strain when playing games with white backgrounds, which are intended for display on a non-backlit Game Boy Color and can therefore appear uncomfortably bright when viewed on a modern backlit screen.",
{
{ "0", NULL },
{ "5", NULL },
{ "10", NULL },
{ "15", NULL },
{ "20", NULL },
{ "25", NULL },
{ "30", NULL },
{ "35", NULL },
{ "40", NULL },
{ "45", NULL },
{ "50", NULL },
{ NULL, NULL },
},
"0"
},
{
"gambatte_gb_hwmode",
"Emulated Hardware (restart)",
"Specify which type of hardware to emulate. 'Auto' is recommended. Selecting 'GBA' unlocks extra features in certain 'GBA enhanced' Game Boy Color games (Shantae, Wendy - Every Witch Way, Legend of Zelda: Oracle of Seasons/Ages...).",
{
{ "Auto", NULL },
{ "GB", NULL },
{ "GBC", NULL },
{ "GBA", NULL },
{ NULL, NULL },
},
"Auto"
},
{
"gambatte_gb_bootloader",
"Use Official Bootloader (restart)",
"Enable support for official Game Boy and Game Boy Color bootloaders, with corresponding start-up logo animations.",
{
{ "enabled", NULL },
{ "disabled", NULL },
{ NULL, NULL },
},
"enabled"
},
{
"gambatte_mix_frames",
"Mix Frames",
"Enable simulation of LCD ghosting effects by blending the current and previous frames. 'Accurate' blends pixel values with high precision. 'Fast' uses an approximation, which causes slight color darkening/shifting but allows full speed operation on very low-end hardware. Frame mixing is required when playing games that rely on LCD ghosting for transparency effects (Wave Race, Ballistic, Chikyuu Kaihou Gun ZAS...).",
{
{ "disabled", NULL },
{ "accurate", "Accurate" },
{ "fast", "Fast" },
{ NULL, NULL },
},
"disabled"
},
#ifdef HAVE_NETWORK
{
"gambatte_show_gb_link_settings",
"Show Game Boy Link Settings",
"Enable configuration of networked 'Game Boy Link' (multiplayer) options. NOTE: Quick Menu must be toggled for this setting to take effect.",
{
{ "enabled", NULL },
{ "disabled", NULL },
{ NULL, NULL },
},
"disabled"
},
{
"gambatte_gb_link_mode",
"Game Boy Link Mode",
"When enabling networked 'Game Boy Link' functionality, specify whether current instance should run as a server or client.",
{
{ "Not Connected", NULL },
{ "Network Server", NULL },
{ "Network Client", NULL },
{ NULL, NULL },
},
"Not Connected"
},
{
"gambatte_gb_link_network_port",
"Network Link Port",
"Specify port used for 'Game Boy Link' network communication.",
{
{ "56400", NULL },
{ "56401", NULL },
{ "56402", NULL },
{ "56403", NULL },
{ "56404", NULL },
{ "56405", NULL },
{ "56406", NULL },
{ "56407", NULL },
{ "56408", NULL },
{ "56409", NULL },
{ "56410", NULL },
{ "56411", NULL },
{ "56412", NULL },
{ "56413", NULL },
{ "56414", NULL },
{ "56415", NULL },
{ "56416", NULL },
{ "56417", NULL },
{ "56418", NULL },
{ "56419", NULL },
{ "56420", NULL },
{ NULL, NULL },
},
"56400"
},
{
"gambatte_gb_link_network_server_ip_1",
"Network Link Server Address Pt. 01: x__.___.___.___",
"1st digit of remote 'Game Boy Link' network server IP address. Only used when 'Game Boy Link Mode' is set to 'Network Client'.",
{
{ "0", NULL },
{ "1", NULL },
{ "2", NULL },
{ "3", NULL },
{ "4", NULL },
{ "5", NULL },
{ "6", NULL },
{ "7", NULL },
{ "8", NULL },
{ "9", NULL },
{ NULL, NULL },
},
"0"
},
{
"gambatte_gb_link_network_server_ip_2",
"Network Link Server Address Pt. 02: _x_.___.___.___",
"2nd digit of remote 'Game Boy Link' network server IP address. Only used when 'Game Boy Link Mode' is set to 'Network Client'.",
{
{ "0", NULL },
{ "1", NULL },
{ "2", NULL },
{ "3", NULL },
{ "4", NULL },
{ "5", NULL },
{ "6", NULL },
{ "7", NULL },
{ "8", NULL },
{ "9", NULL },
{ NULL, NULL },
},
"0"
},
{
"gambatte_gb_link_network_server_ip_3",
"Network Link Server Address Pt. 03: __x.___.___.___",
"3rd digit of remote 'Game Boy Link' network server IP address. Only used when 'Game Boy Link Mode' is set to 'Network Client'.",
{
{ "0", NULL },
{ "1", NULL },
{ "2", NULL },
{ "3", NULL },
{ "4", NULL },
{ "5", NULL },
{ "6", NULL },
{ "7", NULL },
{ "8", NULL },
{ "9", NULL },
{ NULL, NULL },
},
"0"
},
{
"gambatte_gb_link_network_server_ip_4",
"Network Link Server Address Pt. 04: ___.x__.___.___",
"4th digit of remote 'Game Boy Link' network server IP address. Only used when 'Game Boy Link Mode' is set to 'Network Client'.",
{
{ "0", NULL },
{ "1", NULL },
{ "2", NULL },
{ "3", NULL },
{ "4", NULL },
{ "5", NULL },
{ "6", NULL },
{ "7", NULL },
{ "8", NULL },
{ "9", NULL },
{ NULL, NULL },
},
"0"
},
{
"gambatte_gb_link_network_server_ip_5",
"Network Link Server Address Pt. 05: ___._x_.___.___",
"5th digit of remote 'Game Boy Link' network server IP address. Only used when 'Game Boy Link Mode' is set to 'Network Client'.",
{
{ "0", NULL },
{ "1", NULL },
{ "2", NULL },
{ "3", NULL },
{ "4", NULL },
{ "5", NULL },
{ "6", NULL },
{ "7", NULL },
{ "8", NULL },
{ "9", NULL },
{ NULL, NULL },
},
"0"
},
{
"gambatte_gb_link_network_server_ip_6",
"Network Link Server Address Pt. 06: ___.__x.___.___",
"6th digit of remote 'Game Boy Link' network server IP address. Only used when 'Game Boy Link Mode' is set to 'Network Client'.",
{
{ "0", NULL },
{ "1", NULL },
{ "2", NULL },
{ "3", NULL },
{ "4", NULL },
{ "5", NULL },
{ "6", NULL },
{ "7", NULL },
{ "8", NULL },
{ "9", NULL },
{ NULL, NULL },
},
"0"
},
{
"gambatte_gb_link_network_server_ip_7",
"Network Link Server Address Pt. 07: ___.___.x__.___",
"7th digit of remote 'Game Boy Link' network server IP address. Only used when 'Game Boy Link Mode' is set to 'Network Client'.",
{
{ "0", NULL },
{ "1", NULL },
{ "2", NULL },
{ "3", NULL },
{ "4", NULL },
{ "5", NULL },
{ "6", NULL },
{ "7", NULL },
{ "8", NULL },
{ "9", NULL },
{ NULL, NULL },
},
"0"
},
{
"gambatte_gb_link_network_server_ip_8",
"Network Link Server Address Pt. 08: ___.___._x_.___",
"8th digit of remote 'Game Boy Link' network server IP address. Only used when 'Game Boy Link Mode' is set to 'Network Client'.",
{
{ "0", NULL },
{ "1", NULL },
{ "2", NULL },
{ "3", NULL },
{ "4", NULL },
{ "5", NULL },
{ "6", NULL },
{ "7", NULL },
{ "8", NULL },
{ "9", NULL },
{ NULL, NULL },
},
"0"
},
{
"gambatte_gb_link_network_server_ip_9",
"Network Link Server Address Pt. 09: ___.___.__x.___",
"9th digit of remote 'Game Boy Link' network server IP address. Only used when 'Game Boy Link Mode' is set to 'Network Client'.",
{
{ "0", NULL },
{ "1", NULL },
{ "2", NULL },
{ "3", NULL },
{ "4", NULL },
{ "5", NULL },
{ "6", NULL },
{ "7", NULL },
{ "8", NULL },
{ "9", NULL },
{ NULL, NULL },
},
"0"
},
{
"gambatte_gb_link_network_server_ip_10",
"Network Link Server Address Pt. 10: ___.___.___.x__",
"10th digit of remote 'Game Boy Link' network server IP address. Only used when 'Game Boy Link Mode' is set to 'Network Client'.",
{
{ "0", NULL },
{ "1", NULL },
{ "2", NULL },
{ "3", NULL },
{ "4", NULL },
{ "5", NULL },
{ "6", NULL },
{ "7", NULL },
{ "8", NULL },
{ "9", NULL },
{ NULL, NULL },
},
"0"
},
{
"gambatte_gb_link_network_server_ip_11",
"Network Link Server Address Pt. 11: ___.___.___._x_",
"11th digit of remote 'Game Boy Link' network server IP address. Only used when 'Game Boy Link Mode' is set to 'Network Client'.",
{
{ "0", NULL },
{ "1", NULL },
{ "2", NULL },
{ "3", NULL },
{ "4", NULL },
{ "5", NULL },
{ "6", NULL },
{ "7", NULL },
{ "8", NULL },
{ "9", NULL },
{ NULL, NULL },
},
"0"
},
{
"gambatte_gb_link_network_server_ip_12",
"Network Link Server Address Pt. 12: ___.___.___.__x",
"12th digit of remote 'Game Boy Link' network server IP address. Only used when 'Game Boy Link Mode' is set to 'Network Client'.",
{
{ "0", NULL },
{ "1", NULL },
{ "2", NULL },
{ "3", NULL },
{ "4", NULL },
{ "5", NULL },
{ "6", NULL },
{ "7", NULL },
{ "8", NULL },
{ "9", NULL },
{ NULL, NULL },
},
"0"
},
#endif
{ NULL, NULL, NULL, {{0}}, NULL },
};
/* RETRO_LANGUAGE_JAPANESE */
/* RETRO_LANGUAGE_FRENCH */
/* RETRO_LANGUAGE_SPANISH */
/* RETRO_LANGUAGE_GERMAN */
/* RETRO_LANGUAGE_ITALIAN */
/* RETRO_LANGUAGE_DUTCH */
/* RETRO_LANGUAGE_PORTUGUESE_BRAZIL */
/* RETRO_LANGUAGE_PORTUGUESE_PORTUGAL */
/* RETRO_LANGUAGE_RUSSIAN */
/* RETRO_LANGUAGE_KOREAN */
/* RETRO_LANGUAGE_CHINESE_TRADITIONAL */
/* RETRO_LANGUAGE_CHINESE_SIMPLIFIED */
/* RETRO_LANGUAGE_ESPERANTO */
/* RETRO_LANGUAGE_POLISH */
/* RETRO_LANGUAGE_VIETNAMESE */
/* RETRO_LANGUAGE_ARABIC */
/* RETRO_LANGUAGE_GREEK */
/* RETRO_LANGUAGE_TURKISH */
/*
********************************
* Language Mapping
********************************
*/
struct retro_core_option_definition *option_defs_intl[RETRO_LANGUAGE_LAST] = {
option_defs_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 */
};
/*
********************************
* 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)
{
unsigned version = 0;
if (!environ_cb)
return;
if (environ_cb(RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION, &version) && (version == 1))
{
struct retro_core_options_intl core_options_intl;
unsigned language = 0;
core_options_intl.us = option_defs_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 = option_defs_intl[language];
environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL, &core_options_intl);
}
else
{
size_t i;
size_t option_index = 0;
size_t num_options = 0;
struct retro_variable *variables = NULL;
char **values_buf = NULL;
/* Determine number of options
* > Note: We are going to skip a number of irrelevant
* core options when building the retro_variable array,
* but we'll allocate space for all of them. The difference
* in resource usage is negligible, and this allows us to
* keep the code 'cleaner' */
while (true)
{
if (option_defs_us[num_options].key)
num_options++;
else
break;
}
/* 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, "gambatte_show_gb_link_settings") == 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 > 1)
{
size_t j;
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 (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