diff options
Diffstat (limited to 'src/yuzu')
32 files changed, 481 insertions, 175 deletions
| diff --git a/src/yuzu/applets/qt_controller.cpp b/src/yuzu/applets/qt_controller.cpp index 4239c17f5..4104928d1 100644 --- a/src/yuzu/applets/qt_controller.cpp +++ b/src/yuzu/applets/qt_controller.cpp @@ -257,7 +257,7 @@ void QtControllerSelectorDialog::LoadConfiguration() {  }  void QtControllerSelectorDialog::CallConfigureVibrationDialog() { -    ConfigureVibration dialog(this); +    ConfigureVibration dialog(this, system.HIDCore());      dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint |                            Qt::WindowSystemMenuHint); diff --git a/src/yuzu/applets/qt_profile_select.cpp b/src/yuzu/applets/qt_profile_select.cpp index 5b32da923..4cd8f7784 100644 --- a/src/yuzu/applets/qt_profile_select.cpp +++ b/src/yuzu/applets/qt_profile_select.cpp @@ -23,13 +23,13 @@ QString FormatUserEntryText(const QString& username, Common::UUID uuid) {      return QtProfileSelectionDialog::tr(                 "%1\n%2", "%1 is the profile username, %2 is the formatted UUID (e.g. "                           "00112233-4455-6677-8899-AABBCCDDEEFF))") -        .arg(username, QString::fromStdString(uuid.FormatSwitch())); +        .arg(username, QString::fromStdString(uuid.FormattedString()));  }  QString GetImagePath(Common::UUID uuid) {      const auto path =          Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir) / -        fmt::format("system/save/8000000000000010/su/avators/{}.jpg", uuid.FormatSwitch()); +        fmt::format("system/save/8000000000000010/su/avators/{}.jpg", uuid.FormattedString());      return QString::fromStdString(Common::FS::PathToUTF8String(path));  } diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 2c8c10c50..4b943c6ba 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -65,23 +65,25 @@ const std::array<int, 2> Config::default_stick_mod = {  // This must be in alphabetical order according to action name as it must have the same order as  // UISetting::values.shortcuts, which is alphabetically ordered.  // clang-format off -const std::array<UISettings::Shortcut, 20> Config::default_hotkeys{{ +const std::array<UISettings::Shortcut, 22> Config::default_hotkeys{{      {QStringLiteral("Audio Mute/Unmute"),        QStringLiteral("Main Window"), {QStringLiteral("Ctrl+M"),  QStringLiteral("Home+Dpad_Right"), Qt::WindowShortcut}},      {QStringLiteral("Audio Volume Down"),        QStringLiteral("Main Window"), {QStringLiteral("-"),       QStringLiteral("Home+Dpad_Down"), Qt::ApplicationShortcut}},      {QStringLiteral("Audio Volume Up"),          QStringLiteral("Main Window"), {QStringLiteral("+"),       QStringLiteral("Home+Dpad_Up"), Qt::ApplicationShortcut}},      {QStringLiteral("Capture Screenshot"),       QStringLiteral("Main Window"), {QStringLiteral("Ctrl+P"),  QStringLiteral("Screenshot"), Qt::WidgetWithChildrenShortcut}}, +    {QStringLiteral("Change Adapting Filter"),   QStringLiteral("Main Window"), {QStringLiteral("F8"),      QStringLiteral("Home+L"), Qt::ApplicationShortcut}},      {QStringLiteral("Change Docked Mode"),       QStringLiteral("Main Window"), {QStringLiteral("F10"),     QStringLiteral("Home+X"), Qt::ApplicationShortcut}}, +    {QStringLiteral("Change GPU Accuracy"),      QStringLiteral("Main Window"), {QStringLiteral("F9"),      QStringLiteral("Home+R"), Qt::ApplicationShortcut}},      {QStringLiteral("Continue/Pause Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F4"),      QStringLiteral("Home+Plus"), Qt::WindowShortcut}},      {QStringLiteral("Exit Fullscreen"),          QStringLiteral("Main Window"), {QStringLiteral("Esc"),     QStringLiteral(""), Qt::WindowShortcut}},      {QStringLiteral("Exit yuzu"),                QStringLiteral("Main Window"), {QStringLiteral("Ctrl+Q"),  QStringLiteral("Home+Minus"), Qt::WindowShortcut}},      {QStringLiteral("Fullscreen"),               QStringLiteral("Main Window"), {QStringLiteral("F11"),     QStringLiteral("Home+B"), Qt::WindowShortcut}}, -    {QStringLiteral("Load Amiibo"),              QStringLiteral("Main Window"), {QStringLiteral("F2"),      QStringLiteral("Home+A"), Qt::WidgetWithChildrenShortcut}},      {QStringLiteral("Load File"),                QStringLiteral("Main Window"), {QStringLiteral("Ctrl+O"),  QStringLiteral(""), Qt::WidgetWithChildrenShortcut}}, +    {QStringLiteral("Load/Remove Amiibo"),       QStringLiteral("Main Window"), {QStringLiteral("F2"),      QStringLiteral("Home+A"), Qt::WidgetWithChildrenShortcut}},      {QStringLiteral("Restart Emulation"),        QStringLiteral("Main Window"), {QStringLiteral("F6"),      QStringLiteral(""), Qt::WindowShortcut}},      {QStringLiteral("Stop Emulation"),           QStringLiteral("Main Window"), {QStringLiteral("F5"),      QStringLiteral(""), Qt::WindowShortcut}}, -    {QStringLiteral("TAS Start/Stop"),           QStringLiteral("Main Window"), {QStringLiteral("Ctrl+F5"), QStringLiteral(""), Qt::ApplicationShortcut}}, -    {QStringLiteral("TAS Reset"),                QStringLiteral("Main Window"), {QStringLiteral("Ctrl+F6"), QStringLiteral(""), Qt::ApplicationShortcut}},      {QStringLiteral("TAS Record"),               QStringLiteral("Main Window"), {QStringLiteral("Ctrl+F7"), QStringLiteral(""), Qt::ApplicationShortcut}}, +    {QStringLiteral("TAS Reset"),                QStringLiteral("Main Window"), {QStringLiteral("Ctrl+F6"), QStringLiteral(""), Qt::ApplicationShortcut}}, +    {QStringLiteral("TAS Start/Stop"),           QStringLiteral("Main Window"), {QStringLiteral("Ctrl+F5"), QStringLiteral(""), Qt::ApplicationShortcut}},      {QStringLiteral("Toggle Filter Bar"),        QStringLiteral("Main Window"), {QStringLiteral("Ctrl+F"),  QStringLiteral(""), Qt::WindowShortcut}},      {QStringLiteral("Toggle Framerate Limit"),   QStringLiteral("Main Window"), {QStringLiteral("Ctrl+U"),  QStringLiteral("Home+Y"), Qt::ApplicationShortcut}},      {QStringLiteral("Toggle Mouse Panning"),     QStringLiteral("Main Window"), {QStringLiteral("Ctrl+F9"), QStringLiteral(""), Qt::ApplicationShortcut}}, @@ -443,6 +445,7 @@ void Config::ReadCoreValues() {      qt_config->beginGroup(QStringLiteral("Core"));      ReadGlobalSetting(Settings::values.use_multi_core); +    ReadGlobalSetting(Settings::values.use_extended_memory_layout);      qt_config->endGroup();  } @@ -606,6 +609,7 @@ void Config::ReadCpuValues() {      ReadGlobalSetting(Settings::values.cpuopt_unsafe_ignore_standard_fpcr);      ReadGlobalSetting(Settings::values.cpuopt_unsafe_inaccurate_nan);      ReadGlobalSetting(Settings::values.cpuopt_unsafe_fastmem_check); +    ReadGlobalSetting(Settings::values.cpuopt_unsafe_ignore_global_monitor);      if (global) {          ReadBasicSetting(Settings::values.cpu_debug_mode); @@ -618,6 +622,8 @@ void Config::ReadCpuValues() {          ReadBasicSetting(Settings::values.cpuopt_misc_ir);          ReadBasicSetting(Settings::values.cpuopt_reduce_misalign_checks);          ReadBasicSetting(Settings::values.cpuopt_fastmem); +        ReadBasicSetting(Settings::values.cpuopt_fastmem_exclusives); +        ReadBasicSetting(Settings::values.cpuopt_recompile_exclusives);      }      qt_config->endGroup(); @@ -767,6 +773,7 @@ void Config::ReadUIValues() {      ReadBasicSetting(UISettings::values.callout_flags);      ReadBasicSetting(UISettings::values.show_console);      ReadBasicSetting(UISettings::values.pause_when_in_background); +    ReadBasicSetting(UISettings::values.mute_when_in_background);      ReadBasicSetting(UISettings::values.hide_mouse);      qt_config->endGroup(); @@ -1016,6 +1023,7 @@ void Config::SaveCoreValues() {      qt_config->beginGroup(QStringLiteral("Core"));      WriteGlobalSetting(Settings::values.use_multi_core); +    WriteGlobalSetting(Settings::values.use_extended_memory_layout);      qt_config->endGroup();  } @@ -1134,6 +1142,7 @@ void Config::SaveCpuValues() {      WriteGlobalSetting(Settings::values.cpuopt_unsafe_ignore_standard_fpcr);      WriteGlobalSetting(Settings::values.cpuopt_unsafe_inaccurate_nan);      WriteGlobalSetting(Settings::values.cpuopt_unsafe_fastmem_check); +    WriteGlobalSetting(Settings::values.cpuopt_unsafe_ignore_global_monitor);      if (global) {          WriteBasicSetting(Settings::values.cpu_debug_mode); @@ -1146,6 +1155,8 @@ void Config::SaveCpuValues() {          WriteBasicSetting(Settings::values.cpuopt_misc_ir);          WriteBasicSetting(Settings::values.cpuopt_reduce_misalign_checks);          WriteBasicSetting(Settings::values.cpuopt_fastmem); +        WriteBasicSetting(Settings::values.cpuopt_fastmem_exclusives); +        WriteBasicSetting(Settings::values.cpuopt_recompile_exclusives);      }      qt_config->endGroup(); @@ -1295,6 +1306,7 @@ void Config::SaveUIValues() {      WriteBasicSetting(UISettings::values.callout_flags);      WriteBasicSetting(UISettings::values.show_console);      WriteBasicSetting(UISettings::values.pause_when_in_background); +    WriteBasicSetting(UISettings::values.mute_when_in_background);      WriteBasicSetting(UISettings::values.hide_mouse);      qt_config->endGroup(); diff --git a/src/yuzu/configuration/config.h b/src/yuzu/configuration/config.h index 60b20a62f..ae3e36a11 100644 --- a/src/yuzu/configuration/config.h +++ b/src/yuzu/configuration/config.h @@ -46,7 +46,7 @@ public:          default_mouse_buttons;      static const std::array<int, Settings::NativeKeyboard::NumKeyboardKeys> default_keyboard_keys;      static const std::array<int, Settings::NativeKeyboard::NumKeyboardMods> default_keyboard_mods; -    static const std::array<UISettings::Shortcut, 20> default_hotkeys; +    static const std::array<UISettings::Shortcut, 22> default_hotkeys;      static constexpr UISettings::Theme default_theme{  #ifdef _WIN32 diff --git a/src/yuzu/configuration/configure_cpu.cpp b/src/yuzu/configuration/configure_cpu.cpp index f66cab5d4..bf74ccc7c 100644 --- a/src/yuzu/configuration/configure_cpu.cpp +++ b/src/yuzu/configuration/configure_cpu.cpp @@ -36,6 +36,7 @@ void ConfigureCpu::SetConfiguration() {      ui->cpuopt_unsafe_ignore_standard_fpcr->setEnabled(runtime_lock);      ui->cpuopt_unsafe_inaccurate_nan->setEnabled(runtime_lock);      ui->cpuopt_unsafe_fastmem_check->setEnabled(runtime_lock); +    ui->cpuopt_unsafe_ignore_global_monitor->setEnabled(runtime_lock);      ui->cpuopt_unsafe_unfuse_fma->setChecked(Settings::values.cpuopt_unsafe_unfuse_fma.GetValue());      ui->cpuopt_unsafe_reduce_fp_error->setChecked( @@ -46,6 +47,8 @@ void ConfigureCpu::SetConfiguration() {          Settings::values.cpuopt_unsafe_inaccurate_nan.GetValue());      ui->cpuopt_unsafe_fastmem_check->setChecked(          Settings::values.cpuopt_unsafe_fastmem_check.GetValue()); +    ui->cpuopt_unsafe_ignore_global_monitor->setChecked( +        Settings::values.cpuopt_unsafe_ignore_global_monitor.GetValue());      if (Settings::IsConfiguringGlobal()) {          ui->accuracy->setCurrentIndex(static_cast<int>(Settings::values.cpu_accuracy.GetValue())); @@ -82,6 +85,9 @@ void ConfigureCpu::ApplyConfiguration() {      ConfigurationShared::ApplyPerGameSetting(&Settings::values.cpuopt_unsafe_fastmem_check,                                               ui->cpuopt_unsafe_fastmem_check,                                               cpuopt_unsafe_fastmem_check); +    ConfigurationShared::ApplyPerGameSetting(&Settings::values.cpuopt_unsafe_ignore_global_monitor, +                                             ui->cpuopt_unsafe_ignore_global_monitor, +                                             cpuopt_unsafe_ignore_global_monitor);  }  void ConfigureCpu::changeEvent(QEvent* event) { @@ -120,4 +126,7 @@ void ConfigureCpu::SetupPerGameUI() {      ConfigurationShared::SetColoredTristate(ui->cpuopt_unsafe_fastmem_check,                                              Settings::values.cpuopt_unsafe_fastmem_check,                                              cpuopt_unsafe_fastmem_check); +    ConfigurationShared::SetColoredTristate(ui->cpuopt_unsafe_ignore_global_monitor, +                                            Settings::values.cpuopt_unsafe_ignore_global_monitor, +                                            cpuopt_unsafe_ignore_global_monitor);  } diff --git a/src/yuzu/configuration/configure_cpu.h b/src/yuzu/configuration/configure_cpu.h index ed9af0e9f..733e38be4 100644 --- a/src/yuzu/configuration/configure_cpu.h +++ b/src/yuzu/configuration/configure_cpu.h @@ -45,6 +45,7 @@ private:      ConfigurationShared::CheckState cpuopt_unsafe_ignore_standard_fpcr;      ConfigurationShared::CheckState cpuopt_unsafe_inaccurate_nan;      ConfigurationShared::CheckState cpuopt_unsafe_fastmem_check; +    ConfigurationShared::CheckState cpuopt_unsafe_ignore_global_monitor;      const Core::System& system;  }; diff --git a/src/yuzu/configuration/configure_cpu.ui b/src/yuzu/configuration/configure_cpu.ui index d8064db24..5d80a8c91 100644 --- a/src/yuzu/configuration/configure_cpu.ui +++ b/src/yuzu/configuration/configure_cpu.ui @@ -150,6 +150,18 @@            </property>           </widget>          </item> +        <item> +         <widget class="QCheckBox" name="cpuopt_unsafe_ignore_global_monitor"> +          <property name="toolTip"> +           <string> +            <div>This option improves speed by relying only on the semantics of cmpxchg to ensure safety of exclusive access instructions. Please note this may result in deadlocks and other race conditions.</div> +           </string> +          </property> +          <property name="text"> +           <string>Ignore global monitor</string> +          </property> +         </widget> +        </item>         </layout>        </widget>       </item> diff --git a/src/yuzu/configuration/configure_cpu_debug.cpp b/src/yuzu/configuration/configure_cpu_debug.cpp index 05a90963d..616a0be75 100644 --- a/src/yuzu/configuration/configure_cpu_debug.cpp +++ b/src/yuzu/configuration/configure_cpu_debug.cpp @@ -44,6 +44,12 @@ void ConfigureCpuDebug::SetConfiguration() {          Settings::values.cpuopt_reduce_misalign_checks.GetValue());      ui->cpuopt_fastmem->setEnabled(runtime_lock);      ui->cpuopt_fastmem->setChecked(Settings::values.cpuopt_fastmem.GetValue()); +    ui->cpuopt_fastmem_exclusives->setEnabled(runtime_lock); +    ui->cpuopt_fastmem_exclusives->setChecked( +        Settings::values.cpuopt_fastmem_exclusives.GetValue()); +    ui->cpuopt_recompile_exclusives->setEnabled(runtime_lock); +    ui->cpuopt_recompile_exclusives->setChecked( +        Settings::values.cpuopt_recompile_exclusives.GetValue());  }  void ConfigureCpuDebug::ApplyConfiguration() { @@ -56,6 +62,8 @@ void ConfigureCpuDebug::ApplyConfiguration() {      Settings::values.cpuopt_misc_ir = ui->cpuopt_misc_ir->isChecked();      Settings::values.cpuopt_reduce_misalign_checks = ui->cpuopt_reduce_misalign_checks->isChecked();      Settings::values.cpuopt_fastmem = ui->cpuopt_fastmem->isChecked(); +    Settings::values.cpuopt_fastmem_exclusives = ui->cpuopt_fastmem_exclusives->isChecked(); +    Settings::values.cpuopt_recompile_exclusives = ui->cpuopt_recompile_exclusives->isChecked();  }  void ConfigureCpuDebug::changeEvent(QEvent* event) { diff --git a/src/yuzu/configuration/configure_cpu_debug.ui b/src/yuzu/configuration/configure_cpu_debug.ui index 6e635bb2f..2bc268810 100644 --- a/src/yuzu/configuration/configure_cpu_debug.ui +++ b/src/yuzu/configuration/configure_cpu_debug.ui @@ -144,7 +144,34 @@             </string>            </property>            <property name="text"> -           <string>Enable Host MMU Emulation</string> +           <string>Enable Host MMU Emulation (general memory instructions)</string> +          </property> +         </widget> +        </item> +        <item> +         <widget class="QCheckBox" name="cpuopt_fastmem_exclusives"> +          <property name="toolTip"> +           <string> +            <div style="white-space: nowrap">This optimization speeds up exclusive memory accesses by the guest program.</div> +            <div style="white-space: nowrap">Enabling it causes guest exclusive memory reads/writes to be done directly into memory and make use of Host's MMU.</div> +            <div style="white-space: nowrap">Disabling this forces all exclusive memory accesses to use Software MMU Emulation.</div> +           </string> +          </property> +          <property name="text"> +           <string>Enable Host MMU Emulation (exclusive memory instructions)</string> +          </property> +         </widget> +        </item> +        <item> +         <widget class="QCheckBox" name="cpuopt_recompile_exclusives"> +          <property name="toolTip"> +           <string> +            <div style="white-space: nowrap">This optimization speeds up exclusive memory accesses by the guest program.</div> +            <div style="white-space: nowrap">Enabling it reduces the overhead of fastmem failure of exclusive memory accesses.</div> +           </string> +          </property> +          <property name="text"> +           <string>Enable recompilation of exclusive memory instructions</string>            </property>           </widget>          </item> diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp index 464e7a489..19133ccf5 100644 --- a/src/yuzu/configuration/configure_dialog.cpp +++ b/src/yuzu/configuration/configure_dialog.cpp @@ -109,7 +109,7 @@ void ConfigureDialog::ApplyConfiguration() {      ui_tab->ApplyConfiguration();      system_tab->ApplyConfiguration();      profile_tab->ApplyConfiguration(); -    filesystem_tab->applyConfiguration(); +    filesystem_tab->ApplyConfiguration();      input_tab->ApplyConfiguration();      hotkeys_tab->ApplyConfiguration(registry);      cpu_tab->ApplyConfiguration(); diff --git a/src/yuzu/configuration/configure_filesystem.cpp b/src/yuzu/configuration/configure_filesystem.cpp index 9cb317822..d6fb43f8b 100644 --- a/src/yuzu/configuration/configure_filesystem.cpp +++ b/src/yuzu/configuration/configure_filesystem.cpp @@ -14,7 +14,7 @@  ConfigureFilesystem::ConfigureFilesystem(QWidget* parent)      : QWidget(parent), ui(std::make_unique<Ui::ConfigureFilesystem>()) {      ui->setupUi(this); -    this->setConfiguration(); +    SetConfiguration();      connect(ui->nand_directory_button, &QToolButton::pressed, this,              [this] { SetDirectory(DirectoryTarget::NAND, ui->nand_directory_edit); }); @@ -38,7 +38,15 @@ ConfigureFilesystem::ConfigureFilesystem(QWidget* parent)  ConfigureFilesystem::~ConfigureFilesystem() = default; -void ConfigureFilesystem::setConfiguration() { +void ConfigureFilesystem::changeEvent(QEvent* event) { +    if (event->type() == QEvent::LanguageChange) { +        RetranslateUI(); +    } + +    QWidget::changeEvent(event); +} + +void ConfigureFilesystem::SetConfiguration() {      ui->nand_directory_edit->setText(          QString::fromStdString(Common::FS::GetYuzuPathString(Common::FS::YuzuPath::NANDDir)));      ui->sdmc_directory_edit->setText( @@ -60,7 +68,7 @@ void ConfigureFilesystem::setConfiguration() {      UpdateEnabledControls();  } -void ConfigureFilesystem::applyConfiguration() { +void ConfigureFilesystem::ApplyConfiguration() {      Common::FS::SetYuzuPath(Common::FS::YuzuPath::NANDDir,                              ui->nand_directory_edit->text().toStdString());      Common::FS::SetYuzuPath(Common::FS::YuzuPath::SDMCDir, @@ -143,6 +151,6 @@ void ConfigureFilesystem::UpdateEnabledControls() {                                           !ui->gamecard_current_game->isChecked());  } -void ConfigureFilesystem::retranslateUi() { +void ConfigureFilesystem::RetranslateUI() {      ui->retranslateUi(this);  } diff --git a/src/yuzu/configuration/configure_filesystem.h b/src/yuzu/configuration/configure_filesystem.h index 2147cd405..b4f9355eb 100644 --- a/src/yuzu/configuration/configure_filesystem.h +++ b/src/yuzu/configuration/configure_filesystem.h @@ -20,11 +20,13 @@ public:      explicit ConfigureFilesystem(QWidget* parent = nullptr);      ~ConfigureFilesystem() override; -    void applyConfiguration(); -    void retranslateUi(); +    void ApplyConfiguration();  private: -    void setConfiguration(); +    void changeEvent(QEvent* event) override; + +    void RetranslateUI(); +    void SetConfiguration();      enum class DirectoryTarget {          NAND, diff --git a/src/yuzu/configuration/configure_general.cpp b/src/yuzu/configuration/configure_general.cpp index 566879317..08d5444ec 100644 --- a/src/yuzu/configuration/configure_general.cpp +++ b/src/yuzu/configuration/configure_general.cpp @@ -42,10 +42,14 @@ void ConfigureGeneral::SetConfiguration() {      ui->use_multi_core->setEnabled(runtime_lock);      ui->use_multi_core->setChecked(Settings::values.use_multi_core.GetValue()); +    ui->use_extended_memory_layout->setEnabled(runtime_lock); +    ui->use_extended_memory_layout->setChecked( +        Settings::values.use_extended_memory_layout.GetValue());      ui->toggle_check_exit->setChecked(UISettings::values.confirm_before_closing.GetValue());      ui->toggle_user_on_boot->setChecked(UISettings::values.select_user_on_boot.GetValue());      ui->toggle_background_pause->setChecked(UISettings::values.pause_when_in_background.GetValue()); +    ui->toggle_background_mute->setChecked(UISettings::values.mute_when_in_background.GetValue());      ui->toggle_hide_mouse->setChecked(UISettings::values.hide_mouse.GetValue());      ui->toggle_speed_limit->setChecked(Settings::values.use_speed_limit.GetValue()); @@ -90,11 +94,15 @@ void ConfigureGeneral::ResetDefaults() {  void ConfigureGeneral::ApplyConfiguration() {      ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_multi_core, ui->use_multi_core,                                               use_multi_core); +    ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_extended_memory_layout, +                                             ui->use_extended_memory_layout, +                                             use_extended_memory_layout);      if (Settings::IsConfiguringGlobal()) {          UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked();          UISettings::values.select_user_on_boot = ui->toggle_user_on_boot->isChecked();          UISettings::values.pause_when_in_background = ui->toggle_background_pause->isChecked(); +        UISettings::values.mute_when_in_background = ui->toggle_background_mute->isChecked();          UISettings::values.hide_mouse = ui->toggle_hide_mouse->isChecked();          Settings::values.fps_cap.SetValue(ui->fps_cap->value()); @@ -158,6 +166,9 @@ void ConfigureGeneral::SetupPerGameUI() {                                              Settings::values.use_speed_limit, use_speed_limit);      ConfigurationShared::SetColoredTristate(ui->use_multi_core, Settings::values.use_multi_core,                                              use_multi_core); +    ConfigurationShared::SetColoredTristate(ui->use_extended_memory_layout, +                                            Settings::values.use_extended_memory_layout, +                                            use_extended_memory_layout);      connect(ui->toggle_speed_limit, &QCheckBox::clicked, ui->speed_limit, [this]() {          ui->speed_limit->setEnabled(ui->toggle_speed_limit->isChecked() && diff --git a/src/yuzu/configuration/configure_general.h b/src/yuzu/configuration/configure_general.h index 85c1dd4a8..b6f3bb5ed 100644 --- a/src/yuzu/configuration/configure_general.h +++ b/src/yuzu/configuration/configure_general.h @@ -48,6 +48,7 @@ private:      ConfigurationShared::CheckState use_speed_limit;      ConfigurationShared::CheckState use_multi_core; +    ConfigurationShared::CheckState use_extended_memory_layout;      const Core::System& system;  }; diff --git a/src/yuzu/configuration/configure_general.ui b/src/yuzu/configuration/configure_general.ui index 112dc72b3..c6ef2ab70 100644 --- a/src/yuzu/configuration/configure_general.ui +++ b/src/yuzu/configuration/configure_general.ui @@ -143,6 +143,13 @@             </widget>            </item>            <item> +           <widget class="QCheckBox" name="use_extended_memory_layout"> +            <property name="text"> +             <string>Extended memory layout (6GB DRAM)</string> +            </property> +           </widget> +          </item> +          <item>             <widget class="QCheckBox" name="toggle_check_exit">              <property name="text">               <string>Confirm exit while emulation is running</string> @@ -164,6 +171,13 @@             </widget>            </item>            <item> +           <widget class="QCheckBox" name="toggle_background_mute"> +            <property name="text"> +             <string>Mute audio when in background</string> +            </property> +           </widget> +          </item> +          <item>             <widget class="QCheckBox" name="toggle_hide_mouse">              <property name="text">               <string>Hide mouse on inactivity</string> diff --git a/src/yuzu/configuration/configure_hotkeys.cpp b/src/yuzu/configuration/configure_hotkeys.cpp index be10e0a31..53e629a5e 100644 --- a/src/yuzu/configuration/configure_hotkeys.cpp +++ b/src/yuzu/configuration/configure_hotkeys.cpp @@ -178,52 +178,52 @@ void ConfigureHotkeys::SetPollingResult(Core::HID::NpadButton button, const bool  QString ConfigureHotkeys::GetButtonName(Core::HID::NpadButton button) const {      Core::HID::NpadButtonState state{button};      if (state.a) { -        return tr("A"); +        return QStringLiteral("A");      }      if (state.b) { -        return tr("B"); +        return QStringLiteral("B");      }      if (state.x) { -        return tr("X"); +        return QStringLiteral("X");      }      if (state.y) { -        return tr("Y"); +        return QStringLiteral("Y");      }      if (state.l || state.right_sl || state.left_sl) { -        return tr("L"); +        return QStringLiteral("L");      }      if (state.r || state.right_sr || state.left_sr) { -        return tr("R"); +        return QStringLiteral("R");      }      if (state.zl) { -        return tr("ZL"); +        return QStringLiteral("ZL");      }      if (state.zr) { -        return tr("ZR"); +        return QStringLiteral("ZR");      }      if (state.left) { -        return tr("Dpad_Left"); +        return QStringLiteral("Dpad_Left");      }      if (state.right) { -        return tr("Dpad_Right"); +        return QStringLiteral("Dpad_Right");      }      if (state.up) { -        return tr("Dpad_Up"); +        return QStringLiteral("Dpad_Up");      }      if (state.down) { -        return tr("Dpad_Down"); +        return QStringLiteral("Dpad_Down");      }      if (state.stick_l) { -        return tr("Left_Stick"); +        return QStringLiteral("Left_Stick");      }      if (state.stick_r) { -        return tr("Right_Stick"); +        return QStringLiteral("Right_Stick");      }      if (state.minus) { -        return tr("Minus"); +        return QStringLiteral("Minus");      }      if (state.plus) { -        return tr("Plus"); +        return QStringLiteral("Plus");      }      return tr("Invalid");  } diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp index d53179dbb..7c5776189 100644 --- a/src/yuzu/configuration/configure_input.cpp +++ b/src/yuzu/configuration/configure_input.cpp @@ -164,7 +164,7 @@ void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem,              });      connect(ui->vibrationButton, &QPushButton::clicked, -            [this] { CallConfigureDialog<ConfigureVibration>(*this); }); +            [this, &hid_core] { CallConfigureDialog<ConfigureVibration>(*this, hid_core); });      connect(ui->motionButton, &QPushButton::clicked, [this, input_subsystem] {          CallConfigureDialog<ConfigureMotionTouch>(*this, input_subsystem); diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index 752504236..0aa4ac3e4 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp @@ -102,6 +102,10 @@ QString GetButtonName(Common::Input::ButtonNames button_name) {          return QObject::tr("Share");      case Common::Input::ButtonNames::Options:          return QObject::tr("Options"); +    case Common::Input::ButtonNames::Home: +        return QObject::tr("Home"); +    case Common::Input::ButtonNames::Touch: +        return QObject::tr("Touch");      case Common::Input::ButtonNames::ButtonMouseWheel:          return QObject::tr("Wheel", "Indicates the mouse wheel");      case Common::Input::ButtonNames::ButtonBackward: @@ -326,7 +330,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i          connect(button, &QPushButton::clicked, [=, this] {              HandleClick(                  button, button_id, -                [=, this](Common::ParamPackage params) { +                [=, this](const Common::ParamPackage& params) {                      emulated_controller->SetButtonParam(button_id, params);                  },                  InputCommon::Polling::InputType::Button); @@ -392,7 +396,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i          connect(button, &QPushButton::clicked, [=, this] {              HandleClick(                  button, motion_id, -                [=, this](Common::ParamPackage params) { +                [=, this](const Common::ParamPackage& params) {                      emulated_controller->SetMotionParam(motion_id, params);                  },                  InputCommon::Polling::InputType::Motion); @@ -484,6 +488,32 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i                              emulated_controller->SetStickParam(analog_id, {});                              analog_map_buttons[analog_id][sub_button_id]->setText(tr("[not set]"));                          }); +                        context_menu.addAction(tr("Center axis"), [&] { +                            const auto stick_value = +                                emulated_controller->GetSticksValues()[analog_id]; +                            const float offset_x = stick_value.x.properties.offset; +                            const float offset_y = stick_value.y.properties.offset; +                            float raw_value_x = stick_value.x.raw_value; +                            float raw_value_y = stick_value.y.raw_value; +                            // See Core::HID::SanitizeStick() to obtain the original raw axis value +                            if (std::abs(offset_x) < 0.5f) { +                                if (raw_value_x > 0) { +                                    raw_value_x *= 1 + offset_x; +                                } else { +                                    raw_value_x *= 1 - offset_x; +                                } +                            } +                            if (std::abs(offset_x) < 0.5f) { +                                if (raw_value_y > 0) { +                                    raw_value_y *= 1 + offset_y; +                                } else { +                                    raw_value_y *= 1 - offset_y; +                                } +                            } +                            param.Set("offset_x", -raw_value_x + offset_x); +                            param.Set("offset_y", -raw_value_y + offset_y); +                            emulated_controller->SetStickParam(analog_id, param); +                        });                          context_menu.addAction(tr("Invert axis"), [&] {                              if (sub_button_id == 2 || sub_button_id == 3) {                                  const bool invert_value = param.Get("invert_x", "+") == "-"; @@ -497,10 +527,11 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i                                  param.Set("invert_y", invert_str);                                  emulated_controller->SetStickParam(analog_id, param);                              } -                            for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; -                                 ++sub_button_id) { -                                analog_map_buttons[analog_id][sub_button_id]->setText( -                                    AnalogToText(param, analog_sub_buttons[sub_button_id])); +                            for (int analog_sub_button_id = 0; +                                 analog_sub_button_id < ANALOG_SUB_BUTTONS_NUM; +                                 ++analog_sub_button_id) { +                                analog_map_buttons[analog_id][analog_sub_button_id]->setText( +                                    AnalogToText(param, analog_sub_buttons[analog_sub_button_id]));                              }                          });                          context_menu.exec(analog_map_buttons[analog_id][sub_button_id]->mapToGlobal( @@ -783,7 +814,7 @@ void ConfigureInputPlayer::UpdateInputDeviceCombobox() {      if (devices.size() == 1) {          const auto devices_it = std::find_if(              input_devices.begin(), input_devices.end(), -            [first_engine, first_guid, first_port, first_pad](const Common::ParamPackage param) { +            [first_engine, first_guid, first_port, first_pad](const Common::ParamPackage& param) {                  return param.Get("engine", "") == first_engine &&                         param.Get("guid", "") == first_guid && param.Get("port", 0) == first_port &&                         param.Get("pad", 0) == first_pad; @@ -814,7 +845,7 @@ void ConfigureInputPlayer::UpdateInputDeviceCombobox() {      if (is_engine_equal && is_port_equal) {          const auto devices_it = std::find_if(              input_devices.begin(), input_devices.end(), -            [first_engine, first_guid, second_guid, first_port](const Common::ParamPackage param) { +            [first_engine, first_guid, second_guid, first_port](const Common::ParamPackage& param) {                  const bool is_guid_valid =                      (param.Get("guid", "") == first_guid &&                       param.Get("guid2", "") == second_guid) || @@ -1026,7 +1057,7 @@ int ConfigureInputPlayer::GetIndexFromControllerType(Core::HID::NpadStyleIndex t  void ConfigureInputPlayer::UpdateInputDevices() {      input_devices = input_subsystem->GetInputDevices();      ui->comboDevices->clear(); -    for (auto device : input_devices) { +    for (const auto& device : input_devices) {          ui->comboDevices->addItem(QString::fromStdString(device.Get("display", "Unknown")), {});      }  } @@ -1301,6 +1332,9 @@ void ConfigureInputPlayer::HandleClick(      QPushButton* button, std::size_t button_id,      std::function<void(const Common::ParamPackage&)> new_input_setter,      InputCommon::Polling::InputType type) { +    if (timeout_timer->isActive()) { +        return; +    }      if (button == ui->buttonMotionLeft || button == ui->buttonMotionRight) {          button->setText(tr("Shake!"));      } else { @@ -1308,7 +1342,7 @@ void ConfigureInputPlayer::HandleClick(      }      button->setFocus(); -    input_setter = new_input_setter; +    input_setter = std::move(new_input_setter);      input_subsystem->BeginMapping(type); @@ -1358,7 +1392,7 @@ bool ConfigureInputPlayer::IsInputAcceptable(const Common::ParamPackage& params)          return params.Get("engine", "") == "keyboard" || params.Get("engine", "") == "mouse";      } -    const auto current_input_device = input_devices[ui->comboDevices->currentIndex()]; +    const auto& current_input_device = input_devices[ui->comboDevices->currentIndex()];      return params.Get("engine", "") == current_input_device.Get("engine", "") &&             (params.Get("guid", "") == current_input_device.Get("guid", "") ||              params.Get("guid", "") == current_input_device.Get("guid2", "")) && diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp index 6630321cb..fb168b2ca 100644 --- a/src/yuzu/configuration/configure_input_player_widget.cpp +++ b/src/yuzu/configuration/configure_input_player_widget.cpp @@ -70,7 +70,6 @@ void PlayerControlPreview::UpdateColors() {          colors.slider_arrow = QColor(14, 15, 18);          colors.font2 = QColor(255, 255, 255);          colors.indicator = QColor(170, 238, 255); -        colors.indicator2 = QColor(100, 255, 100);          colors.deadzone = QColor(204, 136, 136);          colors.slider_button = colors.button;      } @@ -88,7 +87,6 @@ void PlayerControlPreview::UpdateColors() {          colors.slider_arrow = QColor(65, 68, 73);          colors.font2 = QColor(0, 0, 0);          colors.indicator = QColor(0, 0, 200); -        colors.indicator2 = QColor(0, 150, 0);          colors.deadzone = QColor(170, 0, 0);          colors.slider_button = QColor(153, 149, 149);      } @@ -101,6 +99,8 @@ void PlayerControlPreview::UpdateColors() {      colors.font = QColor(255, 255, 255);      colors.led_on = QColor(255, 255, 0);      colors.led_off = QColor(170, 238, 255); +    colors.indicator2 = QColor(59, 165, 93); +    colors.charging = QColor(250, 168, 26);      colors.left = colors.primary;      colors.right = colors.primary; @@ -357,7 +357,7 @@ void PlayerControlPreview::DrawLeftController(QPainter& p, const QPointF center)      DrawCircle(p, center + QPoint(26, 71), 5);      // Draw battery -    DrawBattery(p, center + QPoint(-170, -140), +    DrawBattery(p, center + QPoint(-160, -140),                  battery_values[Core::HID::EmulatedDeviceIndex::LeftIndex]);  } @@ -484,7 +484,7 @@ void PlayerControlPreview::DrawRightController(QPainter& p, const QPointF center      DrawSymbol(p, center + QPoint(-26, 66), Symbol::House, 5);      // Draw battery -    DrawBattery(p, center + QPoint(110, -140), +    DrawBattery(p, center + QPoint(120, -140),                  battery_values[Core::HID::EmulatedDeviceIndex::RightIndex]);  } @@ -621,9 +621,9 @@ void PlayerControlPreview::DrawDualController(QPainter& p, const QPointF center)      DrawSymbol(p, center + QPoint(50, 60), Symbol::House, 4.2f);      // Draw battery -    DrawBattery(p, center + QPoint(-100, -160), +    DrawBattery(p, center + QPoint(-200, -10),                  battery_values[Core::HID::EmulatedDeviceIndex::LeftIndex]); -    DrawBattery(p, center + QPoint(40, -160), +    DrawBattery(p, center + QPoint(160, -10),                  battery_values[Core::HID::EmulatedDeviceIndex::RightIndex]);  } @@ -694,12 +694,12 @@ void PlayerControlPreview::DrawHandheldController(QPainter& p, const QPointF cen      // ZL and ZR buttons      p.setPen(colors.outline); -    DrawTriggerButton(p, center + QPoint(-210, -130), Direction::Left, button_values[ZL]); -    DrawTriggerButton(p, center + QPoint(210, -130), Direction::Right, button_values[ZR]); +    DrawTriggerButton(p, center + QPoint(-210, -120), Direction::Left, button_values[ZL]); +    DrawTriggerButton(p, center + QPoint(210, -120), Direction::Right, button_values[ZR]);      p.setPen(colors.transparent);      p.setBrush(colors.font); -    DrawSymbol(p, center + QPoint(-210, -130), Symbol::ZL, 1.5f); -    DrawSymbol(p, center + QPoint(210, -130), Symbol::ZR, 1.5f); +    DrawSymbol(p, center + QPoint(-210, -120), Symbol::ZL, 1.5f); +    DrawSymbol(p, center + QPoint(210, -120), Symbol::ZR, 1.5f);      // Minus and Plus button      p.setPen(colors.outline); @@ -725,9 +725,9 @@ void PlayerControlPreview::DrawHandheldController(QPainter& p, const QPointF cen      DrawSymbol(p, center + QPoint(161, 37), Symbol::House, 2.75f);      // Draw battery -    DrawBattery(p, center + QPoint(-200, 110), +    DrawBattery(p, center + QPoint(-188, 95),                  battery_values[Core::HID::EmulatedDeviceIndex::LeftIndex]); -    DrawBattery(p, center + QPoint(130, 110), +    DrawBattery(p, center + QPoint(150, 95),                  battery_values[Core::HID::EmulatedDeviceIndex::RightIndex]);  } @@ -781,12 +781,12 @@ void PlayerControlPreview::DrawProController(QPainter& p, const QPointF center)      // ZL and ZR buttons      p.setPen(colors.outline); -    DrawTriggerButton(p, center + QPoint(-210, -130), Direction::Left, button_values[ZL]); -    DrawTriggerButton(p, center + QPoint(210, -130), Direction::Right, button_values[ZR]); +    DrawTriggerButton(p, center + QPoint(-210, -120), Direction::Left, button_values[ZL]); +    DrawTriggerButton(p, center + QPoint(210, -120), Direction::Right, button_values[ZR]);      p.setPen(colors.transparent);      p.setBrush(colors.font); -    DrawSymbol(p, center + QPoint(-210, -130), Symbol::ZL, 1.5f); -    DrawSymbol(p, center + QPoint(210, -130), Symbol::ZR, 1.5f); +    DrawSymbol(p, center + QPoint(-210, -120), Symbol::ZL, 1.5f); +    DrawSymbol(p, center + QPoint(210, -120), Symbol::ZR, 1.5f);      // Minus and Plus buttons      p.setPen(colors.outline); @@ -818,7 +818,7 @@ void PlayerControlPreview::DrawProController(QPainter& p, const QPointF center)      DrawSymbol(p, center + QPoint(29, -56), Symbol::House, 3.9f);      // Draw battery -    DrawBattery(p, center + QPoint(-30, -160), +    DrawBattery(p, center + QPoint(-20, -160),                  battery_values[Core::HID::EmulatedDeviceIndex::LeftIndex]);  } @@ -875,7 +875,7 @@ void PlayerControlPreview::DrawGCController(QPainter& p, const QPointF center) {      DrawCircleButton(p, center + QPoint(0, -44), button_values[Plus], 8);      // Draw battery -    DrawBattery(p, center + QPoint(-30, -165), +    DrawBattery(p, center + QPoint(-20, 110),                  battery_values[Core::HID::EmulatedDeviceIndex::LeftIndex]);  } @@ -1030,6 +1030,10 @@ constexpr std::array<float, 30 * 2> symbol_c = {      -2.37f, 5.64f,  -0.65f, 6.44f,  1.25f,  6.47f,  3.06f,  5.89f,  4.63f,  4.92f,  4.63f,  6.83f,  }; +constexpr std::array<float, 6 * 2> symbol_charging = { +    6.5f, -1.0f, 1.0f, -1.0f, 1.0f, -3.0f, -6.5f, 1.0f, -1.0f, 1.0f, -1.0f, 3.0f, +}; +  constexpr std::array<float, 12 * 2> house = {      -1.3f, 0.0f,  -0.93f, 0.0f, -0.93f, 1.15f, 0.93f,  1.15f, 0.93f, 0.0f, 1.3f,  0.0f,      0.0f,  -1.2f, -1.3f,  0.0f, -0.43f, 0.0f,  -0.43f, .73f,  0.43f, .73f, 0.43f, 0.0f, @@ -2674,36 +2678,43 @@ void PlayerControlPreview::DrawBattery(QPainter& p, QPointF center,      if (battery == Common::Input::BatteryLevel::None) {          return;      } -    p.setPen(colors.outline); +    // Draw outline +    p.setPen(QPen(colors.button, 5)); +    p.setBrush(colors.transparent); +    p.drawRoundedRect(center.x(), center.y(), 34, 16, 2, 2); + +    p.setPen(QPen(colors.button, 3)); +    p.drawRect(center.x() + 35, center.y() + 4.5f, 4, 7); + +    // Draw Battery shape +    p.setPen(QPen(colors.indicator2, 3));      p.setBrush(colors.transparent); -    p.drawRect(center.x(), center.y(), 56, 20); -    p.drawRect(center.x() + 56, center.y() + 6, 3, 8); -    p.setBrush(colors.deadzone); +    p.drawRoundedRect(center.x(), center.y(), 34, 16, 2, 2); + +    p.setPen(QPen(colors.indicator2, 1)); +    p.setBrush(colors.indicator2); +    p.drawRect(center.x() + 35, center.y() + 4.5f, 4, 7);      switch (battery) {      case Common::Input::BatteryLevel::Charging: -        p.setBrush(colors.indicator2); -        p.drawText(center + QPoint(2, 14), tr("Charging")); +        p.drawRect(center.x(), center.y(), 34, 16); +        p.setPen(colors.slider); +        p.setBrush(colors.charging); +        DrawSymbol(p, center + QPointF(17.0f, 8.0f), Symbol::Charging, 2.1f);          break;      case Common::Input::BatteryLevel::Full: -        p.drawRect(center.x() + 42, center.y(), 14, 20); -        p.drawRect(center.x() + 28, center.y(), 14, 20); -        p.drawRect(center.x() + 14, center.y(), 14, 20); -        p.drawRect(center.x(), center.y(), 14, 20); +        p.drawRect(center.x(), center.y(), 34, 16);          break;      case Common::Input::BatteryLevel::Medium: -        p.drawRect(center.x() + 28, center.y(), 14, 20); -        p.drawRect(center.x() + 14, center.y(), 14, 20); -        p.drawRect(center.x(), center.y(), 14, 20); +        p.drawRect(center.x(), center.y(), 25, 16);          break;      case Common::Input::BatteryLevel::Low: -        p.drawRect(center.x() + 14, center.y(), 14, 20); -        p.drawRect(center.x(), center.y(), 14, 20); +        p.drawRect(center.x(), center.y(), 17, 16);          break;      case Common::Input::BatteryLevel::Critical: -        p.drawRect(center.x(), center.y(), 14, 20); +        p.drawRect(center.x(), center.y(), 6, 16);          break;      case Common::Input::BatteryLevel::Empty: -        p.drawRect(center.x(), center.y(), 5, 20); +        p.drawRect(center.x(), center.y(), 3, 16);          break;      default:          break; @@ -2724,6 +2735,7 @@ void PlayerControlPreview::DrawSymbol(QPainter& p, const QPointF center, Symbol      std::array<QPointF, symbol_sl.size() / 2> sl_icon;      std::array<QPointF, symbol_zr.size() / 2> zr_icon;      std::array<QPointF, symbol_sr.size() / 2> sr_icon; +    std::array<QPointF, symbol_charging.size() / 2> charging_icon;      switch (symbol) {      case Symbol::House:          for (std::size_t point = 0; point < house.size() / 2; ++point) { @@ -2809,6 +2821,13 @@ void PlayerControlPreview::DrawSymbol(QPainter& p, const QPointF center, Symbol          }          p.drawPolygon(sr_icon.data(), static_cast<int>(sr_icon.size()));          break; +    case Symbol::Charging: +        for (std::size_t point = 0; point < symbol_charging.size() / 2; ++point) { +            charging_icon[point] = center + QPointF(symbol_charging[point * 2] * icon_size, +                                                    symbol_charging[point * 2 + 1] * icon_size); +        } +        p.drawPolygon(charging_icon.data(), static_cast<int>(charging_icon.size())); +        break;      }  } diff --git a/src/yuzu/configuration/configure_input_player_widget.h b/src/yuzu/configuration/configure_input_player_widget.h index 4cd5c3be0..3582ef77a 100644 --- a/src/yuzu/configuration/configure_input_player_widget.h +++ b/src/yuzu/configuration/configure_input_player_widget.h @@ -72,6 +72,7 @@ private:          ZL,          ZR,          SR, +        Charging,      };      struct ColorMapping { @@ -94,6 +95,7 @@ private:          QColor slider_button{};          QColor slider_arrow{};          QColor deadzone{}; +        QColor charging{};      };      void UpdateColors(); diff --git a/src/yuzu/configuration/configure_motion_touch.cpp b/src/yuzu/configuration/configure_motion_touch.cpp index 8539a5c8b..4340de304 100644 --- a/src/yuzu/configuration/configure_motion_touch.cpp +++ b/src/yuzu/configuration/configure_motion_touch.cpp @@ -42,23 +42,25 @@ CalibrationConfigurationDialog::CalibrationConfigurationDialog(QWidget* parent,      job = std::make_unique<CalibrationConfigurationJob>(          host, port,          [this](CalibrationConfigurationJob::Status status) { -            QString text; -            switch (status) { -            case CalibrationConfigurationJob::Status::Ready: -                text = tr("Touch the top left corner <br>of your touchpad."); -                break; -            case CalibrationConfigurationJob::Status::Stage1Completed: -                text = tr("Now touch the bottom right corner <br>of your touchpad."); -                break; -            case CalibrationConfigurationJob::Status::Completed: -                text = tr("Configuration completed!"); -                break; -            default: -                break; -            } -            QMetaObject::invokeMethod(this, "UpdateLabelText", Q_ARG(QString, text)); +            QMetaObject::invokeMethod(this, [status, this] { +                QString text; +                switch (status) { +                case CalibrationConfigurationJob::Status::Ready: +                    text = tr("Touch the top left corner <br>of your touchpad."); +                    break; +                case CalibrationConfigurationJob::Status::Stage1Completed: +                    text = tr("Now touch the bottom right corner <br>of your touchpad."); +                    break; +                case CalibrationConfigurationJob::Status::Completed: +                    text = tr("Configuration completed!"); +                    break; +                default: +                    break; +                } +                UpdateLabelText(text); +            });              if (status == CalibrationConfigurationJob::Status::Completed) { -                QMetaObject::invokeMethod(this, "UpdateButtonText", Q_ARG(QString, tr("OK"))); +                QMetaObject::invokeMethod(this, [this] { UpdateButtonText(tr("OK")); });              }          },          [this](u16 min_x_, u16 min_y_, u16 max_x_, u16 max_y_) { @@ -215,11 +217,11 @@ void ConfigureMotionTouch::OnCemuhookUDPTest() {          ui->udp_server->text().toStdString(), static_cast<u16>(ui->udp_port->text().toInt()),          [this] {              LOG_INFO(Frontend, "UDP input test success"); -            QMetaObject::invokeMethod(this, "ShowUDPTestResult", Q_ARG(bool, true)); +            QMetaObject::invokeMethod(this, [this] { ShowUDPTestResult(true); });          },          [this] {              LOG_ERROR(Frontend, "UDP input test failed"); -            QMetaObject::invokeMethod(this, "ShowUDPTestResult", Q_ARG(bool, false)); +            QMetaObject::invokeMethod(this, [this] { ShowUDPTestResult(false); });          });  } diff --git a/src/yuzu/configuration/configure_profile_manager.cpp b/src/yuzu/configuration/configure_profile_manager.cpp index 78b6374c0..d9f6dee4e 100644 --- a/src/yuzu/configuration/configure_profile_manager.cpp +++ b/src/yuzu/configuration/configure_profile_manager.cpp @@ -33,10 +33,10 @@ constexpr std::array<u8, 107> backup_jpeg{      0x01, 0x01, 0x00, 0x00, 0x3f, 0x00, 0xd2, 0xcf, 0x20, 0xff, 0xd9,  }; -QString GetImagePath(Common::UUID uuid) { +QString GetImagePath(const Common::UUID& uuid) {      const auto path =          Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir) / -        fmt::format("system/save/8000000000000010/su/avators/{}.jpg", uuid.FormatSwitch()); +        fmt::format("system/save/8000000000000010/su/avators/{}.jpg", uuid.FormattedString());      return QString::fromStdString(Common::FS::PathToUTF8String(path));  } @@ -55,10 +55,10 @@ QString FormatUserEntryText(const QString& username, Common::UUID uuid) {      return ConfigureProfileManager::tr("%1\n%2",                                         "%1 is the profile username, %2 is the formatted UUID (e.g. "                                         "00112233-4455-6677-8899-AABBCCDDEEFF))") -        .arg(username, QString::fromStdString(uuid.FormatSwitch())); +        .arg(username, QString::fromStdString(uuid.FormattedString()));  } -QPixmap GetIcon(Common::UUID uuid) { +QPixmap GetIcon(const Common::UUID& uuid) {      QPixmap icon{GetImagePath(uuid)};      if (!icon) { @@ -200,7 +200,7 @@ void ConfigureProfileManager::AddUser() {          return;      } -    const auto uuid = Common::UUID::Generate(); +    const auto uuid = Common::UUID::MakeRandom();      profile_manager->CreateNewUser(uuid, username.toStdString());      item_model->appendRow(new QStandardItem{GetIcon(uuid), FormatUserEntryText(username, uuid)}); diff --git a/src/yuzu/configuration/configure_touch_from_button.cpp b/src/yuzu/configuration/configure_touch_from_button.cpp index bde0a08c4..211a00217 100644 --- a/src/yuzu/configuration/configure_touch_from_button.cpp +++ b/src/yuzu/configuration/configure_touch_from_button.cpp @@ -227,6 +227,9 @@ void ConfigureTouchFromButton::RenameMapping() {  }  void ConfigureTouchFromButton::GetButtonInput(const int row_index, const bool is_new) { +    if (timeout_timer->isActive()) { +        return; +    }      binding_list_model->item(row_index, 0)->setText(tr("[press key]"));      input_setter = [this, row_index, is_new](const Common::ParamPackage& params, diff --git a/src/yuzu/configuration/configure_vibration.cpp b/src/yuzu/configuration/configure_vibration.cpp index adce04b27..779b6401c 100644 --- a/src/yuzu/configuration/configure_vibration.cpp +++ b/src/yuzu/configuration/configure_vibration.cpp @@ -9,11 +9,14 @@  #include "common/param_package.h"  #include "common/settings.h" +#include "core/hid/emulated_controller.h" +#include "core/hid/hid_core.h" +#include "core/hid/hid_types.h"  #include "ui_configure_vibration.h"  #include "yuzu/configuration/configure_vibration.h" -ConfigureVibration::ConfigureVibration(QWidget* parent) -    : QDialog(parent), ui(std::make_unique<Ui::ConfigureVibration>()) { +ConfigureVibration::ConfigureVibration(QWidget* parent, Core::HID::HIDCore& hid_core_) +    : QDialog(parent), ui(std::make_unique<Ui::ConfigureVibration>()), hid_core{hid_core_} {      ui->setupUi(this);      vibration_groupboxes = { @@ -31,6 +34,13 @@ ConfigureVibration::ConfigureVibration(QWidget* parent)      const auto& players = Settings::values.players.GetValue();      for (std::size_t i = 0; i < NUM_PLAYERS; ++i) { +        auto controller = hid_core.GetEmulatedControllerByIndex(i); +        Core::HID::ControllerUpdateCallback engine_callback{ +            .on_change = [this, +                          i](Core::HID::ControllerTriggerType type) { VibrateController(type, i); }, +            .is_npad_service = false, +        }; +        controller_callback_key[i] = controller->SetCallback(engine_callback);          vibration_groupboxes[i]->setChecked(players[i].vibration_enabled);          vibration_spinboxes[i]->setValue(players[i].vibration_strength);      } @@ -45,7 +55,14 @@ ConfigureVibration::ConfigureVibration(QWidget* parent)      RetranslateUI();  } -ConfigureVibration::~ConfigureVibration() = default; +ConfigureVibration::~ConfigureVibration() { +    StopVibrations(); + +    for (std::size_t i = 0; i < NUM_PLAYERS; ++i) { +        auto controller = hid_core.GetEmulatedControllerByIndex(i); +        controller->DeleteCallback(controller_callback_key[i]); +    } +};  void ConfigureVibration::ApplyConfiguration() {      auto& players = Settings::values.players.GetValue(); @@ -70,3 +87,54 @@ void ConfigureVibration::changeEvent(QEvent* event) {  void ConfigureVibration::RetranslateUI() {      ui->retranslateUi(this);  } + +void ConfigureVibration::VibrateController(Core::HID::ControllerTriggerType type, +                                           std::size_t player_index) { +    if (type != Core::HID::ControllerTriggerType::Button) { +        return; +    } + +    auto& player = Settings::values.players.GetValue()[player_index]; +    auto controller = hid_core.GetEmulatedControllerByIndex(player_index); +    const int vibration_strenght = vibration_spinboxes[player_index]->value(); +    const auto& buttons = controller->GetButtonsValues(); + +    bool button_is_pressed = false; +    for (std::size_t i = 0; i < buttons.size(); ++i) { +        if (buttons[i].value) { +            button_is_pressed = true; +            break; +        } +    } + +    if (!button_is_pressed) { +        StopVibrations(); +        return; +    } + +    const int old_vibration_enabled = player.vibration_enabled; +    const bool old_vibration_strenght = player.vibration_strength; +    player.vibration_enabled = true; +    player.vibration_strength = vibration_strenght; + +    const Core::HID::VibrationValue vibration{ +        .low_amplitude = 1.0f, +        .low_frequency = 160.0f, +        .high_amplitude = 1.0f, +        .high_frequency = 320.0f, +    }; +    controller->SetVibration(0, vibration); +    controller->SetVibration(1, vibration); + +    // Restore previous values +    player.vibration_enabled = old_vibration_enabled; +    player.vibration_strength = old_vibration_strenght; +} + +void ConfigureVibration::StopVibrations() { +    for (std::size_t i = 0; i < NUM_PLAYERS; ++i) { +        auto controller = hid_core.GetEmulatedControllerByIndex(i); +        controller->SetVibration(0, Core::HID::DEFAULT_VIBRATION_VALUE); +        controller->SetVibration(1, Core::HID::DEFAULT_VIBRATION_VALUE); +    } +} diff --git a/src/yuzu/configuration/configure_vibration.h b/src/yuzu/configuration/configure_vibration.h index 37bbc2653..50b8195fa 100644 --- a/src/yuzu/configuration/configure_vibration.h +++ b/src/yuzu/configuration/configure_vibration.h @@ -15,11 +15,16 @@ namespace Ui {  class ConfigureVibration;  } +namespace Core::HID { +enum class ControllerTriggerType; +class HIDCore; +} // namespace Core::HID +  class ConfigureVibration : public QDialog {      Q_OBJECT  public: -    explicit ConfigureVibration(QWidget* parent); +    explicit ConfigureVibration(QWidget* parent, Core::HID::HIDCore& hid_core_);      ~ConfigureVibration() override;      void ApplyConfiguration(); @@ -27,14 +32,21 @@ public:  private:      void changeEvent(QEvent* event) override;      void RetranslateUI(); +    void VibrateController(Core::HID::ControllerTriggerType type, std::size_t player_index); +    void StopVibrations();      std::unique_ptr<Ui::ConfigureVibration> ui;      static constexpr std::size_t NUM_PLAYERS = 8; -    // Groupboxes encapsulating the vibration strength spinbox. +    /// Groupboxes encapsulating the vibration strength spinbox.      std::array<QGroupBox*, NUM_PLAYERS> vibration_groupboxes; -    // Spinboxes representing the vibration strength percentage. +    /// Spinboxes representing the vibration strength percentage.      std::array<QSpinBox*, NUM_PLAYERS> vibration_spinboxes; + +    /// Callback index to stop the controllers events +    std::array<int, NUM_PLAYERS> controller_callback_key; + +    Core::HID::HIDCore& hid_core;  }; diff --git a/src/yuzu/configuration/configure_vibration.ui b/src/yuzu/configuration/configure_vibration.ui index efdf317a9..447a18eb1 100644 --- a/src/yuzu/configuration/configure_vibration.ui +++ b/src/yuzu/configuration/configure_vibration.ui @@ -17,6 +17,13 @@     <string notr="true"/>    </property>    <layout class="QVBoxLayout"> +   <item row="0" column="0" colspan="4"> +    <widget class="QLabel" name="label_1"> +     <property name="text"> +      <string>Press any controller button to vibrate the controller.</string> +     </property> +    </widget> +   </item>     <item>      <widget class="QGroupBox" name="vibrationStrengthGroup">       <property name="title"> diff --git a/src/yuzu/debugger/console.cpp b/src/yuzu/debugger/console.cpp index f89ea8ea7..4b508b466 100644 --- a/src/yuzu/debugger/console.cpp +++ b/src/yuzu/debugger/console.cpp @@ -30,6 +30,7 @@ void ToggleConsole() {              freopen_s(&temp, "CONIN$", "r", stdin);              freopen_s(&temp, "CONOUT$", "w", stdout);              freopen_s(&temp, "CONOUT$", "w", stderr); +            SetConsoleOutputCP(65001);              SetColorConsoleBackendEnabled(true);          }      } else { diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp index 8b5c4a10a..e3661b390 100644 --- a/src/yuzu/game_list.cpp +++ b/src/yuzu/game_list.cpp @@ -161,7 +161,7 @@ GameListSearchField::GameListSearchField(GameList* parent) : QWidget{parent} {   * @return true if the haystack contains all words of userinput   */  static bool ContainsAllWords(const QString& haystack, const QString& userinput) { -    const QStringList userinput_split = userinput.split(QLatin1Char{' '}, QString::SkipEmptyParts); +    const QStringList userinput_split = userinput.split(QLatin1Char{' '}, Qt::SkipEmptyParts);      return std::all_of(userinput_split.begin(), userinput_split.end(),                         [&haystack](const QString& s) { return haystack.contains(s); }); diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index d9e689d14..06774768d 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -25,6 +25,7 @@  #include "core/file_sys/vfs_real.h"  #include "core/frontend/applets/controller.h"  #include "core/frontend/applets/general_frontend.h" +#include "core/frontend/applets/mii.h"  #include "core/frontend/applets/software_keyboard.h"  #include "core/hid/emulated_controller.h"  #include "core/hid/hid_core.h" @@ -249,9 +250,9 @@ GMainWindow::GMainWindow()  #ifdef ARCHITECTURE_x86_64      const auto& caps = Common::GetCPUCaps();      std::string cpu_string = caps.cpu_string; -    if (caps.avx || caps.avx2 || caps.avx512) { +    if (caps.avx || caps.avx2 || caps.avx512f) {          cpu_string += " | AVX"; -        if (caps.avx512) { +        if (caps.avx512f) {              cpu_string += "512";          } else if (caps.avx2) {              cpu_string += '2'; @@ -806,21 +807,8 @@ void GMainWindow::InitializeWidgets() {      filter_status_button = new QPushButton();      filter_status_button->setObjectName(QStringLiteral("TogglableStatusBarButton"));      filter_status_button->setFocusPolicy(Qt::NoFocus); -    connect(filter_status_button, &QPushButton::clicked, [&] { -        auto filter = Settings::values.scaling_filter.GetValue(); -        if (filter == Settings::ScalingFilter::LastFilter) { -            filter = Settings::ScalingFilter::NearestNeighbor; -        } else { -            filter = static_cast<Settings::ScalingFilter>(static_cast<u32>(filter) + 1); -        } -        if (Settings::values.renderer_backend.GetValue() == Settings::RendererBackend::OpenGL && -            filter == Settings::ScalingFilter::Fsr) { -            filter = Settings::ScalingFilter::NearestNeighbor; -        } -        Settings::values.scaling_filter.SetValue(filter); -        filter_status_button->setChecked(true); -        UpdateFilterText(); -    }); +    connect(filter_status_button, &QPushButton::clicked, this, +            &GMainWindow::OnToggleAdaptingFilter);      auto filter = Settings::values.scaling_filter.GetValue();      if (Settings::values.renderer_backend.GetValue() == Settings::RendererBackend::OpenGL &&          filter == Settings::ScalingFilter::Fsr) { @@ -835,25 +823,7 @@ void GMainWindow::InitializeWidgets() {      dock_status_button = new QPushButton();      dock_status_button->setObjectName(QStringLiteral("TogglableStatusBarButton"));      dock_status_button->setFocusPolicy(Qt::NoFocus); -    connect(dock_status_button, &QPushButton::clicked, [&] { -        const bool is_docked = Settings::values.use_docked_mode.GetValue(); -        auto* player_1 = system->HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1); -        auto* handheld = system->HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld); - -        if (!is_docked && handheld->IsConnected()) { -            QMessageBox::warning(this, tr("Invalid config detected"), -                                 tr("Handheld controller can't be used on docked mode. Pro " -                                    "controller will be selected.")); -            handheld->Disconnect(); -            player_1->SetNpadStyleIndex(Core::HID::NpadStyleIndex::ProController); -            player_1->Connect(); -            controller_dialog->refreshConfiguration(); -        } - -        Settings::values.use_docked_mode.SetValue(!is_docked); -        dock_status_button->setChecked(!is_docked); -        OnDockedModeChanged(is_docked, !is_docked, *system); -    }); +    connect(dock_status_button, &QPushButton::clicked, this, &GMainWindow::OnToggleDockedMode);      dock_status_button->setText(tr("DOCK"));      dock_status_button->setCheckable(true);      dock_status_button->setChecked(Settings::values.use_docked_mode.GetValue()); @@ -863,22 +833,7 @@ void GMainWindow::InitializeWidgets() {      gpu_accuracy_button->setObjectName(QStringLiteral("GPUStatusBarButton"));      gpu_accuracy_button->setCheckable(true);      gpu_accuracy_button->setFocusPolicy(Qt::NoFocus); -    connect(gpu_accuracy_button, &QPushButton::clicked, [this] { -        switch (Settings::values.gpu_accuracy.GetValue()) { -        case Settings::GPUAccuracy::High: { -            Settings::values.gpu_accuracy.SetValue(Settings::GPUAccuracy::Normal); -            break; -        } -        case Settings::GPUAccuracy::Normal: -        case Settings::GPUAccuracy::Extreme: -        default: { -            Settings::values.gpu_accuracy.SetValue(Settings::GPUAccuracy::High); -        } -        } - -        system->ApplySettings(); -        UpdateGPUAccuracyButton(); -    }); +    connect(gpu_accuracy_button, &QPushButton::clicked, this, &GMainWindow::OnToggleGpuAccuracy);      UpdateGPUAccuracyButton();      statusBar()->insertPermanentWidget(0, gpu_accuracy_button); @@ -965,6 +920,7 @@ void GMainWindow::LinkActionShortcut(QAction* action, const QString& action_name      static const QString main_window = QStringLiteral("Main Window");      action->setShortcut(hotkey_registry.GetKeySequence(main_window, action_name));      action->setShortcutContext(hotkey_registry.GetShortcutContext(main_window, action_name)); +    action->setAutoRepeat(false);      this->addAction(action); @@ -979,7 +935,7 @@ void GMainWindow::InitializeHotkeys() {      hotkey_registry.LoadHotkeys();      LinkActionShortcut(ui->action_Load_File, QStringLiteral("Load File")); -    LinkActionShortcut(ui->action_Load_Amiibo, QStringLiteral("Load Amiibo")); +    LinkActionShortcut(ui->action_Load_Amiibo, QStringLiteral("Load/Remove Amiibo"));      LinkActionShortcut(ui->action_Exit, QStringLiteral("Exit yuzu"));      LinkActionShortcut(ui->action_Restart, QStringLiteral("Restart Emulation"));      LinkActionShortcut(ui->action_Pause, QStringLiteral("Continue/Pause Emulation")); @@ -1008,12 +964,10 @@ void GMainWindow::InitializeHotkeys() {              ToggleFullscreen();          }      }); -    connect_shortcut(QStringLiteral("Change Docked Mode"), [&] { -        Settings::values.use_docked_mode.SetValue(!Settings::values.use_docked_mode.GetValue()); -        OnDockedModeChanged(!Settings::values.use_docked_mode.GetValue(), -                            Settings::values.use_docked_mode.GetValue(), *system); -        dock_status_button->setChecked(Settings::values.use_docked_mode.GetValue()); -    }); +    connect_shortcut(QStringLiteral("Change Adapting Filter"), +                     &GMainWindow::OnToggleAdaptingFilter); +    connect_shortcut(QStringLiteral("Change Docked Mode"), &GMainWindow::OnToggleDockedMode); +    connect_shortcut(QStringLiteral("Change GPU Accuracy"), &GMainWindow::OnToggleGpuAccuracy);      connect_shortcut(QStringLiteral("Audio Mute/Unmute"),                       [] { Settings::values.audio_muted = !Settings::values.audio_muted; });      connect_shortcut(QStringLiteral("Audio Volume Down"), [] { @@ -1051,8 +1005,10 @@ void GMainWindow::SetDefaultUIGeometry() {  }  void GMainWindow::RestoreUIState() { +    setWindowFlags(windowFlags() & ~Qt::FramelessWindowHint);      restoreGeometry(UISettings::values.geometry);      restoreState(UISettings::values.state); +    render_window->setWindowFlags(render_window->windowFlags() & ~Qt::FramelessWindowHint);      render_window->restoreGeometry(UISettings::values.renderwindow_geometry);  #if MICROPROFILE_ENABLED      microProfileDialog->restoreGeometry(UISettings::values.microprofile_geometry); @@ -1079,14 +1035,14 @@ void GMainWindow::RestoreUIState() {  }  void GMainWindow::OnAppFocusStateChanged(Qt::ApplicationState state) { -    if (!UISettings::values.pause_when_in_background) { -        return; -    }      if (state != Qt::ApplicationHidden && state != Qt::ApplicationInactive &&          state != Qt::ApplicationActive) {          LOG_DEBUG(Frontend, "ApplicationState unusual flag: {} ", state);      } -    if (emulation_running) { +    if (!emulation_running) { +        return; +    } +    if (UISettings::values.pause_when_in_background) {          if (emu_thread->IsRunning() &&              (state & (Qt::ApplicationHidden | Qt::ApplicationInactive))) {              auto_paused = true; @@ -1096,6 +1052,16 @@ void GMainWindow::OnAppFocusStateChanged(Qt::ApplicationState state) {              OnStartGame();          }      } +    if (UISettings::values.mute_when_in_background) { +        if (!Settings::values.audio_muted && +            (state & (Qt::ApplicationHidden | Qt::ApplicationInactive))) { +            Settings::values.audio_muted = true; +            auto_muted = true; +        } else if (auto_muted && state == Qt::ApplicationActive) { +            Settings::values.audio_muted = false; +            auto_muted = false; +        } +    }  }  void GMainWindow::ConnectWidgetEvents() { @@ -1320,6 +1286,7 @@ bool GMainWindow::LoadROM(const QString& filename, u64 program_id, std::size_t p          std::make_unique<QtControllerSelector>(*this), // Controller Selector          std::make_unique<QtErrorDisplay>(*this),       // Error Display          nullptr,                                       // Parental Controls +        nullptr,                                       // Mii editor          nullptr,                                       // Photo Viewer          std::make_unique<QtProfileSelector>(*this),    // Profile Selector          std::make_unique<QtSoftwareKeyboard>(*this),   // Software Keyboard @@ -1687,7 +1654,7 @@ void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target              const auto user_save_data_path = FileSys::SaveDataFactory::GetFullPath(                  *system, FileSys::SaveDataSpaceId::NandUser, FileSys::SaveDataType::SaveData, -                program_id, user_id->uuid, 0); +                program_id, user_id->AsU128(), 0);              path = Common::FS::ConcatPathSafe(nand_dir, user_save_data_path);          } else { @@ -2865,6 +2832,59 @@ void GMainWindow::OnTasReset() {      input_subsystem->GetTas()->Reset();  } +void GMainWindow::OnToggleDockedMode() { +    const bool is_docked = Settings::values.use_docked_mode.GetValue(); +    auto* player_1 = system->HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1); +    auto* handheld = system->HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld); + +    if (!is_docked && handheld->IsConnected()) { +        QMessageBox::warning(this, tr("Invalid config detected"), +                             tr("Handheld controller can't be used on docked mode. Pro " +                                "controller will be selected.")); +        handheld->Disconnect(); +        player_1->SetNpadStyleIndex(Core::HID::NpadStyleIndex::ProController); +        player_1->Connect(); +        controller_dialog->refreshConfiguration(); +    } + +    Settings::values.use_docked_mode.SetValue(!is_docked); +    dock_status_button->setChecked(!is_docked); +    OnDockedModeChanged(is_docked, !is_docked, *system); +} + +void GMainWindow::OnToggleGpuAccuracy() { +    switch (Settings::values.gpu_accuracy.GetValue()) { +    case Settings::GPUAccuracy::High: { +        Settings::values.gpu_accuracy.SetValue(Settings::GPUAccuracy::Normal); +        break; +    } +    case Settings::GPUAccuracy::Normal: +    case Settings::GPUAccuracy::Extreme: +    default: { +        Settings::values.gpu_accuracy.SetValue(Settings::GPUAccuracy::High); +    } +    } + +    system->ApplySettings(); +    UpdateGPUAccuracyButton(); +} + +void GMainWindow::OnToggleAdaptingFilter() { +    auto filter = Settings::values.scaling_filter.GetValue(); +    if (filter == Settings::ScalingFilter::LastFilter) { +        filter = Settings::ScalingFilter::NearestNeighbor; +    } else { +        filter = static_cast<Settings::ScalingFilter>(static_cast<u32>(filter) + 1); +    } +    if (Settings::values.renderer_backend.GetValue() == Settings::RendererBackend::OpenGL && +        filter == Settings::ScalingFilter::Fsr) { +        filter = Settings::ScalingFilter::NearestNeighbor; +    } +    Settings::values.scaling_filter.SetValue(filter); +    filter_status_button->setChecked(true); +    UpdateFilterText(); +} +  void GMainWindow::OnConfigurePerGame() {      const u64 title_id = system->GetCurrentProcessProgramID();      OpenPerGameConfiguration(title_id, game_path.toStdString()); @@ -2909,6 +2929,25 @@ void GMainWindow::OnLoadAmiibo() {          return;      } +    Service::SM::ServiceManager& sm = system->ServiceManager(); +    auto nfc = sm.GetService<Service::NFP::Module::Interface>("nfp:user"); +    if (nfc == nullptr) { +        QMessageBox::warning(this, tr("Error"), tr("The current game is not looking for amiibos")); +        return; +    } +    const auto nfc_state = nfc->GetCurrentState(); +    if (nfc_state == Service::NFP::DeviceState::TagFound || +        nfc_state == Service::NFP::DeviceState::TagMounted) { +        nfc->CloseAmiibo(); +        QMessageBox::warning(this, tr("Amiibo"), tr("The current amiibo has been removed")); +        return; +    } + +    if (nfc_state != Service::NFP::DeviceState::SearchingForTag) { +        QMessageBox::warning(this, tr("Error"), tr("The current game is not looking for amiibos")); +        return; +    } +      is_amiibo_file_select_active = true;      const QString extensions{QStringLiteral("*.bin")};      const QString file_filter = tr("Amiibo File (%1);; All Files (*.*)").arg(extensions); @@ -2929,6 +2968,15 @@ void GMainWindow::LoadAmiibo(const QString& filename) {          return;      } +    // Remove amiibo if one is connected +    const auto nfc_state = nfc->GetCurrentState(); +    if (nfc_state == Service::NFP::DeviceState::TagFound || +        nfc_state == Service::NFP::DeviceState::TagMounted) { +        nfc->CloseAmiibo(); +        QMessageBox::warning(this, tr("Amiibo"), tr("The current amiibo has been removed")); +        return; +    } +      QFile nfc_file{filename};      if (!nfc_file.open(QIODevice::ReadOnly)) {          QMessageBox::warning(this, tr("Error opening Amiibo data file"), diff --git a/src/yuzu/main.h b/src/yuzu/main.h index ca4ab9af5..6a35b9e3d 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h @@ -284,6 +284,9 @@ private slots:      void OnTasStartStop();      void OnTasRecord();      void OnTasReset(); +    void OnToggleDockedMode(); +    void OnToggleGpuAccuracy(); +    void OnToggleAdaptingFilter();      void OnConfigurePerGame();      void OnLoadAmiibo();      void OnOpenYuzuFolder(); @@ -369,6 +372,7 @@ private:      QString game_path;      bool auto_paused = false; +    bool auto_muted = false;      QTimer mouse_hide_timer;      // FS diff --git a/src/yuzu/main.ui b/src/yuzu/main.ui index 5719b2ee4..6ab95b9a5 100644 --- a/src/yuzu/main.ui +++ b/src/yuzu/main.ui @@ -266,7 +266,7 @@      <bool>false</bool>     </property>     <property name="text"> -    <string>Load &Amiibo...</string> +    <string>Load/Remove &Amiibo...</string>     </property>    </action>    <action name="action_Report_Compatibility"> diff --git a/src/yuzu/uisettings.h b/src/yuzu/uisettings.h index f7298ddad..06e8b46da 100644 --- a/src/yuzu/uisettings.h +++ b/src/yuzu/uisettings.h @@ -73,6 +73,7 @@ struct Values {      Settings::BasicSetting<bool> confirm_before_closing{true, "confirmClose"};      Settings::BasicSetting<bool> first_start{true, "firstStart"};      Settings::BasicSetting<bool> pause_when_in_background{false, "pauseWhenInBackground"}; +    Settings::BasicSetting<bool> mute_when_in_background{false, "muteWhenInBackground"};      Settings::BasicSetting<bool> hide_mouse{true, "hideInactiveMouse"};      Settings::BasicSetting<bool> select_user_on_boot{false, "select_user_on_boot"}; | 
