settings: Preparation for per-game input settings

master
Morph 2020-09-28 10:00:15 +07:00
parent 8ead176639
commit 8f2959f680
19 changed files with 167 additions and 115 deletions

@ -27,7 +27,7 @@ void DefaultControllerApplet::ReconfigureControllers(std::function<void()> callb
->GetAppletResource() ->GetAppletResource()
->GetController<Service::HID::Controller_NPad>(Service::HID::HidController::NPad); ->GetController<Service::HID::Controller_NPad>(Service::HID::HidController::NPad);
auto& players = Settings::values.players; auto& players = Settings::values.players.GetValue();
const std::size_t min_supported_players = const std::size_t min_supported_players =
parameters.enable_single_mode ? 1 : parameters.min_players; parameters.enable_single_mode ? 1 : parameters.min_players;
@ -66,7 +66,7 @@ void DefaultControllerApplet::ReconfigureControllers(std::function<void()> callb
npad.MapSettingsTypeToNPad(Settings::ControllerType::RightJoycon), index); npad.MapSettingsTypeToNPad(Settings::ControllerType::RightJoycon), index);
} }
} else if (index == 0 && parameters.enable_single_mode && parameters.allow_handheld && } else if (index == 0 && parameters.enable_single_mode && parameters.allow_handheld &&
!Settings::values.use_docked_mode) { !Settings::values.use_docked_mode.GetValue()) {
// We should *never* reach here under any normal circumstances. // We should *never* reach here under any normal circumstances.
npad.AddNewControllerAt(npad.MapSettingsTypeToNPad(Settings::ControllerType::Handheld), npad.AddNewControllerAt(npad.MapSettingsTypeToNPad(Settings::ControllerType::Handheld),
index); index);

@ -47,7 +47,7 @@ FramebufferLayout DefaultFrameLayout(u32 width, u32 height) {
FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale) { FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale) {
u32 width, height; u32 width, height;
if (Settings::values.use_docked_mode) { if (Settings::values.use_docked_mode.GetValue()) {
width = ScreenDocked::Width * res_scale; width = ScreenDocked::Width * res_scale;
height = ScreenDocked::Height * res_scale; height = ScreenDocked::Height * res_scale;
} else { } else {

@ -751,7 +751,7 @@ void ICommonStateGetter::GetDefaultDisplayResolution(Kernel::HLERequestContext&
IPC::ResponseBuilder rb{ctx, 4}; IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
if (Settings::values.use_docked_mode) { if (Settings::values.use_docked_mode.GetValue()) {
rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth) * rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth) *
static_cast<u32>(Settings::values.resolution_factor.GetValue())); static_cast<u32>(Settings::values.resolution_factor.GetValue()));
rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight) * rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight) *
@ -824,7 +824,7 @@ void IStorage::Open(Kernel::HLERequestContext& ctx) {
} }
void ICommonStateGetter::GetOperationMode(Kernel::HLERequestContext& ctx) { void ICommonStateGetter::GetOperationMode(Kernel::HLERequestContext& ctx) {
const bool use_docked_mode{Settings::values.use_docked_mode}; const bool use_docked_mode{Settings::values.use_docked_mode.GetValue()};
LOG_DEBUG(Service_AM, "called, use_docked_mode={}", use_docked_mode); LOG_DEBUG(Service_AM, "called, use_docked_mode={}", use_docked_mode);
IPC::ResponseBuilder rb{ctx, 3}; IPC::ResponseBuilder rb{ctx, 3};

@ -222,7 +222,7 @@ void Controller::Execute() {
void Controller::ConfigurationComplete() { void Controller::ConfigurationComplete() {
ControllerSupportResultInfo result_info{}; ControllerSupportResultInfo result_info{};
const auto& players = Settings::values.players; const auto& players = Settings::values.players.GetValue();
// If enable_single_mode is enabled, player_count is 1 regardless of any other parameters. // If enable_single_mode is enabled, player_count is 1 regardless of any other parameters.
// Otherwise, only count connected players from P1-P8. // Otherwise, only count connected players from P1-P8.

@ -69,7 +69,8 @@ void Controller::SetFromCpuBoostMode(CpuBoostMode mode) {
} }
PerformanceMode Controller::GetCurrentPerformanceMode() const { PerformanceMode Controller::GetCurrentPerformanceMode() const {
return Settings::values.use_docked_mode ? PerformanceMode::Docked : PerformanceMode::Handheld; return Settings::values.use_docked_mode.GetValue() ? PerformanceMode::Docked
: PerformanceMode::Handheld;
} }
PerformanceConfiguration Controller::GetCurrentPerformanceConfiguration(PerformanceMode mode) { PerformanceConfiguration Controller::GetCurrentPerformanceConfiguration(PerformanceMode mode) {

@ -184,11 +184,14 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
controller.single_color.button_color = 0; controller.single_color.button_color = 0;
controller.dual_color_error = ColorReadError::ReadOk; controller.dual_color_error = ColorReadError::ReadOk;
controller.left_color.body_color = Settings::values.players[controller_idx].body_color_left; controller.left_color.body_color =
controller.left_color.button_color = Settings::values.players[controller_idx].button_color_left; Settings::values.players.GetValue()[controller_idx].body_color_left;
controller.right_color.body_color = Settings::values.players[controller_idx].body_color_right; controller.left_color.button_color =
Settings::values.players.GetValue()[controller_idx].button_color_left;
controller.right_color.body_color =
Settings::values.players.GetValue()[controller_idx].body_color_right;
controller.right_color.button_color = controller.right_color.button_color =
Settings::values.players[controller_idx].button_color_right; Settings::values.players.GetValue()[controller_idx].button_color_right;
controller.battery_level[0] = BATTERY_FULL; controller.battery_level[0] = BATTERY_FULL;
controller.battery_level[1] = BATTERY_FULL; controller.battery_level[1] = BATTERY_FULL;
@ -218,8 +221,9 @@ void Controller_NPad::OnInit() {
style.pokeball.Assign(1); style.pokeball.Assign(1);
} }
std::transform(Settings::values.players.begin(), Settings::values.players.end(), std::transform(Settings::values.players.GetValue().begin(),
connected_controllers.begin(), [](const Settings::PlayerInput& player) { Settings::values.players.GetValue().end(), connected_controllers.begin(),
[](const Settings::PlayerInput& player) {
return ControllerHolder{MapSettingsTypeToNPad(player.controller_type), return ControllerHolder{MapSettingsTypeToNPad(player.controller_type),
player.connected}; player.connected};
}); });
@ -227,12 +231,13 @@ void Controller_NPad::OnInit() {
// Connect the Player 1 or Handheld controller if none are connected. // Connect the Player 1 or Handheld controller if none are connected.
if (std::none_of(connected_controllers.begin(), connected_controllers.end(), if (std::none_of(connected_controllers.begin(), connected_controllers.end(),
[](const ControllerHolder& controller) { return controller.is_connected; })) { [](const ControllerHolder& controller) { return controller.is_connected; })) {
const auto controller = MapSettingsTypeToNPad(Settings::values.players[0].controller_type); const auto controller =
MapSettingsTypeToNPad(Settings::values.players.GetValue()[0].controller_type);
if (controller == NPadControllerType::Handheld) { if (controller == NPadControllerType::Handheld) {
Settings::values.players[HANDHELD_INDEX].connected = true; Settings::values.players.GetValue()[HANDHELD_INDEX].connected = true;
connected_controllers[HANDHELD_INDEX] = {controller, true}; connected_controllers[HANDHELD_INDEX] = {controller, true};
} else { } else {
Settings::values.players[0].connected = true; Settings::values.players.GetValue()[0].connected = true;
connected_controllers[0] = {controller, true}; connected_controllers[0] = {controller, true};
} }
} }
@ -255,7 +260,7 @@ void Controller_NPad::OnInit() {
} }
void Controller_NPad::OnLoadInputDevices() { void Controller_NPad::OnLoadInputDevices() {
const auto& players = Settings::values.players; const auto& players = Settings::values.players.GetValue();
for (std::size_t i = 0; i < players.size(); ++i) { for (std::size_t i = 0; i < players.size(); ++i) {
std::transform(players[i].buttons.begin() + Settings::NativeButton::BUTTON_HID_BEGIN, std::transform(players[i].buttons.begin() + Settings::NativeButton::BUTTON_HID_BEGIN,
players[i].buttons.begin() + Settings::NativeButton::BUTTON_HID_END, players[i].buttons.begin() + Settings::NativeButton::BUTTON_HID_END,
@ -528,7 +533,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
// Try to read sixaxis sensor states // Try to read sixaxis sensor states
std::array<MotionDevice, 2> motion_devices; std::array<MotionDevice, 2> motion_devices;
if (sixaxis_sensors_enabled && Settings::values.motion_enabled) { if (sixaxis_sensors_enabled && Settings::values.motion_enabled.GetValue()) {
sixaxis_at_rest = true; sixaxis_at_rest = true;
for (std::size_t e = 0; e < motion_devices.size(); ++e) { for (std::size_t e = 0; e < motion_devices.size(); ++e) {
const auto& device = motions[i][e]; const auto& device = motions[i][e];
@ -666,7 +671,7 @@ void Controller_NPad::VibrateController(const std::vector<u32>& controllers,
const std::vector<Vibration>& vibrations) { const std::vector<Vibration>& vibrations) {
LOG_TRACE(Service_HID, "called"); LOG_TRACE(Service_HID, "called");
if (!Settings::values.vibration_enabled || !can_controllers_vibrate) { if (!Settings::values.vibration_enabled.GetValue() || !can_controllers_vibrate) {
return; return;
} }
bool success = true; bool success = true;
@ -714,16 +719,17 @@ void Controller_NPad::UpdateControllerAt(NPadControllerType controller, std::siz
} }
if (controller == NPadControllerType::Handheld) { if (controller == NPadControllerType::Handheld) {
Settings::values.players[HANDHELD_INDEX].controller_type = Settings::values.players.GetValue()[HANDHELD_INDEX].controller_type =
MapNPadToSettingsType(controller); MapNPadToSettingsType(controller);
Settings::values.players[HANDHELD_INDEX].connected = true; Settings::values.players.GetValue()[HANDHELD_INDEX].connected = true;
connected_controllers[HANDHELD_INDEX] = {controller, true}; connected_controllers[HANDHELD_INDEX] = {controller, true};
InitNewlyAddedController(HANDHELD_INDEX); InitNewlyAddedController(HANDHELD_INDEX);
return; return;
} }
Settings::values.players[npad_index].controller_type = MapNPadToSettingsType(controller); Settings::values.players.GetValue()[npad_index].controller_type =
Settings::values.players[npad_index].connected = true; MapNPadToSettingsType(controller);
Settings::values.players.GetValue()[npad_index].connected = true;
connected_controllers[npad_index] = {controller, true}; connected_controllers[npad_index] = {controller, true};
InitNewlyAddedController(npad_index); InitNewlyAddedController(npad_index);
} }
@ -733,7 +739,7 @@ void Controller_NPad::DisconnectNPad(u32 npad_id) {
} }
void Controller_NPad::DisconnectNPadAtIndex(std::size_t npad_index) { void Controller_NPad::DisconnectNPadAtIndex(std::size_t npad_index) {
Settings::values.players[npad_index].connected = false; Settings::values.players.GetValue()[npad_index].connected = false;
connected_controllers[npad_index].is_connected = false; connected_controllers[npad_index].is_connected = false;
auto& controller = shared_memory_entries[npad_index]; auto& controller = shared_memory_entries[npad_index];
@ -895,7 +901,7 @@ bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const
return false; return false;
} }
// Handheld should not be supported in docked mode // Handheld should not be supported in docked mode
if (Settings::values.use_docked_mode) { if (Settings::values.use_docked_mode.GetValue()) {
return false; return false;
} }

@ -935,7 +935,7 @@ void Hid::CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx) {
void Hid::PermitVibration(Kernel::HLERequestContext& ctx) { void Hid::PermitVibration(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
const auto can_vibrate{rp.Pop<bool>()}; const auto can_vibrate{rp.Pop<bool>()};
Settings::values.vibration_enabled = can_vibrate; Settings::values.vibration_enabled.SetValue(can_vibrate);
LOG_DEBUG(Service_HID, "called, can_vibrate={}", can_vibrate); LOG_DEBUG(Service_HID, "called, can_vibrate={}", can_vibrate);
@ -948,7 +948,7 @@ void Hid::IsVibrationPermitted(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 3}; IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
rb.Push(Settings::values.vibration_enabled); rb.Push(Settings::values.vibration_enabled.GetValue());
} }
void Hid::ActivateConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { void Hid::ActivateConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) {

@ -771,7 +771,7 @@ private:
IPC::ResponseBuilder rb{ctx, 6}; IPC::ResponseBuilder rb{ctx, 6};
rb.Push(RESULT_SUCCESS); rb.Push(RESULT_SUCCESS);
if (Settings::values.use_docked_mode) { if (Settings::values.use_docked_mode.GetValue()) {
rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth) * rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth) *
static_cast<u32>(Settings::values.resolution_factor.GetValue())); static_cast<u32>(Settings::values.resolution_factor.GetValue()));
rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight) * rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight) *

@ -49,7 +49,7 @@ void LogSettings() {
}; };
LOG_INFO(Config, "yuzu Configuration:"); LOG_INFO(Config, "yuzu Configuration:");
log_setting("Controls_UseDockedMode", values.use_docked_mode); log_setting("Controls_UseDockedMode", values.use_docked_mode.GetValue());
log_setting("System_RngSeed", values.rng_seed.GetValue().value_or(0)); log_setting("System_RngSeed", values.rng_seed.GetValue().value_or(0));
log_setting("System_CurrentUser", values.current_user); log_setting("System_CurrentUser", values.current_user);
log_setting("System_LanguageIndex", values.language_index.GetValue()); log_setting("System_LanguageIndex", values.language_index.GetValue());
@ -145,6 +145,12 @@ void RestoreGlobalState() {
values.rng_seed.SetGlobal(true); values.rng_seed.SetGlobal(true);
values.custom_rtc.SetGlobal(true); values.custom_rtc.SetGlobal(true);
values.sound_index.SetGlobal(true); values.sound_index.SetGlobal(true);
// Controls
values.players.SetGlobal(true);
values.use_docked_mode.SetGlobal(true);
values.vibration_enabled.SetGlobal(true);
values.motion_enabled.SetGlobal(true);
} }
void Sanitize() { void Sanitize() {

@ -65,6 +65,38 @@ private:
Type local{}; Type local{};
}; };
/**
* The InputSetting class allows for getting a reference to either the global or local members.
* This is required as we cannot easily modify the values of user-defined types within containers
* using the SetValue() member function found in the Setting class. The primary purpose of this
* class is to store an array of 10 PlayerInput structs for both the global and local (per-game)
* setting and allows for easily accessing and modifying both settings.
*/
template <typename Type>
class InputSetting final {
public:
InputSetting() = default;
explicit InputSetting(Type val) : global{val} {}
~InputSetting() = default;
void SetGlobal(bool to_global) {
use_global = to_global;
}
bool UsingGlobal() const {
return use_global;
}
Type& GetValue(bool need_global = false) {
if (use_global || need_global) {
return global;
}
return local;
}
private:
bool use_global = true;
Type global{};
Type local{};
};
struct TouchFromButtonMap { struct TouchFromButtonMap {
std::string name; std::string name;
std::vector<std::string> buttons; std::vector<std::string> buttons;
@ -133,9 +165,17 @@ struct Values {
Setting<s32> sound_index; Setting<s32> sound_index;
// Controls // Controls
std::array<PlayerInput, 10> players; InputSetting<std::array<PlayerInput, 10>> players;
bool use_docked_mode; Setting<bool> use_docked_mode;
Setting<bool> vibration_enabled;
Setting<bool> motion_enabled;
std::string motion_device;
std::string udp_input_address;
u16 udp_input_port;
u8 udp_pad_index;
bool mouse_enabled; bool mouse_enabled;
std::string mouse_device; std::string mouse_device;
@ -149,20 +189,15 @@ struct Values {
ButtonsRaw debug_pad_buttons; ButtonsRaw debug_pad_buttons;
AnalogsRaw debug_pad_analogs; AnalogsRaw debug_pad_analogs;
bool vibration_enabled;
bool motion_enabled;
std::string motion_device;
std::string touch_device;
TouchscreenInput touchscreen; TouchscreenInput touchscreen;
std::atomic_bool is_device_reload_pending{true};
bool use_touch_from_button; bool use_touch_from_button;
std::string touch_device;
int touch_from_button_map_index; int touch_from_button_map_index;
std::string udp_input_address;
u16 udp_input_port;
u8 udp_pad_index;
std::vector<TouchFromButtonMap> touch_from_button_maps; std::vector<TouchFromButtonMap> touch_from_button_maps;
std::atomic_bool is_device_reload_pending{true};
// Data Storage // Data Storage
bool use_virtual_sd; bool use_virtual_sd;
bool gamecard_inserted; bool gamecard_inserted;

@ -213,7 +213,7 @@ void TelemetrySession::AddInitialInfo(Loader::AppLoader& app_loader) {
Settings::values.use_assembly_shaders.GetValue()); Settings::values.use_assembly_shaders.GetValue());
AddField(field_type, "Renderer_UseAsynchronousShaders", AddField(field_type, "Renderer_UseAsynchronousShaders",
Settings::values.use_asynchronous_shaders.GetValue()); Settings::values.use_asynchronous_shaders.GetValue());
AddField(field_type, "System_UseDockedMode", Settings::values.use_docked_mode); AddField(field_type, "System_UseDockedMode", Settings::values.use_docked_mode.GetValue());
} }
bool TelemetrySession::SubmitTestcase() { bool TelemetrySession::SubmitTestcase() {

@ -261,26 +261,26 @@ void QtControllerSelectorDialog::ApplyConfiguration() {
UpdateControllerState(index); UpdateControllerState(index);
} }
const bool pre_docked_mode = Settings::values.use_docked_mode; const bool pre_docked_mode = Settings::values.use_docked_mode.GetValue();
Settings::values.use_docked_mode = ui->radioDocked->isChecked(); Settings::values.use_docked_mode.SetValue(ui->radioDocked->isChecked());
OnDockedModeChanged(pre_docked_mode, Settings::values.use_docked_mode); OnDockedModeChanged(pre_docked_mode, Settings::values.use_docked_mode.GetValue());
Settings::values.vibration_enabled = ui->vibrationGroup->isChecked(); Settings::values.vibration_enabled.SetValue(ui->vibrationGroup->isChecked());
} }
void QtControllerSelectorDialog::LoadConfiguration() { void QtControllerSelectorDialog::LoadConfiguration() {
for (std::size_t index = 0; index < NUM_PLAYERS; ++index) { for (std::size_t index = 0; index < NUM_PLAYERS; ++index) {
const auto connected = Settings::values.players[index].connected || const auto connected = Settings::values.players.GetValue()[index].connected ||
(index == 0 && Settings::values.players[8].connected); (index == 0 && Settings::values.players.GetValue()[8].connected);
player_groupboxes[index]->setChecked(connected); player_groupboxes[index]->setChecked(connected);
connected_controller_checkboxes[index]->setChecked(connected); connected_controller_checkboxes[index]->setChecked(connected);
emulated_controllers[index]->setCurrentIndex( emulated_controllers[index]->setCurrentIndex(
GetIndexFromControllerType(Settings::values.players[index].controller_type)); GetIndexFromControllerType(Settings::values.players.GetValue()[index].controller_type));
} }
UpdateDockedState(Settings::values.players[8].connected); UpdateDockedState(Settings::values.players.GetValue()[8].connected);
ui->vibrationGroup->setChecked(Settings::values.vibration_enabled); ui->vibrationGroup->setChecked(Settings::values.vibration_enabled.GetValue());
} }
void QtControllerSelectorDialog::CallConfigureInputDialog() { void QtControllerSelectorDialog::CallConfigureInputDialog() {
@ -448,7 +448,7 @@ void QtControllerSelectorDialog::UpdateControllerIcon(std::size_t player_index)
} }
void QtControllerSelectorDialog::UpdateControllerState(std::size_t player_index) { void QtControllerSelectorDialog::UpdateControllerState(std::size_t player_index) {
auto& player = Settings::values.players[player_index]; auto& player = Settings::values.players.GetValue()[player_index];
player.controller_type = player.controller_type =
GetControllerTypeFromIndex(emulated_controllers[player_index]->currentIndex()); GetControllerTypeFromIndex(emulated_controllers[player_index]->currentIndex());
@ -461,7 +461,7 @@ void QtControllerSelectorDialog::UpdateControllerState(std::size_t player_index)
} }
// Player 1 and Handheld // Player 1 and Handheld
auto& handheld = Settings::values.players[8]; auto& handheld = Settings::values.players.GetValue()[8];
// If Handheld is selected, copy all the settings from Player 1 to Handheld. // If Handheld is selected, copy all the settings from Player 1 to Handheld.
if (player.controller_type == Settings::ControllerType::Handheld) { if (player.controller_type == Settings::ControllerType::Handheld) {
handheld = player; handheld = player;
@ -527,8 +527,8 @@ void QtControllerSelectorDialog::UpdateDockedState(bool is_handheld) {
ui->radioDocked->setEnabled(!is_handheld); ui->radioDocked->setEnabled(!is_handheld);
ui->radioUndocked->setEnabled(!is_handheld); ui->radioUndocked->setEnabled(!is_handheld);
ui->radioDocked->setChecked(Settings::values.use_docked_mode); ui->radioDocked->setChecked(Settings::values.use_docked_mode.GetValue());
ui->radioUndocked->setChecked(!Settings::values.use_docked_mode); ui->radioUndocked->setChecked(!Settings::values.use_docked_mode.GetValue());
// Also force into undocked mode if the controller type is handheld. // Also force into undocked mode if the controller type is handheld.
if (is_handheld) { if (is_handheld) {
@ -571,8 +571,8 @@ void QtControllerSelectorDialog::DisableUnsupportedPlayers() {
for (std::size_t index = max_supported_players; index < NUM_PLAYERS; ++index) { for (std::size_t index = max_supported_players; index < NUM_PLAYERS; ++index) {
// Disconnect any unsupported players here and disable or hide them if applicable. // Disconnect any unsupported players here and disable or hide them if applicable.
Settings::values.players[index].connected = false; Settings::values.players.GetValue()[index].connected = false;
UpdateController(Settings::values.players[index].controller_type, index, false); UpdateController(Settings::values.players.GetValue()[index].controller_type, index, false);
// Hide the player widgets when max_supported_controllers is less than or equal to 4. // Hide the player widgets when max_supported_controllers is less than or equal to 4.
if (max_supported_players <= 4) { if (max_supported_players <= 4) {
player_widgets[index]->hide(); player_widgets[index]->hide();

@ -276,7 +276,7 @@ void Config::ReadPlayerValue(std::size_t player_index) {
} }
}(); }();
auto& player = Settings::values.players[player_index]; auto& player = Settings::values.players.GetValue()[player_index];
if (player_prefix.isEmpty()) { if (player_prefix.isEmpty()) {
const auto controller = static_cast<Settings::ControllerType>( const auto controller = static_cast<Settings::ControllerType>(
@ -481,7 +481,7 @@ void Config::ReadAudioValues() {
void Config::ReadControlValues() { void Config::ReadControlValues() {
qt_config->beginGroup(QStringLiteral("Controls")); qt_config->beginGroup(QStringLiteral("Controls"));
for (std::size_t p = 0; p < Settings::values.players.size(); ++p) { for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) {
ReadPlayerValue(p); ReadPlayerValue(p);
} }
ReadDebugValues(); ReadDebugValues();
@ -490,11 +490,10 @@ void Config::ReadControlValues() {
ReadTouchscreenValues(); ReadTouchscreenValues();
ReadMotionTouchValues(); ReadMotionTouchValues();
Settings::values.vibration_enabled = ReadSettingGlobal(Settings::values.use_docked_mode, QStringLiteral("use_docked_mode"), false);
ReadSetting(QStringLiteral("vibration_enabled"), true).toBool(); ReadSettingGlobal(Settings::values.vibration_enabled, QStringLiteral("vibration_enabled"),
Settings::values.motion_enabled = ReadSetting(QStringLiteral("motion_enabled"), true).toBool(); true);
Settings::values.use_docked_mode = ReadSettingGlobal(Settings::values.motion_enabled, QStringLiteral("motion_enabled"), true);
ReadSetting(QStringLiteral("use_docked_mode"), false).toBool();
qt_config->endGroup(); qt_config->endGroup();
} }
@ -976,7 +975,7 @@ void Config::SavePlayerValue(std::size_t player_index) {
} }
}(); }();
const auto& player = Settings::values.players[player_index]; const auto& player = Settings::values.players.GetValue()[player_index];
WriteSetting(QStringLiteral("%1type").arg(player_prefix), WriteSetting(QStringLiteral("%1type").arg(player_prefix),
static_cast<u8>(player.controller_type), static_cast<u8>(player.controller_type),
@ -1140,7 +1139,7 @@ void Config::SaveAudioValues() {
void Config::SaveControlValues() { void Config::SaveControlValues() {
qt_config->beginGroup(QStringLiteral("Controls")); qt_config->beginGroup(QStringLiteral("Controls"));
for (std::size_t p = 0; p < Settings::values.players.size(); ++p) { for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) {
SavePlayerValue(p); SavePlayerValue(p);
} }
SaveDebugValues(); SaveDebugValues();
@ -1148,8 +1147,10 @@ void Config::SaveControlValues() {
SaveTouchscreenValues(); SaveTouchscreenValues();
SaveMotionTouchValues(); SaveMotionTouchValues();
WriteSetting(QStringLiteral("vibration_enabled"), Settings::values.vibration_enabled, true); WriteSettingGlobal(QStringLiteral("use_docked_mode"), Settings::values.use_docked_mode, false);
WriteSetting(QStringLiteral("motion_enabled"), Settings::values.motion_enabled, true); WriteSettingGlobal(QStringLiteral("vibration_enabled"), Settings::values.vibration_enabled,
true);
WriteSettingGlobal(QStringLiteral("motion_enabled"), Settings::values.motion_enabled, true);
WriteSetting(QStringLiteral("motion_device"), WriteSetting(QStringLiteral("motion_device"),
QString::fromStdString(Settings::values.motion_device), QString::fromStdString(Settings::values.motion_device),
QStringLiteral("engine:motion_emu,update_period:100,sensitivity:0.01")); QStringLiteral("engine:motion_emu,update_period:100,sensitivity:0.01"));
@ -1157,7 +1158,6 @@ void Config::SaveControlValues() {
QString::fromStdString(Settings::values.touch_device), QString::fromStdString(Settings::values.touch_device),
QStringLiteral("engine:emu_window")); QStringLiteral("engine:emu_window"));
WriteSetting(QStringLiteral("keyboard_enabled"), Settings::values.keyboard_enabled, false); WriteSetting(QStringLiteral("keyboard_enabled"), Settings::values.keyboard_enabled, false);
WriteSetting(QStringLiteral("use_docked_mode"), Settings::values.use_docked_mode, false);
qt_config->endGroup(); qt_config->endGroup();
} }

@ -181,12 +181,12 @@ void ConfigureInput::ApplyConfiguration() {
advanced->ApplyConfiguration(); advanced->ApplyConfiguration();
const bool pre_docked_mode = Settings::values.use_docked_mode; const bool pre_docked_mode = Settings::values.use_docked_mode.GetValue();
Settings::values.use_docked_mode = ui->radioDocked->isChecked(); Settings::values.use_docked_mode.SetValue(ui->radioDocked->isChecked());
OnDockedModeChanged(pre_docked_mode, Settings::values.use_docked_mode); OnDockedModeChanged(pre_docked_mode, Settings::values.use_docked_mode.GetValue());
Settings::values.vibration_enabled = ui->vibrationGroup->isChecked(); Settings::values.vibration_enabled.SetValue(ui->vibrationGroup->isChecked());
Settings::values.motion_enabled = ui->motionGroup->isChecked(); Settings::values.motion_enabled.SetValue(ui->motionGroup->isChecked());
} }
void ConfigureInput::changeEvent(QEvent* event) { void ConfigureInput::changeEvent(QEvent* event) {
@ -203,16 +203,16 @@ void ConfigureInput::RetranslateUI() {
void ConfigureInput::LoadConfiguration() { void ConfigureInput::LoadConfiguration() {
LoadPlayerControllerIndices(); LoadPlayerControllerIndices();
UpdateDockedState(Settings::values.players[8].connected); UpdateDockedState(Settings::values.players.GetValue()[8].connected);
ui->vibrationGroup->setChecked(Settings::values.vibration_enabled); ui->vibrationGroup->setChecked(Settings::values.vibration_enabled.GetValue());
ui->motionGroup->setChecked(Settings::values.motion_enabled); ui->motionGroup->setChecked(Settings::values.motion_enabled.GetValue());
} }
void ConfigureInput::LoadPlayerControllerIndices() { void ConfigureInput::LoadPlayerControllerIndices() {
for (std::size_t i = 0; i < player_connected.size(); ++i) { for (std::size_t i = 0; i < player_connected.size(); ++i) {
const auto connected = Settings::values.players[i].connected || const auto connected = Settings::values.players.GetValue()[i].connected ||
(i == 0 && Settings::values.players[8].connected); (i == 0 && Settings::values.players.GetValue()[8].connected);
player_connected[i]->setChecked(connected); player_connected[i]->setChecked(connected);
} }
} }
@ -241,8 +241,8 @@ void ConfigureInput::UpdateDockedState(bool is_handheld) {
ui->radioDocked->setEnabled(!is_handheld); ui->radioDocked->setEnabled(!is_handheld);
ui->radioUndocked->setEnabled(!is_handheld); ui->radioUndocked->setEnabled(!is_handheld);
ui->radioDocked->setChecked(Settings::values.use_docked_mode); ui->radioDocked->setChecked(Settings::values.use_docked_mode.GetValue());
ui->radioUndocked->setChecked(!Settings::values.use_docked_mode); ui->radioUndocked->setChecked(!Settings::values.use_docked_mode.GetValue());
// Also force into undocked mode if the controller type is handheld. // Also force into undocked mode if the controller type is handheld.
if (is_handheld) { if (is_handheld) {

@ -107,7 +107,7 @@ void ConfigureInputAdvanced::OnControllerButtonClick(int player_idx, int button_
void ConfigureInputAdvanced::ApplyConfiguration() { void ConfigureInputAdvanced::ApplyConfiguration() {
for (std::size_t player_idx = 0; player_idx < controllers_color_buttons.size(); ++player_idx) { for (std::size_t player_idx = 0; player_idx < controllers_color_buttons.size(); ++player_idx) {
auto& player = Settings::values.players[player_idx]; auto& player = Settings::values.players.GetValue()[player_idx];
std::array<u32, 4> colors{}; std::array<u32, 4> colors{};
std::transform(controllers_colors[player_idx].begin(), controllers_colors[player_idx].end(), std::transform(controllers_colors[player_idx].begin(), controllers_colors[player_idx].end(),
colors.begin(), [](QColor color) { return color.rgb(); }); colors.begin(), [](QColor color) { return color.rgb(); });
@ -126,7 +126,7 @@ void ConfigureInputAdvanced::ApplyConfiguration() {
void ConfigureInputAdvanced::LoadConfiguration() { void ConfigureInputAdvanced::LoadConfiguration() {
for (std::size_t player_idx = 0; player_idx < controllers_color_buttons.size(); ++player_idx) { for (std::size_t player_idx = 0; player_idx < controllers_color_buttons.size(); ++player_idx) {
auto& player = Settings::values.players[player_idx]; auto& player = Settings::values.players.GetValue()[player_idx];
std::array<u32, 4> colors = { std::array<u32, 4> colors = {
player.body_color_left, player.body_color_left,
player.button_color_left, player.button_color_left,

@ -544,7 +544,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
ConfigureInputPlayer::~ConfigureInputPlayer() = default; ConfigureInputPlayer::~ConfigureInputPlayer() = default;
void ConfigureInputPlayer::ApplyConfiguration() { void ConfigureInputPlayer::ApplyConfiguration() {
auto& player = Settings::values.players[player_index]; auto& player = Settings::values.players.GetValue()[player_index];
auto& buttons = debug ? Settings::values.debug_pad_buttons : player.buttons; auto& buttons = debug ? Settings::values.debug_pad_buttons : player.buttons;
auto& analogs = debug ? Settings::values.debug_pad_analogs : player.analogs; auto& analogs = debug ? Settings::values.debug_pad_analogs : player.analogs;
@ -572,7 +572,7 @@ void ConfigureInputPlayer::ApplyConfiguration() {
} }
// Player 1 and Handheld // Player 1 and Handheld
auto& handheld = Settings::values.players[HANDHELD_INDEX]; auto& handheld = Settings::values.players.GetValue()[HANDHELD_INDEX];
// If Handheld is selected, copy all the settings from Player 1 to Handheld. // If Handheld is selected, copy all the settings from Player 1 to Handheld.
if (player.controller_type == Settings::ControllerType::Handheld) { if (player.controller_type == Settings::ControllerType::Handheld) {
handheld = player; handheld = player;
@ -609,7 +609,7 @@ void ConfigureInputPlayer::RetranslateUI() {
} }
void ConfigureInputPlayer::LoadConfiguration() { void ConfigureInputPlayer::LoadConfiguration() {
auto& player = Settings::values.players[player_index]; auto& player = Settings::values.players.GetValue()[player_index];
if (debug) { if (debug) {
std::transform(Settings::values.debug_pad_buttons.begin(), std::transform(Settings::values.debug_pad_buttons.begin(),
Settings::values.debug_pad_buttons.end(), buttons_param.begin(), Settings::values.debug_pad_buttons.end(), buttons_param.begin(),
@ -636,7 +636,7 @@ void ConfigureInputPlayer::LoadConfiguration() {
ui->comboControllerType->setCurrentIndex(static_cast<int>(player.controller_type)); ui->comboControllerType->setCurrentIndex(static_cast<int>(player.controller_type));
ui->groupConnectedController->setChecked( ui->groupConnectedController->setChecked(
player.connected || player.connected ||
(player_index == 0 && Settings::values.players[HANDHELD_INDEX].connected)); (player_index == 0 && Settings::values.players.GetValue()[HANDHELD_INDEX].connected));
} }
void ConfigureInputPlayer::ConnectPlayer(bool connected) { void ConfigureInputPlayer::ConnectPlayer(bool connected) {

@ -551,13 +551,14 @@ void GMainWindow::InitializeWidgets() {
dock_status_button->setObjectName(QStringLiteral("TogglableStatusBarButton")); dock_status_button->setObjectName(QStringLiteral("TogglableStatusBarButton"));
dock_status_button->setFocusPolicy(Qt::NoFocus); dock_status_button->setFocusPolicy(Qt::NoFocus);
connect(dock_status_button, &QPushButton::clicked, [&] { connect(dock_status_button, &QPushButton::clicked, [&] {
Settings::values.use_docked_mode = !Settings::values.use_docked_mode; Settings::values.use_docked_mode.SetValue(!Settings::values.use_docked_mode.GetValue());
dock_status_button->setChecked(Settings::values.use_docked_mode); dock_status_button->setChecked(Settings::values.use_docked_mode.GetValue());
OnDockedModeChanged(!Settings::values.use_docked_mode, Settings::values.use_docked_mode); OnDockedModeChanged(!Settings::values.use_docked_mode.GetValue(),
Settings::values.use_docked_mode.GetValue());
}); });
dock_status_button->setText(tr("DOCK")); dock_status_button->setText(tr("DOCK"));
dock_status_button->setCheckable(true); dock_status_button->setCheckable(true);
dock_status_button->setChecked(Settings::values.use_docked_mode); dock_status_button->setChecked(Settings::values.use_docked_mode.GetValue());
statusBar()->insertPermanentWidget(0, dock_status_button); statusBar()->insertPermanentWidget(0, dock_status_button);
// Setup ASync button // Setup ASync button
@ -796,10 +797,11 @@ void GMainWindow::InitializeHotkeys() {
}); });
connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Change Docked Mode"), this), connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Change Docked Mode"), this),
&QShortcut::activated, this, [&] { &QShortcut::activated, this, [&] {
Settings::values.use_docked_mode = !Settings::values.use_docked_mode; Settings::values.use_docked_mode.SetValue(
OnDockedModeChanged(!Settings::values.use_docked_mode, !Settings::values.use_docked_mode.GetValue());
Settings::values.use_docked_mode); OnDockedModeChanged(!Settings::values.use_docked_mode.GetValue(),
dock_status_button->setChecked(Settings::values.use_docked_mode); Settings::values.use_docked_mode.GetValue());
dock_status_button->setChecked(Settings::values.use_docked_mode.GetValue());
}); });
connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Mute Audio"), this), connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Mute Audio"), this),
&QShortcut::activated, this, &QShortcut::activated, this,
@ -2405,7 +2407,8 @@ void GMainWindow::MigrateConfigFiles() {
const QStringList config_dir_list = config_dir.entryList(QStringList(QStringLiteral("*.ini"))); const QStringList config_dir_list = config_dir.entryList(QStringList(QStringLiteral("*.ini")));
Common::FS::CreateFullPath(fmt::format("{}custom" DIR_SEP, config_dir_str)); Common::FS::CreateFullPath(fmt::format("{}custom" DIR_SEP, config_dir_str));
for (QStringList::const_iterator it = config_dir_list.constBegin(); it != config_dir_list.constEnd(); ++it) { for (QStringList::const_iterator it = config_dir_list.constBegin();
it != config_dir_list.constEnd(); ++it) {
const auto filename = it->toStdString(); const auto filename = it->toStdString();
if (filename.find_first_not_of("0123456789abcdefACBDEF", 0) < 16) { if (filename.find_first_not_of("0123456789abcdefACBDEF", 0) < 16) {
continue; continue;
@ -2477,7 +2480,7 @@ void GMainWindow::UpdateStatusBar() {
} }
void GMainWindow::UpdateStatusButtons() { void GMainWindow::UpdateStatusButtons() {
dock_status_button->setChecked(Settings::values.use_docked_mode); dock_status_button->setChecked(Settings::values.use_docked_mode.GetValue());
multicore_status_button->setChecked(Settings::values.use_multi_core.GetValue()); multicore_status_button->setChecked(Settings::values.use_multi_core.GetValue());
Settings::values.use_asynchronous_gpu_emulation.SetValue( Settings::values.use_asynchronous_gpu_emulation.SetValue(
Settings::values.use_asynchronous_gpu_emulation.GetValue() || Settings::values.use_asynchronous_gpu_emulation.GetValue() ||

@ -228,24 +228,24 @@ static const std::array<int, 8> keyboard_mods{
void Config::ReadValues() { void Config::ReadValues() {
// Controls // Controls
for (std::size_t p = 0; p < Settings::values.players.size(); ++p) { for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) {
const auto group = fmt::format("ControlsP{}", p); const auto group = fmt::format("ControlsP{}", p);
for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
Settings::values.players[p].buttons[i] = Settings::values.players.GetValue()[p].buttons[i] =
sdl2_config->Get(group, Settings::NativeButton::mapping[i], default_param); sdl2_config->Get(group, Settings::NativeButton::mapping[i], default_param);
if (Settings::values.players[p].buttons[i].empty()) if (Settings::values.players.GetValue()[p].buttons[i].empty())
Settings::values.players[p].buttons[i] = default_param; Settings::values.players.GetValue()[p].buttons[i] = default_param;
} }
for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
std::string default_param = InputCommon::GenerateAnalogParamFromKeys( std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], default_analogs[i][0], default_analogs[i][1], default_analogs[i][2],
default_analogs[i][3], default_analogs[i][4], 0.5f); default_analogs[i][3], default_analogs[i][4], 0.5f);
Settings::values.players[p].analogs[i] = Settings::values.players.GetValue()[p].analogs[i] =
sdl2_config->Get(group, Settings::NativeAnalog::mapping[i], default_param); sdl2_config->Get(group, Settings::NativeAnalog::mapping[i], default_param);
if (Settings::values.players[p].analogs[i].empty()) if (Settings::values.players.GetValue()[p].analogs[i].empty())
Settings::values.players[p].analogs[i] = default_param; Settings::values.players.GetValue()[p].analogs[i] = default_param;
} }
} }
@ -288,10 +288,10 @@ void Config::ReadValues() {
Settings::values.debug_pad_analogs[i] = default_param; Settings::values.debug_pad_analogs[i] = default_param;
} }
Settings::values.vibration_enabled = Settings::values.vibration_enabled.SetValue(
sdl2_config->GetBoolean("ControlsGeneral", "vibration_enabled", true); sdl2_config->GetBoolean("ControlsGeneral", "vibration_enabled", true));
Settings::values.motion_enabled = Settings::values.motion_enabled.SetValue(
sdl2_config->GetBoolean("ControlsGeneral", "motion_enabled", true); sdl2_config->GetBoolean("ControlsGeneral", "motion_enabled", true));
Settings::values.touchscreen.enabled = Settings::values.touchscreen.enabled =
sdl2_config->GetBoolean("ControlsGeneral", "touch_enabled", true); sdl2_config->GetBoolean("ControlsGeneral", "touch_enabled", true);
Settings::values.touchscreen.device = Settings::values.touchscreen.device =
@ -343,7 +343,8 @@ void Config::ReadValues() {
Settings::values.gamecard_path = sdl2_config->Get("Data Storage", "gamecard_path", ""); Settings::values.gamecard_path = sdl2_config->Get("Data Storage", "gamecard_path", "");
// System // System
Settings::values.use_docked_mode = sdl2_config->GetBoolean("System", "use_docked_mode", false); Settings::values.use_docked_mode.SetValue(
sdl2_config->GetBoolean("System", "use_docked_mode", false));
const auto size = sdl2_config->GetInteger("System", "users_size", 0); const auto size = sdl2_config->GetInteger("System", "users_size", 0);
Settings::values.current_user = std::clamp<int>( Settings::values.current_user = std::clamp<int>(

@ -47,13 +47,13 @@ bool Config::LoadINI(const std::string& default_contents, bool retry) {
void Config::ReadValues() { void Config::ReadValues() {
// Controls // Controls
for (std::size_t p = 0; p < Settings::values.players.size(); ++p) { for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) {
for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
Settings::values.players[p].buttons[i] = ""; Settings::values.players.GetValue()[p].buttons[i] = "";
} }
for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
Settings::values.players[p].analogs[i] = ""; Settings::values.players.GetValue()[p].analogs[i] = "";
} }
} }
@ -75,8 +75,8 @@ void Config::ReadValues() {
Settings::values.debug_pad_analogs[i] = ""; Settings::values.debug_pad_analogs[i] = "";
} }
Settings::values.vibration_enabled = true; Settings::values.vibration_enabled.SetValue(true);
Settings::values.motion_enabled = true; Settings::values.motion_enabled.SetValue(true);
Settings::values.touchscreen.enabled = ""; Settings::values.touchscreen.enabled = "";
Settings::values.touchscreen.device = ""; Settings::values.touchscreen.device = "";
Settings::values.touchscreen.finger = 0; Settings::values.touchscreen.finger = 0;
@ -84,8 +84,8 @@ void Config::ReadValues() {
Settings::values.touchscreen.diameter_x = 15; Settings::values.touchscreen.diameter_x = 15;
Settings::values.touchscreen.diameter_y = 15; Settings::values.touchscreen.diameter_y = 15;
Settings::values.use_docked_mode = Settings::values.use_docked_mode.SetValue(
sdl2_config->GetBoolean("Controls", "use_docked_mode", false); sdl2_config->GetBoolean("Controls", "use_docked_mode", false));
// Data Storage // Data Storage
Settings::values.use_virtual_sd = Settings::values.use_virtual_sd =