From 26a66dc37f1d1bdb1ffe741877fa8463fdce8a27 Mon Sep 17 00:00:00 2001 From: bslenul <33353403+bslenul@users.noreply.github.com> Date: Sun, 30 Oct 2022 13:29:53 +0100 Subject: [PATCH] [Libretro] Update core options to v2 + add a few new ones Updated core options to v2 + added the following options: "Cache Full ISO in RAM", "PSP Model" and "Hardware Tesselation". --- libretro/libretro.cpp | 910 +++++++++++------ libretro/libretro.h | 45 + libretro/libretro_core_options.h | 1359 +++++++++++++++++++++++++ libretro/libretro_core_options_intl.h | 91 ++ libretro/retro_inline.h | 39 + 5 files changed, 2105 insertions(+), 339 deletions(-) create mode 100644 libretro/libretro_core_options.h create mode 100644 libretro/libretro_core_options_intl.h create mode 100644 libretro/retro_inline.h diff --git a/libretro/libretro.cpp b/libretro/libretro.cpp index 9b4a20bd9738..3716f1989e5f 100644 --- a/libretro/libretro.cpp +++ b/libretro/libretro.cpp @@ -45,6 +45,7 @@ #include "libretro/libretro.h" #include "libretro/LibretroGraphicsContext.h" +#include "libretro/libretro_core_options.h" #if PPSSPP_PLATFORM(ANDROID) #include @@ -81,6 +82,10 @@ #define VSYNC_SWAP_INTERVAL_RUN_SPEED_THRESHOLD 5.0f static bool libretro_supports_bitmasks = false; +static bool libretro_supports_option_categories = false; +static bool show_ip_address_options = true; +static bool show_upnp_port_option = true; +static bool show_detect_frame_rate_option = true; static std::string changeProAdhocServer; namespace Libretro @@ -428,239 +433,72 @@ class PrintfLogger : public LogListener }; static PrintfLogger *printfLogger; -template class RetroOption -{ - public: - RetroOption(const char *id, const char *name, std::initializer_list> list) : id_(id), name_(name), list_(list.begin(), list.end()) {} - RetroOption(const char *id, const char *name, std::initializer_list list) : id_(id), name_(name) { - for (auto option : list) - list_.push_back({ option, (T)list_.size() }); - } - RetroOption(const char *id, const char *name, T first, std::initializer_list list) : id_(id), name_(name) { - for (auto option : list) - list_.push_back({ option, first + (int)list_.size() }); - } - RetroOption(const char *id, const char *name, T first, int count, int step = 1) : id_(id), name_(name) { - for (T i = first; i < first + count; i += step) - list_.push_back({ std::to_string(i), i }); - } - RetroOption(const char *id, const char *name, bool initial) : id_(id), name_(name) { - list_.push_back({ initial ? "enabled" : "disabled", initial }); - list_.push_back({ !initial ? "enabled" : "disabled", !initial }); - } - - retro_variable GetOptions() - { - if (options_.empty()) - { - options_ = name_; - options_.push_back(';'); - for (auto &option : list_) - { - if (option.first == list_.begin()->first) - options_ += std::string(" ") + option.first; - else - options_ += std::string("|") + option.first; - } - } - return { id_, options_.c_str() }; - } - - bool Update(T *dest) - { - retro_variable var{ id_ }; - T val = list_.front().second; - - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - for (auto option : list_) - { - if (option.first == var.value) - { - val = option.second; - break; - } - } - } - - if (*dest != val) - { - *dest = val; - return true; - } - - return false; - } - - void Show(bool show) - { - struct retro_core_option_display optionDisplay{id_, show}; - environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY, &optionDisplay); - } - - void Set(const char *val) - { - struct retro_variable var{id_, val}; - environ_cb(RETRO_ENVIRONMENT_SET_VARIABLE, &var); - } - - private: - const char *id_; - const char *name_; - std::string options_; - std::vector> list_; -}; - -#define MAC_INITIALIZER_LIST \ -{ \ - {"0", "0"}, \ - {"1", "1"}, \ - {"2", "2"}, \ - {"3", "3"}, \ - {"4", "4"}, \ - {"5", "5"}, \ - {"6", "6"}, \ - {"7", "7"}, \ - {"8", "8"}, \ - {"9", "9"}, \ - {"a", "a"}, \ - {"b", "b"}, \ - {"c", "c"}, \ - {"d", "d"}, \ - {"e", "e"}, \ - {"f", "f"} \ -} - -static RetroOption ppsspp_cpu_core("ppsspp_cpu_core", "CPU Core", { { "JIT", CPUCore::JIT }, { "IR JIT", CPUCore::IR_JIT }, { "Interpreter", CPUCore::INTERPRETER } }); -static RetroOption ppsspp_locked_cpu_speed("ppsspp_locked_cpu_speed", "Locked CPU Speed", { { "off", 0 }, { "222MHz", 222 }, { "266MHz", 266 }, { "333MHz", 333 } }); -static RetroOption ppsspp_language("ppsspp_language", "Language", { { "Automatic", -1 }, { "English", PSP_SYSTEMPARAM_LANGUAGE_ENGLISH }, { "Japanese", PSP_SYSTEMPARAM_LANGUAGE_JAPANESE }, { "French", PSP_SYSTEMPARAM_LANGUAGE_FRENCH }, { "Spanish", PSP_SYSTEMPARAM_LANGUAGE_SPANISH }, { "German", PSP_SYSTEMPARAM_LANGUAGE_GERMAN }, { "Italian", PSP_SYSTEMPARAM_LANGUAGE_ITALIAN }, { "Dutch", PSP_SYSTEMPARAM_LANGUAGE_DUTCH }, { "Portuguese", PSP_SYSTEMPARAM_LANGUAGE_PORTUGUESE }, { "Russian", PSP_SYSTEMPARAM_LANGUAGE_RUSSIAN }, { "Korean", PSP_SYSTEMPARAM_LANGUAGE_KOREAN }, { "Chinese Traditional", PSP_SYSTEMPARAM_LANGUAGE_CHINESE_TRADITIONAL }, { "Chinese Simplified", PSP_SYSTEMPARAM_LANGUAGE_CHINESE_SIMPLIFIED } }); -static RetroOption ppsspp_rendering_mode("ppsspp_rendering_mode", "Rendering Mode", { { "Buffered", FB_BUFFERED_MODE }, { "Skip Buffer Effects", FB_NON_BUFFERED_MODE } }); -static RetroOption ppsspp_auto_frameskip("ppsspp_auto_frameskip", "Auto Frameskip", false); -static RetroOption ppsspp_frameskip("ppsspp_frameskip", "Frameskip", { "Off", "1", "2", "3", "4", "5", "6", "7", "8" }); -static RetroOption ppsspp_frameskiptype("ppsspp_frameskiptype", "Frameskip Type", { {"Number of frames", 0}, {"Percent of FPS", 1} }); -static RetroOption ppsspp_internal_resolution("ppsspp_internal_resolution", "Internal Resolution (Restart)", 1, { "480x272", "960x544", "1440x816", "1920x1088", "2400x1360", "2880x1632", "3360x1904", "3840x2176", "4320x2448", "4800x2720" }); -static RetroOption ppsspp_button_preference("ppsspp_button_preference", "Confirmation Button", { { "Cross", PSP_SYSTEMPARAM_BUTTON_CROSS }, { "Circle", PSP_SYSTEMPARAM_BUTTON_CIRCLE } }); -static RetroOption ppsspp_fast_memory("ppsspp_fast_memory", "Fast Memory (Speedhack)", true); -static RetroOption ppsspp_block_transfer_gpu("ppsspp_block_transfer_gpu", "Block Transfer GPU", true); -static RetroOption ppsspp_inflight_frames("ppsspp_inflight_frames", "Buffered frames (Slower, less lag, restart)", { { "Up to 2", 2 }, { "Up to 1", 1 }, { "No buffer", 0 }, }); -static RetroOption ppsspp_texture_scaling_level("ppsspp_texture_scaling_level", "Texture Scaling Level", { { "Off", 1 }, { "2x", 2 }, { "3x", 3 }, { "4x", 4 }, { "5x", 5 } }); -static RetroOption ppsspp_texture_scaling_type("ppsspp_texture_scaling_type", "Texture Scaling Type", { { "xbrz", TextureScalerCommon::XBRZ }, { "hybrid", TextureScalerCommon::HYBRID }, { "bicubic", TextureScalerCommon::BICUBIC }, { "hybrid_bicubic", TextureScalerCommon::HYBRID_BICUBIC } }); -static RetroOption ppsspp_texture_shader("ppsspp_texture_shader", "Texture Shader (Vulkan only, overrides Texture Scaling Type)", { {"Off", "Off"}, {"2xBRZ", "Tex2xBRZ"}, {"4xBRZ", "Tex4xBRZ"}, {"MMPX", "TexMMPX"} }); -static RetroOption ppsspp_texture_filtering("ppsspp_texture_filtering", "Texture Filtering", { { "Auto", 1 }, { "Nearest", 2 }, { "Linear", 3 }, {"Auto max quality", 4}}); -static RetroOption ppsspp_texture_anisotropic_filtering("ppsspp_texture_anisotropic_filtering", "Anisotropic Filtering", { "off", "2x", "4x", "8x", "16x" }); -static RetroOption ppsspp_lower_resolution_for_effects("ppsspp_lower_resolution_for_effects", "Lower resolution for effects", { {"Off", 0}, {"Safe", 1}, {"Balanced", 2}, {"Aggressive", 3} }); -static RetroOption ppsspp_texture_deposterize("ppsspp_texture_deposterize", "Texture Deposterize", false); -static RetroOption ppsspp_texture_replacement("ppsspp_texture_replacement", "Texture Replacement", false); -static RetroOption ppsspp_gpu_hardware_transform("ppsspp_gpu_hardware_transform", "GPU Hardware T&L", true); -static RetroOption ppsspp_vertex_cache("ppsspp_vertex_cache", "Vertex Cache (Speedhack)", false); -static RetroOption ppsspp_cheats("ppsspp_cheats", "Internal Cheats Support", false); -static RetroOption ppsspp_io_timing_method("ppsspp_io_timing_method", "IO Timing Method", { { "Fast", IOTimingMethods::IOTIMING_FAST }, { "Host", IOTimingMethods::IOTIMING_HOST }, { "Simulate UMD delays", IOTimingMethods::IOTIMING_REALISTIC } }); -static RetroOption ppsspp_frame_duplication("ppsspp_frame_duplication", "Duplicate Frames in 30 Hz Games", false); -static RetroOption ppsspp_detect_vsync_swap_interval("ppsspp_detect_vsync_swap_interval", "Detect Frame Rate Changes (Notify Frontend)", false); -static RetroOption ppsspp_software_skinning("ppsspp_software_skinning", "Software Skinning", true); -static RetroOption ppsspp_ignore_bad_memory_access("ppsspp_ignore_bad_memory_access", "Ignore bad memory accesses", true); -static RetroOption ppsspp_lazy_texture_caching("ppsspp_lazy_texture_caching", "Lazy texture caching (Speedup)", false); -static RetroOption ppsspp_retain_changed_textures("ppsspp_retain_changed_textures", "Retain changed textures (Speedup, mem hog)", false); -static RetroOption ppsspp_force_lag_sync("ppsspp_force_lag_sync", "Force real clock sync (Slower, less lag)", false); -static RetroOption ppsspp_spline_quality("ppsspp_spline_quality", "Spline/Bezier curves quality", { {"Low", 0}, {"Medium", 1}, {"High", 2} }); -static RetroOption ppsspp_enable_wlan("ppsspp_enable_wlan", "Enable Networking/WLAN (beta, may break games)", false); -static RetroOption ppsspp_change_mac_address[] = { - {"ppsspp_change_mac_address01", "MAC address Pt 1: X-:--:--:--:--:--", MAC_INITIALIZER_LIST}, - {"ppsspp_change_mac_address02", "MAC address Pt 2: -X:--:--:--:--:--", MAC_INITIALIZER_LIST}, - {"ppsspp_change_mac_address03", "MAC address Pt 3: --:X-:--:--:--:--", MAC_INITIALIZER_LIST}, - {"ppsspp_change_mac_address04", "MAC address Pt 4: --:-X:--:--:--:--", MAC_INITIALIZER_LIST}, - {"ppsspp_change_mac_address05", "MAC address Pt 5: --:--:X-:--:--:--", MAC_INITIALIZER_LIST}, - {"ppsspp_change_mac_address06", "MAC address Pt 6: --:--:-X:--:--:--", MAC_INITIALIZER_LIST}, - {"ppsspp_change_mac_address07", "MAC address Pt 7: --:--:--:X-:--:--", MAC_INITIALIZER_LIST}, - {"ppsspp_change_mac_address08", "MAC address Pt 8: --:--:--:-X:--:--", MAC_INITIALIZER_LIST}, - {"ppsspp_change_mac_address09", "MAC address Pt 9: --:--:--:--:X-:--", MAC_INITIALIZER_LIST}, - {"ppsspp_change_mac_address10", "MAC address Pt 10: --:--:--:--:-X:--", MAC_INITIALIZER_LIST}, - {"ppsspp_change_mac_address11", "MAC address Pt 11: --:--:--:--:--:X-", MAC_INITIALIZER_LIST}, - {"ppsspp_change_mac_address12", "MAC address Pt 12: --:--:--:--:--:-X", MAC_INITIALIZER_LIST} -}; -static RetroOption ppsspp_wlan_channel("ppsspp_wlan_channel", "WLAN channel", {{"Auto", 0}, {"1", 1}, {"6", 6}, {"11", 11}} ); -static RetroOption ppsspp_enable_builtin_pro_ad_hoc_server("ppsspp_enable_builtin_pro_ad_hoc_server", "Enable built-in PRO ad hoc server", false); -static RetroOption ppsspp_change_pro_ad_hoc_server_address("ppsspp_change_pro_ad_hoc_server_address", "Change PRO ad hoc server IP address (localhost = multiple instances)", { - {"socom.cc", "socom.cc"}, - {"psp.gameplayer.club", "psp.gameplayer.club"}, - {"myneighborsushicat.com", "myneighborsushicat.com"}, - {"localhost", "localhost"}, - {"IP address", "IP address"} -}); -static RetroOption ppsspp_pro_ad_hoc_ipv4[] = { - {"ppsspp_pro_ad_hoc_server_address01", "PRO ad hoc server IP address Pt 1: x--.---.---.--- ", 0, 10, 1}, - {"ppsspp_pro_ad_hoc_server_address02", "PRO ad hoc server IP address Pt 2: -x-.---.---.--- ", 0, 10, 1}, - {"ppsspp_pro_ad_hoc_server_address03", "PRO ad hoc server IP address Pt 3: --x.---.---.--- ", 0, 10, 1}, - {"ppsspp_pro_ad_hoc_server_address04", "PRO ad hoc server IP address Pt 4: ---.x--.---.--- ", 0, 10, 1}, - {"ppsspp_pro_ad_hoc_server_address05", "PRO ad hoc server IP address Pt 5: ---.-x-.---.--- ", 0, 10, 1}, - {"ppsspp_pro_ad_hoc_server_address06", "PRO ad hoc server IP address Pt 6: ---.--x.---.--- ", 0, 10, 1}, - {"ppsspp_pro_ad_hoc_server_address07", "PRO ad hoc server IP address Pt 7: ---.---.x--.--- ", 0, 10, 1}, - {"ppsspp_pro_ad_hoc_server_address08", "PRO ad hoc server IP address Pt 8: ---.---.-x-.--- ", 0, 10, 1}, - {"ppsspp_pro_ad_hoc_server_address09", "PRO ad hoc server IP address Pt 9: ---.---.--x.--- ", 0, 10, 1}, - {"ppsspp_pro_ad_hoc_server_address10", "PRO ad hoc server IP address Pt 10: ---.---.---.x-- ", 0, 10, 1}, - {"ppsspp_pro_ad_hoc_server_address11", "PRO ad hoc server IP address Pt 11: ---.---.---.-x- ", 0, 10, 1}, - {"ppsspp_pro_ad_hoc_server_address12", "PRO ad hoc server IP address Pt 12: ---.---.---.--x ", 0, 10, 1} -}; -static RetroOption ppsspp_enable_upnp("ppsspp_enable_upnp", "Enable UPnP (need a few seconds to detect)", false); -static RetroOption ppsspp_upnp_use_original_port("ppsspp_upnp_use_original_port", "UPnP use original port (enabled = PSP compatibility)", true); -static RetroOption ppsspp_port_offset("ppsspp_port_offset", "Port offset (0 = PSP compatibility)", 0, 65001, 1000); -static RetroOption ppsspp_minimum_timeout("ppsspp_minimum timeout", "Minimum timeout (override in ms, 0 = default))", 0, 5001, 100); -static RetroOption ppsspp_forced_first_connect("ppsspp_forced_first_connect", "Forced first connect (faster connect)", false); - static bool set_variable_visibility(void) { + struct retro_core_option_display option_display; + struct retro_variable var; bool updated = false; - if (ppsspp_change_pro_ad_hoc_server_address.Update(&changeProAdhocServer)) - updated = true; + // Show/hide IP address options + bool show_ip_address_options_prev = show_ip_address_options; + show_ip_address_options = true; - if (changeProAdhocServer == "IP address") + var.key = "ppsspp_change_pro_ad_hoc_server_address"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value && strcmp(var.value, "IP address")) + show_ip_address_options = false; + + if (show_ip_address_options != show_ip_address_options_prev) { - g_Config.proAdhocServer = ""; - for (int i = 0;;) + option_display.visible = show_ip_address_options; + for (int i = 0; i < 12; i++) { - int addressPt = 0; - ppsspp_pro_ad_hoc_ipv4[i].Show(true); - ppsspp_pro_ad_hoc_ipv4[i].Update(&addressPt); - g_Config.proAdhocServer += static_cast('0' + addressPt); - - if (++i == 12) - break; - - if (i % 3 == 0) - g_Config.proAdhocServer += '.'; + char key[64] = {0}; + option_display.key = key; + snprintf(key, sizeof(key), "ppsspp_pro_ad_hoc_server_address%02d", i + 1); + environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY, &option_display); } - } - else - { - g_Config.proAdhocServer = changeProAdhocServer; - - for (int i = 0; i < 12; ++i) - ppsspp_pro_ad_hoc_ipv4[i].Show(false); - } - - if (ppsspp_enable_upnp.Update(&g_Config.bEnableUPnP)) updated = true; + } - ppsspp_upnp_use_original_port.Show(g_Config.bEnableUPnP); - - bool detectVsyncSwapIntervalOptShownLast = detectVsyncSwapIntervalOptShown; - bool autoFrameSkip = false; - int frameSkip = 0; - bool renderDuplicateFrames = false; + // Show/hide 'UPnP Use Original Port' option + bool show_upnp_port_option_prev = show_upnp_port_option; + show_upnp_port_option = true; - ppsspp_auto_frameskip.Update(&autoFrameSkip); - ppsspp_frameskip.Update(&frameSkip); - ppsspp_frame_duplication.Update(&renderDuplicateFrames); + var.key = "ppsspp_enable_upnp"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value && !strcmp(var.value, "disabled")) + show_upnp_port_option = false; - detectVsyncSwapIntervalOptShown = - !autoFrameSkip && - (frameSkip == 0) && - !renderDuplicateFrames; + if (show_upnp_port_option != show_upnp_port_option_prev) + { + option_display.visible = show_upnp_port_option; + option_display.key = "ppsspp_upnp_use_original_port"; + environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY, &option_display); + updated = true; + } - if (detectVsyncSwapIntervalOptShown != detectVsyncSwapIntervalOptShownLast) + // Show/hide 'Detect Frame Rate Changes' option + bool show_detect_frame_rate_option_prev = show_detect_frame_rate_option; + int frameskip = 0; + bool auto_frameskip = false; + bool dupe_frames = false; + show_detect_frame_rate_option = true; + + var.key = "ppsspp_frameskip"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value && strcmp(var.value, "disabled")) + frameskip = atoi(var.value); + var.key = "ppsspp_auto_frameskip"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value && !strcmp(var.value, "enabled")) + auto_frameskip = true; + var.key = "ppsspp_frame_duplication"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value && !strcmp(var.value, "enabled")) + dupe_frames = true; + + show_detect_frame_rate_option = (frameskip == 0) && !auto_frameskip && !dupe_frames; + if (show_detect_frame_rate_option != show_detect_frame_rate_option_prev) { - ppsspp_detect_vsync_swap_interval.Show(detectVsyncSwapIntervalOptShown); + option_display.visible = show_detect_frame_rate_option; + option_display.key = "ppsspp_detect_vsync_swap_interval"; + environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_DISPLAY, &option_display); updated = true; } @@ -671,59 +509,10 @@ void retro_set_environment(retro_environment_t cb) { environ_cb = cb; + libretro_set_core_options(environ_cb, &libretro_supports_option_categories); struct retro_core_options_update_display_callback update_display_cb; update_display_cb.callback = set_variable_visibility; environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_UPDATE_DISPLAY_CALLBACK, &update_display_cb); - - std::vector vars; - vars.push_back(ppsspp_internal_resolution.GetOptions()); - vars.push_back(ppsspp_cpu_core.GetOptions()); - vars.push_back(ppsspp_locked_cpu_speed.GetOptions()); - vars.push_back(ppsspp_language.GetOptions()); - vars.push_back(ppsspp_button_preference.GetOptions()); - vars.push_back(ppsspp_rendering_mode.GetOptions()); - vars.push_back(ppsspp_gpu_hardware_transform.GetOptions()); - vars.push_back(ppsspp_texture_anisotropic_filtering.GetOptions()); - vars.push_back(ppsspp_spline_quality.GetOptions()); - vars.push_back(ppsspp_auto_frameskip.GetOptions()); - vars.push_back(ppsspp_frameskip.GetOptions()); - vars.push_back(ppsspp_frameskiptype.GetOptions()); - vars.push_back(ppsspp_frame_duplication.GetOptions()); - vars.push_back(ppsspp_detect_vsync_swap_interval.GetOptions()); - vars.push_back(ppsspp_vertex_cache.GetOptions()); - vars.push_back(ppsspp_fast_memory.GetOptions()); - vars.push_back(ppsspp_block_transfer_gpu.GetOptions()); - vars.push_back(ppsspp_inflight_frames.GetOptions()); - vars.push_back(ppsspp_software_skinning.GetOptions()); - vars.push_back(ppsspp_lazy_texture_caching.GetOptions()); - vars.push_back(ppsspp_retain_changed_textures.GetOptions()); - vars.push_back(ppsspp_force_lag_sync.GetOptions()); - vars.push_back(ppsspp_lower_resolution_for_effects.GetOptions()); - vars.push_back(ppsspp_texture_scaling_level.GetOptions()); - vars.push_back(ppsspp_texture_scaling_type.GetOptions()); - vars.push_back(ppsspp_texture_shader.GetOptions()); - vars.push_back(ppsspp_texture_filtering.GetOptions()); - vars.push_back(ppsspp_texture_deposterize.GetOptions()); - vars.push_back(ppsspp_texture_replacement.GetOptions()); - vars.push_back(ppsspp_io_timing_method.GetOptions()); - vars.push_back(ppsspp_ignore_bad_memory_access.GetOptions()); - vars.push_back(ppsspp_cheats.GetOptions()); - vars.push_back(ppsspp_enable_wlan.GetOptions()); - for (int i = 0; i < 12; ++i) - vars.push_back(ppsspp_change_mac_address[i].GetOptions()); - vars.push_back(ppsspp_wlan_channel.GetOptions()); - vars.push_back(ppsspp_enable_builtin_pro_ad_hoc_server.GetOptions()); - vars.push_back(ppsspp_change_pro_ad_hoc_server_address.GetOptions()); - for (int i = 0; i < 12; ++i) - vars.push_back(ppsspp_pro_ad_hoc_ipv4[i].GetOptions()); - vars.push_back(ppsspp_enable_upnp.GetOptions()); - vars.push_back(ppsspp_upnp_use_original_port.GetOptions()); - vars.push_back(ppsspp_port_offset.GetOptions()); - vars.push_back(ppsspp_minimum_timeout.GetOptions()); - vars.push_back(ppsspp_forced_first_connect.GetOptions()); - vars.push_back({}); - - environ_cb(RETRO_ENVIRONMENT_SET_VARIABLES, (void *)vars.data()); } static int get_language_auto(void) @@ -803,46 +592,522 @@ static void check_variables(CoreParameter &coreParam) && !updated) return; - ppsspp_button_preference.Update(&g_Config.iButtonPreference); - ppsspp_fast_memory.Update(&g_Config.bFastMemory); - ppsspp_vertex_cache.Update(&g_Config.bVertexCache); - ppsspp_gpu_hardware_transform.Update(&g_Config.bHardwareTransform); - ppsspp_frameskip.Update(&g_Config.iFrameSkip); - ppsspp_frameskiptype.Update(&g_Config.iFrameSkipType); - ppsspp_auto_frameskip.Update(&g_Config.bAutoFrameSkip); - ppsspp_block_transfer_gpu.Update(&g_Config.bBlockTransferGPU); - ppsspp_texture_filtering.Update(&g_Config.iTexFiltering); - ppsspp_texture_anisotropic_filtering.Update(&g_Config.iAnisotropyLevel); - ppsspp_texture_deposterize.Update(&g_Config.bTexDeposterize); - ppsspp_texture_replacement.Update(&g_Config.bReplaceTextures); - ppsspp_cheats.Update(&g_Config.bEnableCheats); - ppsspp_locked_cpu_speed.Update(&g_Config.iLockedCPUSpeed); - ppsspp_rendering_mode.Update(&g_Config.iRenderingMode); - ppsspp_cpu_core.Update((CPUCore *)&g_Config.iCpuCore); - ppsspp_io_timing_method.Update((IOTimingMethods *)&g_Config.iIOTimingMethod); - ppsspp_lower_resolution_for_effects.Update(&g_Config.iBloomHack); - ppsspp_frame_duplication.Update(&g_Config.bRenderDuplicateFrames); - ppsspp_detect_vsync_swap_interval.Update(&detectVsyncSwapInterval); - ppsspp_software_skinning.Update(&g_Config.bSoftwareSkinning); - ppsspp_ignore_bad_memory_access.Update(&g_Config.bIgnoreBadMemAccess); - ppsspp_lazy_texture_caching.Update(&g_Config.bTextureBackoffCache); - ppsspp_retain_changed_textures.Update(&g_Config.bTextureSecondaryCache); - ppsspp_force_lag_sync.Update(&g_Config.bForceLagSync); - ppsspp_spline_quality.Update(&g_Config.iSplineBezierQuality); - ppsspp_inflight_frames.Update(&g_Config.iInflightFrames); - const bool do_scaling_type_update = ppsspp_texture_scaling_type.Update(&g_Config.iTexScalingType); - const bool do_scaling_level_update = ppsspp_texture_scaling_level.Update(&g_Config.iTexScalingLevel); - const bool do_texture_shader_update = ppsspp_texture_shader.Update(&g_Config.sTextureShaderName); - - g_Config.bTexHardwareScaling = "Off" != g_Config.sTextureShaderName; - - if (gpu && (do_scaling_type_update || do_scaling_level_update || do_texture_shader_update)) + struct retro_variable var = {0}; + std::string sTextureShaderName_prev; + int iInternalResolution_prev; + int iTexScalingType_prev; + int iTexScalingLevel_prev; + + var.key = "ppsspp_language"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (!strcmp(var.value, "Automatic")) + g_Config.iLanguage = -1; + else if (!strcmp(var.value, "English")) + g_Config.iLanguage = PSP_SYSTEMPARAM_LANGUAGE_ENGLISH; + else if (!strcmp(var.value, "Japanese")) + g_Config.iLanguage = PSP_SYSTEMPARAM_LANGUAGE_JAPANESE; + else if (!strcmp(var.value, "French")) + g_Config.iLanguage = PSP_SYSTEMPARAM_LANGUAGE_FRENCH; + else if (!strcmp(var.value, "Spanish")) + g_Config.iLanguage = PSP_SYSTEMPARAM_LANGUAGE_SPANISH; + else if (!strcmp(var.value, "German")) + g_Config.iLanguage = PSP_SYSTEMPARAM_LANGUAGE_GERMAN; + else if (!strcmp(var.value, "Italian")) + g_Config.iLanguage = PSP_SYSTEMPARAM_LANGUAGE_ITALIAN; + else if (!strcmp(var.value, "Dutch")) + g_Config.iLanguage = PSP_SYSTEMPARAM_LANGUAGE_DUTCH; + else if (!strcmp(var.value, "Portuguese")) + g_Config.iLanguage = PSP_SYSTEMPARAM_LANGUAGE_PORTUGUESE; + else if (!strcmp(var.value, "Russian")) + g_Config.iLanguage = PSP_SYSTEMPARAM_LANGUAGE_RUSSIAN; + else if (!strcmp(var.value, "Korean")) + g_Config.iLanguage = PSP_SYSTEMPARAM_LANGUAGE_KOREAN; + else if (!strcmp(var.value, "Chinese Traditional")) + g_Config.iLanguage = PSP_SYSTEMPARAM_LANGUAGE_CHINESE_TRADITIONAL; + else if (!strcmp(var.value, "Chinese Simplified")) + g_Config.iLanguage = PSP_SYSTEMPARAM_LANGUAGE_CHINESE_SIMPLIFIED; + } + + var.key = "ppsspp_cpu_core"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (!strcmp(var.value, "JIT")) + g_Config.iCpuCore = (int)CPUCore::JIT; + else if (!strcmp(var.value, "IR JIT")) + g_Config.iCpuCore = (int)CPUCore::IR_JIT; + else if (!strcmp(var.value, "Interpreter")) + g_Config.iCpuCore = (int)CPUCore::INTERPRETER; + } + + var.key = "ppsspp_fast_memory"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (!strcmp(var.value, "disabled")) + g_Config.bFastMemory = false; + else + g_Config.bFastMemory = true; + } + + var.key = "ppsspp_ignore_bad_memory_access"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (!strcmp(var.value, "disabled")) + g_Config.bIgnoreBadMemAccess = false; + else + g_Config.bIgnoreBadMemAccess = true; + } + + var.key = "ppsspp_io_timing_method"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (!strcmp(var.value, "Fast")) + g_Config.iIOTimingMethod = IOTIMING_FAST; + else if (!strcmp(var.value, "Host")) + g_Config.iIOTimingMethod = IOTIMING_HOST; + else if (!strcmp(var.value, "Simulate UMD delays")) + g_Config.iIOTimingMethod = IOTIMING_REALISTIC; + } + + var.key = "ppsspp_force_lag_sync"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (!strcmp(var.value, "disabled")) + g_Config.bForceLagSync = false; + else + g_Config.bForceLagSync = true; + } + + var.key = "ppsspp_locked_cpu_speed"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + g_Config.iLockedCPUSpeed = atoi(var.value); + + var.key = "ppsspp_cache_iso"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (!strcmp(var.value, "disabled")) + g_Config.bCacheFullIsoInRam = false; + else + g_Config.bCacheFullIsoInRam = true; + } + + var.key = "ppsspp_cheats"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (!strcmp(var.value, "disabled")) + g_Config.bEnableCheats = false; + else + g_Config.bEnableCheats = true; + } + + var.key = "ppsspp_psp_model"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (!strcmp(var.value, "psp_1000")) + g_Config.iPSPModel = PSP_MODEL_FAT; + else if (!strcmp(var.value, "psp_2000_3000")) + g_Config.iPSPModel = PSP_MODEL_SLIM; + } + + var.key = "ppsspp_button_preference"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (!strcmp(var.value, "Cross")) + g_Config.iButtonPreference = PSP_SYSTEMPARAM_BUTTON_CROSS; + else if (!strcmp(var.value, "Circle")) + g_Config.iButtonPreference = PSP_SYSTEMPARAM_BUTTON_CIRCLE; + } + + var.key = "ppsspp_internal_resolution"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + iInternalResolution_prev = g_Config.iInternalResolution; + + if (!strcmp(var.value, "480x272")) + g_Config.iInternalResolution = 1; + else if (!strcmp(var.value, "960x544")) + g_Config.iInternalResolution = 2; + else if (!strcmp(var.value, "1440x816")) + g_Config.iInternalResolution = 3; + else if (!strcmp(var.value, "1920x1088")) + g_Config.iInternalResolution = 4; + else if (!strcmp(var.value, "2400x1360")) + g_Config.iInternalResolution = 5; + else if (!strcmp(var.value, "2880x1632")) + g_Config.iInternalResolution = 6; + else if (!strcmp(var.value, "3360x1904")) + g_Config.iInternalResolution = 7; + else if (!strcmp(var.value, "3840x2176")) + g_Config.iInternalResolution = 8; + else if (!strcmp(var.value, "4320x2448")) + g_Config.iInternalResolution = 9; + else if (!strcmp(var.value, "4800x2720")) + g_Config.iInternalResolution = 10; + } + + var.key = "ppsspp_rendering_mode"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (!strcmp(var.value, "Buffered")) + g_Config.iRenderingMode = FB_BUFFERED_MODE; + else if (!strcmp(var.value, "Skip Buffer Effects")) + g_Config.iRenderingMode = FB_NON_BUFFERED_MODE; + } + + var.key = "ppsspp_block_transfer_gpu"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (!strcmp(var.value, "disabled")) + g_Config.bBlockTransferGPU = false; + else + g_Config.bBlockTransferGPU = true; + } + + var.key = "ppsspp_frameskip"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + g_Config.iFrameSkip = atoi(var.value); + + var.key = "ppsspp_frameskiptype"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (!strcmp(var.value, "Number of frames")) + g_Config.iFrameSkipType = 0; + else if (!strcmp(var.value, "Percent of FPS")) + g_Config.iFrameSkipType = 1; + } + + var.key = "ppsspp_auto_frameskip"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (!strcmp(var.value, "disabled")) + g_Config.bAutoFrameSkip = false; + else + g_Config.bAutoFrameSkip = true; + } + + var.key = "ppsspp_frame_duplication"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (!strcmp(var.value, "disabled")) + g_Config.bRenderDuplicateFrames = false; + else + g_Config.bRenderDuplicateFrames = true; + } + + var.key = "ppsspp_detect_vsync_swap_interval"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (!strcmp(var.value, "disabled")) + detectVsyncSwapInterval = false; + else + detectVsyncSwapInterval = true; + } + + var.key = "ppsspp_inflight_frames"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (!strcmp(var.value, "No buffer")) + g_Config.iInflightFrames = 0; + else if (!strcmp(var.value, "Up to 1")) + g_Config.iInflightFrames = 1; + else if (!strcmp(var.value, "Up to 2")) + g_Config.iInflightFrames = 2; + } + + var.key = "ppsspp_gpu_hardware_transform"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (!strcmp(var.value, "disabled")) + g_Config.bHardwareTransform = false; + else + g_Config.bHardwareTransform = true; + } + + var.key = "ppsspp_software_skinning"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (!strcmp(var.value, "disabled")) + g_Config.bSoftwareSkinning = false; + else + g_Config.bSoftwareSkinning = true; + } + + var.key = "ppsspp_vertex_cache"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (!strcmp(var.value, "disabled")) + g_Config.bVertexCache = false; + else + g_Config.bVertexCache = true; + } + + var.key = "ppsspp_lazy_texture_caching"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (!strcmp(var.value, "disabled")) + g_Config.bTextureBackoffCache = false; + else + g_Config.bTextureBackoffCache = true; + } + + var.key = "ppsspp_retain_changed_textures"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (!strcmp(var.value, "disabled")) + g_Config.bTextureSecondaryCache = false; + else + g_Config.bTextureSecondaryCache = true; + } + + var.key = "ppsspp_spline_quality"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (!strcmp(var.value, "Low")) + g_Config.iSplineBezierQuality = 0; + else if (!strcmp(var.value, "Medium")) + g_Config.iSplineBezierQuality = 1; + else if (!strcmp(var.value, "High")) + g_Config.iSplineBezierQuality = 2; + } + + var.key = "ppsspp_hardware_tesselation"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (!strcmp(var.value, "disabled")) + g_Config.bHardwareTessellation = false; + else + g_Config.bHardwareTessellation = true; + } + + var.key = "ppsspp_lower_resolution_for_effects"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (!strcmp(var.value, "disabled")) + g_Config.iBloomHack = 0; + else if (!strcmp(var.value, "Safe")) + g_Config.iBloomHack = 1; + else if (!strcmp(var.value, "Balanced")) + g_Config.iBloomHack = 2; + else if (!strcmp(var.value, "Aggressive")) + g_Config.iBloomHack = 3; + } + + var.key = "ppsspp_texture_scaling_type"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + iTexScalingType_prev = g_Config.iTexScalingType; + + if (!strcmp(var.value, "xbrz")) + g_Config.iTexScalingType = TextureScalerCommon::XBRZ; + else if (!strcmp(var.value, "hybrid")) + g_Config.iTexScalingType = TextureScalerCommon::HYBRID; + else if (!strcmp(var.value, "bicubic")) + g_Config.iTexScalingType = TextureScalerCommon::BICUBIC; + else if (!strcmp(var.value, "hybrid_bicubic")) + g_Config.iTexScalingType = TextureScalerCommon::HYBRID_BICUBIC; + } + + var.key = "ppsspp_texture_scaling_level"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + iTexScalingLevel_prev = g_Config.iTexScalingLevel; + + if (!strcmp(var.value, "disabled")) + g_Config.iTexScalingLevel = 1; + else if (!strcmp(var.value, "2x")) + g_Config.iTexScalingLevel = 2; + else if (!strcmp(var.value, "3x")) + g_Config.iTexScalingLevel = 3; + else if (!strcmp(var.value, "4x")) + g_Config.iTexScalingLevel = 4; + else if (!strcmp(var.value, "5x")) + g_Config.iTexScalingLevel = 5; + } + + var.key = "ppsspp_texture_deposterize"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (!strcmp(var.value, "disabled")) + g_Config.bTexDeposterize = false; + else + g_Config.bTexDeposterize = true; + } + + var.key = "ppsspp_texture_shader"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + sTextureShaderName_prev = g_Config.sTextureShaderName; + + if (!strcmp(var.value, "disabled")) + g_Config.sTextureShaderName = "Off"; + else if (!strcmp(var.value, "2xBRZ")) + g_Config.sTextureShaderName = "Tex2xBRZ"; + else if (!strcmp(var.value, "4xBRZ")) + g_Config.sTextureShaderName = "Tex4xBRZ"; + else if (!strcmp(var.value, "MMPX")) + g_Config.sTextureShaderName = "TexMMPX"; + } + + var.key = "ppsspp_texture_anisotropic_filtering"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (!strcmp(var.value, "disabled")) + g_Config.iAnisotropyLevel = 0; + else if (!strcmp(var.value, "2x")) + g_Config.iAnisotropyLevel = 1; + else if (!strcmp(var.value, "4x")) + g_Config.iAnisotropyLevel = 2; + else if (!strcmp(var.value, "8x")) + g_Config.iAnisotropyLevel = 3; + else if (!strcmp(var.value, "16x")) + g_Config.iAnisotropyLevel = 4; + } + + var.key = "ppsspp_texture_filtering"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (!strcmp(var.value, "Auto")) + g_Config.iTexFiltering = 1; + else if (!strcmp(var.value, "Nearest")) + g_Config.iTexFiltering = 2; + else if (!strcmp(var.value, "Linear")) + g_Config.iTexFiltering = 3; + else if (!strcmp(var.value, "Auto max quality")) + g_Config.iTexFiltering = 4; + } + + var.key = "ppsspp_texture_replacement"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (!strcmp(var.value, "disabled")) + g_Config.bReplaceTextures = false; + else + g_Config.bReplaceTextures = true; + } + + var.key = "ppsspp_enable_wlan"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (!strcmp(var.value, "disabled")) + g_Config.bEnableWlan = false; + else + g_Config.bEnableWlan = true; + } + + var.key = "ppsspp_wlan_channel"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + g_Config.iWlanAdhocChannel = atoi(var.value); + + var.key = "ppsspp_enable_builtin_pro_ad_hoc_server"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (!strcmp(var.value, "disabled")) + g_Config.bEnableAdhocServer = false; + else + g_Config.bEnableAdhocServer = true; + } + + var.key = "ppsspp_change_pro_ad_hoc_server_address"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + changeProAdhocServer = var.value; + + var.key = "ppsspp_enable_upnp"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (!strcmp(var.value, "disabled")) + g_Config.bEnableUPnP = false; + else + g_Config.bEnableUPnP = true; + } + + var.key = "ppsspp_upnp_use_original_port"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (!strcmp(var.value, "disabled")) + g_Config.bUPnPUseOriginalPort = false; + else + g_Config.bUPnPUseOriginalPort = true; + } + + var.key = "ppsspp_port_offset"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + g_Config.iPortOffset = atoi(var.value); + + var.key = "ppsspp_minimum_timeout"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + g_Config.iMinTimeout = atoi(var.value); + + var.key = "ppsspp_forced_first_connect"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (!strcmp(var.value, "disabled")) + g_Config.bForcedFirstConnect = false; + else + g_Config.bForcedFirstConnect = true; + } + + std::string ppsspp_change_mac_address[12]; + int ppsspp_pro_ad_hoc_ipv4[12]; + char key[64] = {0}; + var.key = key; + g_Config.sMACAddress = ""; + g_Config.proAdhocServer = ""; + for (int i = 0; i < 12; i++) + { + snprintf(key, sizeof(key), "ppsspp_change_mac_address%02d", i + 1); + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + ppsspp_change_mac_address[i] = var.value; + + if (i && i % 2 == 0) + g_Config.sMACAddress += ":"; + + g_Config.sMACAddress += ppsspp_change_mac_address[i]; + } + + snprintf(key, sizeof(key), "ppsspp_pro_ad_hoc_server_address%02d", i + 1); + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + ppsspp_pro_ad_hoc_ipv4[i] = atoi(var.value); + } + + if (g_Config.sMACAddress == "00:00:00:00:00:00") + { + g_Config.sMACAddress = CreateRandMAC(); + + for (int i = 0; i < 12; i++) + { + snprintf(key, sizeof(key), "ppsspp_change_mac_address%02d", i + 1); + std::string digit = {g_Config.sMACAddress[i + i / 2]}; + var.value = digit.c_str(); + environ_cb(RETRO_ENVIRONMENT_SET_VARIABLE, &var); + } + } + + if (changeProAdhocServer == "IP address") + { + g_Config.proAdhocServer = ""; + for (int i = 0; i < 12; i++) + { + if (i && i % 3 == 0) + g_Config.proAdhocServer += '.'; + + int addressPt = ppsspp_pro_ad_hoc_ipv4[i]; + g_Config.proAdhocServer += static_cast('0' + addressPt); + } + } + else + g_Config.proAdhocServer = changeProAdhocServer; + + g_Config.bTexHardwareScaling = g_Config.sTextureShaderName != "Off"; + + if (gpu && (g_Config.iTexScalingType != iTexScalingType_prev + || g_Config.iTexScalingLevel != iTexScalingLevel_prev + || g_Config.sTextureShaderName != sTextureShaderName_prev)) { gpu->ClearCacheNextFrame(); gpu->Resized(); } - ppsspp_language.Update(&g_Config.iLanguage); if (g_Config.iLanguage < 0) g_Config.iLanguage = get_language_auto(); @@ -864,7 +1129,7 @@ static void check_variables(CoreParameter &coreParam) updateAvInfo = true; } - if (ppsspp_internal_resolution.Update(&g_Config.iInternalResolution) && !PSP_IsInited()) + if (g_Config.iInternalResolution != iInternalResolution_prev && !PSP_IsInited()) { coreParam.pixelWidth = coreParam.renderWidth = g_Config.iInternalResolution * 480; coreParam.pixelHeight = coreParam.renderHeight = g_Config.iInternalResolution * 272; @@ -889,40 +1154,6 @@ static void check_variables(CoreParameter &coreParam) bool isFastForwarding = environ_cb(RETRO_ENVIRONMENT_GET_FASTFORWARDING, &isFastForwarding); coreParam.fastForward = isFastForwarding; - ppsspp_enable_wlan.Update(&g_Config.bEnableWlan); - ppsspp_wlan_channel.Update(&g_Config.iWlanAdhocChannel); - ppsspp_enable_builtin_pro_ad_hoc_server.Update(&g_Config.bEnableAdhocServer); - - ppsspp_upnp_use_original_port.Update(&g_Config.bUPnPUseOriginalPort); - ppsspp_port_offset.Update(&g_Config.iPortOffset); - ppsspp_minimum_timeout.Update(&g_Config.iMinTimeout); - ppsspp_forced_first_connect.Update(&g_Config.bForcedFirstConnect); - - g_Config.sMACAddress = ""; - for (int i = 0; i < 12;) - { - std::string digit; - ppsspp_change_mac_address[i].Update(&digit); - g_Config.sMACAddress += digit; - - if (++i == 12) - break; - - if (i % 2 == 0) - g_Config.sMACAddress += ":"; - } - - if (g_Config.sMACAddress == "00:00:00:00:00:00") - { - g_Config.sMACAddress = CreateRandMAC(); - - for (int i = 0; i < 12; ++i) - { - std::string digit = {g_Config.sMACAddress[i + i / 2]}; - ppsspp_change_mac_address[i].Set(digit.c_str()); - } - } - set_variable_visibility(); } @@ -1018,6 +1249,7 @@ void retro_deinit(void) host = nullptr; libretro_supports_bitmasks = false; + libretro_supports_option_categories = false; VsyncSwapIntervalReset(); AudioBufferDeinit(); diff --git a/libretro/libretro.h b/libretro/libretro.h index 2f174837012e..bb114aed3571 100644 --- a/libretro/libretro.h +++ b/libretro/libretro.h @@ -283,6 +283,12 @@ enum retro_language RETRO_LANGUAGE_HEBREW = 21, RETRO_LANGUAGE_ASTURIAN = 22, RETRO_LANGUAGE_FINNISH = 23, + RETRO_LANGUAGE_INDONESIAN = 24, + RETRO_LANGUAGE_SWEDISH = 25, + RETRO_LANGUAGE_UKRAINIAN = 26, + RETRO_LANGUAGE_CZECH = 27, + RETRO_LANGUAGE_CATALAN_VALENCIA = 28, + RETRO_LANGUAGE_CATALAN = 29, RETRO_LANGUAGE_LAST, /* Ensure sizeof(enum) == sizeof(int) */ @@ -1753,6 +1759,12 @@ enum retro_mod * the frontend is attempting to call retro_run(). */ +#define RETRO_ENVIRONMENT_GET_SAVESTATE_CONTEXT (72 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* int * -- + * Tells the core about the context the frontend is asking for savestate. + * (see enum retro_savestate_context) + */ + /* VFS functionality */ /* File paths: @@ -2990,6 +3002,35 @@ enum retro_pixel_format RETRO_PIXEL_FORMAT_UNKNOWN = INT_MAX }; +enum retro_savestate_context +{ + /* Standard savestate written to disk. */ + RETRO_SAVESTATE_CONTEXT_NORMAL = 0, + + /* Savestate where you are guaranteed that the same instance will load the save state. + * You can store internal pointers to code or data. + * It's still a full serialization and deserialization, and could be loaded or saved at any time. + * It won't be written to disk or sent over the network. + */ + RETRO_SAVESTATE_CONTEXT_RUNAHEAD_SAME_INSTANCE = 1, + + /* Savestate where you are guaranteed that the same emulator binary will load that savestate. + * You can skip anything that would slow down saving or loading state but you can not store internal pointers. + * It won't be written to disk or sent over the network. + * Example: "Second Instance" runahead + */ + RETRO_SAVESTATE_CONTEXT_RUNAHEAD_SAME_BINARY = 2, + + /* Savestate used within a rollback netplay feature. + * You should skip anything that would unnecessarily increase bandwidth usage. + * It won't be written to disk but it will be sent over the network. + */ + RETRO_SAVESTATE_CONTEXT_ROLLBACK_NETPLAY = 3, + + /* Ensure sizeof() == sizeof(int). */ + RETRO_SAVESTATE_CONTEXT_UNKNOWN = INT_MAX +}; + struct retro_message { const char *msg; /* Message to be displayed. */ @@ -3461,6 +3502,10 @@ struct retro_core_option_definition const char *default_value; }; +#ifdef __PS3__ +#undef local +#endif + struct retro_core_options_intl { /* Pointer to an array of retro_core_option_definition structs diff --git a/libretro/libretro_core_options.h b/libretro/libretro_core_options.h new file mode 100644 index 000000000000..78cab61d7d45 --- /dev/null +++ b/libretro/libretro_core_options.h @@ -0,0 +1,1359 @@ +#ifndef LIBRETRO_CORE_OPTIONS_H__ +#define LIBRETRO_CORE_OPTIONS_H__ + +#include +#include + +#include "libretro.h" +#include "retro_inline.h" + +#ifndef HAVE_NO_LANGEXTRA +#include "libretro_core_options_intl.h" +#endif + +#define BOOL_OPTIONS \ +{ \ + { "disabled", NULL }, \ + { "enabled", NULL }, \ + { NULL, NULL }, \ +} + +#define MAC_ADDRESS_OPTIONS \ +{ \ + { "0", NULL }, \ + { "1", NULL }, \ + { "2", NULL }, \ + { "3", NULL }, \ + { "4", NULL }, \ + { "5", NULL }, \ + { "6", NULL }, \ + { "7", NULL }, \ + { "8", NULL }, \ + { "9", NULL }, \ + { "a", NULL }, \ + { "b", NULL }, \ + { "c", NULL }, \ + { "d", NULL }, \ + { "e", NULL }, \ + { "f", NULL }, \ + { NULL, NULL }, \ +} + +#define IP_ADDRESS_OPTIONS \ +{ \ + { "0", NULL }, \ + { "1", NULL }, \ + { "2", NULL }, \ + { "3", NULL }, \ + { "4", NULL }, \ + { "5", NULL }, \ + { "6", NULL }, \ + { "7", NULL }, \ + { "8", NULL }, \ + { "9", NULL }, \ + { NULL, NULL }, \ +} + +/* + ******************************** + * VERSION: 2.0 + ******************************** + * + * - 2.0: Add support for core options v2 interface + * - 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_v2_category option_cats_us[] = { + { + "system", + "System", + "Configure system options." + }, + { + "video", + "Video", + "Configure video options." + }, + { + "network", + "Network", + "Configure network options." + }, + { NULL, NULL, NULL }, +}; + +struct retro_core_option_v2_definition option_defs_us[] = { + { + "ppsspp_language", + "Language", + NULL, + "Choose language, 'Automatic' will use the frontend language.", + NULL, + "system", + { + { "Automatic", NULL }, + { "English", NULL }, + { "Japanese", NULL }, + { "French", NULL }, + { "Spanish", NULL }, + { "German", NULL }, + { "Italian", NULL }, + { "Dutch", NULL }, + { "Portuguese", NULL }, + { "Russian", NULL }, + { "Korean", NULL }, + { "Chinese Traditional", NULL }, + { "Chinese Simplified", NULL }, + { NULL, NULL }, + }, + "Automatic" + }, + { + "ppsspp_cpu_core", + "CPU Core", + NULL, + NULL, + NULL, + "system", + { + { "JIT", "Dynarec (JIT)" }, + { "IR JIT", "IR Interpreter" }, + { "Interpreter", NULL }, + { NULL, NULL }, + }, + "JIT" + }, + { + "ppsspp_fast_memory", + "Fast Memory", + NULL, + NULL, + NULL, + "system", + BOOL_OPTIONS, + "enabled" + }, + { + "ppsspp_ignore_bad_memory_access", + "Ignore Bad Memory Accesses", + NULL, + NULL, + NULL, + "system", + BOOL_OPTIONS, + "enabled" + }, + { + "ppsspp_io_timing_method", + "I/O Timing Method", + NULL, + NULL, + NULL, + "system", + { + { "Fast", NULL }, + { "Host", NULL }, + { "Simulate UMD delays", NULL }, + { NULL, NULL }, + }, + "Fast" + }, + { + "ppsspp_force_lag_sync", + "Force Real Clock Sync (Slower, less lag)", + NULL, + NULL, + NULL, + "system", + BOOL_OPTIONS, + "disabled" + }, + { + "ppsspp_locked_cpu_speed", + "Locked CPU Speed", + NULL, + NULL, + NULL, + "system", + { + { "disabled", NULL }, + { "222MHz", NULL }, + { "266MHz", NULL }, + { "333MHz", NULL }, + { NULL, NULL }, + }, + "disabled" + }, + { + "ppsspp_cache_iso", + "Cache Full ISO in RAM", + NULL, + NULL, + NULL, + "system", + BOOL_OPTIONS, + "disabled" + }, + { + "ppsspp_cheats", + "Internal Cheats Support", + NULL, + NULL, + NULL, + "system", + BOOL_OPTIONS, + "disabled" + }, + { + "ppsspp_psp_model", + "PSP Model", + NULL, + NULL, + NULL, + "system", + { + { "psp_1000", "PSP-1000" }, + { "psp_2000_3000", "PSP-2000/3000" }, + { NULL, NULL }, + }, + "psp_2000_3000" + }, + { + "ppsspp_button_preference", + "Confirmation Button", + NULL, + NULL, + NULL, + "system", + { + { "Cross", NULL }, + { "Circle", NULL }, + { NULL, NULL }, + }, + "Cross" + }, + { + "ppsspp_internal_resolution", + "Internal Resolution (Restart)", + NULL, + NULL, + NULL, + "video", + { + { "480x272", NULL }, + { "960x544", NULL }, + { "1440x816", NULL }, + { "1920x1088", NULL }, + { "2400x1360", NULL }, + { "2880x1632", NULL }, + { "3360x1904", NULL }, + { "3840x2176", NULL }, + { "4320x2448", NULL }, + { "4800x2720", NULL }, + { NULL, NULL }, + }, + "480x272" + }, + { + "ppsspp_rendering_mode", + "Rendering Mode", + NULL, + "'Skip Buffer Effects' is faster, but nothing may draw in some games.", + NULL, + "video", + { + { "Buffered", NULL }, + { "Skip Buffer Effects", NULL }, + { NULL, NULL }, + }, + "Buffered" + }, + { + "ppsspp_block_transfer_gpu", + "Block Transfer GPU", + NULL, + "Some games require this to be enabled for correct graphics.", + NULL, + "video", + BOOL_OPTIONS, + "enabled" + }, + { + "ppsspp_frameskip", + "Frameskip", + NULL, + NULL, + NULL, + "video", + { + { "disabled", NULL }, + { "1", NULL }, + { "2", NULL }, + { "3", NULL }, + { "4", NULL }, + { "5", NULL }, + { "6", NULL }, + { "7", NULL }, + { "8", NULL }, + { NULL, NULL }, + }, + "disabled" + }, + { + "ppsspp_frameskiptype", + "Frameskip Type", + NULL, + NULL, + NULL, + "video", + { + { "Number of frames", NULL }, + { "Percent of FPS", NULL }, + { NULL, NULL }, + }, + "Number of frames" + }, + { + "ppsspp_auto_frameskip", + "Auto Frameskip", + NULL, + NULL, + NULL, + "video", + BOOL_OPTIONS, + "disabled" + }, + { + "ppsspp_frame_duplication", + "Duplicate Frames in 30 Hz Games", + NULL, + "Can make framerate smoother in games that run at lower framerates.", + NULL, + "video", + BOOL_OPTIONS, + "disabled" + }, + { + "ppsspp_detect_vsync_swap_interval", + "Detect Frame Rate Changes (Notify frontend)", + NULL, + NULL, + NULL, + "video", + BOOL_OPTIONS, + "disabled" + }, + { + "ppsspp_inflight_frames", + "Buffered Frames (GL/Vulkan only, slower, less lag, restart)", + NULL, + NULL, + NULL, + "video", + { + { "No buffer", NULL }, + { "Up to 1", NULL }, + { "Up to 2", NULL }, + { NULL, NULL }, + }, + "Up to 2" + }, + { + "ppsspp_gpu_hardware_transform", + "Hardware Transform", + NULL, + NULL, + NULL, + "video", + BOOL_OPTIONS, + "enabled" + }, + { + "ppsspp_software_skinning", + "Software Skinning", + NULL, + "Combine skinned model draws on the CPU, faster in most games.", + NULL, + "video", + BOOL_OPTIONS, + "enabled" + }, + { + "ppsspp_vertex_cache", + "Vertex Cache", + NULL, + "Faster, but may cause temporary flicker.", + NULL, + "video", + BOOL_OPTIONS, + "disabled" + }, + { + "ppsspp_lazy_texture_caching", + "Lazy Texture Caching (Speedup)", + NULL, + "Faster, but can cause text problems in a few games.", + NULL, + "video", + BOOL_OPTIONS, + "disabled" + }, + { + "ppsspp_retain_changed_textures", + "Retain Changed Textures (Speedup, mem hog)", + NULL, + "Makes many games slower, but some games a lot faster.", + NULL, + "video", + BOOL_OPTIONS, + "disabled" + }, + { + "ppsspp_spline_quality", + "Spline/Bezier Curves Quality", + NULL, + "Only used by some games, controls smoothness of curves.", + NULL, + "video", + { + { "Low", NULL }, + { "Medium", NULL }, + { "High", NULL }, + { NULL, NULL }, + }, + "High" + }, + { + "ppsspp_hardware_tesselation", + "Hardware Tesselation", + NULL, + "Uses hardware to make curves.", + NULL, + "video", + BOOL_OPTIONS, + "disabled" + }, + { + "ppsspp_lower_resolution_for_effects", + "Lower Resolution for Effects", + NULL, + NULL, + NULL, + "video", + { + { "disabled", NULL }, + { "Safe", NULL }, + { "Balanced", NULL }, + { "Aggressive", NULL }, + { NULL, NULL }, + }, + "disabled" + }, + { + "ppsspp_texture_scaling_type", + "Texture Scaling Type", + NULL, + NULL, + NULL, + "video", + { + { "xbrz", "xBRZ" }, + { "hybrid", "Hybrid" }, + { "bicubic", "Bicubic" }, + { "hybrid_bicubic", "Hybrid + Bicubic" }, + { NULL, NULL }, + }, + "xbrz" + }, + { + "ppsspp_texture_scaling_level", + "Texture Scaling Level", + NULL, + "CPU heavy, some scaling may be delayed to avoid stutter.", + NULL, + "video", + { + { "disabled", NULL }, + { "2x", NULL }, + { "3x", NULL }, + { "4x", NULL }, + { "5x", NULL }, + { NULL, NULL }, + }, + "disabled" + }, + { + "ppsspp_texture_deposterize", + "Texture Deposterize", + NULL, + "Fixes visual banding glitches in upscaled textures.", + NULL, + "video", + BOOL_OPTIONS, + "disabled" + }, + { + "ppsspp_texture_shader", + "Texture Shader (Vulkan only, overrides 'Texture Scaling Type')", + NULL, + NULL, + NULL, + "video", + { + { "disabled", NULL }, + { "2xBRZ", "Tex2xBRZ" }, + { "4xBRZ", "Tex4xBRZ" }, + { "MMPX", "TexMMPX" }, + { NULL, NULL }, + }, + "disabled" + }, + { + "ppsspp_texture_anisotropic_filtering", + "Anisotropic Filtering", + NULL, + NULL, + NULL, + "video", + { + { "disabled", NULL }, + { "2x", NULL }, + { "4x", NULL }, + { "8x", NULL }, + { "16x", NULL }, + { NULL, NULL }, + }, + "16x" + }, + { + "ppsspp_texture_filtering", + "Texture Filtering", + NULL, + NULL, + NULL, + "video", + { + { "Auto", NULL }, + { "Nearest", NULL }, + { "Linear", NULL }, + { "Auto max quality", NULL }, + { NULL, NULL }, + }, + "Auto" + }, + { + "ppsspp_texture_replacement", + "Texture Replacement", + NULL, + NULL, + NULL, + "video", + BOOL_OPTIONS, + "disabled" + }, + { + "ppsspp_enable_wlan", + "Enable Networking/WLAN (Beta, may break games)", + NULL, + NULL, + NULL, + "network", + BOOL_OPTIONS, + "disabled" + }, + { + "ppsspp_change_mac_address01", + "MAC Address Pt 1: X-:--:--:--:--:--", + NULL, + NULL, + NULL, + "network", + MAC_ADDRESS_OPTIONS, + "0" + }, + { + "ppsspp_change_mac_address02", + "MAC Address Pt 2: -X:--:--:--:--:--", + NULL, + NULL, + NULL, + "network", + MAC_ADDRESS_OPTIONS, + "0" + }, + { + "ppsspp_change_mac_address03", + "MAC Address Pt 3: --:X-:--:--:--:--", + NULL, + NULL, + NULL, + "network", + MAC_ADDRESS_OPTIONS, + "0" + }, + { + "ppsspp_change_mac_address04", + "MAC Address Pt 4: --:-X:--:--:--:--", + NULL, + NULL, + NULL, + "network", + MAC_ADDRESS_OPTIONS, + "0" + }, + { + "ppsspp_change_mac_address05", + "MAC Address Pt 5: --:--:X-:--:--:--", + NULL, + NULL, + NULL, + "network", + MAC_ADDRESS_OPTIONS, + "0" + }, + { + "ppsspp_change_mac_address06", + "MAC Address Pt 6: --:--:-X:--:--:--", + NULL, + NULL, + NULL, + "network", + MAC_ADDRESS_OPTIONS, + "0" + }, + { + "ppsspp_change_mac_address07", + "MAC Address Pt 7: --:--:--:X-:--:--", + NULL, + NULL, + NULL, + "network", + MAC_ADDRESS_OPTIONS, + "0" + }, + { + "ppsspp_change_mac_address08", + "MAC Address Pt 8: --:--:--:-X:--:--", + NULL, + NULL, + NULL, + "network", + MAC_ADDRESS_OPTIONS, + "0" + }, + { + "ppsspp_change_mac_address09", + "MAC Address Pt 9: --:--:--:--:X-:--", + NULL, + NULL, + NULL, + "network", + MAC_ADDRESS_OPTIONS, + "0" + }, + { + "ppsspp_change_mac_address10", + "MAC Address Pt 10: --:--:--:--:-X:--", + NULL, + NULL, + NULL, + "network", + MAC_ADDRESS_OPTIONS, + "0" + }, + { + "ppsspp_change_mac_address11", + "MAC Address Pt 11: --:--:--:--:--:X-", + NULL, + NULL, + NULL, + "network", + MAC_ADDRESS_OPTIONS, + "0" + }, + { + "ppsspp_change_mac_address12", + "MAC Address Pt 12: --:--:--:--:--:-X", + NULL, + NULL, + NULL, + "network", + MAC_ADDRESS_OPTIONS, + "0" + }, + { + "ppsspp_wlan_channel", + "WLAN Channel", + NULL, + NULL, + NULL, + "network", + { + { "Auto", NULL }, + { "1", NULL }, + { "6", NULL }, + { "11", NULL }, + { NULL, NULL }, + }, + "Auto" + }, + { + "ppsspp_enable_builtin_pro_ad_hoc_server", + "Enable Built-in PRO Ad Hoc Server", + NULL, + NULL, + NULL, + "network", + BOOL_OPTIONS, + "disabled" + }, + { + "ppsspp_change_pro_ad_hoc_server_address", + "Change PRO Ad Hoc Server IP Address ('localhost' = multiple instances)", + NULL, + NULL, + NULL, + "network", + { + { "socom.cc", NULL }, + { "psp.gameplayer.club", NULL }, + { "myneighborsushicat.com", NULL }, + { "localhost", NULL }, + { "IP address", NULL }, + { NULL, NULL }, + }, + "socom.cc" + }, + { + "ppsspp_pro_ad_hoc_server_address01", + "PRO Ad Hoc Server IP Address Pt 1: x--.---.---.---", + NULL, + NULL, + NULL, + "network", + IP_ADDRESS_OPTIONS, + "0" + }, + { + "ppsspp_pro_ad_hoc_server_address02", + "PRO Ad Hoc Server IP Address Pt 2: -x-.---.---.---", + NULL, + NULL, + NULL, + "network", + IP_ADDRESS_OPTIONS, + "0" + }, + { + "ppsspp_pro_ad_hoc_server_address03", + "PRO Ad Hoc Server IP Address Pt 3: --x.---.---.---", + NULL, + NULL, + NULL, + "network", + IP_ADDRESS_OPTIONS, + "0" + }, + { + "ppsspp_pro_ad_hoc_server_address04", + "PRO Ad Hoc Server IP Address Pt 4: ---.x--.---.---", + NULL, + NULL, + NULL, + "network", + IP_ADDRESS_OPTIONS, + "0" + }, + { + "ppsspp_pro_ad_hoc_server_address05", + "PRO Ad Hoc Server IP Address Pt 5: ---.-x-.---.---", + NULL, + NULL, + NULL, + "network", + IP_ADDRESS_OPTIONS, + "0" + }, + { + "ppsspp_pro_ad_hoc_server_address06", + "PRO Ad Hoc Server IP Address Pt 6: ---.--x.---.---", + NULL, + NULL, + NULL, + "network", + IP_ADDRESS_OPTIONS, + "0" + }, + { + "ppsspp_pro_ad_hoc_server_address07", + "PRO Ad Hoc Server IP Address Pt 7: ---.---.x--.---", + NULL, + NULL, + NULL, + "network", + IP_ADDRESS_OPTIONS, + "0" + }, + { + "ppsspp_pro_ad_hoc_server_address08", + "PRO Ad Hoc Server IP Address Pt 8: ---.---.-x-.---", + NULL, + NULL, + NULL, + "network", + IP_ADDRESS_OPTIONS, + "0" + }, + { + "ppsspp_pro_ad_hoc_server_address09", + "PRO Ad Hoc Server IP Address Pt 9: ---.---.--x.---", + NULL, + NULL, + NULL, + "network", + IP_ADDRESS_OPTIONS, + "0" + }, + { + "ppsspp_pro_ad_hoc_server_address10", + "PRO Ad Hoc Server IP Address Pt 10: ---.---.---.x--", + NULL, + NULL, + NULL, + "network", + IP_ADDRESS_OPTIONS, + "0" + }, + { + "ppsspp_pro_ad_hoc_server_address11", + "PRO Ad Hoc Server IP Address Pt 11: ---.---.---.-x-", + NULL, + NULL, + NULL, + "network", + IP_ADDRESS_OPTIONS, + "0" + }, + { + "ppsspp_pro_ad_hoc_server_address12", + "PRO Ad Hoc Server IP Address Pt 12: ---.---.---.--x", + NULL, + NULL, + NULL, + "network", + IP_ADDRESS_OPTIONS, + "0" + }, + { + "ppsspp_enable_upnp", + "Enable UPnP (Need a few seconds to detect)", + NULL, + NULL, + NULL, + "network", + BOOL_OPTIONS, + "disabled" + }, + { + "ppsspp_upnp_use_original_port", + "UPnP Use Original Port ('ON' = PSP compatibility)", + NULL, + NULL, + NULL, + "network", + BOOL_OPTIONS, + "enabled" + }, + { + "ppsspp_port_offset", + "Port Offset ('0' = PSP compatibility)", + NULL, + NULL, + NULL, + "network", + { + { "0", NULL }, + { "1000", NULL }, + { "2000", NULL }, + { "3000", NULL }, + { "4000", NULL }, + { "5000", NULL }, + { "6000", NULL }, + { "7000", NULL }, + { "8000", NULL }, + { "9000", NULL }, + { "10000", NULL }, + { "11000", NULL }, + { "12000", NULL }, + { "13000", NULL }, + { "14000", NULL }, + { "15000", NULL }, + { "16000", NULL }, + { "17000", NULL }, + { "18000", NULL }, + { "19000", NULL }, + { "20000", NULL }, + { "31000", NULL }, + { "32000", NULL }, + { "33000", NULL }, + { "34000", NULL }, + { "35000", NULL }, + { "36000", NULL }, + { "37000", NULL }, + { "38000", NULL }, + { "39000", NULL }, + { "40000", NULL }, + { "41000", NULL }, + { "42000", NULL }, + { "43000", NULL }, + { "44000", NULL }, + { "45000", NULL }, + { "46000", NULL }, + { "47000", NULL }, + { "48000", NULL }, + { "49000", NULL }, + { "50000", NULL }, + { "51000", NULL }, + { "52000", NULL }, + { "53000", NULL }, + { "54000", NULL }, + { "55000", NULL }, + { "56000", NULL }, + { "57000", NULL }, + { "58000", NULL }, + { "59000", NULL }, + { "60000", NULL }, + { "61000", NULL }, + { "62000", NULL }, + { "63000", NULL }, + { "64000", NULL }, + { "65000", NULL }, + { NULL, NULL }, + }, + "0" + }, + { + "ppsspp_minimum_timeout", + "Minimum Timeout (Override in ms, '0' = default)", + NULL, + NULL, + NULL, + "network", + { + { "0", NULL }, + { "100", NULL }, + { "200", NULL }, + { "300", NULL }, + { "400", NULL }, + { "500", NULL }, + { "600", NULL }, + { "700", NULL }, + { "800", NULL }, + { "900", NULL }, + { "1000", NULL }, + { "1100", NULL }, + { "1200", NULL }, + { "1300", NULL }, + { "1400", NULL }, + { "1500", NULL }, + { "1600", NULL }, + { "1700", NULL }, + { "1800", NULL }, + { "1900", NULL }, + { "2000", NULL }, + { "3100", NULL }, + { "3200", NULL }, + { "3300", NULL }, + { "3400", NULL }, + { "3500", NULL }, + { "3600", NULL }, + { "3700", NULL }, + { "3800", NULL }, + { "3900", NULL }, + { "4000", NULL }, + { "4100", NULL }, + { "4200", NULL }, + { "4300", NULL }, + { "4400", NULL }, + { "4500", NULL }, + { "4600", NULL }, + { "4700", NULL }, + { "4800", NULL }, + { "4900", NULL }, + { "5000", NULL }, + { NULL, NULL }, + }, + "0" + }, + { + "ppsspp_forced_first_connect", + "Forced First Connect (Faster connect)", + NULL, + NULL, + NULL, + "network", + BOOL_OPTIONS, + "disabled" + }, + { NULL, NULL, NULL, NULL, NULL, NULL, {{0}}, NULL }, +}; + +struct retro_core_options_v2 options_us = { + option_cats_us, + option_defs_us +}; + +/* + ******************************** + * Language Mapping + ******************************** +*/ + +#ifndef HAVE_NO_LANGEXTRA +struct retro_core_options_v2 *options_intl[RETRO_LANGUAGE_LAST] = { + &options_us, /* RETRO_LANGUAGE_ENGLISH */ + NULL, /* RETRO_LANGUAGE_JAPANESE */ + NULL, /* RETRO_LANGUAGE_FRENCH */ + NULL, /* RETRO_LANGUAGE_SPANISH */ + NULL, /* RETRO_LANGUAGE_GERMAN */ + NULL, /* RETRO_LANGUAGE_ITALIAN */ + NULL, /* RETRO_LANGUAGE_DUTCH */ + NULL, /* RETRO_LANGUAGE_PORTUGUESE_BRAZIL */ + NULL, /* RETRO_LANGUAGE_PORTUGUESE_PORTUGAL */ + NULL, /* RETRO_LANGUAGE_RUSSIAN */ + NULL, /* RETRO_LANGUAGE_KOREAN */ + NULL, /* RETRO_LANGUAGE_CHINESE_TRADITIONAL */ + NULL, /* RETRO_LANGUAGE_CHINESE_SIMPLIFIED */ + NULL, /* RETRO_LANGUAGE_ESPERANTO */ + NULL, /* RETRO_LANGUAGE_POLISH */ + NULL, /* RETRO_LANGUAGE_VIETNAMESE */ + NULL, /* RETRO_LANGUAGE_ARABIC */ + NULL, /* RETRO_LANGUAGE_GREEK */ + NULL, /* RETRO_LANGUAGE_TURKISH */ + NULL, /* RETRO_LANGUAGE_SLOVAK */ + NULL, /* RETRO_LANGUAGE_PERSIAN */ + NULL, /* RETRO_LANGUAGE_HEBREW */ + NULL, /* RETRO_LANGUAGE_ASTURIAN */ + NULL, /* RETRO_LANGUAGE_FINNISH */ + NULL, /* RETRO_LANGUAGE_INDONESIAN */ + NULL, /* RETRO_LANGUAGE_SWEDISH */ + NULL, /* RETRO_LANGUAGE_UKRAINIAN */ + NULL, /* RETRO_LANGUAGE_CZECH */ +}; +#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, + bool *categories_supported) +{ + unsigned version = 0; +#ifndef HAVE_NO_LANGEXTRA + unsigned language = 0; +#endif + + if (!environ_cb || !categories_supported) + return; + + *categories_supported = false; + + if (!environ_cb(RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION, &version)) + version = 0; + + if (version >= 2) + { +#ifndef HAVE_NO_LANGEXTRA + struct retro_core_options_v2_intl core_options_intl; + + core_options_intl.us = &options_us; + core_options_intl.local = NULL; + + if (environ_cb(RETRO_ENVIRONMENT_GET_LANGUAGE, &language) && + (language < RETRO_LANGUAGE_LAST) && (language != RETRO_LANGUAGE_ENGLISH)) + core_options_intl.local = options_intl[language]; + + *categories_supported = environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2_INTL, + &core_options_intl); +#else + *categories_supported = environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_V2, + &options_us); +#endif + } + else + { + size_t i, j; + size_t option_index = 0; + size_t num_options = 0; + struct retro_core_option_definition + *option_v1_defs_us = NULL; +#ifndef HAVE_NO_LANGEXTRA + size_t num_options_intl = 0; + struct retro_core_option_v2_definition + *option_defs_intl = NULL; + struct retro_core_option_definition + *option_v1_defs_intl = NULL; + struct retro_core_options_intl + core_options_v1_intl; +#endif + struct retro_variable *variables = NULL; + char **values_buf = NULL; + + /* Determine total number of options */ + while (true) + { + if (option_defs_us[num_options].key) + num_options++; + else + break; + } + + if (version >= 1) + { + /* Allocate US array */ + option_v1_defs_us = (struct retro_core_option_definition *) + calloc(num_options + 1, sizeof(struct retro_core_option_definition)); + + /* Copy parameters from option_defs_us array */ + for (i = 0; i < num_options; i++) + { + struct retro_core_option_v2_definition *option_def_us = &option_defs_us[i]; + struct retro_core_option_value *option_values = option_def_us->values; + struct retro_core_option_definition *option_v1_def_us = &option_v1_defs_us[i]; + struct retro_core_option_value *option_v1_values = option_v1_def_us->values; + + option_v1_def_us->key = option_def_us->key; + option_v1_def_us->desc = option_def_us->desc; + option_v1_def_us->info = option_def_us->info; + option_v1_def_us->default_value = option_def_us->default_value; + + /* Values must be copied individually... */ + while (option_values->value) + { + option_v1_values->value = option_values->value; + option_v1_values->label = option_values->label; + + option_values++; + option_v1_values++; + } + } + +#ifndef HAVE_NO_LANGEXTRA + if (environ_cb(RETRO_ENVIRONMENT_GET_LANGUAGE, &language) && + (language < RETRO_LANGUAGE_LAST) && (language != RETRO_LANGUAGE_ENGLISH) && + options_intl[language]) + option_defs_intl = options_intl[language]->definitions; + + if (option_defs_intl) + { + /* Determine number of intl options */ + while (true) + { + if (option_defs_intl[num_options_intl].key) + num_options_intl++; + else + break; + } + + /* Allocate intl array */ + option_v1_defs_intl = (struct retro_core_option_definition *) + calloc(num_options_intl + 1, sizeof(struct retro_core_option_definition)); + + /* Copy parameters from option_defs_intl array */ + for (i = 0; i < num_options_intl; i++) + { + struct retro_core_option_v2_definition *option_def_intl = &option_defs_intl[i]; + struct retro_core_option_value *option_values = option_def_intl->values; + struct retro_core_option_definition *option_v1_def_intl = &option_v1_defs_intl[i]; + struct retro_core_option_value *option_v1_values = option_v1_def_intl->values; + + option_v1_def_intl->key = option_def_intl->key; + option_v1_def_intl->desc = option_def_intl->desc; + option_v1_def_intl->info = option_def_intl->info; + option_v1_def_intl->default_value = option_def_intl->default_value; + + /* Values must be copied individually... */ + while (option_values->value) + { + option_v1_values->value = option_values->value; + option_v1_values->label = option_values->label; + + option_values++; + option_v1_values++; + } + } + } + + core_options_v1_intl.us = option_v1_defs_us; + core_options_v1_intl.local = option_v1_defs_intl; + + environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL, &core_options_v1_intl); +#else + environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS, option_v1_defs_us); +#endif + } + else + { + /* Allocate arrays */ + variables = (struct retro_variable *)calloc(num_options + 1, + sizeof(struct retro_variable)); + values_buf = (char **)calloc(num_options, sizeof(char *)); + + if (!variables || !values_buf) + goto error; + + /* Copy parameters from option_defs_us array */ + for (i = 0; i < num_options; i++) + { + const char *key = option_defs_us[i].key; + const char *desc = option_defs_us[i].desc; + const char *default_value = option_defs_us[i].default_value; + struct retro_core_option_value *values = option_defs_us[i].values; + size_t buf_len = 3; + size_t default_index = 0; + + values_buf[i] = NULL; + + if (desc) + { + size_t num_values = 0; + + /* Determine number of values */ + while (true) + { + if (values[num_values].value) + { + /* Check if this is the default value */ + if (default_value) + if (strcmp(values[num_values].value, default_value) == 0) + default_index = num_values; + + buf_len += strlen(values[num_values].value); + num_values++; + } + else + break; + } + + /* Build values string */ + if (num_values > 0) + { + buf_len += num_values - 1; + buf_len += strlen(desc); + + values_buf[i] = (char *)calloc(buf_len, sizeof(char)); + if (!values_buf[i]) + goto error; + + strcpy(values_buf[i], desc); + strcat(values_buf[i], "; "); + + /* Default value goes first */ + strcat(values_buf[i], values[default_index].value); + + /* Add remaining values */ + for (j = 0; j < num_values; j++) + { + if (j != default_index) + { + strcat(values_buf[i], "|"); + strcat(values_buf[i], values[j].value); + } + } + } + } + + variables[option_index].key = key; + variables[option_index].value = values_buf[i]; + option_index++; + } + + /* Set variables */ + environ_cb(RETRO_ENVIRONMENT_SET_VARIABLES, variables); + } + +error: + /* Clean up */ + + if (option_v1_defs_us) + { + free(option_v1_defs_us); + option_v1_defs_us = NULL; + } + +#ifndef HAVE_NO_LANGEXTRA + if (option_v1_defs_intl) + { + free(option_v1_defs_intl); + option_v1_defs_intl = NULL; + } +#endif + + if (values_buf) + { + for (i = 0; i < num_options; i++) + { + if (values_buf[i]) + { + free(values_buf[i]); + values_buf[i] = NULL; + } + } + + free(values_buf); + values_buf = NULL; + } + + if (variables) + { + free(variables); + variables = NULL; + } + } +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libretro/libretro_core_options_intl.h b/libretro/libretro_core_options_intl.h new file mode 100644 index 000000000000..b2649b6b5ee0 --- /dev/null +++ b/libretro/libretro_core_options_intl.h @@ -0,0 +1,91 @@ +#ifndef LIBRETRO_CORE_OPTIONS_INTL_H__ +#define LIBRETRO_CORE_OPTIONS_INTL_H__ + +#if defined(_MSC_VER) && (_MSC_VER >= 1500 && _MSC_VER < 1900) +/* https://support.microsoft.com/en-us/kb/980263 */ +#pragma execution_character_set("utf-8") +#pragma warning(disable:4566) +#endif + +#include "libretro.h" + +/* + ******************************** + * VERSION: 2.0 + ******************************** + * + * - 2.0: Add support for core options v2 interface + * - 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_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 */ + +/* RETRO_LANGUAGE_SLOVAK */ + +/* RETRO_LANGUAGE_PERSIAN */ + +/* RETRO_LANGUAGE_HEBREW */ + +/* RETRO_LANGUAGE_ASTURIAN */ + +/* RETRO_LANGUAGE_FINNISH */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libretro/retro_inline.h b/libretro/retro_inline.h new file mode 100644 index 000000000000..b27d6dd6d48d --- /dev/null +++ b/libretro/retro_inline.h @@ -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