#include "settings.h" #include "common/string_util.h" #include "host_interface.h" #include #include const char* SettingInfo::StringDefaultValue() const { return default_value ? default_value : ""; } bool SettingInfo::BooleanDefaultValue() const { return default_value ? StringUtil::FromChars(default_value).value_or(false) : false; } s32 SettingInfo::IntegerDefaultValue() const { return default_value ? StringUtil::FromChars(default_value).value_or(0) : 0; } s32 SettingInfo::IntegerMinValue() const { static constexpr s32 fallback_value = std::numeric_limits::min(); return min_value ? StringUtil::FromChars(min_value).value_or(fallback_value) : fallback_value; } s32 SettingInfo::IntegerMaxValue() const { static constexpr s32 fallback_value = std::numeric_limits::max(); return max_value ? StringUtil::FromChars(max_value).value_or(fallback_value) : fallback_value; } s32 SettingInfo::IntegerStepValue() const { static constexpr s32 fallback_value = 1; return step_value ? StringUtil::FromChars(step_value).value_or(fallback_value) : fallback_value; } float SettingInfo::FloatDefaultValue() const { return default_value ? StringUtil::FromChars(default_value).value_or(0.0f) : 0.0f; } float SettingInfo::FloatMinValue() const { static constexpr float fallback_value = std::numeric_limits::min(); return min_value ? StringUtil::FromChars(min_value).value_or(fallback_value) : fallback_value; } float SettingInfo::FloatMaxValue() const { static constexpr float fallback_value = std::numeric_limits::max(); return max_value ? StringUtil::FromChars(max_value).value_or(fallback_value) : fallback_value; } float SettingInfo::FloatStepValue() const { static constexpr float fallback_value = 0.1f; return step_value ? StringUtil::FromChars(step_value).value_or(fallback_value) : fallback_value; } Settings::Settings() = default; bool Settings::HasAnyPerGameMemoryCards() const { return std::any_of(memory_card_types.begin(), memory_card_types.end(), [](MemoryCardType t) { return (t == MemoryCardType::PerGame || t == MemoryCardType::PerGameTitle); }); } void Settings::Load(SettingsInterface& si) { region = ParseConsoleRegionName(si.GetStringValue("Console", "Region", "NTSC-U").c_str()).value_or(DEFAULT_CONSOLE_REGION); emulation_speed = si.GetFloatValue("Main", "EmulationSpeed", 1.0f); speed_limiter_enabled = si.GetBoolValue("Main", "SpeedLimiterEnabled", true); increase_timer_resolution = si.GetBoolValue("Main", "IncreaseTimerResolution", true); start_paused = si.GetBoolValue("Main", "StartPaused", false); start_fullscreen = si.GetBoolValue("Main", "StartFullscreen", false); save_state_on_exit = si.GetBoolValue("Main", "SaveStateOnExit", true); confim_power_off = si.GetBoolValue("Main", "ConfirmPowerOff", true); load_devices_from_save_states = si.GetBoolValue("Main", "LoadDevicesFromSaveStates", false); cpu_execution_mode = ParseCPUExecutionMode( si.GetStringValue("CPU", "ExecutionMode", GetCPUExecutionModeName(DEFAULT_CPU_EXECUTION_MODE)).c_str()) .value_or(DEFAULT_CPU_EXECUTION_MODE); gpu_renderer = ParseRendererName(si.GetStringValue("GPU", "Renderer", GetRendererName(DEFAULT_GPU_RENDERER)).c_str()) .value_or(DEFAULT_GPU_RENDERER); gpu_adapter = si.GetStringValue("GPU", "Adapter", ""); gpu_resolution_scale = static_cast(si.GetIntValue("GPU", "ResolutionScale", 1)); gpu_use_debug_device = si.GetBoolValue("GPU", "UseDebugDevice", false); gpu_true_color = si.GetBoolValue("GPU", "TrueColor", true); gpu_scaled_dithering = si.GetBoolValue("GPU", "ScaledDithering", false); gpu_texture_filtering = si.GetBoolValue("GPU", "TextureFiltering", false); gpu_disable_interlacing = si.GetBoolValue("GPU", "DisableInterlacing", true); gpu_force_ntsc_timings = si.GetBoolValue("GPU", "ForceNTSCTimings", false); display_crop_mode = ParseDisplayCropMode( si.GetStringValue("Display", "CropMode", GetDisplayCropModeName(DEFAULT_DISPLAY_CROP_MODE)).c_str()) .value_or(DEFAULT_DISPLAY_CROP_MODE); display_aspect_ratio = ParseDisplayAspectRatio( si.GetStringValue("Display", "AspectRatio", GetDisplayAspectRatioName(DEFAULT_DISPLAY_ASPECT_RATIO)).c_str()) .value_or(DEFAULT_DISPLAY_ASPECT_RATIO); display_linear_filtering = si.GetBoolValue("Display", "LinearFiltering", true); display_integer_scaling = si.GetBoolValue("Display", "IntegerScaling", false); display_show_osd_messages = si.GetBoolValue("Display", "ShowOSDMessages", true); display_show_fps = si.GetBoolValue("Display", "ShowFPS", false); display_show_vps = si.GetBoolValue("Display", "ShowVPS", false); display_show_speed = si.GetBoolValue("Display", "ShowSpeed", false); video_sync_enabled = si.GetBoolValue("Display", "VSync", true); cdrom_read_thread = si.GetBoolValue("CDROM", "ReadThread", true); cdrom_region_check = si.GetBoolValue("CDROM", "RegionCheck", true); audio_backend = ParseAudioBackend(si.GetStringValue("Audio", "Backend", GetAudioBackendName(DEFAULT_AUDIO_BACKEND)).c_str()) .value_or(DEFAULT_AUDIO_BACKEND); audio_output_volume = si.GetIntValue("Audio", "OutputVolume", 100); audio_buffer_size = si.GetIntValue("Audio", "BufferSize", HostInterface::DEFAULT_AUDIO_BUFFER_SIZE); audio_output_muted = si.GetBoolValue("Audio", "OutputMuted", false); audio_sync_enabled = si.GetBoolValue("Audio", "Sync", true); audio_dump_on_boot = si.GetBoolValue("Audio", "DumpOnBoot", false); dma_max_slice_ticks = si.GetIntValue("Hacks", "DMAMaxSliceTicks", DEFAULT_DMA_MAX_SLICE_TICKS); dma_halt_ticks = si.GetIntValue("Hacks", "DMAHaltTicks", DEFAULT_DMA_HALT_TICKS); gpu_fifo_size = static_cast(si.GetIntValue("Hacks", "GPUFIFOSize", DEFAULT_GPU_FIFO_SIZE)); gpu_max_run_ahead = si.GetIntValue("Hacks", "GPUMaxRunAhead", DEFAULT_GPU_MAX_RUN_AHEAD); bios_path = si.GetStringValue("BIOS", "Path", "bios/scph1001.bin"); bios_patch_tty_enable = si.GetBoolValue("BIOS", "PatchTTYEnable", false); bios_patch_fast_boot = si.GetBoolValue("BIOS", "PatchFastBoot", false); controller_types[0] = ParseControllerTypeName( si.GetStringValue("Controller1", "Type", GetControllerTypeName(DEFAULT_CONTROLLER_1_TYPE)).c_str()) .value_or(DEFAULT_CONTROLLER_1_TYPE); controller_types[1] = ParseControllerTypeName( si.GetStringValue("Controller2", "Type", GetControllerTypeName(DEFAULT_CONTROLLER_2_TYPE)).c_str()) .value_or(DEFAULT_CONTROLLER_2_TYPE); // NOTE: The default value here if not present in the config is shared, but SetDefaultSettings() makes per-game. // This is so we don't break older builds which had the shared card by default. memory_card_types[0] = ParseMemoryCardTypeName( si.GetStringValue("MemoryCards", "Card1Type", GetMemoryCardTypeName(DEFAULT_MEMORY_CARD_1_TYPE)).c_str()) .value_or(DEFAULT_MEMORY_CARD_1_TYPE); memory_card_paths[0] = si.GetStringValue("MemoryCards", "Card1Path", "memcards/shared_card_1.mcd"); memory_card_types[1] = ParseMemoryCardTypeName( si.GetStringValue("MemoryCards", "Card2Type", GetMemoryCardTypeName(DEFAULT_MEMORY_CARD_2_TYPE)).c_str()) .value_or(DEFAULT_MEMORY_CARD_2_TYPE); memory_card_paths[1] = si.GetStringValue("MemoryCards", "Card2Path", "memcards/shared_card_2.mcd"); log_level = ParseLogLevelName(si.GetStringValue("Logging", "LogLevel", GetLogLevelName(DEFAULT_LOG_LEVEL)).c_str()) .value_or(DEFAULT_LOG_LEVEL); log_filter = si.GetStringValue("Logging", "LogFilter", ""); log_to_console = si.GetBoolValue("Logging", "LogToConsole", false); log_to_debug = si.GetBoolValue("Logging", "LogToDebug", false); log_to_window = si.GetBoolValue("Logging", "LogToWindow", false); log_to_file = si.GetBoolValue("Logging", "LogToFile", false); debugging.show_vram = si.GetBoolValue("Debug", "ShowVRAM"); debugging.dump_cpu_to_vram_copies = si.GetBoolValue("Debug", "DumpCPUToVRAMCopies"); debugging.dump_vram_to_cpu_copies = si.GetBoolValue("Debug", "DumpVRAMToCPUCopies"); debugging.show_gpu_state = si.GetBoolValue("Debug", "ShowGPUState"); debugging.show_cdrom_state = si.GetBoolValue("Debug", "ShowCDROMState"); debugging.show_spu_state = si.GetBoolValue("Debug", "ShowSPUState"); debugging.show_timers_state = si.GetBoolValue("Debug", "ShowTimersState"); debugging.show_mdec_state = si.GetBoolValue("Debug", "ShowMDECState"); } void Settings::Save(SettingsInterface& si) const { si.SetStringValue("Console", "Region", GetConsoleRegionName(region)); si.SetFloatValue("Main", "EmulationSpeed", emulation_speed); si.SetBoolValue("Main", "SpeedLimiterEnabled", speed_limiter_enabled); si.SetBoolValue("Main", "IncreaseTimerResolution", increase_timer_resolution); si.SetBoolValue("Main", "StartPaused", start_paused); si.SetBoolValue("Main", "StartFullscreen", start_fullscreen); si.SetBoolValue("Main", "SaveStateOnExit", save_state_on_exit); si.SetBoolValue("Main", "ConfirmPowerOff", confim_power_off); si.SetBoolValue("Main", "LoadDevicesFromSaveStates", load_devices_from_save_states); si.SetStringValue("CPU", "ExecutionMode", GetCPUExecutionModeName(cpu_execution_mode)); si.SetStringValue("GPU", "Renderer", GetRendererName(gpu_renderer)); si.SetStringValue("GPU", "Adapter", gpu_adapter.c_str()); si.SetIntValue("GPU", "ResolutionScale", static_cast(gpu_resolution_scale)); si.SetBoolValue("GPU", "UseDebugDevice", gpu_use_debug_device); si.SetBoolValue("GPU", "TrueColor", gpu_true_color); si.SetBoolValue("GPU", "ScaledDithering", gpu_scaled_dithering); si.SetBoolValue("GPU", "TextureFiltering", gpu_texture_filtering); si.SetBoolValue("GPU", "DisableInterlacing", gpu_disable_interlacing); si.SetBoolValue("GPU", "ForceNTSCTimings", gpu_force_ntsc_timings); si.SetStringValue("Display", "CropMode", GetDisplayCropModeName(display_crop_mode)); si.SetStringValue("Display", "AspectRatio", GetDisplayAspectRatioName(display_aspect_ratio)); si.SetBoolValue("Display", "LinearFiltering", display_linear_filtering); si.SetBoolValue("Display", "IntegerScaling", display_integer_scaling); si.SetBoolValue("Display", "ShowOSDMessages", display_show_osd_messages); si.SetBoolValue("Display", "ShowFPS", display_show_fps); si.SetBoolValue("Display", "ShowVPS", display_show_vps); si.SetBoolValue("Display", "ShowSpeed", display_show_speed); si.SetBoolValue("Display", "VSync", video_sync_enabled); si.SetBoolValue("CDROM", "ReadThread", cdrom_read_thread); si.SetBoolValue("CDROM", "RegionCheck", cdrom_region_check); si.SetStringValue("Audio", "Backend", GetAudioBackendName(audio_backend)); si.SetIntValue("Audio", "OutputVolume", audio_output_volume); si.SetIntValue("Audio", "BufferSize", audio_buffer_size); si.SetBoolValue("Audio", "OutputMuted", audio_output_muted); si.SetBoolValue("Audio", "Sync", audio_sync_enabled); si.SetBoolValue("Audio", "DumpOnBoot", audio_dump_on_boot); si.SetIntValue("Hacks", "DMAMaxSliceTicks", dma_max_slice_ticks); si.SetIntValue("Hacks", "DMAHaltTicks", dma_halt_ticks); si.SetIntValue("Hacks", "GPUFIFOSize", gpu_fifo_size); si.SetIntValue("Hacks", "GPUMaxRunAhead", gpu_max_run_ahead); si.SetStringValue("BIOS", "Path", bios_path.c_str()); si.SetBoolValue("BIOS", "PatchTTYEnable", bios_patch_tty_enable); si.SetBoolValue("BIOS", "PatchFastBoot", bios_patch_fast_boot); if (controller_types[0] != ControllerType::None) si.SetStringValue("Controller1", "Type", GetControllerTypeName(controller_types[0])); else si.DeleteValue("Controller1", "Type"); if (controller_types[1] != ControllerType::None) si.SetStringValue("Controller2", "Type", GetControllerTypeName(controller_types[1])); else si.DeleteValue("Controller2", "Type"); si.SetStringValue("MemoryCards", "Card1Type", GetMemoryCardTypeName(memory_card_types[0])); si.SetStringValue("MemoryCards", "Card1Path", memory_card_paths[0].c_str()); si.SetStringValue("MemoryCards", "Card2Type", GetMemoryCardTypeName(memory_card_types[1])); si.SetStringValue("MemoryCards", "Card2Path", memory_card_paths[1].c_str()); si.SetStringValue("Logging", "LogLevel", GetLogLevelName(log_level)); si.SetStringValue("Logging", "LogFilter", log_filter.c_str()); si.SetBoolValue("Logging", "LogToConsole", log_to_console); si.SetBoolValue("Logging", "LogToDebug", log_to_debug); si.SetBoolValue("Logging", "LogToWindow", log_to_window); si.SetBoolValue("Logging", "LogToFile", log_to_file); si.SetBoolValue("Debug", "ShowVRAM", debugging.show_vram); si.SetBoolValue("Debug", "DumpCPUToVRAMCopies", debugging.dump_cpu_to_vram_copies); si.SetBoolValue("Debug", "DumpVRAMToCPUCopies", debugging.dump_vram_to_cpu_copies); si.SetBoolValue("Debug", "ShowGPUState", debugging.show_gpu_state); si.SetBoolValue("Debug", "ShowCDROMState", debugging.show_cdrom_state); si.SetBoolValue("Debug", "ShowSPUState", debugging.show_spu_state); si.SetBoolValue("Debug", "ShowTimersState", debugging.show_timers_state); si.SetBoolValue("Debug", "ShowMDECState", debugging.show_mdec_state); } static std::array s_log_level_names = { {"None", "Error", "Warning", "Perf", "Success", "Info", "Dev", "Profile", "Debug", "Trace"}}; static std::array s_log_level_display_names = { {"None", "Error", "Warning", "Performance", "Success", "Information", "Developer", "Profile", "Debug", "Trace"}}; std::optional Settings::ParseLogLevelName(const char* str) { int index = 0; for (const char* name : s_log_level_names) { if (StringUtil::Strcasecmp(name, str) == 0) return static_cast(index); index++; } return std::nullopt; } const char* Settings::GetLogLevelName(LOGLEVEL level) { return s_log_level_names[static_cast(level)]; } const char* Settings::GetLogLevelDisplayName(LOGLEVEL level) { return s_log_level_display_names[static_cast(level)]; } static std::array s_console_region_names = {{"Auto", "NTSC-J", "NTSC-U", "PAL"}}; static std::array s_console_region_display_names = { {"Auto-Detect", "NTSC-J (Japan)", "NTSC-U (US)", "PAL (Europe, Australia)"}}; std::optional Settings::ParseConsoleRegionName(const char* str) { int index = 0; for (const char* name : s_console_region_names) { if (StringUtil::Strcasecmp(name, str) == 0) return static_cast(index); index++; } return std::nullopt; } const char* Settings::GetConsoleRegionName(ConsoleRegion region) { return s_console_region_names[static_cast(region)]; } const char* Settings::GetConsoleRegionDisplayName(ConsoleRegion region) { return s_console_region_display_names[static_cast(region)]; } static std::array s_disc_region_names = {{"NTSC-J", "NTSC-U", "PAL", "Other"}}; static std::array s_disc_region_display_names = { {"NTSC-J (Japan)", "NTSC-U (US)", "PAL (Europe, Australia)", "Other"}}; std::optional Settings::ParseDiscRegionName(const char* str) { int index = 0; for (const char* name : s_disc_region_names) { if (StringUtil::Strcasecmp(name, str) == 0) return static_cast(index); index++; } return std::nullopt; } const char* Settings::GetDiscRegionName(DiscRegion region) { return s_disc_region_names[static_cast(region)]; } const char* Settings::GetDiscRegionDisplayName(DiscRegion region) { return s_disc_region_display_names[static_cast(region)]; } static std::array s_cpu_execution_mode_names = {{"Interpreter", "CachedInterpreter", "Recompiler"}}; static std::array s_cpu_execution_mode_display_names = { {"Intepreter (Slowest)", "Cached Interpreter (Faster)", "Recompiler (Fastest)"}}; std::optional Settings::ParseCPUExecutionMode(const char* str) { u8 index = 0; for (const char* name : s_cpu_execution_mode_names) { if (StringUtil::Strcasecmp(name, str) == 0) return static_cast(index); index++; } return std::nullopt; } const char* Settings::GetCPUExecutionModeName(CPUExecutionMode mode) { return s_cpu_execution_mode_names[static_cast(mode)]; } const char* Settings::GetCPUExecutionModeDisplayName(CPUExecutionMode mode) { return s_cpu_execution_mode_display_names[static_cast(mode)]; } static std::array s_gpu_renderer_names = {{ #ifdef WIN32 "D3D11", #endif "Vulkan", "OpenGL", "Software"}}; static std::array s_gpu_renderer_display_names = {{ #ifdef WIN32 "Hardware (D3D11)", #endif "Hardware (Vulkan)", "Hardware (OpenGL)", "Software"}}; std::optional Settings::ParseRendererName(const char* str) { int index = 0; for (const char* name : s_gpu_renderer_names) { if (StringUtil::Strcasecmp(name, str) == 0) return static_cast(index); index++; } return std::nullopt; } const char* Settings::GetRendererName(GPURenderer renderer) { return s_gpu_renderer_names[static_cast(renderer)]; } const char* Settings::GetRendererDisplayName(GPURenderer renderer) { return s_gpu_renderer_display_names[static_cast(renderer)]; } static std::array s_display_crop_mode_names = {{"None", "Overscan", "Borders"}}; static std::array s_display_crop_mode_display_names = {{"None", "Only Overscan Area", "All Borders"}}; std::optional Settings::ParseDisplayCropMode(const char* str) { int index = 0; for (const char* name : s_display_crop_mode_names) { if (StringUtil::Strcasecmp(name, str) == 0) return static_cast(index); index++; } return std::nullopt; } const char* Settings::GetDisplayCropModeName(DisplayCropMode crop_mode) { return s_display_crop_mode_names[static_cast(crop_mode)]; } const char* Settings::GetDisplayCropModeDisplayName(DisplayCropMode crop_mode) { return s_display_crop_mode_display_names[static_cast(crop_mode)]; } static std::array s_display_aspect_ratio_names = {{"4:3", "16:9", "2:1 (VRAM 1:1)", "1:1"}}; static constexpr std::array s_display_aspect_ratio_values = {{4.0f / 3.0f, 16.0f / 9.0f, 2.0f / 1.0f, 1.0f}}; std::optional Settings::ParseDisplayAspectRatio(const char* str) { int index = 0; for (const char* name : s_display_aspect_ratio_names) { if (StringUtil::Strcasecmp(name, str) == 0) return static_cast(index); index++; } return std::nullopt; } const char* Settings::GetDisplayAspectRatioName(DisplayAspectRatio ar) { return s_display_aspect_ratio_names[static_cast(ar)]; } float Settings::GetDisplayAspectRatioValue(DisplayAspectRatio ar) { return s_display_aspect_ratio_values[static_cast(ar)]; } static std::array s_audio_backend_names = {{"Null", "Cubeb", "SDL"}}; static std::array s_audio_backend_display_names = {{"Null (No Output)", "Cubeb", "SDL"}}; std::optional Settings::ParseAudioBackend(const char* str) { int index = 0; for (const char* name : s_audio_backend_names) { if (StringUtil::Strcasecmp(name, str) == 0) return static_cast(index); index++; } return std::nullopt; } const char* Settings::GetAudioBackendName(AudioBackend backend) { return s_audio_backend_names[static_cast(backend)]; } const char* Settings::GetAudioBackendDisplayName(AudioBackend backend) { return s_audio_backend_display_names[static_cast(backend)]; } static std::array s_controller_type_names = { {"None", "DigitalController", "AnalogController", "NamcoGunCon", "PlayStationMouse", "NeGcon"}}; static std::array s_controller_display_names = { {"None", "Digital Controller", "Analog Controller (DualShock)", "Namco GunCon", "PlayStation Mouse", "NeGcon"}}; std::optional Settings::ParseControllerTypeName(const char* str) { int index = 0; for (const char* name : s_controller_type_names) { if (StringUtil::Strcasecmp(name, str) == 0) return static_cast(index); index++; } return std::nullopt; } const char* Settings::GetControllerTypeName(ControllerType type) { return s_controller_type_names[static_cast(type)]; } const char* Settings::GetControllerTypeDisplayName(ControllerType type) { return s_controller_display_names[static_cast(type)]; } static std::array s_memory_card_type_names = {{"None", "Shared", "PerGame", "PerGameTitle"}}; static std::array s_memory_card_type_display_names = {{"No Memory Card", "Shared Between All Games", "Separate Card Per Game (Game Code)", "Separate Card Per Game (Game Title)"}}; std::optional Settings::ParseMemoryCardTypeName(const char* str) { int index = 0; for (const char* name : s_memory_card_type_names) { if (StringUtil::Strcasecmp(name, str) == 0) return static_cast(index); index++; } return std::nullopt; } const char* Settings::GetMemoryCardTypeName(MemoryCardType type) { return s_memory_card_type_names[static_cast(type)]; } const char* Settings::GetMemoryCardTypeDisplayName(MemoryCardType type) { return s_memory_card_type_display_names[static_cast(type)]; }