settings.h
1 // Copyright 2014 Citra Emulator Project 2 // Licensed under GPLv2 or any later version 3 // Refer to the license.txt file included. 4 5 #pragma once 6 7 #include <algorithm> 8 #include <array> 9 #include <atomic> 10 #include <string> 11 #include <unordered_map> 12 #include <vector> 13 #include "audio_core/input_details.h" 14 #include "audio_core/sink_details.h" 15 #include "common/common_types.h" 16 #include "core/hle/service/cam/cam_params.h" 17 18 namespace Settings { 19 20 enum class GraphicsAPI { 21 Software = 0, 22 OpenGL = 1, 23 Vulkan = 2, 24 }; 25 26 enum class InitClock : u32 { 27 SystemTime = 0, 28 FixedTime = 1, 29 }; 30 31 enum class InitTicks : u32 { 32 Random = 0, 33 Fixed = 1, 34 }; 35 36 enum class LayoutOption : u32 { 37 Default, 38 SingleScreen, 39 LargeScreen, 40 SideScreen, 41 #ifndef ANDROID 42 SeparateWindows, 43 #endif 44 HybridScreen, 45 // Similiar to default, but better for mobile devices in portrait mode. Top screen in clamped to 46 // the top of the frame, and the bottom screen is enlarged to match the top screen. 47 MobilePortrait, 48 49 // Similiar to LargeScreen, but better for mobile devices in landscape mode. The screens are 50 // clamped to the top of the frame, and the bottom screen is a bit bigger. 51 MobileLandscape, 52 }; 53 54 enum class StereoRenderOption : u32 { 55 Off = 0, 56 SideBySide = 1, 57 Anaglyph = 2, 58 Interlaced = 3, 59 ReverseInterlaced = 4, 60 CardboardVR = 5 61 }; 62 63 // Which eye to render when 3d is off. 800px wide mode could be added here in the future, when 64 // implemented 65 enum class MonoRenderOption : u32 { 66 LeftEye = 0, 67 RightEye = 1, 68 }; 69 70 enum class AudioEmulation : u32 { 71 HLE = 0, 72 LLE = 1, 73 LLEMultithreaded = 2, 74 }; 75 76 enum class TextureFilter : u32 { 77 None = 0, 78 Anime4K = 1, 79 Bicubic = 2, 80 ScaleForce = 3, 81 xBRZ = 4, 82 MMPX = 5, 83 }; 84 85 enum class TextureSampling : u32 { 86 GameControlled = 0, 87 NearestNeighbor = 1, 88 Linear = 2, 89 }; 90 91 namespace NativeButton { 92 93 enum Values { 94 A, 95 B, 96 X, 97 Y, 98 Up, 99 Down, 100 Left, 101 Right, 102 L, 103 R, 104 Start, 105 Select, 106 Debug, 107 Gpio14, 108 109 ZL, 110 ZR, 111 112 Home, 113 Power, 114 115 NumButtons, 116 }; 117 118 constexpr int BUTTON_HID_BEGIN = A; 119 constexpr int BUTTON_IR_BEGIN = ZL; 120 constexpr int BUTTON_NS_BEGIN = Power; 121 122 constexpr int BUTTON_HID_END = BUTTON_IR_BEGIN; 123 constexpr int BUTTON_IR_END = BUTTON_NS_BEGIN; 124 constexpr int BUTTON_NS_END = NumButtons; 125 126 constexpr int NUM_BUTTONS_HID = BUTTON_HID_END - BUTTON_HID_BEGIN; 127 constexpr int NUM_BUTTONS_IR = BUTTON_IR_END - BUTTON_IR_BEGIN; 128 constexpr int NUM_BUTTONS_NS = BUTTON_NS_END - BUTTON_NS_BEGIN; 129 130 static const std::array<const char*, NumButtons> mapping = {{ 131 "button_a", 132 "button_b", 133 "button_x", 134 "button_y", 135 "button_up", 136 "button_down", 137 "button_left", 138 "button_right", 139 "button_l", 140 "button_r", 141 "button_start", 142 "button_select", 143 "button_debug", 144 "button_gpio14", 145 "button_zl", 146 "button_zr", 147 "button_home", 148 "button_power", 149 }}; 150 151 } // namespace NativeButton 152 153 namespace NativeAnalog { 154 enum Values { 155 CirclePad, 156 CStick, 157 NumAnalogs, 158 }; 159 160 constexpr std::array<const char*, NumAnalogs> mapping = {{ 161 "circle_pad", 162 "c_stick", 163 }}; 164 } // namespace NativeAnalog 165 166 /** The Setting class is a simple resource manager. It defines a label and default value alongside 167 * the actual value of the setting for simpler and less-error prone use with frontend 168 * configurations. Specifying a default value and label is required. A minimum and maximum range can 169 * be specified for sanitization. 170 */ 171 template <typename Type, bool ranged = false> 172 class Setting { 173 protected: 174 Setting() = default; 175 176 /** 177 * Only sets the setting to the given initializer, leaving the other members to their default 178 * initializers. 179 * 180 * @param global_val Initial value of the setting 181 */ 182 explicit Setting(const Type& val) : value{val} {} 183 184 public: 185 /** 186 * Sets a default value, label, and setting value. 187 * 188 * @param default_val Intial value of the setting, and default value of the setting 189 * @param name Label for the setting 190 */ 191 explicit Setting(const Type& default_val, const std::string& name) 192 requires(!ranged) 193 : value{default_val}, default_value{default_val}, label{name} {} 194 virtual ~Setting() = default; 195 196 /** 197 * Sets a default value, minimum value, maximum value, and label. 198 * 199 * @param default_val Intial value of the setting, and default value of the setting 200 * @param min_val Sets the minimum allowed value of the setting 201 * @param max_val Sets the maximum allowed value of the setting 202 * @param name Label for the setting 203 */ 204 explicit Setting(const Type& default_val, const Type& min_val, const Type& max_val, 205 const std::string& name) 206 requires(ranged) 207 : value{default_val}, 208 default_value{default_val}, maximum{max_val}, minimum{min_val}, label{name} {} 209 210 /** 211 * Returns a reference to the setting's value. 212 * 213 * @returns A reference to the setting 214 */ 215 [[nodiscard]] virtual const Type& GetValue() const { 216 return value; 217 } 218 219 /** 220 * Sets the setting to the given value. 221 * 222 * @param val The desired value 223 */ 224 virtual void SetValue(const Type& val) { 225 Type temp{ranged ? std::clamp(val, minimum, maximum) : val}; 226 std::swap(value, temp); 227 } 228 229 /** 230 * Returns the value that this setting was created with. 231 * 232 * @returns A reference to the default value 233 */ 234 [[nodiscard]] const Type& GetDefault() const { 235 return default_value; 236 } 237 238 /** 239 * Returns the label this setting was created with. 240 * 241 * @returns A reference to the label 242 */ 243 [[nodiscard]] const std::string& GetLabel() const { 244 return label; 245 } 246 247 /** 248 * Assigns a value to the setting. 249 * 250 * @param val The desired setting value 251 * 252 * @returns A reference to the setting 253 */ 254 virtual const Type& operator=(const Type& val) { 255 Type temp{ranged ? std::clamp(val, minimum, maximum) : val}; 256 std::swap(value, temp); 257 return value; 258 } 259 260 /** 261 * Returns a reference to the setting. 262 * 263 * @returns A reference to the setting 264 */ 265 explicit virtual operator const Type&() const { 266 return value; 267 } 268 269 protected: 270 Type value{}; ///< The setting 271 const Type default_value{}; ///< The default value 272 const Type maximum{}; ///< Maximum allowed value of the setting 273 const Type minimum{}; ///< Minimum allowed value of the setting 274 const std::string label{}; ///< The setting's label 275 }; 276 277 /** 278 * The SwitchableSetting class is a slightly more complex version of the Setting class. This adds a 279 * custom setting to switch to when a guest application specifically requires it. The effect is that 280 * other components of the emulator can access the setting's intended value without any need for the 281 * component to ask whether the custom or global setting is needed at the moment. 282 * 283 * By default, the global setting is used. 284 */ 285 template <typename Type, bool ranged = false> 286 class SwitchableSetting : virtual public Setting<Type, ranged> { 287 public: 288 /** 289 * Sets a default value, label, and setting value. 290 * 291 * @param default_val Intial value of the setting, and default value of the setting 292 * @param name Label for the setting 293 */ 294 explicit SwitchableSetting(const Type& default_val, const std::string& name) 295 requires(!ranged) 296 : Setting<Type>{default_val, name} {} 297 virtual ~SwitchableSetting() = default; 298 299 /** 300 * Sets a default value, minimum value, maximum value, and label. 301 * 302 * @param default_val Intial value of the setting, and default value of the setting 303 * @param min_val Sets the minimum allowed value of the setting 304 * @param max_val Sets the maximum allowed value of the setting 305 * @param name Label for the setting 306 */ 307 explicit SwitchableSetting(const Type& default_val, const Type& min_val, const Type& max_val, 308 const std::string& name) 309 requires(ranged) 310 : Setting<Type, true>{default_val, min_val, max_val, name} {} 311 312 /** 313 * Tells this setting to represent either the global or custom setting when other member 314 * functions are used. 315 * 316 * @param to_global Whether to use the global or custom setting. 317 */ 318 void SetGlobal(bool to_global) { 319 use_global = to_global; 320 } 321 322 /** 323 * Returns whether this setting is using the global setting or not. 324 * 325 * @returns The global state 326 */ 327 [[nodiscard]] bool UsingGlobal() const { 328 return use_global; 329 } 330 331 /** 332 * Returns either the global or custom setting depending on the values of this setting's global 333 * state or if the global value was specifically requested. 334 * 335 * @param need_global Request global value regardless of setting's state; defaults to false 336 * 337 * @returns The required value of the setting 338 */ 339 [[nodiscard]] virtual const Type& GetValue() const override { 340 if (use_global) { 341 return this->value; 342 } 343 return custom; 344 } 345 [[nodiscard]] virtual const Type& GetValue(bool need_global) const { 346 if (use_global || need_global) { 347 return this->value; 348 } 349 return custom; 350 } 351 352 /** 353 * Sets the current setting value depending on the global state. 354 * 355 * @param val The new value 356 */ 357 void SetValue(const Type& val) override { 358 Type temp{ranged ? std::clamp(val, this->minimum, this->maximum) : val}; 359 if (use_global) { 360 std::swap(this->value, temp); 361 } else { 362 std::swap(custom, temp); 363 } 364 } 365 366 /** 367 * Assigns the current setting value depending on the global state. 368 * 369 * @param val The new value 370 * 371 * @returns A reference to the current setting value 372 */ 373 const Type& operator=(const Type& val) override { 374 Type temp{ranged ? std::clamp(val, this->minimum, this->maximum) : val}; 375 if (use_global) { 376 std::swap(this->value, temp); 377 return this->value; 378 } 379 std::swap(custom, temp); 380 return custom; 381 } 382 383 /** 384 * Returns the current setting value depending on the global state. 385 * 386 * @returns A reference to the current setting value 387 */ 388 virtual explicit operator const Type&() const override { 389 if (use_global) { 390 return this->value; 391 } 392 return custom; 393 } 394 395 protected: 396 bool use_global{true}; ///< The setting's global state 397 Type custom{}; ///< The custom value of the setting 398 }; 399 400 struct InputProfile { 401 std::string name; 402 std::array<std::string, NativeButton::NumButtons> buttons; 403 std::array<std::string, NativeAnalog::NumAnalogs> analogs; 404 std::string motion_device; 405 std::string touch_device; 406 bool use_touch_from_button; 407 int touch_from_button_map_index; 408 std::string udp_input_address; 409 u16 udp_input_port; 410 u8 udp_pad_index; 411 }; 412 413 struct TouchFromButtonMap { 414 std::string name; 415 std::vector<std::string> buttons; 416 }; 417 418 /// A special region value indicating that citra will automatically select a region 419 /// value to fit the region lockout info of the game 420 static constexpr s32 REGION_VALUE_AUTO_SELECT = -1; 421 422 struct Values { 423 // Controls 424 InputProfile current_input_profile; ///< The current input profile 425 int current_input_profile_index; ///< The current input profile index 426 std::vector<InputProfile> input_profiles; ///< The list of input profiles 427 std::vector<TouchFromButtonMap> touch_from_button_maps; 428 429 SwitchableSetting<bool> enable_gamemode{true, "enable_gamemode"}; 430 431 // Core 432 Setting<bool> use_cpu_jit{true, "use_cpu_jit"}; 433 SwitchableSetting<s32, true> cpu_clock_percentage{100, 5, 400, "cpu_clock_percentage"}; 434 SwitchableSetting<bool> is_new_3ds{true, "is_new_3ds"}; 435 SwitchableSetting<bool> lle_applets{false, "lle_applets"}; 436 437 // Data Storage 438 Setting<bool> use_virtual_sd{true, "use_virtual_sd"}; 439 Setting<bool> use_custom_storage{false, "use_custom_storage"}; 440 441 // System 442 SwitchableSetting<s32> region_value{REGION_VALUE_AUTO_SELECT, "region_value"}; 443 Setting<InitClock> init_clock{InitClock::SystemTime, "init_clock"}; 444 Setting<u64> init_time{946681277ULL, "init_time"}; 445 Setting<s64> init_time_offset{0, "init_time_offset"}; 446 Setting<InitTicks> init_ticks_type{InitTicks::Random, "init_ticks_type"}; 447 Setting<s64> init_ticks_override{0, "init_ticks_override"}; 448 Setting<bool> plugin_loader_enabled{false, "plugin_loader"}; 449 Setting<bool> allow_plugin_loader{true, "allow_plugin_loader"}; 450 451 // Renderer 452 SwitchableSetting<GraphicsAPI, true> graphics_api { 453 #if defined(ENABLE_OPENGL) 454 GraphicsAPI::OpenGL, 455 #elif defined(ENABLE_VULKAN) 456 GraphicsAPI::Vulkan, 457 #elif defined(ENABLE_SOFTWARE_RENDERER) 458 GraphicsAPI::Software, 459 #else 460 // TODO: Add a null renderer backend for this, perhaps. 461 #error "At least one renderer must be enabled." 462 #endif 463 GraphicsAPI::Software, GraphicsAPI::Vulkan, "graphics_api" 464 }; 465 SwitchableSetting<u32> physical_device{0, "physical_device"}; 466 Setting<bool> use_gles{false, "use_gles"}; 467 Setting<bool> renderer_debug{false, "renderer_debug"}; 468 Setting<bool> dump_command_buffers{false, "dump_command_buffers"}; 469 SwitchableSetting<bool> spirv_shader_gen{true, "spirv_shader_gen"}; 470 SwitchableSetting<bool> async_shader_compilation{false, "async_shader_compilation"}; 471 SwitchableSetting<bool> async_presentation{true, "async_presentation"}; 472 SwitchableSetting<bool> use_hw_shader{true, "use_hw_shader"}; 473 SwitchableSetting<bool> use_disk_shader_cache{true, "use_disk_shader_cache"}; 474 SwitchableSetting<bool> shaders_accurate_mul{true, "shaders_accurate_mul"}; 475 SwitchableSetting<bool> use_vsync_new{true, "use_vsync_new"}; 476 Setting<bool> use_shader_jit{true, "use_shader_jit"}; 477 SwitchableSetting<u32, true> resolution_factor{1, 0, 10, "resolution_factor"}; 478 SwitchableSetting<u16, true> frame_limit{100, 0, 1000, "frame_limit"}; 479 SwitchableSetting<TextureFilter> texture_filter{TextureFilter::None, "texture_filter"}; 480 SwitchableSetting<TextureSampling> texture_sampling{TextureSampling::GameControlled, 481 "texture_sampling"}; 482 483 SwitchableSetting<LayoutOption> layout_option{LayoutOption::Default, "layout_option"}; 484 SwitchableSetting<bool> swap_screen{false, "swap_screen"}; 485 SwitchableSetting<bool> upright_screen{false, "upright_screen"}; 486 SwitchableSetting<float, true> large_screen_proportion{4.f, 1.f, 16.f, 487 "large_screen_proportion"}; 488 Setting<bool> custom_layout{false, "custom_layout"}; 489 Setting<u16> custom_top_left{0, "custom_top_left"}; 490 Setting<u16> custom_top_top{0, "custom_top_top"}; 491 Setting<u16> custom_top_right{400, "custom_top_right"}; 492 Setting<u16> custom_top_bottom{240, "custom_top_bottom"}; 493 Setting<u16> custom_bottom_left{40, "custom_bottom_left"}; 494 Setting<u16> custom_bottom_top{240, "custom_bottom_top"}; 495 Setting<u16> custom_bottom_right{360, "custom_bottom_right"}; 496 Setting<u16> custom_bottom_bottom{480, "custom_bottom_bottom"}; 497 Setting<u16> custom_second_layer_opacity{100, "custom_second_layer_opacity"}; 498 499 SwitchableSetting<float> bg_red{0.f, "bg_red"}; 500 SwitchableSetting<float> bg_green{0.f, "bg_green"}; 501 SwitchableSetting<float> bg_blue{0.f, "bg_blue"}; 502 503 SwitchableSetting<StereoRenderOption> render_3d{StereoRenderOption::Off, "render_3d"}; 504 SwitchableSetting<u32> factor_3d{0, "factor_3d"}; 505 SwitchableSetting<MonoRenderOption> mono_render_option{MonoRenderOption::LeftEye, 506 "mono_render_option"}; 507 508 Setting<u32> cardboard_screen_size{85, "cardboard_screen_size"}; 509 Setting<s32> cardboard_x_shift{0, "cardboard_x_shift"}; 510 Setting<s32> cardboard_y_shift{0, "cardboard_y_shift"}; 511 512 SwitchableSetting<bool> filter_mode{true, "filter_mode"}; 513 SwitchableSetting<std::string> pp_shader_name{"none (builtin)", "pp_shader_name"}; 514 SwitchableSetting<std::string> anaglyph_shader_name{"dubois (builtin)", "anaglyph_shader_name"}; 515 516 SwitchableSetting<bool> dump_textures{false, "dump_textures"}; 517 SwitchableSetting<bool> custom_textures{false, "custom_textures"}; 518 SwitchableSetting<bool> preload_textures{false, "preload_textures"}; 519 SwitchableSetting<bool> async_custom_loading{true, "async_custom_loading"}; 520 521 // Audio 522 bool audio_muted; 523 SwitchableSetting<AudioEmulation> audio_emulation{AudioEmulation::HLE, "audio_emulation"}; 524 SwitchableSetting<bool> enable_audio_stretching{true, "enable_audio_stretching"}; 525 SwitchableSetting<float, true> volume{1.f, 0.f, 1.f, "volume"}; 526 Setting<AudioCore::SinkType> output_type{AudioCore::SinkType::Auto, "output_type"}; 527 Setting<std::string> output_device{"auto", "output_device"}; 528 Setting<AudioCore::InputType> input_type{AudioCore::InputType::Auto, "input_type"}; 529 Setting<std::string> input_device{"auto", "input_device"}; 530 531 // Camera 532 std::array<std::string, Service::CAM::NumCameras> camera_name; 533 std::array<std::string, Service::CAM::NumCameras> camera_config; 534 std::array<int, Service::CAM::NumCameras> camera_flip; 535 536 // Debugging 537 bool record_frame_times; 538 std::unordered_map<std::string, bool> lle_modules; 539 Setting<bool> delay_start_for_lle_modules{true, "delay_start_for_lle_modules"}; 540 Setting<bool> use_gdbstub{false, "use_gdbstub"}; 541 Setting<u16> gdbstub_port{24689, "gdbstub_port"}; 542 543 // Miscellaneous 544 Setting<std::string> log_filter{"*:Info", "log_filter"}; 545 546 // Video Dumping 547 std::string output_format; 548 std::string format_options; 549 550 std::string video_encoder; 551 std::string video_encoder_options; 552 u64 video_bitrate; 553 554 std::string audio_encoder; 555 std::string audio_encoder_options; 556 u64 audio_bitrate; 557 }; 558 559 extern Values values; 560 561 bool IsConfiguringGlobal(); 562 void SetConfiguringGlobal(bool is_global); 563 564 float Volume(); 565 566 void LogSettings(); 567 568 // Restore the global state of all applicable settings in the Values struct 569 void RestoreGlobalState(bool is_powered_on); 570 571 // Input profiles 572 void LoadProfile(int index); 573 void SaveProfile(int index); 574 void CreateProfile(std::string name); 575 void DeleteProfile(int index); 576 void RenameCurrentProfile(std::string new_name); 577 578 } // namespace Settings