mirror of https://github.com/bsnes-emu/bsnes.git
Merge branch 'libretro-core-options'
This commit is contained in:
commit
0b2411ecc6
|
@ -6,7 +6,7 @@
|
|||
#include <assert.h>
|
||||
#include <signal.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#ifndef WIIU
|
||||
#define AUDIO_FREQUENCY 384000
|
||||
#else
|
||||
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include <Core/gb.h>
|
||||
#include "libretro.h"
|
||||
#include "libretro_core_options.inc"
|
||||
|
||||
#ifdef _WIN32
|
||||
static const char slash = '\\';
|
||||
|
@ -45,20 +46,24 @@ char battery_save_path[512];
|
|||
char symbols_path[512];
|
||||
|
||||
enum model {
|
||||
MODEL_DMG,
|
||||
MODEL_CGB,
|
||||
MODEL_DMG_B,
|
||||
MODEL_CGB_C,
|
||||
MODEL_CGB_E,
|
||||
MODEL_AGB,
|
||||
MODEL_SGB,
|
||||
MODEL_SGB_PAL,
|
||||
MODEL_SGB_NTSC,
|
||||
MODEL_SGB2,
|
||||
MODEL_AUTO
|
||||
};
|
||||
|
||||
static const GB_model_t libretro_to_internal_model[] =
|
||||
{
|
||||
[MODEL_DMG] = GB_MODEL_DMG_B,
|
||||
[MODEL_CGB] = GB_MODEL_CGB_E,
|
||||
[MODEL_DMG_B] = GB_MODEL_DMG_B,
|
||||
[MODEL_CGB_C] = GB_MODEL_CGB_C,
|
||||
[MODEL_CGB_E] = GB_MODEL_CGB_E,
|
||||
[MODEL_AGB] = GB_MODEL_AGB,
|
||||
[MODEL_SGB] = GB_MODEL_SGB,
|
||||
[MODEL_SGB_PAL] = GB_MODEL_SGB_PAL,
|
||||
[MODEL_SGB_NTSC] = GB_MODEL_SGB_NTSC,
|
||||
[MODEL_SGB2] = GB_MODEL_SGB2
|
||||
};
|
||||
|
||||
|
@ -73,7 +78,7 @@ enum audio_out {
|
|||
};
|
||||
|
||||
static enum model model[2];
|
||||
static enum model auto_model = MODEL_CGB;
|
||||
static enum model auto_model = MODEL_CGB_E;
|
||||
|
||||
static uint32_t *frame_buf = NULL;
|
||||
static uint32_t *frame_buf_copy = NULL;
|
||||
|
@ -230,33 +235,68 @@ static uint32_t rgb_encode(GB_gameboy_t *gb, uint8_t r, uint8_t g, uint8_t b)
|
|||
|
||||
static retro_environment_t environ_cb;
|
||||
|
||||
/* variables for single cart mode */
|
||||
static const struct retro_variable vars_single[] = {
|
||||
{ "sameboy_color_correction_mode", "Color correction; emulate hardware|preserve brightness|reduce contrast|harsh reality|off|correct curves" },
|
||||
{ "sameboy_high_pass_filter_mode", "High-pass filter; accurate|remove dc offset|off" },
|
||||
{ "sameboy_model", "Emulated model (Restart game); Auto|Game Boy|Game Boy Color|Game Boy Advance|Super Game Boy|Super Game Boy 2" },
|
||||
{ "sameboy_border", "Display border; Super Game Boy only|always|never" },
|
||||
{ "sameboy_rumble", "Enable rumble; rumble-enabled games|all games|never" },
|
||||
{ "sameboy_rtc", "Real Time Clock emulation; sync to system clock|accurate" },
|
||||
{ NULL }
|
||||
};
|
||||
static void set_variable_visibility(void)
|
||||
{
|
||||
struct retro_core_option_display option_display_singlecart;
|
||||
struct retro_core_option_display option_display_dualcart;
|
||||
|
||||
/* variables for dual cart dual gameboy mode */
|
||||
static const struct retro_variable vars_dual[] = {
|
||||
{ "sameboy_link", "Link cable emulation; enabled|disabled" },
|
||||
/*{ "sameboy_ir", "Infrared Sensor Emulation; disabled|enabled" },*/
|
||||
{ "sameboy_screen_layout", "Screen layout; top-down|left-right" },
|
||||
{ "sameboy_audio_output", "Audio output; Game Boy #1|Game Boy #2" },
|
||||
{ "sameboy_model_1", "Emulated model for Game Boy #1 (Restart game); Auto|Game Boy|Game Boy Color|Game Boy Advance" },
|
||||
{ "sameboy_model_2", "Emulated model for Game Boy #2 (Restart game); Auto|Game Boy|Game Boy Color|Game Boy Advance" },
|
||||
{ "sameboy_color_correction_mode_1", "Color correction for Game Boy #1; emulate hardware|preserve brightness|reduce contrast|harsh reality|off|correct curves" },
|
||||
{ "sameboy_color_correction_mode_2", "Color correction for Game Boy #2; emulate hardware|preserve brightness|harsh reality|off|correct curves" },
|
||||
{ "sameboy_high_pass_filter_mode_1", "High-pass filter for Game Boy #1; accurate|remove dc offset|off" },
|
||||
{ "sameboy_high_pass_filter_mode_2", "High-pass filter for Game Boy #2; accurate|remove dc offset|off" },
|
||||
{ "sameboy_rumble_1", "Enable rumble for Game Boy #1; rumble-enabled games|all games|never" },
|
||||
{ "sameboy_rumble_2", "Enable rumble for Game Boy #2; rumble-enabled games|all games|never" },
|
||||
{ NULL }
|
||||
};
|
||||
size_t i;
|
||||
size_t num_options = 0;
|
||||
|
||||
// Show/hide options depending on the number of emulated devices
|
||||
if (emulated_devices == 1) {
|
||||
option_display_singlecart.visible = true;
|
||||
option_display_dualcart.visible = false;
|
||||
}
|
||||
else if (emulated_devices == 2) {
|
||||
option_display_singlecart.visible = false;
|
||||
option_display_dualcart.visible = true;
|
||||
}
|
||||
|
||||
// Determine number of options
|
||||
while (true) {
|
||||
if (!option_defs_us[num_options].key) break;
|
||||
num_options++;
|
||||
}
|
||||
|
||||
// Copy parameters from option_defs_us array
|
||||
for (i = 0; i < num_options; i++) {
|
||||
const char *key = option_defs_us[i].key;
|
||||
if ((strcmp(key, "sameboy_model") == 0) ||
|
||||
(strcmp(key, "sameboy_rtc") == 0) ||
|
||||
(strcmp(key, "sameboy_scaling_filter") == 0) ||
|
||||
(strcmp(key, "sameboy_mono_palette") == 0) ||
|
||||
(strcmp(key, "sameboy_color_correction_mode") == 0) ||
|
||||
(strcmp(key, "sameboy_light_temperature") == 0) ||
|
||||
(strcmp(key, "sameboy_border") == 0) ||
|
||||
(strcmp(key, "sameboy_high_pass_filter_mode") == 0) ||
|
||||
(strcmp(key, "sameboy_audio_interference") == 0) ||
|
||||
(strcmp(key, "sameboy_rumble") == 0)) {
|
||||
option_display_singlecart.key = key;
|
||||
environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY, &option_display_singlecart);
|
||||
}
|
||||
else if ((strcmp(key, "sameboy_link") == 0) ||
|
||||
(strcmp(key, "sameboy_screen_layout") == 0) ||
|
||||
(strcmp(key, "sameboy_audio_output") == 0) ||
|
||||
(strcmp(key, "sameboy_model_1") == 0) ||
|
||||
(strcmp(key, "sameboy_model_2") == 0) ||
|
||||
(strcmp(key, "sameboy_mono_palette_1") == 0) ||
|
||||
(strcmp(key, "sameboy_mono_palette_2") == 0) ||
|
||||
(strcmp(key, "sameboy_color_correction_mode_1") == 0) ||
|
||||
(strcmp(key, "sameboy_color_correction_mode_2") == 0) ||
|
||||
(strcmp(key, "sameboy_light_temperature_1") == 0) ||
|
||||
(strcmp(key, "sameboy_light_temperature_2") == 0) ||
|
||||
(strcmp(key, "sameboy_high_pass_filter_mode_1") == 0) ||
|
||||
(strcmp(key, "sameboy_high_pass_filter_mode_2") == 0) ||
|
||||
(strcmp(key, "sameboy_audio_interference_1") == 0) ||
|
||||
(strcmp(key, "sameboy_audio_interference_2") == 0) ||
|
||||
(strcmp(key, "sameboy_rumble_1") == 0) ||
|
||||
(strcmp(key, "sameboy_rumble_2") == 0)) {
|
||||
option_display_dualcart.key = key;
|
||||
environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY, &option_display_dualcart);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const struct retro_subsystem_memory_info gb1_memory[] = {
|
||||
{ "srm", RETRO_MEMORY_GAMEBOY_1_SRAM },
|
||||
|
@ -388,8 +428,7 @@ static void boot_rom_load(GB_gameboy_t *gb, GB_boot_rom_t type)
|
|||
[GB_BOOT_ROM_AGB] = "agb",
|
||||
}[type];
|
||||
|
||||
const uint8_t *boot_code = (const unsigned char *[])
|
||||
{
|
||||
const uint8_t *boot_code = (const unsigned char *[]) {
|
||||
[GB_BOOT_ROM_DMG0] = dmg_boot, // dmg0 not implemented yet
|
||||
[GB_BOOT_ROM_DMG] = dmg_boot,
|
||||
[GB_BOOT_ROM_MGB] = dmg_boot, // mgb not implemented yet
|
||||
|
@ -527,7 +566,7 @@ static void init_for_current_model(unsigned id)
|
|||
}
|
||||
|
||||
/* Let's be extremely nitpicky about how devices and descriptors are set */
|
||||
if (emulated_devices == 1 && (model[0] == MODEL_SGB || model[0] == MODEL_SGB2)) {
|
||||
if (emulated_devices == 1 && (model[0] == MODEL_SGB_PAL || model[0] == MODEL_SGB_NTSC || model[0] == MODEL_SGB2)) {
|
||||
static const struct retro_controller_info ports[] = {
|
||||
{ controllers_sgb, 1 },
|
||||
{ controllers_sgb, 1 },
|
||||
|
@ -555,13 +594,73 @@ static void init_for_current_model(unsigned id)
|
|||
environ_cb(RETRO_ENVIRONMENT_SET_CONTROLLER_INFO, (void*)ports);
|
||||
environ_cb(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, descriptors_2p);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void check_variables()
|
||||
{
|
||||
struct retro_variable var = {0};
|
||||
if (emulated_devices == 1) {
|
||||
|
||||
var.key = "sameboy_model";
|
||||
var.value = NULL;
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
|
||||
enum model new_model = model[0];
|
||||
if (strcmp(var.value, "Game Boy") == 0) {
|
||||
new_model = MODEL_DMG_B;
|
||||
}
|
||||
else if (strcmp(var.value, "Game Boy Color C") == 0) {
|
||||
new_model = MODEL_CGB_C;
|
||||
}
|
||||
else if (strcmp(var.value, "Game Boy Color") == 0) {
|
||||
new_model = MODEL_CGB_E;
|
||||
}
|
||||
else if (strcmp(var.value, "Game Boy Advance") == 0) {
|
||||
new_model = MODEL_AGB;
|
||||
}
|
||||
else if (strcmp(var.value, "Super Game Boy") == 0) {
|
||||
new_model = MODEL_SGB_NTSC;
|
||||
}
|
||||
else if (strcmp(var.value, "Super Game Boy PAL") == 0) {
|
||||
new_model = MODEL_SGB_PAL;
|
||||
}
|
||||
else if (strcmp(var.value, "Super Game Boy 2") == 0) {
|
||||
new_model = MODEL_SGB2;
|
||||
}
|
||||
else {
|
||||
new_model = MODEL_AUTO;
|
||||
}
|
||||
|
||||
model[0] = new_model;
|
||||
}
|
||||
|
||||
var.key = "sameboy_rtc";
|
||||
var.value = NULL;
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
|
||||
if (strcmp(var.value, "sync to system clock") == 0) {
|
||||
GB_set_rtc_mode(&gameboy[0], GB_RTC_MODE_SYNC_TO_HOST);
|
||||
}
|
||||
else if (strcmp(var.value, "accurate") == 0) {
|
||||
GB_set_rtc_mode(&gameboy[0], GB_RTC_MODE_ACCURATE);
|
||||
}
|
||||
}
|
||||
|
||||
var.key = "sameboy_mono_palette";
|
||||
var.value = NULL;
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
|
||||
if (strcmp(var.value, "greyscale") == 0) {
|
||||
GB_set_palette(&gameboy[0], &GB_PALETTE_GREY);
|
||||
}
|
||||
else if (strcmp(var.value, "lime") == 0) {
|
||||
GB_set_palette(&gameboy[0], &GB_PALETTE_DMG);
|
||||
}
|
||||
else if (strcmp(var.value, "olive") == 0) {
|
||||
GB_set_palette(&gameboy[0], &GB_PALETTE_MGB);
|
||||
}
|
||||
else if (strcmp(var.value, "teal") == 0) {
|
||||
GB_set_palette(&gameboy[0], &GB_PALETTE_GBL);
|
||||
}
|
||||
}
|
||||
|
||||
var.key = "sameboy_color_correction_mode";
|
||||
var.value = NULL;
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
|
||||
|
@ -585,29 +684,25 @@ static void check_variables()
|
|||
}
|
||||
}
|
||||
|
||||
var.key = "sameboy_rumble";
|
||||
var.key = "sameboy_light_temperature";
|
||||
var.value = NULL;
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
|
||||
GB_set_light_temperature(&gameboy[0], atof(var.value));
|
||||
}
|
||||
|
||||
var.key = "sameboy_border";
|
||||
var.value = NULL;
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
|
||||
if (strcmp(var.value, "never") == 0) {
|
||||
GB_set_rumble_mode(&gameboy[0], GB_RUMBLE_DISABLED);
|
||||
GB_set_border_mode(&gameboy[0], GB_BORDER_NEVER);
|
||||
}
|
||||
else if (strcmp(var.value, "rumble-enabled games") == 0) {
|
||||
GB_set_rumble_mode(&gameboy[0], GB_RUMBLE_CARTRIDGE_ONLY);
|
||||
else if (strcmp(var.value, "Super Game Boy only") == 0) {
|
||||
GB_set_border_mode(&gameboy[0], GB_BORDER_SGB);
|
||||
}
|
||||
else if (strcmp(var.value, "all games") == 0) {
|
||||
GB_set_rumble_mode(&gameboy[0], GB_RUMBLE_ALL_GAMES);
|
||||
}
|
||||
}
|
||||
|
||||
var.key = "sameboy_rtc";
|
||||
var.value = NULL;
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
|
||||
if (strcmp(var.value, "sync to system clock") == 0) {
|
||||
GB_set_rtc_mode(&gameboy[0], GB_RTC_MODE_SYNC_TO_HOST);
|
||||
}
|
||||
else if (strcmp(var.value, "accurate") == 0) {
|
||||
GB_set_rtc_mode(&gameboy[0], GB_RTC_MODE_ACCURATE);
|
||||
else if (strcmp(var.value, "always") == 0) {
|
||||
GB_set_border_mode(&gameboy[0], GB_BORDER_ALWAYS);
|
||||
}
|
||||
geometry_updated = true;
|
||||
}
|
||||
|
||||
var.key = "sameboy_high_pass_filter_mode";
|
||||
|
@ -624,21 +719,96 @@ static void check_variables()
|
|||
}
|
||||
}
|
||||
|
||||
var.key = "sameboy_model";
|
||||
var.key = "sameboy_audio_interference";
|
||||
var.value = NULL;
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
|
||||
GB_set_interference_volume(&gameboy[0], atoi(var.value) / 100.0);
|
||||
}
|
||||
|
||||
var.key = "sameboy_rumble";
|
||||
var.value = NULL;
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
|
||||
if (strcmp(var.value, "never") == 0) {
|
||||
GB_set_rumble_mode(&gameboy[0], GB_RUMBLE_DISABLED);
|
||||
}
|
||||
else if (strcmp(var.value, "rumble-enabled games") == 0) {
|
||||
GB_set_rumble_mode(&gameboy[0], GB_RUMBLE_CARTRIDGE_ONLY);
|
||||
}
|
||||
else if (strcmp(var.value, "all games") == 0) {
|
||||
GB_set_rumble_mode(&gameboy[0], GB_RUMBLE_ALL_GAMES);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
GB_set_border_mode(&gameboy[0], GB_BORDER_NEVER);
|
||||
GB_set_border_mode(&gameboy[1], GB_BORDER_NEVER);
|
||||
GB_set_rtc_mode(&gameboy[0], GB_RTC_MODE_ACCURATE);
|
||||
GB_set_rtc_mode(&gameboy[1], GB_RTC_MODE_ACCURATE);
|
||||
|
||||
var.key = "sameboy_link";
|
||||
var.value = NULL;
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
|
||||
bool tmp = link_cable_emulation;
|
||||
if (strcmp(var.value, "enabled") == 0) {
|
||||
link_cable_emulation = true;
|
||||
}
|
||||
else {
|
||||
link_cable_emulation = false;
|
||||
}
|
||||
if (link_cable_emulation && link_cable_emulation != tmp) {
|
||||
set_link_cable_state(true);
|
||||
}
|
||||
else if (!link_cable_emulation && link_cable_emulation != tmp) {
|
||||
set_link_cable_state(false);
|
||||
}
|
||||
}
|
||||
|
||||
var.key = "sameboy_screen_layout";
|
||||
var.value = NULL;
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
|
||||
if (strcmp(var.value, "top-down") == 0) {
|
||||
screen_layout = LAYOUT_TOP_DOWN;
|
||||
}
|
||||
else {
|
||||
screen_layout = LAYOUT_LEFT_RIGHT;
|
||||
}
|
||||
|
||||
geometry_updated = true;
|
||||
}
|
||||
|
||||
var.key = "sameboy_audio_output";
|
||||
var.value = NULL;
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
|
||||
if (strcmp(var.value, "Game Boy #1") == 0) {
|
||||
audio_out = GB_1;
|
||||
}
|
||||
else {
|
||||
audio_out = GB_2;
|
||||
}
|
||||
}
|
||||
|
||||
var.key = "sameboy_model_1";
|
||||
var.value = NULL;
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
|
||||
enum model new_model = model[0];
|
||||
if (strcmp(var.value, "Game Boy") == 0) {
|
||||
new_model = MODEL_DMG;
|
||||
new_model = MODEL_DMG_B;
|
||||
}
|
||||
else if (strcmp(var.value, "Game Boy Color C") == 0) {
|
||||
new_model = MODEL_CGB_C;
|
||||
}
|
||||
else if (strcmp(var.value, "Game Boy Color") == 0) {
|
||||
new_model = MODEL_CGB;
|
||||
new_model = MODEL_CGB_E;
|
||||
}
|
||||
else if (strcmp(var.value, "Game Boy Advance") == 0) {
|
||||
new_model = MODEL_AGB;
|
||||
}
|
||||
else if (strcmp(var.value, "Super Game Boy") == 0) {
|
||||
new_model = MODEL_SGB;
|
||||
new_model = MODEL_SGB_NTSC;
|
||||
}
|
||||
else if (strcmp(var.value, "Super Game Boy PAL") == 0) {
|
||||
new_model = MODEL_SGB_PAL;
|
||||
}
|
||||
else if (strcmp(var.value, "Super Game Boy 2") == 0) {
|
||||
new_model = MODEL_SGB2;
|
||||
|
@ -650,27 +820,72 @@ static void check_variables()
|
|||
model[0] = new_model;
|
||||
}
|
||||
|
||||
var.key = "sameboy_border";
|
||||
var.key = "sameboy_model_2";
|
||||
var.value = NULL;
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
|
||||
if (strcmp(var.value, "never") == 0) {
|
||||
GB_set_border_mode(&gameboy[0], GB_BORDER_NEVER);
|
||||
enum model new_model = model[1];
|
||||
if (strcmp(var.value, "Game Boy") == 0) {
|
||||
new_model = MODEL_DMG_B;
|
||||
}
|
||||
else if (strcmp(var.value, "Super Game Boy only") == 0) {
|
||||
GB_set_border_mode(&gameboy[0], GB_BORDER_SGB);
|
||||
else if (strcmp(var.value, "Game Boy Color C") == 0) {
|
||||
new_model = MODEL_CGB_C;
|
||||
}
|
||||
else if (strcmp(var.value, "always") == 0) {
|
||||
GB_set_border_mode(&gameboy[0], GB_BORDER_ALWAYS);
|
||||
else if (strcmp(var.value, "Game Boy Color") == 0) {
|
||||
new_model = MODEL_CGB_E;
|
||||
}
|
||||
|
||||
geometry_updated = true;
|
||||
else if (strcmp(var.value, "Game Boy Advance") == 0) {
|
||||
new_model = MODEL_AGB;
|
||||
}
|
||||
else if (strcmp(var.value, "Super Game Boy") == 0) {
|
||||
new_model = MODEL_SGB_NTSC;
|
||||
}
|
||||
else if (strcmp(var.value, "Super Game Boy PAL") == 0) {
|
||||
new_model = MODEL_SGB_PAL;
|
||||
}
|
||||
else if (strcmp(var.value, "Super Game Boy 2") == 0) {
|
||||
new_model = MODEL_SGB2;
|
||||
}
|
||||
else {
|
||||
GB_set_border_mode(&gameboy[0], GB_BORDER_NEVER);
|
||||
GB_set_border_mode(&gameboy[1], GB_BORDER_NEVER);
|
||||
GB_set_rtc_mode(&gameboy[0], GB_RTC_MODE_ACCURATE);
|
||||
GB_set_rtc_mode(&gameboy[1], GB_RTC_MODE_ACCURATE);
|
||||
new_model = MODEL_AUTO;
|
||||
}
|
||||
|
||||
model[1] = new_model;
|
||||
}
|
||||
|
||||
var.key = "sameboy_mono_palette_1";
|
||||
var.value = NULL;
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
|
||||
if (strcmp(var.value, "greyscale") == 0) {
|
||||
GB_set_palette(&gameboy[0], &GB_PALETTE_GREY);
|
||||
}
|
||||
else if (strcmp(var.value, "lime") == 0) {
|
||||
GB_set_palette(&gameboy[0], &GB_PALETTE_DMG);
|
||||
}
|
||||
else if (strcmp(var.value, "olive") == 0) {
|
||||
GB_set_palette(&gameboy[0], &GB_PALETTE_MGB);
|
||||
}
|
||||
else if (strcmp(var.value, "teal") == 0) {
|
||||
GB_set_palette(&gameboy[0], &GB_PALETTE_GBL);
|
||||
}
|
||||
}
|
||||
|
||||
var.key = "sameboy_mono_palette_2";
|
||||
var.value = NULL;
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
|
||||
if (strcmp(var.value, "greyscale") == 0) {
|
||||
GB_set_palette(&gameboy[1], &GB_PALETTE_GREY);
|
||||
}
|
||||
else if (strcmp(var.value, "lime") == 0) {
|
||||
GB_set_palette(&gameboy[1], &GB_PALETTE_DMG);
|
||||
}
|
||||
else if (strcmp(var.value, "olive") == 0) {
|
||||
GB_set_palette(&gameboy[1], &GB_PALETTE_MGB);
|
||||
}
|
||||
else if (strcmp(var.value, "teal") == 0) {
|
||||
GB_set_palette(&gameboy[1], &GB_PALETTE_GBL);
|
||||
}
|
||||
}
|
||||
|
||||
var.key = "sameboy_color_correction_mode_1";
|
||||
var.value = NULL;
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
|
||||
|
@ -715,35 +930,18 @@ static void check_variables()
|
|||
else if (strcmp(var.value, "harsh reality") == 0) {
|
||||
GB_set_color_correction_mode(&gameboy[1], GB_COLOR_CORRECTION_LOW_CONTRAST);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var.key = "sameboy_rumble_1";
|
||||
var.key = "sameboy_light_temperature_1";
|
||||
var.value = NULL;
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
|
||||
if (strcmp(var.value, "never") == 0) {
|
||||
GB_set_rumble_mode(&gameboy[0], GB_RUMBLE_DISABLED);
|
||||
}
|
||||
else if (strcmp(var.value, "rumble-enabled games") == 0) {
|
||||
GB_set_rumble_mode(&gameboy[0], GB_RUMBLE_CARTRIDGE_ONLY);
|
||||
}
|
||||
else if (strcmp(var.value, "all games") == 0) {
|
||||
GB_set_rumble_mode(&gameboy[0], GB_RUMBLE_ALL_GAMES);
|
||||
}
|
||||
GB_set_light_temperature(&gameboy[0], atof(var.value));
|
||||
}
|
||||
|
||||
var.key = "sameboy_rumble_2";
|
||||
var.key = "sameboy_light_temperature_2";
|
||||
var.value = NULL;
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
|
||||
if (strcmp(var.value, "never") == 0) {
|
||||
GB_set_rumble_mode(&gameboy[1], GB_RUMBLE_DISABLED);
|
||||
}
|
||||
else if (strcmp(var.value, "rumble-enabled games") == 0) {
|
||||
GB_set_rumble_mode(&gameboy[1], GB_RUMBLE_CARTRIDGE_ONLY);
|
||||
}
|
||||
else if (strcmp(var.value, "all games") == 0) {
|
||||
GB_set_rumble_mode(&gameboy[1], GB_RUMBLE_ALL_GAMES);
|
||||
}
|
||||
GB_set_light_temperature(&gameboy[1], atof(var.value));
|
||||
}
|
||||
|
||||
var.key = "sameboy_high_pass_filter_mode_1";
|
||||
|
@ -774,100 +972,48 @@ static void check_variables()
|
|||
}
|
||||
}
|
||||
|
||||
var.key = "sameboy_model_1";
|
||||
var.key = "sameboy_audio_interference_1";
|
||||
var.value = NULL;
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
|
||||
enum model new_model = model[0];
|
||||
if (strcmp(var.value, "Game Boy") == 0) {
|
||||
new_model = MODEL_DMG;
|
||||
}
|
||||
else if (strcmp(var.value, "Game Boy Color") == 0) {
|
||||
new_model = MODEL_CGB;
|
||||
}
|
||||
else if (strcmp(var.value, "Game Boy Advance") == 0) {
|
||||
new_model = MODEL_AGB;
|
||||
}
|
||||
else if (strcmp(var.value, "Super Game Boy") == 0) {
|
||||
new_model = MODEL_SGB;
|
||||
}
|
||||
else if (strcmp(var.value, "Super Game Boy 2") == 0) {
|
||||
new_model = MODEL_SGB2;
|
||||
}
|
||||
else {
|
||||
new_model = MODEL_AUTO;
|
||||
GB_set_interference_volume(&gameboy[0], atoi(var.value) / 100.0);
|
||||
}
|
||||
|
||||
model[0] = new_model;
|
||||
}
|
||||
|
||||
var.key = "sameboy_model_2";
|
||||
var.key = "sameboy_audio_interference_2";
|
||||
var.value = NULL;
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
|
||||
enum model new_model = model[1];
|
||||
if (strcmp(var.value, "Game Boy") == 0) {
|
||||
new_model = MODEL_DMG;
|
||||
}
|
||||
else if (strcmp(var.value, "Game Boy Color") == 0) {
|
||||
new_model = MODEL_CGB;
|
||||
}
|
||||
else if (strcmp(var.value, "Game Boy Advance") == 0) {
|
||||
new_model = MODEL_AGB;
|
||||
}
|
||||
else if (strcmp(var.value, "Super Game Boy") == 0) {
|
||||
new_model = MODEL_SGB;
|
||||
}
|
||||
else if (strcmp(var.value, "Super Game Boy 2") == 0) {
|
||||
new_model = MODEL_SGB;
|
||||
}
|
||||
else {
|
||||
new_model = MODEL_AUTO;
|
||||
GB_set_interference_volume(&gameboy[1], atoi(var.value) / 100.0);
|
||||
}
|
||||
|
||||
model[1] = new_model;
|
||||
}
|
||||
|
||||
var.key = "sameboy_screen_layout";
|
||||
var.key = "sameboy_rumble_1";
|
||||
var.value = NULL;
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
|
||||
if (strcmp(var.value, "top-down") == 0) {
|
||||
screen_layout = LAYOUT_TOP_DOWN;
|
||||
if (strcmp(var.value, "never") == 0) {
|
||||
GB_set_rumble_mode(&gameboy[0], GB_RUMBLE_DISABLED);
|
||||
}
|
||||
else if (strcmp(var.value, "rumble-enabled games") == 0) {
|
||||
GB_set_rumble_mode(&gameboy[0], GB_RUMBLE_CARTRIDGE_ONLY);
|
||||
}
|
||||
else if (strcmp(var.value, "all games") == 0) {
|
||||
GB_set_rumble_mode(&gameboy[0], GB_RUMBLE_ALL_GAMES);
|
||||
}
|
||||
else {
|
||||
screen_layout = LAYOUT_LEFT_RIGHT;
|
||||
}
|
||||
|
||||
geometry_updated = true;
|
||||
}
|
||||
|
||||
var.key = "sameboy_link";
|
||||
var.key = "sameboy_rumble_2";
|
||||
var.value = NULL;
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
|
||||
bool tmp = link_cable_emulation;
|
||||
if (strcmp(var.value, "enabled") == 0) {
|
||||
link_cable_emulation = true;
|
||||
if (strcmp(var.value, "never") == 0) {
|
||||
GB_set_rumble_mode(&gameboy[1], GB_RUMBLE_DISABLED);
|
||||
}
|
||||
else {
|
||||
link_cable_emulation = false;
|
||||
else if (strcmp(var.value, "rumble-enabled games") == 0) {
|
||||
GB_set_rumble_mode(&gameboy[1], GB_RUMBLE_CARTRIDGE_ONLY);
|
||||
}
|
||||
if (link_cable_emulation && link_cable_emulation != tmp) {
|
||||
set_link_cable_state(true);
|
||||
}
|
||||
else if (!link_cable_emulation && link_cable_emulation != tmp) {
|
||||
set_link_cable_state(false);
|
||||
else if (strcmp(var.value, "all games") == 0) {
|
||||
GB_set_rumble_mode(&gameboy[1], GB_RUMBLE_ALL_GAMES);
|
||||
}
|
||||
}
|
||||
|
||||
var.key = "sameboy_audio_output";
|
||||
var.value = NULL;
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
|
||||
if (strcmp(var.value, "Game Boy #1") == 0) {
|
||||
audio_out = GB_1;
|
||||
}
|
||||
else {
|
||||
audio_out = GB_2;
|
||||
}
|
||||
}
|
||||
}
|
||||
set_variable_visibility();
|
||||
}
|
||||
|
||||
void retro_init(void)
|
||||
|
@ -968,6 +1114,8 @@ void retro_set_environment(retro_environment_t cb)
|
|||
{
|
||||
environ_cb = cb;
|
||||
|
||||
libretro_set_core_options(environ_cb);
|
||||
|
||||
cb(RETRO_ENVIRONMENT_SET_SUBSYSTEM_INFO, (void*)subsystems);
|
||||
}
|
||||
|
||||
|
@ -1035,7 +1183,7 @@ void retro_run(void)
|
|||
GB_update_keys_status(&gameboy[0], 0);
|
||||
GB_update_keys_status(&gameboy[1], 1);
|
||||
}
|
||||
else if (emulated_devices == 1 && (model[0] == MODEL_SGB || model[0] == MODEL_SGB2)) {
|
||||
else if (emulated_devices == 1 && (model[0] == MODEL_SGB_PAL || model[0] == MODEL_SGB_NTSC || model[0] == MODEL_SGB2)) {
|
||||
for (unsigned i = 0; i < 4; i++) {
|
||||
GB_update_keys_status(&gameboy[0], i);
|
||||
}
|
||||
|
@ -1094,7 +1242,6 @@ void retro_run(void)
|
|||
|
||||
bool retro_load_game(const struct retro_game_info *info)
|
||||
{
|
||||
environ_cb(RETRO_ENVIRONMENT_SET_VARIABLES, (void *)vars_single);
|
||||
check_variables();
|
||||
|
||||
frame_buf = (uint32_t *)malloc(MAX_VIDEO_PIXELS * emulated_devices * sizeof(uint32_t));
|
||||
|
@ -1106,7 +1253,7 @@ bool retro_load_game(const struct retro_game_info *info)
|
|||
return false;
|
||||
}
|
||||
|
||||
auto_model = (info->path[strlen(info->path) - 1] & ~0x20) == 'C' ? MODEL_CGB : MODEL_DMG;
|
||||
auto_model = (info->path[strlen(info->path) - 1] & ~0x20) == 'C' ? MODEL_CGB_E : MODEL_DMG_B;
|
||||
snprintf(retro_game_path, sizeof(retro_game_path), "%s", info->path);
|
||||
|
||||
for (int i = 0; i < emulated_devices; i++) {
|
||||
|
@ -1157,7 +1304,6 @@ bool retro_load_game_special(unsigned type, const struct retro_game_info *info,
|
|||
return false; /* all other types are unhandled for now */
|
||||
}
|
||||
|
||||
environ_cb(RETRO_ENVIRONMENT_SET_VARIABLES, (void *)vars_dual);
|
||||
check_variables();
|
||||
|
||||
frame_buf = (uint32_t*)malloc(emulated_devices * MAX_VIDEO_PIXELS * sizeof(uint32_t));
|
||||
|
@ -1172,7 +1318,7 @@ bool retro_load_game_special(unsigned type, const struct retro_game_info *info,
|
|||
return false;
|
||||
}
|
||||
|
||||
auto_model = (info->path[strlen(info->path) - 1] & ~0x20) == 'C' ? MODEL_CGB : MODEL_DMG;
|
||||
auto_model = (info->path[strlen(info->path) - 1] & ~0x20) == 'C' ? MODEL_CGB_E : MODEL_DMG_B;
|
||||
snprintf(retro_game_path, sizeof(retro_game_path), "%s", info->path);
|
||||
|
||||
for (int i = 0; i < emulated_devices; i++) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2010-2018 The RetroArch team
|
||||
/* Copyright (C) 2010-2020 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this libretro API header (libretro.h).
|
||||
|
@ -69,7 +69,7 @@ extern "C" {
|
|||
# endif
|
||||
# endif
|
||||
# else
|
||||
# if defined(__GNUC__) && __GNUC__ >= 4 && !defined(__CELLOS_LV2__)
|
||||
# if defined(__GNUC__) && __GNUC__ >= 4
|
||||
# define RETRO_API RETRO_CALLCONV __attribute__((__visibility__("default")))
|
||||
# else
|
||||
# define RETRO_API RETRO_CALLCONV
|
||||
|
@ -278,6 +278,11 @@ enum retro_language
|
|||
RETRO_LANGUAGE_ARABIC = 16,
|
||||
RETRO_LANGUAGE_GREEK = 17,
|
||||
RETRO_LANGUAGE_TURKISH = 18,
|
||||
RETRO_LANGUAGE_SLOVAK = 19,
|
||||
RETRO_LANGUAGE_PERSIAN = 20,
|
||||
RETRO_LANGUAGE_HEBREW = 21,
|
||||
RETRO_LANGUAGE_ASTURIAN = 22,
|
||||
RETRO_LANGUAGE_FINNISH = 23,
|
||||
RETRO_LANGUAGE_LAST,
|
||||
|
||||
/* Ensure sizeof(enum) == sizeof(int) */
|
||||
|
@ -708,6 +713,9 @@ enum retro_mod
|
|||
* state of rumble motors in controllers.
|
||||
* A strong and weak motor is supported, and they can be
|
||||
* controlled indepedently.
|
||||
* Should be called from either retro_init() or retro_load_game().
|
||||
* Should not be called from retro_set_environment().
|
||||
* Returns false if rumble functionality is unavailable.
|
||||
*/
|
||||
#define RETRO_ENVIRONMENT_GET_INPUT_DEVICE_CAPABILITIES 24
|
||||
/* uint64_t * --
|
||||
|
@ -1117,7 +1125,7 @@ enum retro_mod
|
|||
* 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
|
||||
* 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.
|
||||
|
@ -1132,8 +1140,8 @@ enum retro_mod
|
|||
* 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 only be called if RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION
|
||||
* 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).
|
||||
|
@ -1169,8 +1177,6 @@ enum retro_mod
|
|||
* 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",
|
||||
|
@ -1196,8 +1202,8 @@ enum retro_mod
|
|||
* 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 only be called if RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION
|
||||
* 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).
|
||||
|
@ -1248,6 +1254,140 @@ enum retro_mod
|
|||
* default when calling SET_VARIABLES/SET_CORE_OPTIONS.
|
||||
*/
|
||||
|
||||
#define RETRO_ENVIRONMENT_GET_PREFERRED_HW_RENDER 56
|
||||
/* unsigned * --
|
||||
*
|
||||
* Allows an implementation to ask frontend preferred hardware
|
||||
* context to use. Core should use this information to deal
|
||||
* with what specific context to request with SET_HW_RENDER.
|
||||
*
|
||||
* 'data' points to an unsigned variable
|
||||
*/
|
||||
|
||||
#define RETRO_ENVIRONMENT_GET_DISK_CONTROL_INTERFACE_VERSION 57
|
||||
/* unsigned * --
|
||||
* Unsigned value is the API version number of the disk control
|
||||
* interface supported by the frontend. If callback return false,
|
||||
* API version is assumed to be 0.
|
||||
*
|
||||
* In legacy code, the disk control interface is defined by passing
|
||||
* a struct of type retro_disk_control_callback to
|
||||
* RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE.
|
||||
* This may be still be done regardless of the disk control
|
||||
* interface version.
|
||||
*
|
||||
* If version is >= 1 however, the disk control interface may
|
||||
* instead be defined by passing a struct of type
|
||||
* retro_disk_control_ext_callback to
|
||||
* RETRO_ENVIRONMENT_SET_DISK_CONTROL_EXT_INTERFACE.
|
||||
* This allows the core to provide additional information about
|
||||
* disk images to the frontend and/or enables extra
|
||||
* disk control functionality by the frontend.
|
||||
*/
|
||||
|
||||
#define RETRO_ENVIRONMENT_SET_DISK_CONTROL_EXT_INTERFACE 58
|
||||
/* const struct retro_disk_control_ext_callback * --
|
||||
* Sets an interface which frontend can use to eject and insert
|
||||
* disk images, and also obtain information about individual
|
||||
* disk image files registered by the core.
|
||||
* This is used for games which consist of multiple images and
|
||||
* must be manually swapped out by the user (e.g. PSX, floppy disk
|
||||
* based systems).
|
||||
*/
|
||||
|
||||
#define RETRO_ENVIRONMENT_GET_MESSAGE_INTERFACE_VERSION 59
|
||||
/* unsigned * --
|
||||
* Unsigned value is the API version number of the message
|
||||
* interface supported by the frontend. If callback returns
|
||||
* false, API version is assumed to be 0.
|
||||
*
|
||||
* In legacy code, messages may be displayed in an
|
||||
* implementation-specific manner by passing a struct
|
||||
* of type retro_message to RETRO_ENVIRONMENT_SET_MESSAGE.
|
||||
* This may be still be done regardless of the message
|
||||
* interface version.
|
||||
*
|
||||
* If version is >= 1 however, messages may instead be
|
||||
* displayed by passing a struct of type retro_message_ext
|
||||
* to RETRO_ENVIRONMENT_SET_MESSAGE_EXT. This allows the
|
||||
* core to specify message logging level, priority and
|
||||
* destination (OSD, logging interface or both).
|
||||
*/
|
||||
|
||||
#define RETRO_ENVIRONMENT_SET_MESSAGE_EXT 60
|
||||
/* const struct retro_message_ext * --
|
||||
* Sets a message to be displayed in an implementation-specific
|
||||
* manner for a certain amount of 'frames'. Additionally allows
|
||||
* the core to specify message logging level, priority and
|
||||
* destination (OSD, logging interface or both).
|
||||
* Should not be used for trivial messages, which should simply be
|
||||
* logged via RETRO_ENVIRONMENT_GET_LOG_INTERFACE (or as a
|
||||
* fallback, stderr).
|
||||
*/
|
||||
|
||||
#define RETRO_ENVIRONMENT_GET_INPUT_MAX_USERS 61
|
||||
/* unsigned * --
|
||||
* Unsigned value is the number of active input devices
|
||||
* provided by the frontend. This may change between
|
||||
* frames, but will remain constant for the duration
|
||||
* of each frame.
|
||||
* If callback returns true, a core need not poll any
|
||||
* input device with an index greater than or equal to
|
||||
* the number of active devices.
|
||||
* If callback returns false, the number of active input
|
||||
* devices is unknown. In this case, all input devices
|
||||
* should be considered active.
|
||||
*/
|
||||
|
||||
#define RETRO_ENVIRONMENT_SET_AUDIO_BUFFER_STATUS_CALLBACK 62
|
||||
/* const struct retro_audio_buffer_status_callback * --
|
||||
* Lets the core know the occupancy level of the frontend
|
||||
* audio buffer. Can be used by a core to attempt frame
|
||||
* skipping in order to avoid buffer under-runs.
|
||||
* A core may pass NULL to disable buffer status reporting
|
||||
* in the frontend.
|
||||
*/
|
||||
|
||||
#define RETRO_ENVIRONMENT_SET_MINIMUM_AUDIO_LATENCY 63
|
||||
/* const unsigned * --
|
||||
* Sets minimum frontend audio latency in milliseconds.
|
||||
* Resultant audio latency may be larger than set value,
|
||||
* or smaller if a hardware limit is encountered. A frontend
|
||||
* is expected to honour requests up to 512 ms.
|
||||
*
|
||||
* - If value is less than current frontend
|
||||
* audio latency, callback has no effect
|
||||
* - If value is zero, default frontend audio
|
||||
* latency is set
|
||||
*
|
||||
* May be used by a core to increase audio latency and
|
||||
* therefore decrease the probability of buffer under-runs
|
||||
* (crackling) when performing 'intensive' operations.
|
||||
* A core utilising RETRO_ENVIRONMENT_SET_AUDIO_BUFFER_STATUS_CALLBACK
|
||||
* to implement audio-buffer-based frame skipping may achieve
|
||||
* optimal results by setting the audio latency to a 'high'
|
||||
* (typically 6x or 8x) integer multiple of the expected
|
||||
* frame time.
|
||||
*
|
||||
* WARNING: This can only be called from within retro_run().
|
||||
* Calling this can require a full reinitialization of audio
|
||||
* drivers in the frontend, so it is important to call it very
|
||||
* sparingly, and usually only with the users explicit consent.
|
||||
* An eventual driver reinitialize will happen so that audio
|
||||
* callbacks happening after this call within the same retro_run()
|
||||
* call will target the newly initialized driver.
|
||||
*/
|
||||
|
||||
#define RETRO_ENVIRONMENT_SET_FASTFORWARDING_OVERRIDE 64
|
||||
/* const struct retro_fastforwarding_override * --
|
||||
* Used by a libretro core to override the current
|
||||
* fastforwarding mode of the frontend.
|
||||
* If NULL is passed to this function, the frontend
|
||||
* will return true if fastforwarding override
|
||||
* functionality is supported (no change in
|
||||
* fastforwarding state will occur in this case).
|
||||
*/
|
||||
|
||||
/* VFS functionality */
|
||||
|
||||
/* File paths:
|
||||
|
@ -1924,6 +2064,10 @@ enum retro_sensor_action
|
|||
{
|
||||
RETRO_SENSOR_ACCELEROMETER_ENABLE = 0,
|
||||
RETRO_SENSOR_ACCELEROMETER_DISABLE,
|
||||
RETRO_SENSOR_GYROSCOPE_ENABLE,
|
||||
RETRO_SENSOR_GYROSCOPE_DISABLE,
|
||||
RETRO_SENSOR_ILLUMINANCE_ENABLE,
|
||||
RETRO_SENSOR_ILLUMINANCE_DISABLE,
|
||||
|
||||
RETRO_SENSOR_DUMMY = INT_MAX
|
||||
};
|
||||
|
@ -1932,6 +2076,10 @@ enum retro_sensor_action
|
|||
#define RETRO_SENSOR_ACCELEROMETER_X 0
|
||||
#define RETRO_SENSOR_ACCELEROMETER_Y 1
|
||||
#define RETRO_SENSOR_ACCELEROMETER_Z 2
|
||||
#define RETRO_SENSOR_GYROSCOPE_X 3
|
||||
#define RETRO_SENSOR_GYROSCOPE_Y 4
|
||||
#define RETRO_SENSOR_GYROSCOPE_Z 5
|
||||
#define RETRO_SENSOR_ILLUMINANCE 6
|
||||
|
||||
typedef bool (RETRO_CALLCONV *retro_set_sensor_state_t)(unsigned port,
|
||||
enum retro_sensor_action action, unsigned rate);
|
||||
|
@ -2129,6 +2277,30 @@ struct retro_frame_time_callback
|
|||
retro_usec_t reference;
|
||||
};
|
||||
|
||||
/* Notifies a libretro core of the current occupancy
|
||||
* level of the frontend audio buffer.
|
||||
*
|
||||
* - active: 'true' if audio buffer is currently
|
||||
* in use. Will be 'false' if audio is
|
||||
* disabled in the frontend
|
||||
*
|
||||
* - occupancy: Given as a value in the range [0,100],
|
||||
* corresponding to the occupancy percentage
|
||||
* of the audio buffer
|
||||
*
|
||||
* - underrun_likely: 'true' if the frontend expects an
|
||||
* audio buffer underrun during the
|
||||
* next frame (indicates that a core
|
||||
* should attempt frame skipping)
|
||||
*
|
||||
* It will be called right before retro_run() every frame. */
|
||||
typedef void (RETRO_CALLCONV *retro_audio_buffer_status_callback_t)(
|
||||
bool active, unsigned occupancy, bool underrun_likely);
|
||||
struct retro_audio_buffer_status_callback
|
||||
{
|
||||
retro_audio_buffer_status_callback_t callback;
|
||||
};
|
||||
|
||||
/* Pass this to retro_video_refresh_t if rendering to hardware.
|
||||
* Passing NULL to retro_video_refresh_t is still a frame dupe as normal.
|
||||
* */
|
||||
|
@ -2289,7 +2461,8 @@ struct retro_keyboard_callback
|
|||
retro_keyboard_event_t callback;
|
||||
};
|
||||
|
||||
/* Callbacks for RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE.
|
||||
/* Callbacks for RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE &
|
||||
* RETRO_ENVIRONMENT_SET_DISK_CONTROL_EXT_INTERFACE.
|
||||
* Should be set for implementations which can swap out multiple disk
|
||||
* images in runtime.
|
||||
*
|
||||
|
@ -2347,6 +2520,53 @@ typedef bool (RETRO_CALLCONV *retro_replace_image_index_t)(unsigned index,
|
|||
* with replace_image_index. */
|
||||
typedef bool (RETRO_CALLCONV *retro_add_image_index_t)(void);
|
||||
|
||||
/* Sets initial image to insert in drive when calling
|
||||
* core_load_game().
|
||||
* Since we cannot pass the initial index when loading
|
||||
* content (this would require a major API change), this
|
||||
* is set by the frontend *before* calling the core's
|
||||
* retro_load_game()/retro_load_game_special() implementation.
|
||||
* A core should therefore cache the index/path values and handle
|
||||
* them inside retro_load_game()/retro_load_game_special().
|
||||
* - If 'index' is invalid (index >= get_num_images()), the
|
||||
* core should ignore the set value and instead use 0
|
||||
* - 'path' is used purely for error checking - i.e. when
|
||||
* content is loaded, the core should verify that the
|
||||
* disk specified by 'index' has the specified file path.
|
||||
* This is to guard against auto selecting the wrong image
|
||||
* if (for example) the user should modify an existing M3U
|
||||
* playlist. We have to let the core handle this because
|
||||
* set_initial_image() must be called before loading content,
|
||||
* i.e. the frontend cannot access image paths in advance
|
||||
* and thus cannot perform the error check itself.
|
||||
* If set path and content path do not match, the core should
|
||||
* ignore the set 'index' value and instead use 0
|
||||
* Returns 'false' if index or 'path' are invalid, or core
|
||||
* does not support this functionality
|
||||
*/
|
||||
typedef bool (RETRO_CALLCONV *retro_set_initial_image_t)(unsigned index, const char *path);
|
||||
|
||||
/* Fetches the path of the specified disk image file.
|
||||
* Returns 'false' if index is invalid (index >= get_num_images())
|
||||
* or path is otherwise unavailable.
|
||||
*/
|
||||
typedef bool (RETRO_CALLCONV *retro_get_image_path_t)(unsigned index, char *path, size_t len);
|
||||
|
||||
/* Fetches a core-provided 'label' for the specified disk
|
||||
* image file. In the simplest case this may be a file name
|
||||
* (without extension), but for cores with more complex
|
||||
* content requirements information may be provided to
|
||||
* facilitate user disk swapping - for example, a core
|
||||
* running floppy-disk-based content may uniquely label
|
||||
* save disks, data disks, level disks, etc. with names
|
||||
* corresponding to in-game disk change prompts (so the
|
||||
* frontend can provide better user guidance than a 'dumb'
|
||||
* disk index value).
|
||||
* Returns 'false' if index is invalid (index >= get_num_images())
|
||||
* or label is otherwise unavailable.
|
||||
*/
|
||||
typedef bool (RETRO_CALLCONV *retro_get_image_label_t)(unsigned index, char *label, size_t len);
|
||||
|
||||
struct retro_disk_control_callback
|
||||
{
|
||||
retro_set_eject_state_t set_eject_state;
|
||||
|
@ -2360,6 +2580,27 @@ struct retro_disk_control_callback
|
|||
retro_add_image_index_t add_image_index;
|
||||
};
|
||||
|
||||
struct retro_disk_control_ext_callback
|
||||
{
|
||||
retro_set_eject_state_t set_eject_state;
|
||||
retro_get_eject_state_t get_eject_state;
|
||||
|
||||
retro_get_image_index_t get_image_index;
|
||||
retro_set_image_index_t set_image_index;
|
||||
retro_get_num_images_t get_num_images;
|
||||
|
||||
retro_replace_image_index_t replace_image_index;
|
||||
retro_add_image_index_t add_image_index;
|
||||
|
||||
/* NOTE: Frontend will only attempt to record/restore
|
||||
* last used disk index if both set_initial_image()
|
||||
* and get_image_path() are implemented */
|
||||
retro_set_initial_image_t set_initial_image; /* Optional - may be NULL */
|
||||
|
||||
retro_get_image_path_t get_image_path; /* Optional - may be NULL */
|
||||
retro_get_image_label_t get_image_label; /* Optional - may be NULL */
|
||||
};
|
||||
|
||||
enum retro_pixel_format
|
||||
{
|
||||
/* 0RGB1555, native endian.
|
||||
|
@ -2390,6 +2631,104 @@ struct retro_message
|
|||
unsigned frames; /* Duration in frames of message. */
|
||||
};
|
||||
|
||||
enum retro_message_target
|
||||
{
|
||||
RETRO_MESSAGE_TARGET_ALL = 0,
|
||||
RETRO_MESSAGE_TARGET_OSD,
|
||||
RETRO_MESSAGE_TARGET_LOG
|
||||
};
|
||||
|
||||
enum retro_message_type
|
||||
{
|
||||
RETRO_MESSAGE_TYPE_NOTIFICATION = 0,
|
||||
RETRO_MESSAGE_TYPE_NOTIFICATION_ALT,
|
||||
RETRO_MESSAGE_TYPE_STATUS,
|
||||
RETRO_MESSAGE_TYPE_PROGRESS
|
||||
};
|
||||
|
||||
struct retro_message_ext
|
||||
{
|
||||
/* Message string to be displayed/logged */
|
||||
const char *msg;
|
||||
/* Duration (in ms) of message when targeting the OSD */
|
||||
unsigned duration;
|
||||
/* Message priority when targeting the OSD
|
||||
* > When multiple concurrent messages are sent to
|
||||
* the frontend and the frontend does not have the
|
||||
* capacity to display them all, messages with the
|
||||
* *highest* priority value should be shown
|
||||
* > There is no upper limit to a message priority
|
||||
* value (within the bounds of the unsigned data type)
|
||||
* > In the reference frontend (RetroArch), the same
|
||||
* priority values are used for frontend-generated
|
||||
* notifications, which are typically assigned values
|
||||
* between 0 and 3 depending upon importance */
|
||||
unsigned priority;
|
||||
/* Message logging level (info, warn, error, etc.) */
|
||||
enum retro_log_level level;
|
||||
/* Message destination: OSD, logging interface or both */
|
||||
enum retro_message_target target;
|
||||
/* Message 'type' when targeting the OSD
|
||||
* > RETRO_MESSAGE_TYPE_NOTIFICATION: Specifies that a
|
||||
* message should be handled in identical fashion to
|
||||
* a standard frontend-generated notification
|
||||
* > RETRO_MESSAGE_TYPE_NOTIFICATION_ALT: Specifies that
|
||||
* message is a notification that requires user attention
|
||||
* or action, but that it should be displayed in a manner
|
||||
* that differs from standard frontend-generated notifications.
|
||||
* This would typically correspond to messages that should be
|
||||
* displayed immediately (independently from any internal
|
||||
* frontend message queue), and/or which should be visually
|
||||
* distinguishable from frontend-generated notifications.
|
||||
* For example, a core may wish to inform the user of
|
||||
* information related to a disk-change event. It is
|
||||
* expected that the frontend itself may provide a
|
||||
* notification in this case; if the core sends a
|
||||
* message of type RETRO_MESSAGE_TYPE_NOTIFICATION, an
|
||||
* uncomfortable 'double-notification' may occur. A message
|
||||
* of RETRO_MESSAGE_TYPE_NOTIFICATION_ALT should therefore
|
||||
* be presented such that visual conflict with regular
|
||||
* notifications does not occur
|
||||
* > RETRO_MESSAGE_TYPE_STATUS: Indicates that message
|
||||
* is not a standard notification. This typically
|
||||
* corresponds to 'status' indicators, such as a core's
|
||||
* internal FPS, which are intended to be displayed
|
||||
* either permanently while a core is running, or in
|
||||
* a manner that does not suggest user attention or action
|
||||
* is required. 'Status' type messages should therefore be
|
||||
* displayed in a different on-screen location and in a manner
|
||||
* easily distinguishable from both standard frontend-generated
|
||||
* notifications and messages of type RETRO_MESSAGE_TYPE_NOTIFICATION_ALT
|
||||
* > RETRO_MESSAGE_TYPE_PROGRESS: Indicates that message reports
|
||||
* the progress of an internal core task. For example, in cases
|
||||
* where a core itself handles the loading of content from a file,
|
||||
* this may correspond to the percentage of the file that has been
|
||||
* read. Alternatively, an audio/video playback core may use a
|
||||
* message of type RETRO_MESSAGE_TYPE_PROGRESS to display the current
|
||||
* playback position as a percentage of the runtime. 'Progress' type
|
||||
* messages should therefore be displayed as a literal progress bar,
|
||||
* where:
|
||||
* - 'retro_message_ext.msg' is the progress bar title/label
|
||||
* - 'retro_message_ext.progress' determines the length of
|
||||
* the progress bar
|
||||
* NOTE: Message type is a *hint*, and may be ignored
|
||||
* by the frontend. If a frontend lacks support for
|
||||
* displaying messages via alternate means than standard
|
||||
* frontend-generated notifications, it will treat *all*
|
||||
* messages as having the type RETRO_MESSAGE_TYPE_NOTIFICATION */
|
||||
enum retro_message_type type;
|
||||
/* Task progress when targeting the OSD and message is
|
||||
* of type RETRO_MESSAGE_TYPE_PROGRESS
|
||||
* > -1: Unmetered/indeterminate
|
||||
* > 0-100: Current progress percentage
|
||||
* NOTE: Since message type is a hint, a frontend may ignore
|
||||
* progress values. Where relevant, a core should therefore
|
||||
* include progress percentage within the message string,
|
||||
* such that the message intent remains clear when displayed
|
||||
* as a standard frontend-generated notification */
|
||||
int8_t progress;
|
||||
};
|
||||
|
||||
/* Describes how the libretro implementation maps a libretro input bind
|
||||
* to its internal input system through a human readable string.
|
||||
* This string can be used to better let a user configure input. */
|
||||
|
@ -2410,7 +2749,7 @@ struct retro_input_descriptor
|
|||
struct retro_system_info
|
||||
{
|
||||
/* All pointers are owned by libretro implementation, and pointers must
|
||||
* remain valid until retro_deinit() is called. */
|
||||
* remain valid until it is unloaded. */
|
||||
|
||||
const char *library_name; /* Descriptive name of library. Should not
|
||||
* contain any version numbers, etc. */
|
||||
|
@ -2504,8 +2843,20 @@ struct retro_core_option_display
|
|||
};
|
||||
|
||||
/* 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) */
|
||||
* > Note: We have to set a maximum value due the limitations
|
||||
* of the C language - i.e. it is not possible to create an
|
||||
* array of structs each containing a variable sized array,
|
||||
* so the retro_core_option_definition values array must
|
||||
* have a fixed size. The size limit of 128 is a balancing
|
||||
* act - it needs to be large enough to support all 'sane'
|
||||
* core options, but setting it too large may impact low memory
|
||||
* platforms. In practise, if a core option has more than
|
||||
* 128 values then the implementation is likely flawed.
|
||||
* To quote the above API reference:
|
||||
* "The number of possible options should be very limited
|
||||
* i.e. it should be feasible to cycle through options
|
||||
* without a keyboard."
|
||||
*/
|
||||
#define RETRO_NUM_CORE_OPTION_VALUES_MAX 128
|
||||
|
||||
struct retro_core_option_value
|
||||
|
@ -2597,6 +2948,47 @@ struct retro_framebuffer
|
|||
Set by frontend in GET_CURRENT_SOFTWARE_FRAMEBUFFER. */
|
||||
};
|
||||
|
||||
/* Used by a libretro core to override the current
|
||||
* fastforwarding mode of the frontend */
|
||||
struct retro_fastforwarding_override
|
||||
{
|
||||
/* Specifies the runtime speed multiplier that
|
||||
* will be applied when 'fastforward' is true.
|
||||
* For example, a value of 5.0 when running 60 FPS
|
||||
* content will cap the fast-forward rate at 300 FPS.
|
||||
* Note that the target multiplier may not be achieved
|
||||
* if the host hardware has insufficient processing
|
||||
* power.
|
||||
* Setting a value of 0.0 (or greater than 0.0 but
|
||||
* less than 1.0) will result in an uncapped
|
||||
* fast-forward rate (limited only by hardware
|
||||
* capacity).
|
||||
* If the value is negative, it will be ignored
|
||||
* (i.e. the frontend will use a runtime speed
|
||||
* multiplier of its own choosing) */
|
||||
float ratio;
|
||||
|
||||
/* If true, fastforwarding mode will be enabled.
|
||||
* If false, fastforwarding mode will be disabled. */
|
||||
bool fastforward;
|
||||
|
||||
/* If true, and if supported by the frontend, an
|
||||
* on-screen notification will be displayed while
|
||||
* 'fastforward' is true.
|
||||
* If false, and if supported by the frontend, any
|
||||
* on-screen fast-forward notifications will be
|
||||
* suppressed */
|
||||
bool notification;
|
||||
|
||||
/* If true, the core will have sole control over
|
||||
* when fastforwarding mode is enabled/disabled;
|
||||
* the frontend will not be able to change the
|
||||
* state set by 'fastforward' until either
|
||||
* 'inhibit_toggle' is set to false, or the core
|
||||
* is unloaded */
|
||||
bool inhibit_toggle;
|
||||
};
|
||||
|
||||
/* Callbacks */
|
||||
|
||||
/* Environment callback. Gives implementations a way of performing
|
||||
|
|
|
@ -0,0 +1,679 @@
|
|||
#ifndef LIBRETRO_CORE_OPTIONS_H__
|
||||
#define LIBRETRO_CORE_OPTIONS_H__
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "libretro.h"
|
||||
#include "retro_inline.h"
|
||||
|
||||
/*
|
||||
********************************
|
||||
* VERSION: 1.3
|
||||
********************************
|
||||
*
|
||||
* - 1.3: Move translations to libretro_core_options_intl.h
|
||||
* - libretro_core_options_intl.h includes BOM and utf-8
|
||||
* fix for MSVC 2010-2013
|
||||
* - Added HAVE_NO_LANGEXTRA flag to disable translations
|
||||
* on platforms/compilers without BOM support
|
||||
* - 1.2: Use core options v1 interface when
|
||||
* RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION is >= 1
|
||||
* (previously required RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION == 1)
|
||||
* - 1.1: Support generation of core options v0 retro_core_option_value
|
||||
* arrays containing options with a single value
|
||||
* - 1.0: First commit
|
||||
*/
|
||||
|
||||
#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[] = {
|
||||
|
||||
/* Core options used in single cart mode */
|
||||
|
||||
{
|
||||
"sameboy_model",
|
||||
"System - Emulated Model (Requires Restart)",
|
||||
"Chooses which system model the content should be started on. Certain games may activate special in-game features when ran on specific models. This option requires a content restart in order to take effect.",
|
||||
{
|
||||
{ "Auto", "Detect automatically" },
|
||||
{ "Game Boy", "Game Boy (DMG-CPU B)" },
|
||||
{ "Game Boy Color C", "Game Boy Color (CPU-CGB C) (Experimental)" },
|
||||
{ "Game Boy Color", "Game Boy Color (CPU-CGB E)" },
|
||||
{ "Game Boy Advance", NULL },
|
||||
{ "Super Game Boy", "Super Game Boy NTSC" },
|
||||
{ "Super Game Boy PAL", NULL },
|
||||
{ "Super Game Boy 2", NULL },
|
||||
{ NULL, NULL },
|
||||
},
|
||||
"Auto"
|
||||
},
|
||||
{
|
||||
"sameboy_rtc",
|
||||
"System - Real Time Clock Emulation",
|
||||
"Specifies how the emulation of the real-time clock feature used in certain Game Boy and Game Boy Color games should function.",
|
||||
{
|
||||
{ "sync to system clock", "Sync to System Clock" },
|
||||
{ "accurate", "Accurate" },
|
||||
{ NULL, NULL },
|
||||
},
|
||||
"sync to system clock"
|
||||
},
|
||||
|
||||
{
|
||||
"sameboy_mono_palette",
|
||||
"Video - GB Mono Palette",
|
||||
"Selects the color palette that should be used when playing Game Boy games.",
|
||||
{
|
||||
{ "greyscale", "Greyscale" },
|
||||
{ "lime", "Lime (Game Boy)" },
|
||||
{ "olive", "Olive (Game Boy Pocket)" },
|
||||
{ "teal", "Teal (Game Boy Light)" },
|
||||
{ NULL, NULL },
|
||||
},
|
||||
"greyscale"
|
||||
},
|
||||
{
|
||||
"sameboy_color_correction_mode",
|
||||
"Video - GBC Color Correction",
|
||||
"Defines which type of color correction should be applied when playing Game Boy Color games.",
|
||||
{
|
||||
{ "emulate hardware", "Emulate Hardware" },
|
||||
{ "preserve brightness", "Preserve Brightness" },
|
||||
{ "reduce contrast", "Reduce Contrast" },
|
||||
{ "correct curves", "Correct Color Curves" },
|
||||
{ "harsh reality", "Harsh Reality (Low Contrast)" },
|
||||
{ "off", "Disabled" },
|
||||
{ NULL, NULL },
|
||||
},
|
||||
"emulate hardware"
|
||||
},
|
||||
{
|
||||
"sameboy_light_temperature",
|
||||
"Video - Ambient Light Temperature",
|
||||
"Simulates an ambient light’s effect on non-backlit Game Boy screens, by setting a user-controlled color temperature. This option has no effect if the content is run on an original Game Boy (DMG) emulated model.",
|
||||
{
|
||||
{ "1.0", "1000K (Warmest)" },
|
||||
{ "0.9", "1550K" },
|
||||
{ "0.8", "2100K" },
|
||||
{ "0.7", "2650K" },
|
||||
{ "0.6", "3200K" },
|
||||
{ "0.5", "3750K" },
|
||||
{ "0.4", "4300K" },
|
||||
{ "0.3", "4850K" },
|
||||
{ "0.2", "5400K" },
|
||||
{ "0.1", "5950K" },
|
||||
{ "0", "6500K (Neutral White)" },
|
||||
{ "-0.1", "7050K" },
|
||||
{ "-0.2", "7600K" },
|
||||
{ "-0.3", "8150K" },
|
||||
{ "-0.4", "8700K" },
|
||||
{ "-0.5", "9250K" },
|
||||
{ "-0.6", "9800K" },
|
||||
{ "-0.7", "10350K" },
|
||||
{ "-0.8", "10900K" },
|
||||
{ "-0.9", "11450K" },
|
||||
{ "-1.0", "12000K (Coolest)" },
|
||||
{ NULL, NULL },
|
||||
},
|
||||
"0"
|
||||
},
|
||||
{
|
||||
"sameboy_border",
|
||||
"Video - Display Border",
|
||||
"Defines when to display an on-screen border around the content.",
|
||||
{
|
||||
{ "always", "Always" },
|
||||
{ "Super Game Boy only", "Only for Super Game Boy" },
|
||||
{ "never", "Disabled" },
|
||||
{ NULL, NULL },
|
||||
},
|
||||
"Super Game Boy only"
|
||||
},
|
||||
{
|
||||
"sameboy_high_pass_filter_mode",
|
||||
"Audio - Highpass Filter",
|
||||
"Applies a filter to the audio output, removing certain pop sounds caused by the DC Offset. If disabled, the sound will be rendered as output by the Game Boy APU, but popping effects will be heard when the emulator is paused or resumed. 'Accurate' will apply a global filter, masking popping sounds while also reducing lower frequencies. 'Preserve Waveform' applies the filter only to the DC Offset.",
|
||||
{
|
||||
{ "accurate", "Accurate" },
|
||||
{ "remove dc offset", "Preserve Waveform" },
|
||||
{ "off", "Disabled" },
|
||||
{ NULL, NULL },
|
||||
},
|
||||
"accurate"
|
||||
},
|
||||
{
|
||||
"sameboy_audio_interference",
|
||||
"Audio - Interference Volume",
|
||||
"Controls the volume of the buzzing effect caused by the electrical interference between the Game Boy SoC and the system speakers.",
|
||||
{
|
||||
{ "0", "0%" },
|
||||
{ "5", "5%" },
|
||||
{ "10", "10%" },
|
||||
{ "15", "15%" },
|
||||
{ "20", "20%" },
|
||||
{ "25", "25%" },
|
||||
{ "30", "30%" },
|
||||
{ "35", "35%" },
|
||||
{ "40", "40%" },
|
||||
{ "45", "45%" },
|
||||
{ "50", "50%" },
|
||||
{ "55", "55%" },
|
||||
{ "60", "60%" },
|
||||
{ "65", "65%" },
|
||||
{ "70", "70%" },
|
||||
{ "75", "75%" },
|
||||
{ "80", "80%" },
|
||||
{ "85", "85%" },
|
||||
{ "90", "90%" },
|
||||
{ "95", "95%" },
|
||||
{ "100", "100%" },
|
||||
{ NULL, NULL },
|
||||
},
|
||||
"0"
|
||||
},
|
||||
{
|
||||
"sameboy_rumble",
|
||||
"Input - Rumble Mode",
|
||||
"Defines which type of content should trigger rumble effects.",
|
||||
{
|
||||
{ "all games", "Always" },
|
||||
{ "rumble-enabled games", "Only for rumble-enabled games" },
|
||||
{ "never", "Never" },
|
||||
{ NULL, NULL },
|
||||
},
|
||||
"rumble-enabled games"
|
||||
},
|
||||
|
||||
/* Core options used in dual cart mode */
|
||||
|
||||
{
|
||||
"sameboy_link",
|
||||
"System - Link Cable Emulation",
|
||||
"Enables the emulation of the link cable, allowing communication and exchange of data between two Game Boy systems.",
|
||||
{
|
||||
{ "enabled", "Enabled" },
|
||||
{ "disabled", "Disabled" },
|
||||
{ NULL, NULL },
|
||||
},
|
||||
"enabled"
|
||||
},
|
||||
{
|
||||
"sameboy_screen_layout",
|
||||
"System - Screen Layout",
|
||||
"When emulating two systems at once, this option defines the respective position of the two screens.",
|
||||
{
|
||||
{ "top-down", "Top-Down" },
|
||||
{ "left-right", "Left-Right" },
|
||||
{ NULL, NULL },
|
||||
},
|
||||
"top-down"
|
||||
},
|
||||
{
|
||||
"sameboy_audio_output",
|
||||
"System - Audio Output",
|
||||
"Selects which of the two emulated Game Boy systems should output audio.",
|
||||
{
|
||||
{ "Game Boy #1", NULL },
|
||||
{ "Game Boy #2", NULL },
|
||||
{ NULL, NULL },
|
||||
},
|
||||
"Game Boy #1"
|
||||
},
|
||||
{
|
||||
"sameboy_model_1",
|
||||
"System - Emulated Model for Game Boy #1 (Requires Restart)",
|
||||
"Chooses which system model the content should be started on for Game Boy #1. Certain games may activate special in-game features when ran on specific models. This option requires a content restart in order to take effect.",
|
||||
{
|
||||
{ "Auto", "Detect automatically" },
|
||||
{ "Game Boy", "Game Boy (DMG-CPU B)" },
|
||||
{ "Game Boy Color C", "Game Boy Color (CPU-CGB C) (Experimental)" },
|
||||
{ "Game Boy Color", "Game Boy Color (CPU-CGB E)" },
|
||||
{ "Game Boy Advance", NULL },
|
||||
{ "Super Game Boy", "Super Game Boy NTSC" },
|
||||
{ "Super Game Boy PAL", NULL },
|
||||
{ "Super Game Boy 2", NULL },
|
||||
{ NULL, NULL },
|
||||
},
|
||||
"Auto"
|
||||
},
|
||||
{
|
||||
"sameboy_model_2",
|
||||
"System - Emulated Model for Game Boy #2 (Requires Restart)",
|
||||
"Chooses which system model the content should be started on for Game Boy #2. Certain games may activate special in-game features when ran on specific models. This option requires a content restart in order to take effect.",
|
||||
{
|
||||
{ "Auto", "Detect automatically" },
|
||||
{ "Game Boy", "Game Boy (DMG-CPU B)" },
|
||||
{ "Game Boy Color C", "Game Boy Color (CPU-CGB C) (Experimental)" },
|
||||
{ "Game Boy Color", "Game Boy Color (CPU-CGB E)" },
|
||||
{ "Game Boy Advance", NULL },
|
||||
{ "Super Game Boy", "Super Game Boy NTSC" },
|
||||
{ "Super Game Boy PAL", NULL },
|
||||
{ "Super Game Boy 2", NULL },
|
||||
{ NULL, NULL },
|
||||
},
|
||||
"Auto"
|
||||
},
|
||||
{
|
||||
"sameboy_mono_palette_1",
|
||||
"Video - GB Mono Palette for Game Boy #1",
|
||||
"Selects the color palette that should be used when playing Game Boy games on Game Boy #1.",
|
||||
{
|
||||
{ "greyscale", "Greyscale" },
|
||||
{ "lime", "Lime (Game Boy)" },
|
||||
{ "olive", "Olive (Game Boy Pocket)" },
|
||||
{ "teal", "Teal (Game Boy Light)" },
|
||||
{ NULL, NULL },
|
||||
},
|
||||
"greyscale"
|
||||
},
|
||||
{
|
||||
"sameboy_mono_palette_2",
|
||||
"Video - GB Mono Palette for Game Boy #2",
|
||||
"Selects the color palette that should be used when playing Game Boy games on Game Boy #2.",
|
||||
{
|
||||
{ "greyscale", "Greyscale" },
|
||||
{ "lime", "Lime (Game Boy)" },
|
||||
{ "olive", "Olive (Game Boy Pocket)" },
|
||||
{ "teal", "Teal (Game Boy Light)" },
|
||||
{ NULL, NULL },
|
||||
},
|
||||
"greyscale"
|
||||
},
|
||||
{
|
||||
"sameboy_color_correction_mode_1",
|
||||
"Video - GBC Color Correction for Game Boy #1",
|
||||
"Defines which type of color correction should be applied when playing Game Boy Color games on Game Boy #1.",
|
||||
{
|
||||
{ "emulate hardware", "Emulate Hardware" },
|
||||
{ "preserve brightness", "Preserve Brightness" },
|
||||
{ "reduce contrast", "Reduce Contrast" },
|
||||
{ "correct curves", "Correct Color Curves" },
|
||||
{ "harsh reality", "Harsh Reality (Low Contrast)" },
|
||||
{ "off", "Disabled" },
|
||||
{ NULL, NULL },
|
||||
},
|
||||
"emulate hardware"
|
||||
},
|
||||
{
|
||||
"sameboy_color_correction_mode_2",
|
||||
"Video - GBC Color Correction for Game Boy #2",
|
||||
"Defines which type of color correction should be applied when playing Game Boy Color games on Game Boy #2.",
|
||||
{
|
||||
{ "emulate hardware", "Emulate Hardware" },
|
||||
{ "preserve brightness", "Preserve Brightness" },
|
||||
{ "reduce contrast", "Reduce Contrast" },
|
||||
{ "correct curves", "Correct Color Curves" },
|
||||
{ "harsh reality", "Harsh Reality (Low Contrast)" },
|
||||
{ "off", "Disabled" },
|
||||
{ NULL, NULL },
|
||||
},
|
||||
"emulate hardware"
|
||||
},
|
||||
{
|
||||
"sameboy_light_temperature_1",
|
||||
"Video - Ambient Light Temperature for Game Boy #1",
|
||||
"Simulates an ambient light’s effect on non-backlit Game Boy screens, by setting a user-controlled color temperature applied to the screen of Game Boy #1. This option has no effect if the content is run on an original Game Boy (DMG) emulated model.",
|
||||
{
|
||||
{ "1.0", "1000K (Warmest)" },
|
||||
{ "0.9", "1550K" },
|
||||
{ "0.8", "2100K" },
|
||||
{ "0.7", "2650K" },
|
||||
{ "0.6", "3200K" },
|
||||
{ "0.5", "3750K" },
|
||||
{ "0.4", "4300K" },
|
||||
{ "0.3", "4850K" },
|
||||
{ "0.2", "5400K" },
|
||||
{ "0.1", "5950K" },
|
||||
{ "0", "6500K (Neutral White)" },
|
||||
{ "-0.1", "7050K" },
|
||||
{ "-0.2", "7600K" },
|
||||
{ "-0.3", "8150K" },
|
||||
{ "-0.4", "8700K" },
|
||||
{ "-0.5", "9250K" },
|
||||
{ "-0.6", "9800K" },
|
||||
{ "-0.7", "10350K" },
|
||||
{ "-0.8", "10900K" },
|
||||
{ "-0.9", "11450K" },
|
||||
{ "-1.0", "12000K (Coolest)" },
|
||||
{ NULL, NULL },
|
||||
},
|
||||
"0"
|
||||
},
|
||||
{
|
||||
"sameboy_light_temperature_2",
|
||||
"Video - Ambient Light Temperature for Game Boy #2",
|
||||
"Simulates an ambient light’s effect on non-backlit Game Boy screens, by setting a user-controlled color temperature applied to the screen of Game Boy #2. This option has no effect if the content is run on an original Game Boy (DMG) emulated model.",
|
||||
{
|
||||
{ "1.0", "1000K (Warmest)" },
|
||||
{ "0.9", "1550K" },
|
||||
{ "0.8", "2100K" },
|
||||
{ "0.7", "2650K" },
|
||||
{ "0.6", "3200K" },
|
||||
{ "0.5", "3750K" },
|
||||
{ "0.4", "4300K" },
|
||||
{ "0.3", "4850K" },
|
||||
{ "0.2", "5400K" },
|
||||
{ "0.1", "5950K" },
|
||||
{ "0", "6500K (Neutral White)" },
|
||||
{ "-0.1", "7050K" },
|
||||
{ "-0.2", "7600K" },
|
||||
{ "-0.3", "8150K" },
|
||||
{ "-0.4", "8700K" },
|
||||
{ "-0.5", "9250K" },
|
||||
{ "-0.6", "9800K" },
|
||||
{ "-0.7", "10350K" },
|
||||
{ "-0.8", "10900K" },
|
||||
{ "-0.9", "11450K" },
|
||||
{ "-1.0", "12000K (Coolest)" },
|
||||
{ NULL, NULL },
|
||||
},
|
||||
"0"
|
||||
},
|
||||
{
|
||||
"sameboy_high_pass_filter_mode_1",
|
||||
"Audio - Highpass Filter for Game Boy #1",
|
||||
"Applies a filter to the audio output for Game Boy #1, removing certain pop sounds caused by the DC Offset. If disabled, the sound will be rendered as output by the Game Boy APU, but popping effects will be heard when the emulator is paused or resumed. 'Accurate' will apply a global filter, masking popping sounds while also reducing lower frequencies. 'Preserve Waveform' applies the filter only to the DC Offset.",
|
||||
{
|
||||
{ "accurate", "Accurate" },
|
||||
{ "remove dc offset", "Preserve Waveform" },
|
||||
{ "off", "disabled" },
|
||||
{ NULL, NULL },
|
||||
},
|
||||
"accurate"
|
||||
},
|
||||
{
|
||||
"sameboy_high_pass_filter_mode_2",
|
||||
"Audio - Highpass Filter for Game Boy #2",
|
||||
"Applies a filter to the audio output for Game Boy #2, removing certain pop sounds caused by the DC Offset. If disabled, the sound will be rendered as output by the Game Boy APU, but popping effects will be heard when the emulator is paused or resumed. 'Accurate' will apply a global filter, masking popping sounds while also reducing lower frequencies. 'Preserve Waveform' applies the filter only to the DC Offset.",
|
||||
{
|
||||
{ "accurate", "Accurate" },
|
||||
{ "remove dc offset", "Preserve Waveform" },
|
||||
{ "off", "disabled" },
|
||||
{ NULL, NULL },
|
||||
},
|
||||
"accurate"
|
||||
},
|
||||
{
|
||||
"sameboy_audio_interference_1",
|
||||
"Audio - Interference Volume for Game Boy #1",
|
||||
"Controls the volume of the buzzing effect caused by the electrical interference between the Game Boy SoC and the system speakers on Game Boy #1.",
|
||||
{
|
||||
{ "0", "0%" },
|
||||
{ "5", "5%" },
|
||||
{ "10", "10%" },
|
||||
{ "15", "15%" },
|
||||
{ "20", "20%" },
|
||||
{ "25", "25%" },
|
||||
{ "30", "30%" },
|
||||
{ "35", "35%" },
|
||||
{ "40", "40%" },
|
||||
{ "45", "45%" },
|
||||
{ "50", "50%" },
|
||||
{ "55", "55%" },
|
||||
{ "60", "60%" },
|
||||
{ "65", "65%" },
|
||||
{ "70", "70%" },
|
||||
{ "75", "75%" },
|
||||
{ "80", "80%" },
|
||||
{ "85", "85%" },
|
||||
{ "90", "90%" },
|
||||
{ "95", "95%" },
|
||||
{ "100", "100%" },
|
||||
{ NULL, NULL },
|
||||
},
|
||||
"0"
|
||||
},
|
||||
{
|
||||
"sameboy_audio_interference_2",
|
||||
"Audio - Interference Volume for Game Boy #2",
|
||||
"Controls the volume of the buzzing effect caused by the electrical interference between the Game Boy SoC and the system speakers on Game Boy #2.",
|
||||
{
|
||||
{ "0", "0%" },
|
||||
{ "5", "5%" },
|
||||
{ "10", "10%" },
|
||||
{ "15", "15%" },
|
||||
{ "20", "20%" },
|
||||
{ "25", "25%" },
|
||||
{ "30", "30%" },
|
||||
{ "35", "35%" },
|
||||
{ "40", "40%" },
|
||||
{ "45", "45%" },
|
||||
{ "50", "50%" },
|
||||
{ "55", "55%" },
|
||||
{ "60", "60%" },
|
||||
{ "65", "65%" },
|
||||
{ "70", "70%" },
|
||||
{ "75", "75%" },
|
||||
{ "80", "80%" },
|
||||
{ "85", "85%" },
|
||||
{ "90", "90%" },
|
||||
{ "95", "95%" },
|
||||
{ "100", "100%" },
|
||||
{ NULL, NULL },
|
||||
},
|
||||
"0"
|
||||
},
|
||||
{
|
||||
"sameboy_rumble_1",
|
||||
"Input - Rumble Mode for Game Boy #1",
|
||||
"Defines which type of content should trigger rumble effects when played on Game Boy #1.",
|
||||
{
|
||||
{ "all games", "Always" },
|
||||
{ "rumble-enabled games", "Only for rumble-enabled games" },
|
||||
{ "never", "Never" },
|
||||
{ NULL, NULL },
|
||||
},
|
||||
"rumble-enabled games"
|
||||
},
|
||||
{
|
||||
"sameboy_rumble_2",
|
||||
"Input - Rumble Mode for Game Boy #2",
|
||||
"Defines which type of content should trigger rumble effects when played on Game Boy #2.",
|
||||
{
|
||||
{ "all games", "Always" },
|
||||
{ "rumble-enabled games", "Only for rumble-enabled games" },
|
||||
{ "never", "Never" },
|
||||
{ NULL, NULL },
|
||||
},
|
||||
"rumble-enabled games"
|
||||
},
|
||||
|
||||
{ NULL, NULL, NULL, {{0}}, NULL },
|
||||
};
|
||||
|
||||
/*
|
||||
********************************
|
||||
* Language Mapping
|
||||
********************************
|
||||
*/
|
||||
|
||||
#ifndef HAVE_NO_LANGEXTRA
|
||||
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 */
|
||||
NULL, /* RETRO_LANGUAGE_SLOVAK */
|
||||
NULL, /* RETRO_LANGUAGE_PERSIAN */
|
||||
NULL, /* RETRO_LANGUAGE_HEBREW */
|
||||
NULL, /* RETRO_LANGUAGE_ASTURIAN */
|
||||
NULL, /* RETRO_LANGUAGE_FINNISH */
|
||||
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
********************************
|
||||
* Functions
|
||||
********************************
|
||||
*/
|
||||
|
||||
/* Handles configuration/setting of core options.
|
||||
* Should be called as early as possible - ideally inside
|
||||
* retro_set_environment(), and no later than retro_load_game()
|
||||
* > 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)) {
|
||||
#ifndef HAVE_NO_LANGEXTRA
|
||||
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
|
||||
environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS, &option_defs_us);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
size_t i;
|
||||
size_t num_options = 0;
|
||||
struct retro_variable *variables = NULL;
|
||||
char **values_buf = NULL;
|
||||
|
||||
/* Determine number of options */
|
||||
while (true) {
|
||||
if (!option_defs_us[num_options].key) break;
|
||||
num_options++;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
if (desc) {
|
||||
size_t num_values = 0;
|
||||
|
||||
/* Determine number of values */
|
||||
while (true) {
|
||||
if (!values[num_values].value) break;
|
||||
|
||||
/* 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++;
|
||||
}
|
||||
|
||||
/* Build values string */
|
||||
if (num_values > 0) {
|
||||
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[i].key = key;
|
||||
variables[i].value = values_buf[i];
|
||||
}
|
||||
|
||||
/* 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
|
|
@ -0,0 +1,39 @@
|
|||
/* Copyright (C) 2010-2020 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (retro_inline.h).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __LIBRETRO_SDK_INLINE_H
|
||||
#define __LIBRETRO_SDK_INLINE_H
|
||||
|
||||
#ifndef INLINE
|
||||
|
||||
#if defined(_WIN32) || defined(__INTEL_COMPILER)
|
||||
#define INLINE __inline
|
||||
#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
|
||||
#define INLINE inline
|
||||
#elif defined(__GNUC__)
|
||||
#define INLINE __inline__
|
||||
#else
|
||||
#define INLINE
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
Loading…
Reference in New Issue