From ab5c03b1d9a2d21a77b046c331d2c365401e3b98 Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Wed, 26 Jul 2023 01:10:02 +1000 Subject: [PATCH] Pad: Fixes and cleanup (#9623) * Pad: Get rid of redundant object lookup * Pad: Serialize 'stage' state [SAVEVERSION+] * Pad: Reduce Freeze duplication and add markers Catch any possible unhandled device type change. [SAVEVERSION+] * Pad: Localize controller type names * Pad: Handle mismatch between state and current config * Misc: Drop .at() from vector/array access We don't use exceptions. * Pad: Remove redundant GetUnifiedSlot() Sio has routines for converting these. * Sio2: Remove redundant optional in Pad() * Pad: Constify and finalize controller classes * Pad: Move PadManager to Pad namespace No point having a class when there's only a single instance. * Pad: Move PadConfig to Pad namespace * Pad: Move PadMacros to Pad namespace * Pad: Re-localize controller bindings/settings * Pad: Make controller info local Don't want to create duplicates. * Pad: Use span for ControllerInfo settings/bindings * Pad: Fix auto-toggled macro buttons * Pad: Fix pressure for macros * Pad: Merge PadConfig/PadManager/PadMacros Faster compile time. * Pad: Fix incorrect condition in Sio0::SetTxData() * Pad: Add deadzone for macro triggers --- .../Settings/ControllerBindingWidgets.cpp | 56 +-- pcsx2-qt/Settings/ControllerBindingWidgets.h | 5 +- .../Settings/ControllerMacroEditWidget.ui | 45 ++- .../Settings/ControllerSettingsDialog.cpp | 18 +- pcsx2-qt/Settings/GameSummaryWidget.cpp | 4 +- pcsx2-qt/SetupWizardDialog.cpp | 10 +- pcsx2/CMakeLists.txt | 10 +- pcsx2/Counters.cpp | 26 +- pcsx2/GS/Renderers/HW/GSTextureCache.cpp | 4 +- pcsx2/ImGui/FullscreenUI.cpp | 64 ++-- pcsx2/ImGui/ImGuiOverlays.cpp | 114 +++--- pcsx2/Input/InputManager.cpp | 22 +- pcsx2/Recording/PadData.cpp | 96 ++--- pcsx2/SIO/Memcard/MemoryCardProtocol.cpp | 4 +- pcsx2/SIO/Pad/{PadConfig.cpp => Pad.cpp} | 335 ++++++++++++++---- pcsx2/SIO/Pad/{PadConfig.h => Pad.h} | 63 ++-- pcsx2/SIO/Pad/PadBase.cpp | 15 + pcsx2/SIO/Pad/PadBase.h | 20 +- pcsx2/SIO/Pad/PadDualshock2.cpp | 239 ++++++++----- pcsx2/SIO/Pad/PadDualshock2.h | 96 +++-- pcsx2/SIO/Pad/PadDualshock2Types.h | 133 ------- pcsx2/SIO/Pad/PadGuitar.cpp | 117 +++--- pcsx2/SIO/Pad/PadGuitar.h | 43 ++- pcsx2/SIO/Pad/PadGuitarTypes.h | 62 ---- pcsx2/SIO/Pad/PadMacros.cpp | 90 ----- pcsx2/SIO/Pad/PadMacros.h | 53 --- pcsx2/SIO/Pad/PadManager.cpp | 139 -------- pcsx2/SIO/Pad/PadManager.h | 46 --- pcsx2/SIO/Pad/PadNotConnected.cpp | 37 +- pcsx2/SIO/Pad/PadNotConnected.h | 43 +-- pcsx2/SIO/Pad/PadTypes.h | 20 ++ pcsx2/SIO/Sio.h | 6 +- pcsx2/SIO/Sio0.cpp | 9 +- pcsx2/SIO/Sio2.cpp | 32 +- pcsx2/SaveState.cpp | 11 +- pcsx2/VMManager.cpp | 35 +- pcsx2/pcsx2.vcxproj | 10 +- pcsx2/pcsx2.vcxproj.filters | 22 +- pcsx2/ps2/Iop/IopHwRead.cpp | 4 +- pcsx2/ps2/Iop/IopHwWrite.cpp | 4 +- 40 files changed, 1010 insertions(+), 1152 deletions(-) rename pcsx2/SIO/Pad/{PadConfig.cpp => Pad.cpp} (64%) rename pcsx2/SIO/Pad/{PadConfig.h => Pad.h} (70%) delete mode 100644 pcsx2/SIO/Pad/PadDualshock2Types.h delete mode 100644 pcsx2/SIO/Pad/PadGuitarTypes.h delete mode 100644 pcsx2/SIO/Pad/PadMacros.cpp delete mode 100644 pcsx2/SIO/Pad/PadMacros.h delete mode 100644 pcsx2/SIO/Pad/PadManager.cpp delete mode 100644 pcsx2/SIO/Pad/PadManager.h diff --git a/pcsx2-qt/Settings/ControllerBindingWidgets.cpp b/pcsx2-qt/Settings/ControllerBindingWidgets.cpp index 8e1a536523..b9022de405 100644 --- a/pcsx2-qt/Settings/ControllerBindingWidgets.cpp +++ b/pcsx2-qt/Settings/ControllerBindingWidgets.cpp @@ -26,7 +26,7 @@ #include "common/StringUtil.h" #include "pcsx2/Host.h" -#include "pcsx2/SIO/Pad/PadConfig.h" +#include "pcsx2/SIO/Pad/Pad.h" #include "Settings/ControllerBindingWidgets.h" #include "Settings/ControllerSettingsDialog.h" @@ -52,7 +52,7 @@ ControllerBindingWidget::ControllerBindingWidget(QWidget* parent, ControllerSett onTypeChanged(); ControllerSettingWidgetBinder::BindWidgetToInputProfileString( - m_dialog->getProfileSettingsInterface(), m_ui.controllerType, m_config_section, "Type", g_PadConfig.GetDefaultPadType(port)); + m_dialog->getProfileSettingsInterface(), m_ui.controllerType, m_config_section, "Type", Pad::GetDefaultPadType(port)); connect(m_ui.controllerType, QOverload::of(&QComboBox::currentIndexChanged), this, &ControllerBindingWidget::onTypeChanged); connect(m_ui.bindings, &QPushButton::clicked, this, &ControllerBindingWidget::onBindingsClicked); @@ -71,14 +71,14 @@ QIcon ControllerBindingWidget::getIcon() const void ControllerBindingWidget::populateControllerTypes() { - for (const auto& [name, display_name] : g_PadConfig.GetControllerTypeNames()) - m_ui.controllerType->addItem(qApp->translate("Pad", display_name), QString::fromStdString(name)); + for (const auto& [name, display_name] : Pad::GetControllerTypeNames()) + m_ui.controllerType->addItem(QString::fromUtf8(display_name), QString::fromUtf8(name)); } void ControllerBindingWidget::onTypeChanged() { const bool is_initializing = (m_ui.stackedWidget->count() == 0); - m_controller_type = m_dialog->getStringValue(m_config_section.c_str(), "Type", g_PadConfig.GetDefaultPadType(m_port_number)); + m_controller_type = m_dialog->getStringValue(m_config_section.c_str(), "Type", Pad::GetDefaultPadType(m_port_number)); if (m_bindings_widget) { @@ -99,9 +99,9 @@ void ControllerBindingWidget::onTypeChanged() m_macros_widget = nullptr; } - const PadConfig::ControllerInfo* cinfo = g_PadConfig.GetControllerInfo(m_controller_type); - const bool has_settings = (cinfo && cinfo->num_settings > 0); - const bool has_macros = (cinfo && cinfo->num_bindings > 0); + const Pad::ControllerInfo* cinfo = Pad::GetControllerInfo(m_controller_type); + const bool has_settings = (cinfo && !cinfo->settings.empty()); + const bool has_macros = (cinfo && !cinfo->bindings.empty()); m_ui.settings->setEnabled(has_settings); m_ui.macros->setEnabled(has_macros); @@ -123,9 +123,8 @@ void ControllerBindingWidget::onTypeChanged() if (has_settings) { - const std::span settings(cinfo->settings, cinfo->num_settings); m_settings_widget = new ControllerCustomSettingsWidget( - settings, m_config_section, std::string(), "Pad", getDialog(), m_ui.stackedWidget); + cinfo->settings, m_config_section, std::string(), "Pad", getDialog(), m_ui.stackedWidget); m_ui.stackedWidget->addWidget(m_settings_widget); } @@ -218,13 +217,13 @@ void ControllerBindingWidget::onClearBindingsClicked() { { auto lock = Host::GetSettingsLock(); - g_PadConfig.ClearPortBindings(*Host::Internal::GetBaseSettingsLayer(), m_port_number); + Pad::ClearPortBindings(*Host::Internal::GetBaseSettingsLayer(), m_port_number); } Host::CommitBaseSettingChanges(); } else { - g_PadConfig.ClearPortBindings(*m_dialog->getProfileSettingsInterface(), m_port_number); + Pad::ClearPortBindings(*m_dialog->getProfileSettingsInterface(), m_port_number); m_dialog->getProfileSettingsInterface()->Save(); } @@ -248,14 +247,14 @@ void ControllerBindingWidget::doDeviceAutomaticBinding(const QString& device) { { auto lock = Host::GetSettingsLock(); - result = g_PadConfig.MapController(*Host::Internal::GetBaseSettingsLayer(), m_port_number, mapping); + result = Pad::MapController(*Host::Internal::GetBaseSettingsLayer(), m_port_number, mapping); } if (result) Host::CommitBaseSettingChanges(); } else { - result = g_PadConfig.MapController(*m_dialog->getProfileSettingsInterface(), m_port_number, mapping); + result = Pad::MapController(*m_dialog->getProfileSettingsInterface(), m_port_number, mapping); if (result) { m_dialog->getProfileSettingsInterface()->Save(); @@ -320,7 +319,7 @@ ControllerMacroEditWidget::ControllerMacroEditWidget(ControllerMacroWidget* pare ControllerSettingsDialog* dialog = m_bwidget->getDialog(); const std::string& section = m_bwidget->getConfigSection(); - const PadConfig::ControllerInfo* cinfo = g_PadConfig.GetControllerInfo(m_bwidget->getControllerType()); + const Pad::ControllerInfo* cinfo = Pad::GetControllerInfo(m_bwidget->getControllerType()); if (!cinfo) { // Shouldn't ever happen. @@ -333,20 +332,19 @@ ControllerMacroEditWidget::ControllerMacroEditWidget(ControllerMacroWidget* pare for (const std::string_view& button : buttons_split) { - for (u32 i = 0; i < cinfo->num_bindings; i++) + for (const InputBindingInfo& bi : cinfo->bindings) { - if (button == cinfo->bindings[i].name) + if (button == bi.name) { - m_binds.push_back(&cinfo->bindings[i]); + m_binds.push_back(&bi); break; } } } // populate list view - for (u32 i = 0; i < cinfo->num_bindings; i++) + for (const InputBindingInfo& bi : cinfo->bindings) { - const InputBindingInfo& bi = cinfo->bindings[i]; if (bi.bind_type == InputBindingInfo::Type::Motor) continue; @@ -358,8 +356,12 @@ ControllerMacroEditWidget::ControllerMacroEditWidget(ControllerMacroWidget* pare ControllerSettingWidgetBinder::BindWidgetToInputProfileNormalized( dialog->getProfileSettingsInterface(), m_ui.pressure, section, fmt::format("Macro{}Pressure", index + 1u), 100.0f, 1.0f); + ControllerSettingWidgetBinder::BindWidgetToInputProfileNormalized( + dialog->getProfileSettingsInterface(), m_ui.deadzone, section, fmt::format("Macro{}Deadzone", index + 1u), 100.0f, 0.0f); connect(m_ui.pressure, &QSlider::valueChanged, this, &ControllerMacroEditWidget::onPressureChanged); + connect(m_ui.deadzone, &QSlider::valueChanged, this, &ControllerMacroEditWidget::onDeadzoneChanged); onPressureChanged(); + onDeadzoneChanged(); m_frequency = dialog->getIntValue(section.c_str(), fmt::format("Macro{}Frequency", index + 1u).c_str(), 0); updateFrequencyText(); @@ -392,6 +394,11 @@ void ControllerMacroEditWidget::onPressureChanged() m_ui.pressureValue->setText(tr("%1%").arg(m_ui.pressure->value())); } +void ControllerMacroEditWidget::onDeadzoneChanged() +{ + m_ui.deadzoneValue->setText(tr("%1%").arg(m_ui.deadzone->value())); +} + void ControllerMacroEditWidget::onSetFrequencyClicked() { bool okay; @@ -431,12 +438,12 @@ void ControllerMacroEditWidget::updateFrequencyText() void ControllerMacroEditWidget::updateBinds() { ControllerSettingsDialog* dialog = m_bwidget->getDialog(); - const PadConfig::ControllerInfo* cinfo = g_PadConfig.GetControllerInfo(m_bwidget->getControllerType()); + const Pad::ControllerInfo* cinfo = Pad::GetControllerInfo(m_bwidget->getControllerType()); if (!cinfo) return; std::vector new_binds; - for (u32 i = 0, bind_index = 0; i < cinfo->num_bindings; i++) + for (u32 i = 0, bind_index = 0; i < static_cast(cinfo->bindings.size()); i++) { const InputBindingInfo& bi = cinfo->bindings[i]; if (bi.bind_type == InputBindingInfo::Type::Motor) @@ -801,16 +808,15 @@ QIcon ControllerBindingWidget_Base::getIcon() const void ControllerBindingWidget_Base::initBindingWidgets() { - const PadConfig::ControllerInfo* cinfo = g_PadConfig.GetControllerInfo(getControllerType()); + const Pad::ControllerInfo* cinfo = Pad::GetControllerInfo(getControllerType()); if (!cinfo) return; const std::string& config_section = getConfigSection(); SettingsInterface* sif = getDialog()->getProfileSettingsInterface(); - for (u32 i = 0; i < cinfo->num_bindings; i++) + for (const InputBindingInfo& bi : cinfo->bindings) { - const InputBindingInfo& bi = cinfo->bindings[i]; if (bi.bind_type == InputBindingInfo::Type::Axis || bi.bind_type == InputBindingInfo::Type::HalfAxis || bi.bind_type == InputBindingInfo::Type::Button || bi.bind_type == InputBindingInfo::Type::Pointer || bi.bind_type == InputBindingInfo::Type::Device) diff --git a/pcsx2-qt/Settings/ControllerBindingWidgets.h b/pcsx2-qt/Settings/ControllerBindingWidgets.h index d3479e3cf4..d4bf53be7b 100644 --- a/pcsx2-qt/Settings/ControllerBindingWidgets.h +++ b/pcsx2-qt/Settings/ControllerBindingWidgets.h @@ -15,7 +15,7 @@ #pragma once -#include "pcsx2/SIO/Pad/PadMacros.h" +#include "pcsx2/SIO/Pad/PadTypes.h" #include @@ -92,7 +92,7 @@ public: void updateListItem(u32 index); private: - static constexpr u32 NUM_MACROS = PadMacros::NUM_MACRO_BUTTONS_PER_CONTROLLER; + static constexpr u32 NUM_MACROS = Pad::NUM_MACRO_BUTTONS_PER_CONTROLLER; void createWidgets(ControllerBindingWidget* parent); @@ -115,6 +115,7 @@ public: private Q_SLOTS: void onPressureChanged(); + void onDeadzoneChanged(); void onSetFrequencyClicked(); void updateBinds(); diff --git a/pcsx2-qt/Settings/ControllerMacroEditWidget.ui b/pcsx2-qt/Settings/ControllerMacroEditWidget.ui index 31f3c5f44e..3e259a902b 100644 --- a/pcsx2-qt/Settings/ControllerMacroEditWidget.ui +++ b/pcsx2-qt/Settings/ControllerMacroEditWidget.ui @@ -7,7 +7,7 @@ 0 0 691 - 547 + 433 @@ -83,6 +83,9 @@ QSlider::TicksBelow + + 10 + @@ -123,6 +126,46 @@ + + + + + + Deadzone: + + + + + + + 0 + + + 100 + + + 100 + + + Qt::Horizontal + + + QSlider::TicksBelow + + + 10 + + + + + + + 100% + + + + + diff --git a/pcsx2-qt/Settings/ControllerSettingsDialog.cpp b/pcsx2-qt/Settings/ControllerSettingsDialog.cpp index 2451832369..2db2cfceb1 100644 --- a/pcsx2-qt/Settings/ControllerSettingsDialog.cpp +++ b/pcsx2-qt/Settings/ControllerSettingsDialog.cpp @@ -22,7 +22,7 @@ #include "Settings/HotkeySettingsWidget.h" #include "pcsx2/INISettingsInterface.h" -#include "pcsx2/SIO/Pad/PadConfig.h" +#include "pcsx2/SIO/Pad/Pad.h" #include "pcsx2/SIO/Sio.h" #include "pcsx2/VMManager.h" @@ -130,7 +130,7 @@ void ControllerSettingsDialog::onNewProfileClicked() { // from global auto lock = Host::GetSettingsLock(); - g_PadConfig.CopyConfiguration(&temp_si, *Host::Internal::GetBaseSettingsLayer(), true, true, false); + Pad::CopyConfiguration(&temp_si, *Host::Internal::GetBaseSettingsLayer(), true, true, false); USB::CopyConfiguration(&temp_si, *Host::Internal::GetBaseSettingsLayer(), true, true); } else @@ -138,7 +138,7 @@ void ControllerSettingsDialog::onNewProfileClicked() // from profile const bool copy_hotkey_bindings = m_profile_interface->GetBoolValue("Pad", "UseProfileHotkeyBindings", false); temp_si.SetBoolValue("Pad", "UseProfileHotkeyBindings", copy_hotkey_bindings); - g_PadConfig.CopyConfiguration(&temp_si, *m_profile_interface, true, true, copy_hotkey_bindings); + Pad::CopyConfiguration(&temp_si, *m_profile_interface, true, true, copy_hotkey_bindings); USB::CopyConfiguration(&temp_si, *m_profile_interface, true, true); } } @@ -167,7 +167,7 @@ void ControllerSettingsDialog::onLoadProfileClicked() { auto lock = Host::GetSettingsLock(); - g_PadConfig.CopyConfiguration(Host::Internal::GetBaseSettingsLayer(), *m_profile_interface, true, true, false); + Pad::CopyConfiguration(Host::Internal::GetBaseSettingsLayer(), *m_profile_interface, true, true, false); USB::CopyConfiguration(Host::Internal::GetBaseSettingsLayer(), *m_profile_interface, true, true); } Host::CommitBaseSettingChanges(); @@ -403,8 +403,8 @@ void ControllerSettingsDialog::createWidgets() m_port_bindings[global_slot] = new ControllerBindingWidget(m_ui.settingsContainer, this, global_slot); m_ui.settingsContainer->addWidget(m_port_bindings[global_slot]); - const PadConfig::ControllerInfo* ci = g_PadConfig.GetControllerInfo(m_port_bindings[global_slot]->getControllerType()); - const QString display_name(ci ? qApp->translate("Pad", ci->display_name) : QStringLiteral("Unknown")); + const Pad::ControllerInfo* ci = Pad::GetControllerInfo(m_port_bindings[global_slot]->getControllerType()); + const QString display_name(QString::fromUtf8(ci ? ci->GetLocalizedName() : "Unknown")); QListWidgetItem* item = new QListWidgetItem(); //: Controller Port is an official term from Sony. Find the official translation for your language inside the console's manual. @@ -459,8 +459,8 @@ void ControllerSettingsDialog::updateListDescription(u32 global_slot, Controller const auto [port, slot] = sioConvertPadToPortAndSlot(global_slot); const bool mtap_enabled = getBoolValue("Pad", (port == 0) ? "MultitapPort1" : "MultitapPort2", false); - const PadConfig::ControllerInfo* ci = g_PadConfig.GetControllerInfo(widget->getControllerType()); - const QString display_name(ci ? qApp->translate("Pad", ci->display_name) : QStringLiteral("Unknown")); + const Pad::ControllerInfo* ci = Pad::GetControllerInfo(widget->getControllerType()); + const QString display_name = QString::fromUtf8(ci ? ci->GetLocalizedName() : "Unknown"); //: Controller Port is an official term from Sony. Find the official translation for your language inside the console's manual. item->setText(mtap_enabled ? (tr("Controller Port %1%2\n%3").arg(port + 1).arg(s_mtap_slot_names[slot]).arg(display_name)) : @@ -492,7 +492,7 @@ void ControllerSettingsDialog::updateListDescription(u32 port, USBDeviceWidget* void ControllerSettingsDialog::refreshProfileList() { - const std::vector names(g_PadConfig.GetInputProfileNames()); + const std::vector names = Pad::GetInputProfileNames(); QSignalBlocker sb(m_ui.currentProfile); m_ui.currentProfile->clear(); diff --git a/pcsx2-qt/Settings/GameSummaryWidget.cpp b/pcsx2-qt/Settings/GameSummaryWidget.cpp index 1b2b5ef847..3e4239984b 100644 --- a/pcsx2-qt/Settings/GameSummaryWidget.cpp +++ b/pcsx2-qt/Settings/GameSummaryWidget.cpp @@ -15,7 +15,7 @@ #include "PrecompiledHeader.h" -#include "pcsx2/SIO/Pad/PadConfig.h" +#include "pcsx2/SIO/Pad/Pad.h" #include "GameSummaryWidget.h" #include "SettingsDialog.h" #include "MainWindow.h" @@ -69,7 +69,7 @@ GameSummaryWidget::~GameSummaryWidget() = default; void GameSummaryWidget::populateInputProfiles() { - for (const std::string& name : g_PadConfig.GetInputProfileNames()) + for (const std::string& name : Pad::GetInputProfileNames()) m_ui.inputProfile->addItem(QString::fromStdString(name)); } diff --git a/pcsx2-qt/SetupWizardDialog.cpp b/pcsx2-qt/SetupWizardDialog.cpp index e9ebe8d9b2..5cd164e53c 100644 --- a/pcsx2-qt/SetupWizardDialog.cpp +++ b/pcsx2-qt/SetupWizardDialog.cpp @@ -15,7 +15,7 @@ #include "PrecompiledHeader.h" -#include "pcsx2/SIO/Pad/PadConfig.h" +#include "pcsx2/SIO/Pad/Pad.h" #include "QtHost.h" #include "QtUtils.h" #include "SettingWidgetBinder.h" @@ -414,10 +414,10 @@ void SetupWizardDialog::setupControllerPage() const std::string section = fmt::format("Pad{}", port + 1); const PadWidgets& w = pad_widgets[port]; - for (const auto& [name, display_name] : g_PadConfig.GetControllerTypeNames()) - w.type_combo->addItem(qApp->translate("Pad", display_name), QString::fromStdString(name)); + for (const auto& [name, display_name] : Pad::GetControllerTypeNames()) + w.type_combo->addItem(QString::fromUtf8(display_name), QString::fromUtf8(name)); ControllerSettingWidgetBinder::BindWidgetToInputProfileString( - nullptr, w.type_combo, section, "Type", g_PadConfig.GetDefaultPadType(port)); + nullptr, w.type_combo, section, "Type", Pad::GetDefaultPadType(port)); w.mapping_result->setText((port == 0) ? tr("Default (Keyboard)") : tr("Default (None)")); @@ -473,7 +473,7 @@ void SetupWizardDialog::doDeviceAutomaticBinding(u32 port, QLabel* update_label, bool result; { auto lock = Host::GetSettingsLock(); - result = g_PadConfig.MapController(*Host::Internal::GetBaseSettingsLayer(), port, mapping); + result = Pad::MapController(*Host::Internal::GetBaseSettingsLayer(), port, mapping); } if (!result) return; diff --git a/pcsx2/CMakeLists.txt b/pcsx2/CMakeLists.txt index cdfb9f3531..b4d2f3698e 100644 --- a/pcsx2/CMakeLists.txt +++ b/pcsx2/CMakeLists.txt @@ -482,23 +482,17 @@ endif() # Host PAD set(pcsx2PADSources + SIO/Pad/Pad.cpp SIO/Pad/PadBase.cpp - SIO/Pad/PadConfig.cpp SIO/Pad/PadDualshock2.cpp SIO/Pad/PadGuitar.cpp - SIO/Pad/PadMacros.cpp - SIO/Pad/PadManager.cpp SIO/Pad/PadNotConnected.cpp ) set(pcsx2PADHeaders + SIO/Pad/Pad.h SIO/Pad/PadBase.h - SIO/Pad/PadConfig.h SIO/Pad/PadDualshock2.h - SIO/Pad/PadDualshock2Types.h SIO/Pad/PadGuitar.h - SIO/Pad/PadGuitarTypes.h - SIO/Pad/PadMacros.h - SIO/Pad/PadManager.h SIO/Pad/PadNotConnected.h SIO/Pad/PadTypes.h ) diff --git a/pcsx2/Counters.cpp b/pcsx2/Counters.cpp index 2c1d5232bb..212ffddaff 100644 --- a/pcsx2/Counters.cpp +++ b/pcsx2/Counters.cpp @@ -547,20 +547,6 @@ static __fi void DoFMVSwitch() RendererSwitched = false; } -// Convenience function to update UI thread and set patches. -static __fi void VSyncUpdateCore() -{ - DoFMVSwitch(); - - VMManager::Internal::VSyncOnCPUThread(); -} - -static __fi void VSyncCheckExit() -{ - if (VMManager::Internal::IsExecutionInterrupted()) - Cpu->ExitExecution(); -} - // Framelimiter - Measures the delta time between calls and stalls until a // certain amount of time passes if such time hasn't passed yet. static __fi void frameLimit() @@ -605,13 +591,13 @@ static __fi void frameLimit() static __fi void VSyncStart(u32 sCycle) { - // Update vibration at the end of a frame. - VSyncUpdateCore(); + // End-of-frame tasks. + DoFMVSwitch(); + VMManager::Internal::VSyncOnCPUThread(); frameLimit(); // limit FPS gsPostVsyncStart(); // MUST be after framelimit; doing so before causes funk with frame times! - VSyncCheckExit(); - + if(EmuConfig.Trace.Enabled && EmuConfig.Trace.EE.m_EnableAll) SysTrace.EE.Counters.Write( " ================ EE COUNTER VSYNC START (frame: %d) ================", g_FrameCount ); @@ -642,6 +628,10 @@ static __fi void VSyncStart(u32 sCycle) // Therefore, there needs to be some delay in order for it to see the interrupt flag before the interrupt is acknowledged, likely helped on real hardware by the pipelines. // Without the patch and fixing this, the games have other issues, so I'm not going to rush to fix it. // Refraction + + // Bail out before the next frame starts if we're paused, or the CPU has changed + if (VMManager::Internal::IsExecutionInterrupted()) + Cpu->ExitExecution(); } static __fi void GSVSync() diff --git a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp index 0b529511dd..2d2f7cbcc8 100644 --- a/pcsx2/GS/Renderers/HW/GSTextureCache.cpp +++ b/pcsx2/GS/Renderers/HW/GSTextureCache.cpp @@ -5823,8 +5823,8 @@ bool GSTextureCache::SurfaceOffsetKeyEqual::operator()(const GSTextureCache::Sur { for (size_t i = 0; i < lhs.elems.size(); ++i) { - const SurfaceOffsetKeyElem& lhs_elem = lhs.elems.at(i); - const SurfaceOffsetKeyElem& rhs_elem = rhs.elems.at(i); + const SurfaceOffsetKeyElem& lhs_elem = lhs.elems[i]; + const SurfaceOffsetKeyElem& rhs_elem = rhs.elems[i]; if (lhs_elem.bp != rhs_elem.bp || lhs_elem.bw != rhs_elem.bw || lhs_elem.psm != rhs_elem.psm diff --git a/pcsx2/ImGui/FullscreenUI.cpp b/pcsx2/ImGui/FullscreenUI.cpp index 2d0d843c1f..b5e42a8cc8 100644 --- a/pcsx2/ImGui/FullscreenUI.cpp +++ b/pcsx2/ImGui/FullscreenUI.cpp @@ -48,8 +48,7 @@ #include "common/Timer.h" #include "SIO/Memcard/MemoryCardFile.h" -#include "SIO/Pad/PadConfig.h" -#include "SIO/Pad/PadMacros.h" +#include "SIO/Pad/Pad.h" #include "SIO/Sio.h" #include "imgui.h" @@ -2273,7 +2272,7 @@ void FullscreenUI::StartAutomaticBinding(u32 port) Host::RunOnCPUThread([port, name = std::move(names[index])]() { auto lock = Host::GetSettingsLock(); SettingsInterface* bsi = GetEditingSettingsInterface(); - const bool result = g_PadConfig.MapController(*bsi, port, InputManager::GetGenericBindingMapping(name)); + const bool result = Pad::MapController(*bsi, port, InputManager::GetGenericBindingMapping(name)); SetSettingsChanged(bsi); @@ -3650,7 +3649,7 @@ void FullscreenUI::CopyGlobalControllerSettingsToGame() SettingsInterface* dsi = GetEditingSettingsInterface(true); SettingsInterface* ssi = GetEditingSettingsInterface(false); - g_PadConfig.CopyConfiguration(dsi, *ssi, true, true, false); + Pad::CopyConfiguration(dsi, *ssi, true, true, false); USB::CopyConfiguration(dsi, *ssi, true, true); SetSettingsChanged(dsi); @@ -3661,15 +3660,15 @@ void FullscreenUI::ResetControllerSettings() { SettingsInterface* dsi = GetEditingSettingsInterface(); - g_PadConfig.SetDefaultControllerConfig(*dsi); - g_PadConfig.SetDefaultHotkeyConfig(*dsi); + Pad::SetDefaultControllerConfig(*dsi); + Pad::SetDefaultHotkeyConfig(*dsi); USB::SetDefaultConfiguration(dsi); ShowToast(std::string(), "Controller settings reset to default."); } void FullscreenUI::DoLoadInputProfile() { - std::vector profiles(g_PadConfig.GetInputProfileNames()); + std::vector profiles = Pad::GetInputProfileNames(); if (profiles.empty()) { ShowToast(std::string(), "No input profiles available."); @@ -3695,7 +3694,7 @@ void FullscreenUI::DoLoadInputProfile() auto lock = Host::GetSettingsLock(); SettingsInterface* dsi = GetEditingSettingsInterface(); - g_PadConfig.CopyConfiguration(dsi, ssi, true, true, IsEditingGameSettings(dsi)); + Pad::CopyConfiguration(dsi, ssi, true, true, IsEditingGameSettings(dsi)); USB::CopyConfiguration(dsi, ssi, true, true); SetSettingsChanged(dsi); ShowToast(std::string(), fmt::format("Input profile '{}' loaded.", title)); @@ -3709,7 +3708,7 @@ void FullscreenUI::DoSaveInputProfile(const std::string& name) auto lock = Host::GetSettingsLock(); SettingsInterface* ssi = GetEditingSettingsInterface(); - g_PadConfig.CopyConfiguration(&dsi, *ssi, true, true, IsEditingGameSettings(ssi)); + Pad::CopyConfiguration(&dsi, *ssi, true, true, IsEditingGameSettings(ssi)); USB::CopyConfiguration(&dsi, *ssi, true, true); if (dsi.Save()) ShowToast(std::string(), fmt::format("Input profile '{}' saved.", name)); @@ -3719,7 +3718,7 @@ void FullscreenUI::DoSaveInputProfile(const std::string& name) void FullscreenUI::DoSaveInputProfile() { - std::vector profiles(g_PadConfig.GetInputProfileNames()); + std::vector profiles = Pad::GetInputProfileNames(); ImGuiFullscreen::ChoiceDialogOptions coptions; coptions.reserve(profiles.size() + 1); @@ -3853,11 +3852,11 @@ void FullscreenUI::DrawControllerSettingsPage() .c_str()); const char* section = sections[global_slot]; - const std::string type(bsi->GetStringValue(section, "Type", g_PadConfig.GetDefaultPadType(global_slot))); - const PadConfig::ControllerInfo* ci = g_PadConfig.GetControllerInfo(type); + const std::string type(bsi->GetStringValue(section, "Type", Pad::GetDefaultPadType(global_slot))); + const Pad::ControllerInfo* ci = Pad::GetControllerInfo(type); if (MenuButton(ICON_FA_GAMEPAD " Controller Type", ci ? ci->display_name : "Unknown")) { - const std::vector> raw_options = g_PadConfig.GetControllerTypeNames(); + const std::vector> raw_options = Pad::GetControllerTypeNames(); ImGuiFullscreen::ChoiceDialogOptions options; options.reserve(raw_options.size()); for (auto& it : raw_options) @@ -3878,7 +3877,7 @@ void FullscreenUI::DrawControllerSettingsPage() }); } - if (!ci || ci->num_bindings == 0) + if (!ci || ci->bindings.empty()) { ImGui::PopID(); continue; @@ -3887,20 +3886,17 @@ void FullscreenUI::DrawControllerSettingsPage() if (MenuButton(ICON_FA_MAGIC " Automatic Mapping", "Attempts to map the selected port to a chosen controller.")) StartAutomaticBinding(global_slot); - for (u32 i = 0; i < ci->num_bindings; i++) - { - const InputBindingInfo& bi = ci->bindings[i]; - DrawInputBindingButton(bsi, bi.bind_type, section, bi.name, bi.display_name, true); - } + for (const InputBindingInfo& bi : ci->bindings) + DrawInputBindingButton(bsi, bi.bind_type, section, bi.name, Host::TranslateToCString("Pad", bi.display_name), true); MenuHeading((mtap_enabled[mtap_port] ? fmt::format(ICON_FA_MICROCHIP " Controller Port {}{} Macros", mtap_port + 1, mtap_slot_names[mtap_slot]) : fmt::format(ICON_FA_MICROCHIP " Controller Port {} Macros", mtap_port + 1)) .c_str()); - static bool macro_button_expanded[Pad::NUM_CONTROLLER_PORTS][PadMacros::NUM_MACRO_BUTTONS_PER_CONTROLLER] = {}; + static bool macro_button_expanded[Pad::NUM_CONTROLLER_PORTS][Pad::NUM_MACRO_BUTTONS_PER_CONTROLLER] = {}; - for (u32 macro_index = 0; macro_index < PadMacros::NUM_MACRO_BUTTONS_PER_CONTROLLER; macro_index++) + for (u32 macro_index = 0; macro_index < Pad::NUM_MACRO_BUTTONS_PER_CONTROLLER; macro_index++) { bool& expanded = macro_button_expanded[global_slot][macro_index]; expanded ^= MenuHeadingButton(fmt::format(ICON_FA_MICROCHIP " Macro Button {}", macro_index + 1).c_str(), @@ -3916,25 +3912,23 @@ void FullscreenUI::DrawControllerSettingsPage() { std::vector buttons_split(StringUtil::SplitString(binds_string, '&', true)); ImGuiFullscreen::ChoiceDialogOptions options; - for (u32 i = 0; i < ci->num_bindings; i++) + for (const InputBindingInfo& bi : ci->bindings) { - const InputBindingInfo& bi = ci->bindings[i]; if (bi.bind_type != InputBindingInfo::Type::Button && bi.bind_type != InputBindingInfo::Type::Axis && bi.bind_type != InputBindingInfo::Type::HalfAxis) { continue; } - options.emplace_back(bi.display_name, std::any_of(buttons_split.begin(), buttons_split.end(), - [bi](const std::string_view& it) { return (it == bi.name); })); + options.emplace_back(Host::TranslateToCString("Pad", bi.display_name), std::any_of(buttons_split.begin(), buttons_split.end(), + [bi](const std::string_view& it) { return (it == bi.name); })); } OpenChoiceDialog(fmt::format("Select Macro {} Binds", macro_index + 1).c_str(), true, std::move(options), [section, macro_index, ci](s32 index, const std::string& title, bool checked) { // convert display name back to bind name std::string_view to_modify; - for (u32 j = 0; j < ci->num_bindings; j++) + for (const InputBindingInfo& bi : ci->bindings) { - const InputBindingInfo& bi = ci->bindings[j]; if (bi.display_name == title) { to_modify = bi.name; @@ -3984,6 +3978,10 @@ void FullscreenUI::DrawControllerSettingsPage() DrawFloatSpinBoxSetting(bsi, ICON_FA_ARROW_DOWN " Pressure", "Determines how much pressure is simulated when macro is active.", section, pressure_key.c_str(), 1.0f, 0.01f, 1.0f, 0.01f, 100.0f, "%.0f%%"); + const std::string deadzone_key(fmt::format("Macro{}Deadzone", macro_index + 1)); + DrawFloatSpinBoxSetting(bsi, ICON_FA_ARROW_DOWN " Pressure", "Determines the pressure required to activate the macro.", + section, deadzone_key.c_str(), 0.0f, 0.00f, 1.0f, 0.01f, 100.0f, "%.0f%%"); + ImGui::SetNextWindowSize(LayoutScale(500.0f, 180.0f)); ImGui::SetNextWindowPos(ImGui::GetIO().DisplaySize * 0.5f, ImGuiCond_Always, ImVec2(0.5f, 0.5f)); @@ -4018,18 +4016,15 @@ void FullscreenUI::DrawControllerSettingsPage() ImGui::PopFont(); } - if (ci->num_settings > 0) + if (!ci->settings.empty()) { MenuHeading((mtap_enabled[mtap_port] ? fmt::format(ICON_FA_SLIDERS_H " Controller Port {}{} Settings", mtap_port + 1, mtap_slot_names[mtap_slot]) : fmt::format(ICON_FA_SLIDERS_H " Controller Port {} Settings", mtap_port + 1)) .c_str()); - for (u32 i = 0; i < ci->num_settings; i++) - { - const SettingInfo& si = ci->settings[i]; + for (const SettingInfo& si : ci->settings) DrawSettingInfoSetting(bsi, section, si.name, si); - } } ImGui::PopID(); @@ -4109,7 +4104,10 @@ void FullscreenUI::DrawControllerSettingsPage() const std::string section(USB::GetConfigSection(port)); for (const InputBindingInfo& bi : bindings) - DrawInputBindingButton(bsi, bi.bind_type, section.c_str(), USB::GetConfigSubKey(type, bi.name).c_str(), bi.display_name); + { + DrawInputBindingButton(bsi, bi.bind_type, section.c_str(), USB::GetConfigSubKey(type, bi.name).c_str(), + Host::TranslateToCString("USB", bi.display_name)); + } } const std::span settings(USB::GetDeviceSettings(type, subtype)); diff --git a/pcsx2/ImGui/ImGuiOverlays.cpp b/pcsx2/ImGui/ImGuiOverlays.cpp index cb08ae12b0..7f58def09d 100644 --- a/pcsx2/ImGui/ImGuiOverlays.cpp +++ b/pcsx2/ImGui/ImGuiOverlays.cpp @@ -29,11 +29,11 @@ #include "ImGui/ImGuiOverlays.h" #include "Input/InputManager.h" #include "PerformanceMetrics.h" +#include "Recording/InputRecording.h" +#include "SIO/Pad/Pad.h" +#include "SIO/Pad/PadBase.h" #include "USB/USB.h" #include "VMManager.h" -#include "pcsx2/Recording/InputRecording.h" -#include "SIO/Pad/PadConfig.h" -#include "SIO/Pad/PadManager.h" #include "common/BitUtils.h" #include "common/StringUtil.h" @@ -485,18 +485,8 @@ void ImGuiManager::DrawInputsOverlay() for (u32 slot = 0; slot < Pad::NUM_CONTROLLER_PORTS; slot++) { - const std::optional padOpt = g_PadManager.GetPad(slot); - - if (padOpt.has_value()) - { - PadBase* pad = padOpt.value(); - const Pad::ControllerType ctype = pad->GetType(); - - if (ctype != Pad::ControllerType::NotConnected) - { - num_ports++; - } - } + if (Pad::HasConnectedPad(slot)) + num_ports++; } for (u32 port = 0; port < USB::NUM_PORTS; port++) @@ -515,65 +505,55 @@ void ImGuiManager::DrawInputsOverlay() for (u32 slot = 0; slot < Pad::NUM_CONTROLLER_PORTS; slot++) { - const std::optional padOpt = g_PadManager.GetPad(slot); + const PadBase* const pad = Pad::GetPad(slot); + const Pad::ControllerType ctype = pad->GetType(); + if (ctype == Pad::ControllerType::NotConnected) + continue; + + text.clear(); + fmt::format_to(std::back_inserter(text), "P{} |", slot + 1u); - if (padOpt.has_value()) + const Pad::ControllerInfo& cinfo = pad->GetInfo(); + for (u32 bind = 0; bind < static_cast(cinfo.bindings.size()); bind++) { - PadBase* pad = padOpt.value(); - const Pad::ControllerType ctype = pad->GetType(); - - if (ctype == Pad::ControllerType::NotConnected) - continue; - - const PadConfig::ControllerInfo* cinfo = g_PadConfig.GetControllerInfo(ctype); - - if (!cinfo) - continue; - - text.clear(); - fmt::format_to(std::back_inserter(text), "P{} |", slot + 1u); - - for (u32 bind = 0; bind < cinfo->num_bindings; bind++) + const InputBindingInfo& bi = cinfo.bindings[bind]; + switch (bi.bind_type) { - const InputBindingInfo& bi = cinfo->bindings[bind]; - switch (bi.bind_type) + case InputBindingInfo::Type::Axis: + case InputBindingInfo::Type::HalfAxis: { - case InputBindingInfo::Type::Axis: - case InputBindingInfo::Type::HalfAxis: - { - // axes are always shown - const float value = static_cast(pad->GetRawInput(bind)) * (1.0f / 255.0f); - if (value >= (254.0f / 255.0f)) - fmt::format_to(std::back_inserter(text), " {}", bi.name); - else if (value > (1.0f / 255.0f)) - fmt::format_to(std::back_inserter(text), " {}: {:.2f}", bi.name, value); - } - break; - - case InputBindingInfo::Type::Button: - { - // buttons only shown when active - const float value = static_cast(pad->GetRawInput(bind)) * (1.0f / 255.0f); - if (value >= 0.5f) - fmt::format_to(std::back_inserter(text), " {}", bi.name); - } - break; - - case InputBindingInfo::Type::Motor: - case InputBindingInfo::Type::Macro: - case InputBindingInfo::Type::Unknown: - default: - break; + // axes are always shown + const float value = static_cast(pad->GetRawInput(bind)) * (1.0f / 255.0f); + if (value >= (254.0f / 255.0f)) + fmt::format_to(std::back_inserter(text), " {}", bi.name); + else if (value > (1.0f / 255.0f)) + fmt::format_to(std::back_inserter(text), " {}: {:.2f}", bi.name, value); } + break; + + case InputBindingInfo::Type::Button: + { + // buttons only shown when active + const float value = static_cast(pad->GetRawInput(bind)) * (1.0f / 255.0f); + if (value >= 0.5f) + fmt::format_to(std::back_inserter(text), " {}", bi.name); + } + break; + + case InputBindingInfo::Type::Motor: + case InputBindingInfo::Type::Macro: + case InputBindingInfo::Type::Unknown: + default: + break; } - - dl->AddText(font, font->FontSize, ImVec2(current_x + shadow_offset, current_y + shadow_offset), shadow_color, text.c_str(), - text.c_str() + text.length(), 0.0f, &clip_rect); - dl->AddText( - font, font->FontSize, ImVec2(current_x, current_y), text_color, text.c_str(), text.c_str() + text.length(), 0.0f, &clip_rect); - - current_y += font->FontSize + spacing; } + + dl->AddText(font, font->FontSize, ImVec2(current_x + shadow_offset, current_y + shadow_offset), shadow_color, text.c_str(), + text.c_str() + text.length(), 0.0f, &clip_rect); + dl->AddText( + font, font->FontSize, ImVec2(current_x, current_y), text_color, text.c_str(), text.c_str() + text.length(), 0.0f, &clip_rect); + + current_y += font->FontSize + spacing; } for (u32 port = 0; port < USB::NUM_PORTS; port++) diff --git a/pcsx2/Input/InputManager.cpp b/pcsx2/Input/InputManager.cpp index 08950324bb..ac09cf1cce 100644 --- a/pcsx2/Input/InputManager.cpp +++ b/pcsx2/Input/InputManager.cpp @@ -18,9 +18,7 @@ #include "ImGui/ImGuiManager.h" #include "Input/InputManager.h" #include "Input/InputSource.h" -#include "SIO/Pad/PadConfig.h" -#include "SIO/Pad/PadMacros.h" -#include "SIO/Pad/PadManager.h" +#include "SIO/Pad/Pad.h" #include "USB/USB.h" #include "VMManager.h" @@ -634,14 +632,12 @@ void InputManager::AddPadBindings(SettingsInterface& si, u32 pad_index, const ch if (type.empty() || type == "None") return; - const PadConfig::ControllerInfo* cinfo = g_PadConfig.GetControllerInfo(type); + const Pad::ControllerInfo* cinfo = Pad::GetControllerInfo(type); if (!cinfo) return; - for (u32 i = 0; i < cinfo->num_bindings; i++) + for (const InputBindingInfo& bi : cinfo->bindings) { - const InputBindingInfo& bi = cinfo->bindings[i]; - switch (bi.bind_type) { case InputBindingInfo::Type::Button: @@ -656,7 +652,7 @@ void InputManager::AddPadBindings(SettingsInterface& si, u32 pad_index, const ch const float deadzone = si.GetFloatValue(section.c_str(), fmt::format("{}Deadzone", bi.name).c_str(), 0.0f); AddBindings( bindings, InputAxisEventHandler{[pad_index, bind_index = bi.bind_index, sensitivity, deadzone](float value) { - g_PadManager.SetControllerState(pad_index, bind_index, ApplySingleBindingScale(sensitivity, deadzone, value)); + Pad::SetControllerState(pad_index, bind_index, ApplySingleBindingScale(sensitivity, deadzone, value)); }}); } } @@ -669,13 +665,15 @@ void InputManager::AddPadBindings(SettingsInterface& si, u32 pad_index, const ch } } - for (u32 macro_button_index = 0; macro_button_index < PadMacros::NUM_MACRO_BUTTONS_PER_CONTROLLER; macro_button_index++) + for (u32 macro_button_index = 0; macro_button_index < Pad::NUM_MACRO_BUTTONS_PER_CONTROLLER; macro_button_index++) { const std::vector bindings(si.GetStringList(section.c_str(), fmt::format("Macro{}", macro_button_index + 1).c_str())); if (!bindings.empty()) { - AddBindings(bindings, InputButtonEventHandler{[pad_index, macro_button_index](bool state) { - g_PadMacros.SetMacroButtonState(pad_index, macro_button_index, state); + const float deadzone = si.GetFloatValue(section.c_str(), fmt::format("Macro{}Deadzone", macro_button_index + 1).c_str(), 0.0f); + AddBindings(bindings, InputAxisEventHandler{[pad_index, macro_button_index, deadzone](float value) { + const bool state = (value > deadzone); + Pad::SetMacroButtonState(pad_index, macro_button_index, state); }}); } } @@ -1293,7 +1291,7 @@ void InputManager::ReloadBindings(SettingsInterface& si, SettingsInterface& bind // If there's an input profile, we load pad bindings from it alone, rather than // falling back to the base configuration. for (u32 pad = 0; pad < Pad::NUM_CONTROLLER_PORTS; pad++) - AddPadBindings(binding_si, pad, g_PadConfig.GetDefaultPadType(pad)); + AddPadBindings(binding_si, pad, Pad::GetDefaultPadType(pad)); constexpr float ui_ctrl_range = 100.0f; constexpr float pointer_sensitivity = 0.05f; diff --git a/pcsx2/Recording/PadData.cpp b/pcsx2/Recording/PadData.cpp index 577ebb34e3..735e1a55ed 100644 --- a/pcsx2/Recording/PadData.cpp +++ b/pcsx2/Recording/PadData.cpp @@ -17,8 +17,8 @@ #include "DebugTools/Debug.h" #include "Recording/PadData.h" -#include "SIO/Pad/PadManager.h" -#include "SIO/Pad/PadDualshock2Types.h" +#include "SIO/Pad/Pad.h" +#include "SIO/Pad/PadDualshock2.h" #include "SIO/Sio.h" #include @@ -28,7 +28,7 @@ PadData::PadData(const int port, const int slot) m_port = port; m_slot = slot; m_ext_port = sioConvertPortAndSlotToPad(m_port, m_slot); - PadBase* pad = g_PadManager.GetPad(m_ext_port); + PadBase* pad = Pad::GetPad(m_ext_port); // Get the state of the buttons // TODO - for the new recording file format, allow informing max number of buttons per frame per controller as well (ie. the analog button) const u32 buttons = pad->GetButtons(); @@ -56,23 +56,23 @@ PadData::PadData(const int port, const int slot) m_rightAnalog = pad->GetRawRightAnalog(); m_leftAnalog = pad->GetRawLeftAnalog(); // Get pressure bytes (12 of them) - m_left = {(0b10000000 & m_compactPressFlagsGroupOne) == 0, pad->GetRawInput(Dualshock2::Inputs::PAD_LEFT)}; - m_down = {(0b01000000 & m_compactPressFlagsGroupOne) == 0, pad->GetRawInput(Dualshock2::Inputs::PAD_DOWN)}; - m_right = {(0b00100000 & m_compactPressFlagsGroupOne) == 0, pad->GetRawInput(Dualshock2::Inputs::PAD_RIGHT)}; - m_up = {(0b00010000 & m_compactPressFlagsGroupOne) == 0, pad->GetRawInput(Dualshock2::Inputs::PAD_UP)}; + m_left = {(0b10000000 & m_compactPressFlagsGroupOne) == 0, pad->GetRawInput(PadDualshock2::Inputs::PAD_LEFT)}; + m_down = {(0b01000000 & m_compactPressFlagsGroupOne) == 0, pad->GetRawInput(PadDualshock2::Inputs::PAD_DOWN)}; + m_right = {(0b00100000 & m_compactPressFlagsGroupOne) == 0, pad->GetRawInput(PadDualshock2::Inputs::PAD_RIGHT)}; + m_up = {(0b00010000 & m_compactPressFlagsGroupOne) == 0, pad->GetRawInput(PadDualshock2::Inputs::PAD_UP)}; m_start = (0b00001000 & m_compactPressFlagsGroupOne) == 0; m_r3 = (0b00000100 & m_compactPressFlagsGroupOne) == 0; m_l3 = (0b00000010 & m_compactPressFlagsGroupOne) == 0; m_select = (0b00000001 & m_compactPressFlagsGroupOne) == 0; - m_square = {(0b10000000 & m_compactPressFlagsGroupTwo) == 0, pad->GetRawInput(Dualshock2::Inputs::PAD_SQUARE)}; - m_cross = {(0b01000000 & m_compactPressFlagsGroupTwo) == 0, pad->GetRawInput(Dualshock2::Inputs::PAD_CROSS)}; - m_circle = {(0b00100000 & m_compactPressFlagsGroupTwo) == 0, pad->GetRawInput(Dualshock2::Inputs::PAD_CIRCLE)}; - m_triangle = {(0b00010000 & m_compactPressFlagsGroupTwo) == 0, pad->GetRawInput(Dualshock2::Inputs::PAD_TRIANGLE)}; - m_r1 = {(0b00001000 & m_compactPressFlagsGroupTwo) == 0, pad->GetRawInput(Dualshock2::Inputs::PAD_R1)}; - m_l1 = {(0b00000100 & m_compactPressFlagsGroupTwo) == 0, pad->GetRawInput(Dualshock2::Inputs::PAD_L1)}; - m_r2 = {(0b00000010 & m_compactPressFlagsGroupTwo) == 0, pad->GetRawInput(Dualshock2::Inputs::PAD_R2)}; - m_l2 = {(0b00000001 & m_compactPressFlagsGroupTwo) == 0, pad->GetRawInput(Dualshock2::Inputs::PAD_L2)}; + m_square = {(0b10000000 & m_compactPressFlagsGroupTwo) == 0, pad->GetRawInput(PadDualshock2::Inputs::PAD_SQUARE)}; + m_cross = {(0b01000000 & m_compactPressFlagsGroupTwo) == 0, pad->GetRawInput(PadDualshock2::Inputs::PAD_CROSS)}; + m_circle = {(0b00100000 & m_compactPressFlagsGroupTwo) == 0, pad->GetRawInput(PadDualshock2::Inputs::PAD_CIRCLE)}; + m_triangle = {(0b00010000 & m_compactPressFlagsGroupTwo) == 0, pad->GetRawInput(PadDualshock2::Inputs::PAD_TRIANGLE)}; + m_r1 = {(0b00001000 & m_compactPressFlagsGroupTwo) == 0, pad->GetRawInput(PadDualshock2::Inputs::PAD_R1)}; + m_l1 = {(0b00000100 & m_compactPressFlagsGroupTwo) == 0, pad->GetRawInput(PadDualshock2::Inputs::PAD_L1)}; + m_r2 = {(0b00000010 & m_compactPressFlagsGroupTwo) == 0, pad->GetRawInput(PadDualshock2::Inputs::PAD_R2)}; + m_l2 = {(0b00000001 & m_compactPressFlagsGroupTwo) == 0, pad->GetRawInput(PadDualshock2::Inputs::PAD_L2)}; } PadData::PadData(const int port, const int slot, const std::array data) @@ -81,54 +81,54 @@ PadData::PadData(const int port, const int slot, const std::array data) m_slot = slot; m_ext_port = sioConvertPortAndSlotToPad(m_port, m_slot); - m_compactPressFlagsGroupOne = data.at(0); - m_compactPressFlagsGroupTwo = data.at(1); + m_compactPressFlagsGroupOne = data[0]; + m_compactPressFlagsGroupTwo = data[1]; - m_rightAnalog = {data.at(2), data.at(3)}; - m_leftAnalog = {data.at(4), data.at(5)}; + m_rightAnalog = {data[2], data[3]}; + m_leftAnalog = {data[4], data[5]}; - m_left = {(0b10000000 & m_compactPressFlagsGroupOne) == 0, data.at(7)}; - m_down = {(0b01000000 & m_compactPressFlagsGroupOne) == 0, data.at(9)}; - m_right = {(0b00100000 & m_compactPressFlagsGroupOne) == 0, data.at(6)}; - m_up = {(0b00010000 & m_compactPressFlagsGroupOne) == 0, data.at(8)}; + m_left = {(0b10000000 & m_compactPressFlagsGroupOne) == 0, data[7]}; + m_down = {(0b01000000 & m_compactPressFlagsGroupOne) == 0, data[9]}; + m_right = {(0b00100000 & m_compactPressFlagsGroupOne) == 0, data[6]}; + m_up = {(0b00010000 & m_compactPressFlagsGroupOne) == 0, data[8]}; m_start = (0b00001000 & m_compactPressFlagsGroupOne) == 0; m_r3 = (0b00000100 & m_compactPressFlagsGroupOne) == 0; m_l3 = (0b00000010 & m_compactPressFlagsGroupOne) == 0; m_select = (0b00000001 & m_compactPressFlagsGroupOne) == 0; - m_square = {(0b10000000 & m_compactPressFlagsGroupTwo) == 0, data.at(13)}; - m_cross = {(0b01000000 & m_compactPressFlagsGroupTwo) == 0, data.at(12)}; - m_circle = {(0b00100000 & m_compactPressFlagsGroupTwo) == 0, data.at(11)}; - m_triangle = {(0b00010000 & m_compactPressFlagsGroupTwo) == 0, data.at(10)}; - m_r1 = {(0b00001000 & m_compactPressFlagsGroupTwo) == 0, data.at(15)}; - m_l1 = {(0b00000100 & m_compactPressFlagsGroupTwo) == 0, data.at(14)}; - m_r2 = {(0b00000010 & m_compactPressFlagsGroupTwo) == 0, data.at(17)}; - m_l2 = {(0b00000001 & m_compactPressFlagsGroupTwo) == 0, data.at(16)}; + m_square = {(0b10000000 & m_compactPressFlagsGroupTwo) == 0, data[13]}; + m_cross = {(0b01000000 & m_compactPressFlagsGroupTwo) == 0, data[12]}; + m_circle = {(0b00100000 & m_compactPressFlagsGroupTwo) == 0, data[11]}; + m_triangle = {(0b00010000 & m_compactPressFlagsGroupTwo) == 0, data[10]}; + m_r1 = {(0b00001000 & m_compactPressFlagsGroupTwo) == 0, data[15]}; + m_l1 = {(0b00000100 & m_compactPressFlagsGroupTwo) == 0, data[14]}; + m_r2 = {(0b00000010 & m_compactPressFlagsGroupTwo) == 0, data[17]}; + m_l2 = {(0b00000001 & m_compactPressFlagsGroupTwo) == 0, data[16]}; } void PadData::OverrideActualController() const { - PadBase* pad = g_PadManager.GetPad(m_ext_port); + PadBase* pad = Pad::GetPad(m_ext_port); pad->SetRawAnalogs(m_leftAnalog, m_rightAnalog); - pad->Set(Dualshock2::Inputs::PAD_RIGHT, std::get<1>(m_right)); - pad->Set(Dualshock2::Inputs::PAD_LEFT, std::get<1>(m_left)); - pad->Set(Dualshock2::Inputs::PAD_UP, std::get<1>(m_up)); - pad->Set(Dualshock2::Inputs::PAD_DOWN, std::get<1>(m_down)); - pad->Set(Dualshock2::Inputs::PAD_START, m_start); - pad->Set(Dualshock2::Inputs::PAD_SELECT, m_select); - pad->Set(Dualshock2::Inputs::PAD_R3, m_r3); - pad->Set(Dualshock2::Inputs::PAD_L3, m_l3); + pad->Set(PadDualshock2::Inputs::PAD_RIGHT, std::get<1>(m_right)); + pad->Set(PadDualshock2::Inputs::PAD_LEFT, std::get<1>(m_left)); + pad->Set(PadDualshock2::Inputs::PAD_UP, std::get<1>(m_up)); + pad->Set(PadDualshock2::Inputs::PAD_DOWN, std::get<1>(m_down)); + pad->Set(PadDualshock2::Inputs::PAD_START, m_start); + pad->Set(PadDualshock2::Inputs::PAD_SELECT, m_select); + pad->Set(PadDualshock2::Inputs::PAD_R3, m_r3); + pad->Set(PadDualshock2::Inputs::PAD_L3, m_l3); - pad->Set(Dualshock2::Inputs::PAD_SQUARE, std::get<1>(m_square)); - pad->Set(Dualshock2::Inputs::PAD_CROSS, std::get<1>(m_cross)); - pad->Set(Dualshock2::Inputs::PAD_CIRCLE, std::get<1>(m_circle)); - pad->Set(Dualshock2::Inputs::PAD_TRIANGLE, std::get<1>(m_triangle)); + pad->Set(PadDualshock2::Inputs::PAD_SQUARE, std::get<1>(m_square)); + pad->Set(PadDualshock2::Inputs::PAD_CROSS, std::get<1>(m_cross)); + pad->Set(PadDualshock2::Inputs::PAD_CIRCLE, std::get<1>(m_circle)); + pad->Set(PadDualshock2::Inputs::PAD_TRIANGLE, std::get<1>(m_triangle)); - pad->Set(Dualshock2::Inputs::PAD_R1, std::get<1>(m_r1)); - pad->Set(Dualshock2::Inputs::PAD_L1, std::get<1>(m_l1)); - pad->Set(Dualshock2::Inputs::PAD_R2, std::get<1>(m_r2)); - pad->Set(Dualshock2::Inputs::PAD_L2, std::get<1>(m_l2)); + pad->Set(PadDualshock2::Inputs::PAD_R1, std::get<1>(m_r1)); + pad->Set(PadDualshock2::Inputs::PAD_L1, std::get<1>(m_l1)); + pad->Set(PadDualshock2::Inputs::PAD_R2, std::get<1>(m_r2)); + pad->Set(PadDualshock2::Inputs::PAD_L2, std::get<1>(m_l2)); } void addButtonInfoToString(std::string label, std::string& str, std::tuple buttonInfo) diff --git a/pcsx2/SIO/Memcard/MemoryCardProtocol.cpp b/pcsx2/SIO/Memcard/MemoryCardProtocol.cpp index 4aa1c8a5be..b5fbbd11da 100644 --- a/pcsx2/SIO/Memcard/MemoryCardProtocol.cpp +++ b/pcsx2/SIO/Memcard/MemoryCardProtocol.cpp @@ -297,7 +297,7 @@ u8 MemoryCardProtocol::PS1Read(u8 data) mcd->Read(ps1McState.buf.data(), ps1McState.buf.size()); [[fallthrough]]; default: - ret = ps1McState.buf.at(ps1McState.currentByte - 10); + ret = ps1McState.buf[ps1McState.currentByte - 10]; ps1McState.checksum ^= ret; break; } @@ -372,7 +372,7 @@ u8 MemoryCardProtocol::PS1Write(u8 data) ps1McState.checksum = ps1McState.sectorAddrMSB ^ ps1McState.sectorAddrLSB; [[fallthrough]]; default: - ps1McState.buf.at(ps1McState.currentByte - 6) = data; + ps1McState.buf[ps1McState.currentByte - 6] = data; ps1McState.checksum ^= data; ret = 0x00; break; diff --git a/pcsx2/SIO/Pad/PadConfig.cpp b/pcsx2/SIO/Pad/Pad.cpp similarity index 64% rename from pcsx2/SIO/Pad/PadConfig.cpp rename to pcsx2/SIO/Pad/Pad.cpp index 3e5fca68a1..f3fb373a28 100644 --- a/pcsx2/SIO/Pad/PadConfig.cpp +++ b/pcsx2/SIO/Pad/Pad.cpp @@ -15,28 +15,67 @@ #include "PrecompiledHeader.h" -#include "SIO/Pad/PadConfig.h" +#include "Host.h" +#include "Input/InputManager.h" +#include "SIO/Pad/Pad.h" +#include "SIO/Pad/PadDualshock2.h" +#include "SIO/Pad/PadGuitar.h" +#include "SIO/Pad/PadNotConnected.h" +#include "SIO/Sio.h" -#include "SIO/Pad/PadManager.h" -#include "SIO/Pad/PadMacros.h" -#include "SIO/Pad/PadDualshock2Types.h" -#include "SIO/Pad/PadGuitarTypes.h" +#include "IconsFontAwesome5.h" #include "common/FileSystem.h" #include "common/Path.h" -#include "common/StringUtil.h" #include "common/SettingsInterface.h" +#include "common/StringUtil.h" -#include "Input/InputManager.h" +#include "fmt/format.h" -PadConfig g_PadConfig; +#include -PadConfig::PadConfig() = default; -PadConfig::~PadConfig() = default; - -void PadConfig::LoadConfig(const SettingsInterface& si) +namespace Pad { - g_PadMacros.ClearMacros(); + struct MacroButton + { + std::vector buttons; ///< Buttons to activate. + float pressure; ///< Pressure to apply when macro is active. + u32 toggle_frequency; ///< Interval at which the buttons will be toggled, if not 0. + u32 toggle_counter; ///< When this counter reaches zero, buttons will be toggled. + bool toggle_state; ///< Current state for turbo. + bool trigger_state; ///< Whether the macro button is active. + }; + + static std::unique_ptr CreatePad(u8 unifiedSlot, Pad::ControllerType controllerType); + static PadBase* ChangePadType(u8 unifiedSlot, Pad::ControllerType controllerType); + + void LoadMacroButtonConfig( + const SettingsInterface& si, u32 pad, const std::string_view& type, const std::string& section); + static void ApplyMacroButton(u32 controller, const MacroButton& mb); + + static std::array, NUM_CONTROLLER_PORTS> s_macro_buttons; + static std::array, NUM_CONTROLLER_PORTS> s_controllers; +} + +bool Pad::Initialize() +{ + return true; +} + +void Pad::Shutdown() +{ + for (auto& port : s_controllers) + port.reset(); +} + +const char* Pad::ControllerInfo::GetLocalizedName() const +{ + return Host::TranslateToCString("Pad", display_name); +} + +void Pad::LoadConfig(const SettingsInterface& si) +{ + s_macro_buttons = {}; EmuConfig.MultitapPort0_Enabled = si.GetBoolValue("Pad", "MultitapPort1", false); EmuConfig.MultitapPort1_Enabled = si.GetBoolValue("Pad", "MultitapPort2", false); @@ -47,18 +86,18 @@ void PadConfig::LoadConfig(const SettingsInterface& si) const std::string section(GetConfigSection(i)); const std::string type(si.GetStringValue(section.c_str(), "Type", GetDefaultPadType(i))); const ControllerInfo* ci = GetControllerInfo(type); - PadBase* pad = g_PadManager.GetPad(i); + PadBase* pad = Pad::GetPad(i); // If a pad is not yet constructed, at minimum place a NotConnected pad in the slot. // Do not abort the for loop - If there pad settings, we want those to be applied to the slot. if (!pad) { - pad = g_PadManager.ChangePadType(i, Pad::ControllerType::NotConnected); + pad = Pad::ChangePadType(i, Pad::ControllerType::NotConnected); } if (!ci) { - pad = g_PadManager.ChangePadType(i, Pad::ControllerType::NotConnected); + pad = Pad::ChangePadType(i, Pad::ControllerType::NotConnected); continue; } @@ -67,7 +106,7 @@ void PadConfig::LoadConfig(const SettingsInterface& si) if (ci->type != oldType) { - pad = g_PadManager.ChangePadType(i, ci->type); + pad = Pad::ChangePadType(i, ci->type); } const float axis_deadzone = si.GetFloatValue(section.c_str(), "Deadzone", Pad::DEFAULT_STICK_DEADZONE); @@ -94,17 +133,16 @@ void PadConfig::LoadConfig(const SettingsInterface& si) const int invert_r = si.GetIntValue(section.c_str(), "InvertR", 0); pad->SetAnalogInvertL((invert_l & 1) != 0, (invert_l & 2) != 0); pad->SetAnalogInvertR((invert_r & 1) != 0, (invert_r & 2) != 0); - LoadMacroButtonConfig(si, i, type, section); } } -const char* PadConfig::GetDefaultPadType(u32 pad) +const char* Pad::GetDefaultPadType(u32 pad) { return (pad == 0) ? "DualShock2" : "None"; } -void PadConfig::SetDefaultControllerConfig(SettingsInterface& si) +void Pad::SetDefaultControllerConfig(SettingsInterface& si) { si.ClearSection("InputSources"); si.ClearSection("Hotkeys"); @@ -136,9 +174,8 @@ void PadConfig::SetDefaultControllerConfig(SettingsInterface& si) const ControllerInfo* ci = GetControllerInfo(type); if (ci) { - for (u32 i = 0; i < ci->num_settings; i++) + for (const SettingInfo& csi : ci->settings) { - const SettingInfo& csi = ci->settings[i]; switch (csi.type) { case SettingInfo::Type::Boolean: @@ -168,7 +205,7 @@ void PadConfig::SetDefaultControllerConfig(SettingsInterface& si) MapController(si, 0, InputManager::GetGenericBindingMapping("Keyboard")); } -void PadConfig::SetDefaultHotkeyConfig(SettingsInterface& si) +void Pad::SetDefaultHotkeyConfig(SettingsInterface& si) { // PCSX2 Controller Settings - Hotkeys @@ -215,74 +252,70 @@ void PadConfig::SetDefaultHotkeyConfig(SettingsInterface& si) si.SetStringValue("Hotkeys", "HoldTurbo", "Keyboard/Period"); } - -static const PadConfig::ControllerInfo s_controller_info[] = { - {Pad::ControllerType::NotConnected, "None", "Not Connected", - nullptr, 0, - nullptr, 0, - Pad::VibrationCapabilities::NoVibration}, - {Pad::ControllerType::DualShock2, "DualShock2", "DualShock 2", - Dualshock2::defaultBindings, std::size(Dualshock2::defaultBindings), - Dualshock2::defaultSettings, std::size(Dualshock2::defaultSettings), - Pad::VibrationCapabilities::LargeSmallMotors}, - {Pad::ControllerType::Guitar, "Guitar", "Guitar", - Guitar::defaultBindings, std::size(Guitar::defaultBindings), - Guitar::defaultSettings, std::size(Guitar::defaultSettings), - Pad::VibrationCapabilities::NoVibration}, +static const Pad::ControllerInfo* s_controller_info[] = { + &PadNotConnected::ControllerInfo, + &PadDualshock2::ControllerInfo, + &PadGuitar::ControllerInfo, }; -const PadConfig::ControllerInfo* PadConfig::GetControllerInfo(Pad::ControllerType type) +const Pad::ControllerInfo* Pad::GetControllerInfo(Pad::ControllerType type) { - for (const ControllerInfo& info : s_controller_info) + for (const ControllerInfo* info : s_controller_info) { - if (type == info.type) - return &info; + if (type == info->type) + return info; } return nullptr; } -const PadConfig::ControllerInfo* PadConfig::GetControllerInfo(const std::string_view& name) +const Pad::ControllerInfo* Pad::GetControllerInfo(const std::string_view& name) { - for (const ControllerInfo& info : s_controller_info) + for (const ControllerInfo* info : s_controller_info) { - if (name == info.name) - return &info; + if (name == info->name) + return info; } return nullptr; } -const std::vector> PadConfig::GetControllerTypeNames() +const char* Pad::GetControllerTypeName(Pad::ControllerType type) +{ + // Not localized, because it should never happen. + const ControllerInfo* ci = GetControllerInfo(type); + return ci ? ci->GetLocalizedName() : "UNKNOWN"; +} + +const std::vector> Pad::GetControllerTypeNames() { std::vector> ret; - for (const ControllerInfo& info : s_controller_info) - ret.emplace_back(info.name, info.display_name); + for (const ControllerInfo* info : s_controller_info) + ret.emplace_back(info->name, info->GetLocalizedName()); return ret; } -std::vector PadConfig::GetControllerBinds(const std::string_view& type) +std::vector Pad::GetControllerBinds(const std::string_view& type) { std::vector ret; const ControllerInfo* info = GetControllerInfo(type); if (info) { - for (u32 i = 0; i < info->num_bindings; i++) + for (const InputBindingInfo& bi : info->bindings) { - const InputBindingInfo& bi = info->bindings[i]; if (bi.bind_type == InputBindingInfo::Type::Unknown || bi.bind_type == InputBindingInfo::Type::Motor) continue; - ret.emplace_back(info->bindings[i].name); + ret.emplace_back(bi.name); } } return ret; } -void PadConfig::ClearPortBindings(SettingsInterface& si, u32 port) +void Pad::ClearPortBindings(SettingsInterface& si, u32 port) { const std::string section(StringUtil::StdStringFromFormat("Pad%u", port + 1)); const std::string type(si.GetStringValue(section.c_str(), "Type", GetDefaultPadType(port))); @@ -291,11 +324,11 @@ void PadConfig::ClearPortBindings(SettingsInterface& si, u32 port) if (!info) return; - for (u32 i = 0; i < info->num_bindings; i++) - si.DeleteValue(section.c_str(), info->bindings[i].name); + for (const InputBindingInfo& bi : info->bindings) + si.DeleteValue(section.c_str(), bi.name); } -void PadConfig::CopyConfiguration(SettingsInterface* dest_si, const SettingsInterface& src_si, +void Pad::CopyConfiguration(SettingsInterface* dest_si, const SettingsInterface& src_si, bool copy_pad_config, bool copy_pad_bindings, bool copy_hotkey_bindings) { if (copy_pad_config) @@ -329,15 +362,14 @@ void PadConfig::CopyConfiguration(SettingsInterface* dest_si, const SettingsInte if (copy_pad_bindings) { - for (u32 i = 0; i < info->num_bindings; i++) - { - const InputBindingInfo& bi = info->bindings[i]; + for (const InputBindingInfo& bi : info->bindings) dest_si->CopyStringListValue(src_si, section.c_str(), bi.name); - } - for (u32 i = 0; i < PadMacros::NUM_MACRO_BUTTONS_PER_CONTROLLER; i++) + for (u32 i = 0; i < NUM_MACRO_BUTTONS_PER_CONTROLLER; i++) { dest_si->CopyStringListValue(src_si, section.c_str(), fmt::format("Macro{}", i + 1).c_str()); + dest_si->CopyFloatValue(src_si, section.c_str(), fmt::format("Macro{}Pressure", i + 1).c_str()); + dest_si->CopyFloatValue(src_si, section.c_str(), fmt::format("Macro{}Deadzone", i + 1).c_str()); dest_si->CopyStringValue(src_si, section.c_str(), fmt::format("Macro{}Binds", i + 1).c_str()); dest_si->CopyUIntValue(src_si, section.c_str(), fmt::format("Macro{}Frequency", i + 1).c_str()); } @@ -353,9 +385,8 @@ void PadConfig::CopyConfiguration(SettingsInterface* dest_si, const SettingsInte dest_si->CopyFloatValue(src_si, section.c_str(), "SmallMotorScale"); } - for (u32 i = 0; i < info->num_settings; i++) + for (const SettingInfo& csi : info->settings) { - const SettingInfo& csi = info->settings[i]; switch (csi.type) { case SettingInfo::Type::Boolean: @@ -417,7 +448,7 @@ static u32 TryMapGenericMapping(SettingsInterface& si, const std::string& sectio } -bool PadConfig::MapController(SettingsInterface& si, u32 controller, +bool Pad::MapController(SettingsInterface& si, u32 controller, const std::vector>& mapping) { const std::string section(StringUtil::StdStringFromFormat("Pad%u", controller + 1)); @@ -427,9 +458,8 @@ bool PadConfig::MapController(SettingsInterface& si, u32 controller, return false; u32 num_mappings = 0; - for (u32 i = 0; i < info->num_bindings; i++) + for (const InputBindingInfo& bi : info->bindings) { - const InputBindingInfo& bi = info->bindings[i]; if (bi.generic_mapping == GenericInputBinding::Unknown) continue; @@ -451,7 +481,7 @@ bool PadConfig::MapController(SettingsInterface& si, u32 controller, return (num_mappings > 0); } -std::vector PadConfig::GetInputProfileNames() +std::vector Pad::GetInputProfileNames() { FileSystem::FindResultsArray results; FileSystem::FindFiles(EmuFolders::InputProfiles.c_str(), "*.ini", @@ -465,17 +495,123 @@ std::vector PadConfig::GetInputProfileNames() return ret; } -std::string PadConfig::GetConfigSection(u32 pad_index) +std::string Pad::GetConfigSection(u32 pad_index) { return fmt::format("Pad{}", pad_index + 1); } -void PadConfig::LoadMacroButtonConfig(const SettingsInterface& si, u32 pad, const std::string_view& type, const std::string& section) +std::unique_ptr Pad::CreatePad(u8 unifiedSlot, ControllerType controllerType) +{ + switch (controllerType) + { + case ControllerType::DualShock2: + return std::make_unique(unifiedSlot); + case ControllerType::Guitar: + return std::make_unique(unifiedSlot); + default: + return std::make_unique(unifiedSlot); + } +} + +PadBase* Pad::ChangePadType(u8 unifiedSlot, ControllerType controllerType) +{ + s_controllers[unifiedSlot] = CreatePad(unifiedSlot, controllerType); + return s_controllers[unifiedSlot].get(); +} + +bool Pad::HasConnectedPad(u8 unifiedSlot) +{ + return ( + unifiedSlot < NUM_CONTROLLER_PORTS && s_controllers[unifiedSlot]->GetType() != ControllerType::NotConnected); +} + +PadBase* Pad::GetPad(u8 port, u8 slot) +{ + const u8 unifiedSlot = sioConvertPortAndSlotToPad(port, slot); + return s_controllers[unifiedSlot].get(); +} + +PadBase* Pad::GetPad(const u8 unifiedSlot) +{ + return s_controllers[unifiedSlot].get(); +} + +void Pad::SetControllerState(u32 controller, u32 bind, float value) +{ + if (controller >= NUM_CONTROLLER_PORTS) + return; + + s_controllers[controller]->Set(bind, value); +} + +bool Pad::Freeze(StateWrapper& sw) +{ + if (sw.IsReading()) + { + if (!sw.DoMarker("PAD")) + { + Console.Error("PAD state is invalid! Leaving the current state in place."); + return false; + } + + for (u32 unifiedSlot = 0; unifiedSlot < NUM_CONTROLLER_PORTS; unifiedSlot++) + { + ControllerType type; + sw.Do(&type); + if (sw.HasError()) + return false; + + std::unique_ptr tempPad; + PadBase* pad = GetPad(unifiedSlot); + if (!pad || pad->GetType() != type) + { + const auto& [port, slot] = sioConvertPadToPortAndSlot(unifiedSlot); + Host::AddIconOSDMessage(fmt::format("UnfreezePad{}Changed", unifiedSlot), ICON_FA_GAMEPAD, + fmt::format(TRANSLATE_FS("Pad", + "Controller port {}, slot {} has a {} connected, but the save state has a " + "{}.\nLeaving the original controller type connected, but this may cause issues."), + port, slot, + Pad::GetControllerTypeName(pad ? pad->GetType() : Pad::ControllerType::NotConnected), + Pad::GetControllerTypeName(type))); + + // Reset the transfer etc state of the pad, at least it has a better chance of surviving. + if (pad) + pad->SoftReset(); + + // But we still need to pull the data from the state.. + tempPad = CreatePad(unifiedSlot, type); + pad = tempPad.get(); + } + + if (!pad->Freeze(sw)) + return false; + } + } + else + { + if (!sw.DoMarker("PAD")) + return false; + + for (u32 unifiedSlot = 0; unifiedSlot < NUM_CONTROLLER_PORTS; unifiedSlot++) + { + PadBase* pad = GetPad(unifiedSlot); + ControllerType type = pad->GetType(); + sw.Do(&type); + if (sw.HasError() || !pad->Freeze(sw)) + return false; + } + } + + return !sw.HasError(); +} + + +void Pad::LoadMacroButtonConfig(const SettingsInterface& si, u32 pad, const std::string_view& type, const std::string& section) { // lazily initialized std::vector binds; - for (u32 i = 0; i < PadMacros::NUM_MACRO_BUTTONS_PER_CONTROLLER; i++) + for (u32 i = 0; i < NUM_MACRO_BUTTONS_PER_CONTROLLER; i++) { std::string binds_string; if (!si.GetStringValue(section.c_str(), StringUtil::StdStringFromFormat("Macro%uBinds", i + 1).c_str(), &binds_string)) @@ -485,6 +621,8 @@ void PadConfig::LoadMacroButtonConfig(const SettingsInterface& si, u32 pad, cons if (binds.empty()) binds = GetControllerBinds(type); + const float pressure = si.GetFloatValue(section.c_str(), fmt::format("Macro{}Pressure", i + 1).c_str(), 1.0f); + // convert binds std::vector bind_indices; std::vector buttons_split(StringUtil::SplitString(binds_string, '&', true)); @@ -504,8 +642,63 @@ void PadConfig::LoadMacroButtonConfig(const SettingsInterface& si, u32 pad, cons if (bind_indices.empty()) continue; - PadMacros::MacroButton& macro = g_PadMacros.GetMacroButton(pad, i); + MacroButton& macro = s_macro_buttons[pad][i]; macro.buttons = std::move(bind_indices); macro.toggle_frequency = frequency; + macro.pressure = pressure; + } +} + +void Pad::SetMacroButtonState(u32 pad, u32 index, bool state) +{ + if (pad >= Pad::NUM_CONTROLLER_PORTS || index >= NUM_MACRO_BUTTONS_PER_CONTROLLER) + return; + + MacroButton& mb = s_macro_buttons[pad][index]; + if (mb.buttons.empty() || mb.trigger_state == state) + return; + + mb.toggle_counter = mb.toggle_frequency; + mb.trigger_state = state; + if (mb.toggle_state != state) + { + mb.toggle_state = state; + ApplyMacroButton(pad, mb); + } +} + +void Pad::ApplyMacroButton(u32 controller, const Pad::MacroButton& mb) +{ + const float value = mb.toggle_state ? mb.pressure : 0.0f; + PadBase* const pad = Pad::GetPad(controller); + + for (const u32 btn : mb.buttons) + pad->Set(btn, value); +} + +void Pad::UpdateMacroButtons() +{ + for (u32 pad = 0; pad < Pad::NUM_CONTROLLER_PORTS; pad++) + { + for (u32 index = 0; index < NUM_MACRO_BUTTONS_PER_CONTROLLER; index++) + { + Pad::MacroButton& mb = s_macro_buttons[pad][index]; + + if (!mb.trigger_state || mb.toggle_frequency == 0) + { + continue; + } + + mb.toggle_counter--; + + if (mb.toggle_counter > 0) + { + continue; + } + + mb.toggle_counter = mb.toggle_frequency; + mb.toggle_state = !mb.toggle_state; + ApplyMacroButton(pad, mb); + } } } \ No newline at end of file diff --git a/pcsx2/SIO/Pad/PadConfig.h b/pcsx2/SIO/Pad/Pad.h similarity index 70% rename from pcsx2/SIO/Pad/PadConfig.h rename to pcsx2/SIO/Pad/Pad.h index 214b82ac74..6f1c28f506 100644 --- a/pcsx2/SIO/Pad/PadConfig.h +++ b/pcsx2/SIO/Pad/Pad.h @@ -15,58 +15,69 @@ #pragma once +#include "Config.h" #include "SIO/Pad/PadTypes.h" -#include "Config.h" +#include + +class PadBase; -class SettingsInterface; enum class GenericInputBinding : u8; +class SettingsInterface; +class StateWrapper; -class PadConfig +namespace Pad { -public: // Constants - struct ControllerInfo - { - Pad::ControllerType type; - const char* name; - const char* display_name; - const InputBindingInfo* bindings; - u32 num_bindings; - const SettingInfo* settings; - u32 num_settings; - Pad::VibrationCapabilities vibration_caps; - }; - -public: // Public members - PadConfig(); - ~PadConfig(); + bool Initialize(); + void Shutdown(); // Returns the default type for the specified port. const char* GetDefaultPadType(u32 pad); + // Reloads configuration. void LoadConfig(const SettingsInterface& si); + // Restores default configuration. void SetDefaultControllerConfig(SettingsInterface& si); void SetDefaultHotkeyConfig(SettingsInterface& si); + // Clears all bindings for a given port. void ClearPortBindings(SettingsInterface& si, u32 port); + // Copies pad configuration from one interface (ini) to another. - void CopyConfiguration(SettingsInterface* dest_si, const SettingsInterface& src_si, - bool copy_pad_config = true, bool copy_pad_bindings = true, bool copy_hotkey_bindings = true); + void CopyConfiguration(SettingsInterface* dest_si, const SettingsInterface& src_si, bool copy_pad_config = true, + bool copy_pad_bindings = true, bool copy_hotkey_bindings = true); + // Returns a list of controller type names. Pair of [name, display name]. const std::vector> GetControllerTypeNames(); + // Returns the list of binds for the specified controller type. std::vector GetControllerBinds(const std::string_view& type); + // Returns general information for the specified controller type. const ControllerInfo* GetControllerInfo(Pad::ControllerType type); const ControllerInfo* GetControllerInfo(const std::string_view& name); + const char* GetControllerTypeName(Pad::ControllerType type); + // Performs automatic controller mapping with the provided list of generic mappings. - bool MapController(SettingsInterface& si, u32 controller, - const std::vector>& mapping); + bool MapController( + SettingsInterface& si, u32 controller, const std::vector>& mapping); + // Returns a list of input profiles available. std::vector GetInputProfileNames(); std::string GetConfigSection(u32 pad_index); - void LoadMacroButtonConfig(const SettingsInterface& si, u32 pad, const std::string_view& type, const std::string& section); -}; -extern PadConfig g_PadConfig; + bool HasConnectedPad(u8 unifiedSlot); + + PadBase* GetPad(u8 port, u8 slot); + PadBase* GetPad(const u8 unifiedSlot); + + // Sets the specified bind on a controller to the specified pressure (normalized to 0..1). + void SetControllerState(u32 controller, u32 bind, float value); + + bool Freeze(StateWrapper& sw); + + // Sets the state of the specified macro button. + void SetMacroButtonState(u32 pad, u32 index, bool state); + void UpdateMacroButtons(); +}; // namespace Pad diff --git a/pcsx2/SIO/Pad/PadBase.cpp b/pcsx2/SIO/Pad/PadBase.cpp index 2c01fbbb73..ef0f6e7beb 100644 --- a/pcsx2/SIO/Pad/PadBase.cpp +++ b/pcsx2/SIO/Pad/PadBase.cpp @@ -34,3 +34,18 @@ void PadBase::FullReset() this->isInConfig = false; this->currentMode = Pad::Mode::DIGITAL; } + +bool PadBase::Freeze(StateWrapper& sw) +{ + if (!sw.DoMarker("PadBase")) + return false; + + // Protected PadBase members + sw.Do(&rawInputs); + sw.Do(&unifiedSlot); + sw.Do(&isInConfig); + sw.Do(¤tMode); + sw.Do(¤tCommand); + sw.Do(&commandBytesReceived); + return !sw.HasError(); +} diff --git a/pcsx2/SIO/Pad/PadBase.h b/pcsx2/SIO/Pad/PadBase.h index 2a39487323..e99c8068ee 100644 --- a/pcsx2/SIO/Pad/PadBase.h +++ b/pcsx2/SIO/Pad/PadBase.h @@ -39,25 +39,27 @@ public: // Public members void FullReset(); virtual void Init() = 0; - virtual Pad::ControllerType GetType() = 0; + virtual Pad::ControllerType GetType() const = 0; + virtual const Pad::ControllerInfo& GetInfo() const = 0; + virtual void Set(u32 index, float value) = 0; virtual void SetRawAnalogs(const std::tuple left, const std::tuple right) = 0; virtual void SetAxisScale(float deadzone, float scale) = 0; virtual void SetTriggerScale(float deadzone, float scale) = 0; - virtual float GetVibrationScale(u32 motor) = 0; + virtual float GetVibrationScale(u32 motor) const = 0; virtual void SetVibrationScale(u32 motor, float scale) = 0; - virtual float GetPressureModifier() = 0; + virtual float GetPressureModifier() const = 0; virtual void SetPressureModifier(float mod) = 0; virtual void SetButtonDeadzone(float deadzone) = 0; virtual void SetAnalogInvertL(bool x, bool y) = 0; virtual void SetAnalogInvertR(bool x, bool y) = 0; - virtual u8 GetRawInput(u32 index) = 0; - virtual std::tuple GetRawLeftAnalog() = 0; - virtual std::tuple GetRawRightAnalog() = 0; - virtual u32 GetButtons() = 0; - virtual u8 GetPressure(u32 index) = 0; + virtual u8 GetRawInput(u32 index) const = 0; + virtual std::tuple GetRawLeftAnalog() const = 0; + virtual std::tuple GetRawRightAnalog() const = 0; + virtual u32 GetButtons() const = 0; + virtual u8 GetPressure(u32 index) const = 0; - virtual void Freeze(StateWrapper& sw) = 0; + virtual bool Freeze(StateWrapper& sw); virtual u8 SendCommandByte(u8 commandByte) = 0; }; diff --git a/pcsx2/SIO/Pad/PadDualshock2.cpp b/pcsx2/SIO/Pad/PadDualshock2.cpp index 914184720b..7b7863e267 100644 --- a/pcsx2/SIO/Pad/PadDualshock2.cpp +++ b/pcsx2/SIO/Pad/PadDualshock2.cpp @@ -16,8 +16,7 @@ #include "PrecompiledHeader.h" #include "SIO/Pad/PadDualshock2.h" - -#include "SIO/Pad/PadManager.h" +#include "SIO/Pad/Pad.h" #include "SIO/Sio.h" #include "SIO/Sio0.h" @@ -25,6 +24,77 @@ #include "Input/InputManager.h" #include "Host.h" +static const InputBindingInfo s_bindings[] = { + // clang-format off + {"Up", TRANSLATE_NOOP("Pad", "D-Pad Up"), InputBindingInfo::Type::Button, PadDualshock2::Inputs::PAD_UP, GenericInputBinding::DPadUp}, + {"Right", TRANSLATE_NOOP("Pad", "D-Pad Right"), InputBindingInfo::Type::Button, PadDualshock2::Inputs::PAD_RIGHT, GenericInputBinding::DPadRight}, + {"Down", TRANSLATE_NOOP("Pad", "D-Pad Down"), InputBindingInfo::Type::Button, PadDualshock2::Inputs::PAD_DOWN, GenericInputBinding::DPadDown}, + {"Left", TRANSLATE_NOOP("Pad", "D-Pad Left"), InputBindingInfo::Type::Button, PadDualshock2::Inputs::PAD_LEFT, GenericInputBinding::DPadLeft}, + {"Triangle", TRANSLATE_NOOP("Pad", "Triangle"), InputBindingInfo::Type::Button, PadDualshock2::Inputs::PAD_TRIANGLE, GenericInputBinding::Triangle}, + {"Circle", TRANSLATE_NOOP("Pad", "Circle"), InputBindingInfo::Type::Button, PadDualshock2::Inputs::PAD_CIRCLE, GenericInputBinding::Circle}, + {"Cross", TRANSLATE_NOOP("Pad", "Cross"), InputBindingInfo::Type::Button, PadDualshock2::Inputs::PAD_CROSS, GenericInputBinding::Cross}, + {"Square", TRANSLATE_NOOP("Pad", "Square"), InputBindingInfo::Type::Button, PadDualshock2::Inputs::PAD_SQUARE, GenericInputBinding::Square}, + {"Select", TRANSLATE_NOOP("Pad", "Select"), InputBindingInfo::Type::Button, PadDualshock2::Inputs::PAD_SELECT, GenericInputBinding::Select}, + {"Start", TRANSLATE_NOOP("Pad", "Start"), InputBindingInfo::Type::Button, PadDualshock2::Inputs::PAD_START, GenericInputBinding::Start}, + {"L1", TRANSLATE_NOOP("Pad", "L1 (Left Bumper)"), InputBindingInfo::Type::Button, PadDualshock2::Inputs::PAD_L1, GenericInputBinding::L1}, + {"L2", TRANSLATE_NOOP("Pad", "L2 (Left Trigger)"), InputBindingInfo::Type::HalfAxis, PadDualshock2::Inputs::PAD_L2, GenericInputBinding::L2}, + {"R1", TRANSLATE_NOOP("Pad", "R1 (Right Bumper)"), InputBindingInfo::Type::Button, PadDualshock2::Inputs::PAD_R1, GenericInputBinding::R1}, + {"R2", TRANSLATE_NOOP("Pad", "R2 (Right Trigger)"), InputBindingInfo::Type::HalfAxis, PadDualshock2::Inputs::PAD_R2, GenericInputBinding::R2}, + {"L3", TRANSLATE_NOOP("Pad", "L3 (Left Stick Button)"), InputBindingInfo::Type::Button, PadDualshock2::Inputs::PAD_L3, GenericInputBinding::L3}, + {"R3", TRANSLATE_NOOP("Pad", "R3 (Right Stick Button)"), InputBindingInfo::Type::Button, PadDualshock2::Inputs::PAD_R3, GenericInputBinding::R3}, + {"Analog", TRANSLATE_NOOP("Pad", "Analog Toggle"), InputBindingInfo::Type::Button, PadDualshock2::Inputs::PAD_ANALOG, GenericInputBinding::System}, + {"Pressure", TRANSLATE_NOOP("Pad", "Apply Pressure"), InputBindingInfo::Type::Button, PadDualshock2::Inputs::PAD_PRESSURE, GenericInputBinding::Unknown}, + {"LUp", TRANSLATE_NOOP("Pad", "Left Stick Up"), InputBindingInfo::Type::HalfAxis, PadDualshock2::Inputs::PAD_L_UP, GenericInputBinding::LeftStickUp}, + {"LRight", TRANSLATE_NOOP("Pad", "Left Stick Right"), InputBindingInfo::Type::HalfAxis, PadDualshock2::Inputs::PAD_L_RIGHT, GenericInputBinding::LeftStickRight}, + {"LDown", TRANSLATE_NOOP("Pad", "Left Stick Down"), InputBindingInfo::Type::HalfAxis, PadDualshock2::Inputs::PAD_L_DOWN, GenericInputBinding::LeftStickDown}, + {"LLeft", TRANSLATE_NOOP("Pad", "Left Stick Left"), InputBindingInfo::Type::HalfAxis, PadDualshock2::Inputs::PAD_L_LEFT, GenericInputBinding::LeftStickLeft}, + {"RUp", TRANSLATE_NOOP("Pad", "Right Stick Up"), InputBindingInfo::Type::HalfAxis, PadDualshock2::Inputs::PAD_R_UP, GenericInputBinding::RightStickUp}, + {"RRight", TRANSLATE_NOOP("Pad", "Right Stick Right"), InputBindingInfo::Type::HalfAxis, PadDualshock2::Inputs::PAD_R_RIGHT, GenericInputBinding::RightStickRight}, + {"RDown", TRANSLATE_NOOP("Pad", "Right Stick Down"), InputBindingInfo::Type::HalfAxis, PadDualshock2::Inputs::PAD_R_DOWN, GenericInputBinding::RightStickDown}, + {"RLeft", TRANSLATE_NOOP("Pad", "Right Stick Left"), InputBindingInfo::Type::HalfAxis, PadDualshock2::Inputs::PAD_R_LEFT, GenericInputBinding::RightStickLeft}, + {"LargeMotor", TRANSLATE_NOOP("Pad", "Large (Low Frequency) Motor"), InputBindingInfo::Type::Motor, 0, GenericInputBinding::LargeMotor}, + {"SmallMotor", TRANSLATE_NOOP("Pad", "Small (High Frequency) Motor"), InputBindingInfo::Type::Motor, 0, GenericInputBinding::SmallMotor}, + // clang-format on +}; + +static const char* s_invert_options[] = {TRANSLATE_NOOP("Pad", "Not Inverted"), + TRANSLATE_NOOP("Pad", "Invert Left/Right"), TRANSLATE_NOOP("Pad", "Invert Up/Down"), + TRANSLATE_NOOP("Pad", "Invert Left/Right + Up/Down"), nullptr}; + +static const SettingInfo s_settings[] = { + {SettingInfo::Type::IntegerList, "InvertL", TRANSLATE_NOOP("Pad", "Invert Left Stick"), + TRANSLATE_NOOP("Pad", "Inverts the direction of the left analog stick."), "0", "0", "3", nullptr, nullptr, + s_invert_options, nullptr, 0.0f}, + {SettingInfo::Type::IntegerList, "InvertR", TRANSLATE_NOOP("Pad", "Invert Right Stick"), + TRANSLATE_NOOP("Pad", "Inverts the direction of the right analog stick."), "0", "0", "3", nullptr, nullptr, + s_invert_options, nullptr, 0.0f}, + {SettingInfo::Type::Float, "Deadzone", TRANSLATE_NOOP("Pad", "Analog Deadzone"), + TRANSLATE_NOOP( + "Pad", "Sets the analog stick deadzone, i.e. the fraction of the stick movement which will be ignored."), + "0.00", "0.00", "1.00", "0.01", "%.0f%%", nullptr, nullptr, 100.0f}, + {SettingInfo::Type::Float, "AxisScale", TRANSLATE_NOOP("Pad", "Analog Sensitivity"), + TRANSLATE_NOOP("Pad", + "Sets the analog stick axis scaling factor. A value between 1.30 and 1.40 is recommended when using recent " + "controllers, e.g. DualShock 4, Xbox One Controller."), + "1.33", "0.01", "2.00", "0.01", "%.0f%%", nullptr, nullptr, 100.0f}, + {SettingInfo::Type::Float, "LargeMotorScale", TRANSLATE_NOOP("Pad", "Large Motor Vibration Scale"), + TRANSLATE_NOOP("Pad", "Increases or decreases the intensity of low frequency vibration sent by the game."), + "1.00", "0.00", "2.00", "0.01", "%.0f%%", nullptr, nullptr, 100.0f}, + {SettingInfo::Type::Float, "SmallMotorScale", TRANSLATE_NOOP("Pad", "Small Motor Vibration Scale"), + TRANSLATE_NOOP("Pad", "Increases or decreases the intensity of high frequency vibration sent by the game."), + "1.00", "0.00", "2.00", "0.01", "%.0f%%", nullptr, nullptr, 100.0f}, + {SettingInfo::Type::Float, "ButtonDeadzone", TRANSLATE_NOOP("Pad", "Button/Trigger Deadzone"), + TRANSLATE_NOOP("Pad", "Sets the deadzone for activating buttons/triggers, i.e. the fraction of the trigger " + "which will be ignored."), + "0.00", "0.00", "1.00", "0.01", "%.0f%%", nullptr, nullptr, 100.0f}, + {SettingInfo::Type::Float, "PressureModifier", TRANSLATE_NOOP("Pad", "Modifier Pressure"), + TRANSLATE_NOOP("Pad", "Sets the pressure when the modifier button is held."), "0.50", "0.01", "1.00", "0.01", + "%.0f%%", nullptr, nullptr, 100.0f}, +}; + +const Pad::ControllerInfo PadDualshock2::ControllerInfo = {Pad::ControllerType::DualShock2, "DualShock2", + TRANSLATE_NOOP("Pad", "DualShock 2"), s_bindings, s_settings, Pad::VibrationCapabilities::LargeSmallMotors}; + u8 PadDualshock2::Mystery(u8 commandByte) { switch (commandBytesReceived) @@ -57,19 +127,18 @@ u8 PadDualshock2::ButtonQuery(u8 commandByte) u8 PadDualshock2::Poll(u8 commandByte) { - PadBase* pad = g_PadManager.GetPad(this->unifiedSlot); - const u32 buttons = pad->GetButtons(); + const u32 buttons = GetButtons(); switch (commandBytesReceived) { case 3: - this->vibrationMotors.at(0) = commandByte; + this->vibrationMotors[0] = commandByte; return (buttons >> 8) & 0xff; case 4: - this->vibrationMotors.at(1) = commandByte; + this->vibrationMotors[1] = commandByte; InputManager::SetPadVibrationIntensity(this->unifiedSlot, - std::min(static_cast(this->vibrationMotors.at(0)) * GetVibrationScale(0) * (1.0f / 255.0f), 1.0f), - std::min(static_cast(this->vibrationMotors.at(1)) * GetVibrationScale(1) * (1.0f / 255.0f), 1.0f) + std::min(static_cast(this->vibrationMotors[0]) * GetVibrationScale(0) * (1.0f / 255.0f), 1.0f), + std::min(static_cast(this->vibrationMotors[1]) * GetVibrationScale(1) * (1.0f / 255.0f), 1.0f) ); // PS1 mode: If the controller is still in digital mode, it is time to stop acknowledging. @@ -80,40 +149,40 @@ u8 PadDualshock2::Poll(u8 commandByte) return buttons & 0xff; case 5: - return pad->GetPressure(Dualshock2::Inputs::PAD_R_RIGHT); + return GetPressure(Inputs::PAD_R_RIGHT); case 6: - return pad->GetPressure(Dualshock2::Inputs::PAD_R_UP); + return GetPressure(Inputs::PAD_R_UP); case 7: - return pad->GetPressure(Dualshock2::Inputs::PAD_L_RIGHT); + return GetPressure(Inputs::PAD_L_RIGHT); case 8: // PS1 mode: If the controller reaches this byte, it is in analog mode and has irrefutably reached the last byte. // There's simply nothing to check, we know it's done and time to stop acknowledgements. g_Sio0.SetAcknowledge(false); - return pad->GetPressure(Dualshock2::Inputs::PAD_L_UP); + return GetPressure(Inputs::PAD_L_UP); case 9: - return IsButtonBitSet(buttons, 13) ? pad->GetPressure(Dualshock2::Inputs::PAD_RIGHT) : 0; + return IsButtonBitSet(buttons, 13) ? GetPressure(Inputs::PAD_RIGHT) : 0; case 10: - return IsButtonBitSet(buttons, 15) ? pad->GetPressure(Dualshock2::Inputs::PAD_LEFT) : 0; + return IsButtonBitSet(buttons, 15) ? GetPressure(Inputs::PAD_LEFT) : 0; case 11: - return IsButtonBitSet(buttons, 12) ? pad->GetPressure(Dualshock2::Inputs::PAD_UP) : 0; + return IsButtonBitSet(buttons, 12) ? GetPressure(Inputs::PAD_UP) : 0; case 12: - return IsButtonBitSet(buttons, 14) ? pad->GetPressure(Dualshock2::Inputs::PAD_DOWN) : 0; + return IsButtonBitSet(buttons, 14) ? GetPressure(Inputs::PAD_DOWN) : 0; case 13: - return IsButtonBitSet(buttons, 4) ? pad->GetPressure(Dualshock2::Inputs::PAD_TRIANGLE) : 0; + return IsButtonBitSet(buttons, 4) ? GetPressure(Inputs::PAD_TRIANGLE) : 0; case 14: - return IsButtonBitSet(buttons, 5) ? pad->GetPressure(Dualshock2::Inputs::PAD_CIRCLE) : 0; + return IsButtonBitSet(buttons, 5) ? GetPressure(Inputs::PAD_CIRCLE) : 0; case 15: - return IsButtonBitSet(buttons, 6) ? pad->GetPressure(Dualshock2::Inputs::PAD_CROSS) : 0; + return IsButtonBitSet(buttons, 6) ? GetPressure(Inputs::PAD_CROSS) : 0; case 16: - return IsButtonBitSet(buttons, 7) ? pad->GetPressure(Dualshock2::Inputs::PAD_SQUARE) : 0; + return IsButtonBitSet(buttons, 7) ? GetPressure(Inputs::PAD_SQUARE) : 0; case 17: - return IsButtonBitSet(buttons, 2) ? pad->GetPressure(Dualshock2::Inputs::PAD_L1) : 0; + return IsButtonBitSet(buttons, 2) ? GetPressure(Inputs::PAD_L1) : 0; case 18: - return IsButtonBitSet(buttons, 3) ? pad->GetPressure(Dualshock2::Inputs::PAD_R1) : 0; + return IsButtonBitSet(buttons, 3) ? GetPressure(Inputs::PAD_R1) : 0; case 19: - return IsButtonBitSet(buttons, 0) ? pad->GetPressure(Dualshock2::Inputs::PAD_L2) : 0; + return IsButtonBitSet(buttons, 0) ? GetPressure(Inputs::PAD_L2) : 0; case 20: - return IsButtonBitSet(buttons, 1) ? pad->GetPressure(Dualshock2::Inputs::PAD_R2) : 0; + return IsButtonBitSet(buttons, 1) ? GetPressure(Inputs::PAD_R2) : 0; } Console.Warning("%s(%02X) Did not reach a valid return path! Returning zero as a failsafe!", __FUNCTION__, commandByte); @@ -224,17 +293,15 @@ u8 PadDualshock2::StatusInfo(u8 commandByte) u8 PadDualshock2::Constant1(u8 commandByte) { - static bool stage; - switch (commandBytesReceived) { case 3: - stage = commandByte; + commandStage = commandByte != 0; return 0x00; case 5: return 0x01; case 6: - if (stage) + if (commandStage) { return 0x01; } @@ -243,7 +310,7 @@ u8 PadDualshock2::Constant1(u8 commandByte) return 0x02; } case 7: - if (stage) + if (commandStage) { return 0x01; } @@ -253,7 +320,7 @@ u8 PadDualshock2::Constant1(u8 commandByte) } case 8: g_Sio0.SetAcknowledge(false); - return (stage ? 0x14 : 0x0a); + return (commandStage ? 0x14 : 0x0a); default: return 0x00; } @@ -275,15 +342,13 @@ u8 PadDualshock2::Constant2(u8 commandByte) u8 PadDualshock2::Constant3(u8 commandByte) { - static bool stage; - switch (commandBytesReceived) { case 3: - stage = commandByte; + commandStage = (commandByte != 0); return 0x00; case 6: - if (stage) + if (commandStage) { return 0x07; } @@ -379,38 +444,43 @@ void PadDualshock2::Init() for (u8 i = 0; i < this->rawInputs.size(); i++) { - this->rawInputs.at(i) = 0; + this->rawInputs[i] = 0; } for (u8 i = 0; i < this->pressures.size(); i++) { - this->pressures.at(i) = 0; + this->pressures[i] = 0; } this->axisScale = 1.0f; this->axisDeadzone = 0.0f; - this->vibrationScale.at(0) = 0.0f; - this->vibrationScale.at(1) = 1.0f; + this->vibrationScale[0] = 0.0f; + this->vibrationScale[1] = 1.0f; this->pressureModifier = 0.5f; this->buttonDeadzone = 0.0f; } -Pad::ControllerType PadDualshock2::GetType() +Pad::ControllerType PadDualshock2::GetType() const { return Pad::ControllerType::DualShock2; } +const Pad::ControllerInfo& PadDualshock2::GetInfo() const +{ + return ControllerInfo; +} + void PadDualshock2::Set(u32 index, float value) { - if (index > Dualshock2::Inputs::LENGTH) + if (index > Inputs::LENGTH) { return; } // Since we reordered the buttons for better UI, we need to remap them here. - static constexpr std::array bitmaskMapping = {{ + static constexpr std::array bitmaskMapping = {{ 12, // PAD_UP 13, // PAD_RIGHT 14, // PAD_DOWN @@ -445,17 +515,17 @@ void PadDualshock2::Set(u32 index, float value) // merge left/right or up/down into rx or ry #define MERGE(pos, neg) ((this->rawInputs[pos] != 0) ? (127u + ((this->rawInputs[pos] + 1u) / 2u)) : (127u - (this->rawInputs[neg] / 2u))) - if (index <= Dualshock2::Inputs::PAD_L_LEFT) + if (index <= Inputs::PAD_L_LEFT) { // Left Stick - this->analogs.lx = this->analogs.lxInvert ? MERGE(Dualshock2::Inputs::PAD_L_LEFT, Dualshock2::Inputs::PAD_L_RIGHT) : MERGE(Dualshock2::Inputs::PAD_L_RIGHT, Dualshock2::Inputs::PAD_L_LEFT); - this->analogs.ly = this->analogs.lyInvert ? MERGE(Dualshock2::Inputs::PAD_L_UP, Dualshock2::Inputs::PAD_L_DOWN) : MERGE(Dualshock2::Inputs::PAD_L_DOWN, Dualshock2::Inputs::PAD_L_UP); + this->analogs.lx = this->analogs.lxInvert ? MERGE(Inputs::PAD_L_LEFT, Inputs::PAD_L_RIGHT) : MERGE(Inputs::PAD_L_RIGHT, Inputs::PAD_L_LEFT); + this->analogs.ly = this->analogs.lyInvert ? MERGE(Inputs::PAD_L_UP, Inputs::PAD_L_DOWN) : MERGE(Inputs::PAD_L_DOWN, Inputs::PAD_L_UP); } else { // Right Stick - this->analogs.rx = this->analogs.rxInvert ? MERGE(Dualshock2::Inputs::PAD_R_LEFT, Dualshock2::Inputs::PAD_R_RIGHT) : MERGE(Dualshock2::Inputs::PAD_R_RIGHT, Dualshock2::Inputs::PAD_R_LEFT); - this->analogs.ry = this->analogs.ryInvert ? MERGE(Dualshock2::Inputs::PAD_R_UP, Dualshock2::Inputs::PAD_R_DOWN) : MERGE(Dualshock2::Inputs::PAD_R_DOWN, Dualshock2::Inputs::PAD_R_UP); + this->analogs.rx = this->analogs.rxInvert ? MERGE(Inputs::PAD_R_LEFT, Inputs::PAD_R_RIGHT) : MERGE(Inputs::PAD_R_RIGHT, Inputs::PAD_R_LEFT); + this->analogs.ry = this->analogs.ryInvert ? MERGE(Inputs::PAD_R_UP, Inputs::PAD_R_DOWN) : MERGE(Inputs::PAD_R_DOWN, Inputs::PAD_R_UP); } #undef MERGE @@ -466,15 +536,15 @@ void PadDualshock2::Set(u32 index, float value) { #define MERGE_F(pos, neg) ((this->rawInputs[pos] != 0) ? (static_cast(this->rawInputs[pos]) / 255.0f) : (static_cast(this->rawInputs[neg]) / -255.0f)) float posX, posY; - if (index <= Dualshock2::Inputs::PAD_L_LEFT) + if (index <= Inputs::PAD_L_LEFT) { - posX = this->analogs.lxInvert ? MERGE_F(Dualshock2::Inputs::PAD_L_LEFT, Dualshock2::Inputs::PAD_L_RIGHT) : MERGE_F(Dualshock2::Inputs::PAD_L_RIGHT, Dualshock2::Inputs::PAD_L_LEFT); - posY = this->analogs.lyInvert ? MERGE_F(Dualshock2::Inputs::PAD_L_UP, Dualshock2::Inputs::PAD_L_DOWN) : MERGE_F(Dualshock2::Inputs::PAD_L_DOWN, Dualshock2::Inputs::PAD_L_UP); + posX = this->analogs.lxInvert ? MERGE_F(Inputs::PAD_L_LEFT, Inputs::PAD_L_RIGHT) : MERGE_F(Inputs::PAD_L_RIGHT, Inputs::PAD_L_LEFT); + posY = this->analogs.lyInvert ? MERGE_F(Inputs::PAD_L_UP, Inputs::PAD_L_DOWN) : MERGE_F(Inputs::PAD_L_DOWN, Inputs::PAD_L_UP); } else { - posX = this->analogs.rxInvert ? MERGE_F(Dualshock2::Inputs::PAD_R_LEFT, Dualshock2::Inputs::PAD_R_RIGHT) : MERGE_F(Dualshock2::Inputs::PAD_R_RIGHT, Dualshock2::Inputs::PAD_R_LEFT); - posY = this->analogs.ryInvert ? MERGE_F(Dualshock2::Inputs::PAD_R_UP, Dualshock2::Inputs::PAD_R_DOWN) : MERGE_F(Dualshock2::Inputs::PAD_R_DOWN, Dualshock2::Inputs::PAD_R_UP); + posX = this->analogs.rxInvert ? MERGE_F(Inputs::PAD_R_LEFT, Inputs::PAD_R_RIGHT) : MERGE_F(Inputs::PAD_R_RIGHT, Inputs::PAD_R_LEFT); + posY = this->analogs.ryInvert ? MERGE_F(Inputs::PAD_R_UP, Inputs::PAD_R_DOWN) : MERGE_F(Inputs::PAD_R_DOWN, Inputs::PAD_R_UP); } // No point checking if we're at dead center (usually keyboard with no buttons pressed). @@ -494,7 +564,7 @@ void PadDualshock2::Set(u32 index, float value) if (inX && inY) { // In deadzone. Set to 127 (center). - if (index <= Dualshock2::Inputs::PAD_L_LEFT) + if (index <= Inputs::PAD_L_LEFT) { this->analogs.lx = this->analogs.ly = 127; } @@ -520,7 +590,7 @@ void PadDualshock2::Set(u32 index, float value) else { // Don't affect L2/R2, since they are analog on most pads. - const float pMod = ((this->buttons & (1u << Dualshock2::Inputs::PAD_PRESSURE)) == 0 && !IsTriggerKey(index)) ? this->pressureModifier : 1.0f; + const float pMod = ((this->buttons & (1u << Inputs::PAD_PRESSURE)) == 0 && !IsTriggerKey(index)) ? this->pressureModifier : 1.0f; const float dzValue = (value < this->buttonDeadzone) ? 0.0f : value; this->rawInputs[index] = static_cast(std::clamp(dzValue * pMod * 255.0f, 0.0f, 255.0f)); @@ -534,11 +604,11 @@ void PadDualshock2::Set(u32 index, float value) } // Adjust pressure of all other face buttons which are active when pressure modifier is pressed.. - if (index == Dualshock2::Inputs::PAD_PRESSURE) + if (index == Inputs::PAD_PRESSURE) { - const float adjustPMod = ((this->buttons & (1u << Dualshock2::Inputs::PAD_PRESSURE)) == 0) ? this->pressureModifier : (1.0f / this->pressureModifier); + const float adjustPMod = ((this->buttons & (1u << Inputs::PAD_PRESSURE)) == 0) ? this->pressureModifier : (1.0f / this->pressureModifier); - for (u32 i = 0; i < Dualshock2::Inputs::LENGTH; i++) + for (u32 i = 0; i < Inputs::LENGTH; i++) { if (i == index || IsAnalogKey(i) || IsTriggerKey(i)) { @@ -551,7 +621,7 @@ void PadDualshock2::Set(u32 index, float value) } } - if (index == Dualshock2::Inputs::PAD_ANALOG && !this->analogPressed && value > 0) + if (index == Inputs::PAD_ANALOG && !this->analogPressed && value > 0) { this->analogPressed = true; @@ -605,7 +675,7 @@ void PadDualshock2::SetTriggerScale(float deadzone, float scale) this->triggerScale = scale; } -float PadDualshock2::GetVibrationScale(u32 motor) +float PadDualshock2::GetVibrationScale(u32 motor) const { return this->vibrationScale[motor]; } @@ -615,7 +685,7 @@ void PadDualshock2::SetVibrationScale(u32 motor, float scale) this->vibrationScale[motor] = scale; } -float PadDualshock2::GetPressureModifier() +float PadDualshock2::GetPressureModifier() const { return this->pressureModifier; } @@ -642,63 +712,59 @@ void PadDualshock2::SetAnalogInvertR(bool x, bool y) this->analogs.ryInvert = y; } -u8 PadDualshock2::GetRawInput(u32 index) +u8 PadDualshock2::GetRawInput(u32 index) const { - return this->rawInputs[index]; + return rawInputs[index]; } -std::tuple PadDualshock2::GetRawLeftAnalog() +std::tuple PadDualshock2::GetRawLeftAnalog() const { - return {this->analogs.lx, this->analogs.ly}; + return {analogs.lx, analogs.ly}; } -std::tuple PadDualshock2::GetRawRightAnalog() +std::tuple PadDualshock2::GetRawRightAnalog() const { - return {this->analogs.rx, this->analogs.ry}; + return {analogs.rx, analogs.ry}; } -u32 PadDualshock2::GetButtons() +u32 PadDualshock2::GetButtons() const { - return this->buttons; + return buttons; } -u8 PadDualshock2::GetPressure(u32 index) +u8 PadDualshock2::GetPressure(u32 index) const { switch (index) { - case Dualshock2::Inputs::PAD_R_LEFT: - case Dualshock2::Inputs::PAD_R_RIGHT: + case Inputs::PAD_R_LEFT: + case Inputs::PAD_R_RIGHT: return this->analogs.rx; - case Dualshock2::Inputs::PAD_R_DOWN: - case Dualshock2::Inputs::PAD_R_UP: + case Inputs::PAD_R_DOWN: + case Inputs::PAD_R_UP: return this->analogs.ry; - case Dualshock2::Inputs::PAD_L_LEFT: - case Dualshock2::Inputs::PAD_L_RIGHT: + case Inputs::PAD_L_LEFT: + case Inputs::PAD_L_RIGHT: return this->analogs.lx; - case Dualshock2::Inputs::PAD_L_DOWN: - case Dualshock2::Inputs::PAD_L_UP: + case Inputs::PAD_L_DOWN: + case Inputs::PAD_L_UP: return this->analogs.ly; default: - return this->rawInputs.at(index); + return this->rawInputs[index]; } } -void PadDualshock2::Freeze(StateWrapper& sw) +bool PadDualshock2::Freeze(StateWrapper& sw) { - // Protected PadBase members - sw.Do(&rawInputs); - sw.Do(&unifiedSlot); - sw.Do(&isInConfig); - sw.Do(¤tMode); - sw.Do(¤tCommand); - sw.Do(&commandBytesReceived); + if (!PadBase::Freeze(sw) || !sw.DoMarker("PadDualshock2")) + return false; // Private PadDualshock2 members sw.Do(&buttons); - sw.DoBytes(&analogs, sizeof(Dualshock2::Analogs)); + sw.DoBytes(&analogs, sizeof(Analogs)); sw.Do(&analogLight); sw.Do(&analogLocked); sw.Do(&analogPressed); + sw.Do(&commandStage); sw.Do(&responseBytes); sw.Do(&pressures); sw.Do(&vibrationMotors); @@ -709,6 +775,7 @@ void PadDualshock2::Freeze(StateWrapper& sw) sw.Do(&vibrationScale); sw.Do(&pressureModifier); sw.Do(&buttonDeadzone); + return !sw.HasError(); } u8 PadDualshock2::SendCommandByte(u8 commandByte) diff --git a/pcsx2/SIO/Pad/PadDualshock2.h b/pcsx2/SIO/Pad/PadDualshock2.h index 052b5876e7..eaa1ff4308 100644 --- a/pcsx2/SIO/Pad/PadDualshock2.h +++ b/pcsx2/SIO/Pad/PadDualshock2.h @@ -16,7 +16,6 @@ #pragma once #include "SIO/Pad/PadBase.h" -#include "SIO/Pad/PadDualshock2Types.h" #include @@ -25,30 +24,68 @@ static inline bool IsButtonBitSet(u32 value, size_t bit) return !(value & (1 << bit)); } -static inline bool IsAnalogKey(int index) +class PadDualshock2 final : public PadBase { - return ((index >= Dualshock2::Inputs::PAD_L_UP) && (index <= Dualshock2::Inputs::PAD_R_LEFT)); -} +public: + enum Inputs + { + PAD_UP, // Directional pad up + PAD_RIGHT, // Directional pad right + PAD_DOWN, // Directional pad down + PAD_LEFT, // Directional pad left + PAD_TRIANGLE, // Triangle button + PAD_CIRCLE, // Circle button + PAD_CROSS, // Cross button + PAD_SQUARE, // Square button + PAD_SELECT, // Select button + PAD_START, // Start button + PAD_L1, // L1 button + PAD_L2, // L2 button + PAD_R1, // R1 button + PAD_R2, // R2 button + PAD_L3, // Left joystick button (L3) + PAD_R3, // Right joystick button (R3) + PAD_ANALOG, // Analog mode toggle + PAD_PRESSURE, // Pressure modifier + PAD_L_UP, // Left joystick (Up) + PAD_L_RIGHT, // Left joystick (Right) + PAD_L_DOWN, // Left joystick (Down) + PAD_L_LEFT, // Left joystick (Left) + PAD_R_UP, // Right joystick (Up) + PAD_R_RIGHT, // Right joystick (Right) + PAD_R_DOWN, // Right joystick (Down) + PAD_R_LEFT, // Right joystick (Left) + LENGTH, + }; -static inline bool IsTriggerKey(int index) -{ - return (index == Dualshock2::Inputs::PAD_L2 || index == Dualshock2::Inputs::PAD_R2); -} + static constexpr u32 PRESSURE_BUTTONS = 12; + static constexpr u8 VIBRATION_MOTORS = 2; -class PadDualshock2 : public PadBase -{ private: + struct Analogs + { + u8 lx = 0x7f; + u8 ly = 0x7f; + u8 rx = 0x7f; + u8 ry = 0x7f; + u8 lxInvert = 0x7f; + u8 lyInvert = 0x7f; + u8 rxInvert = 0x7f; + u8 ryInvert = 0x7f; + }; + u32 buttons; - Dualshock2::Analogs analogs; + Analogs analogs; bool analogLight = false; bool analogLocked = false; // Analog button can be held without changing its state. // We track here if it is currently held down, to avoid flipping in // and out of analog mode every frame. bool analogPressed = false; + bool commandStage = false; u32 responseBytes; - std::array pressures; - std::array vibrationMotors; + std::array pressures; + std::array vibrationMotors; float axisScale; float axisDeadzone; float triggerScale; @@ -74,28 +111,41 @@ private: public: PadDualshock2(u8 unifiedSlot); - virtual ~PadDualshock2(); + ~PadDualshock2() override; + + static inline bool IsAnalogKey(int index) + { + return ((index >= Inputs::PAD_L_UP) && (index <= Inputs::PAD_R_LEFT)); + } + + static inline bool IsTriggerKey(int index) + { + return (index == Inputs::PAD_L2 || index == Inputs::PAD_R2); + } void Init() override; - Pad::ControllerType GetType() override; + Pad::ControllerType GetType() const override; + const Pad::ControllerInfo& GetInfo() const override; void Set(u32 index, float value) override; void SetRawAnalogs(const std::tuple left, const std::tuple right) override; void SetAxisScale(float deadzone, float scale) override; void SetTriggerScale(float deadzone, float scale) override; - float GetVibrationScale(u32 motor) override; + float GetVibrationScale(u32 motor) const override; void SetVibrationScale(u32 motor, float scale) override; - float GetPressureModifier() override; + float GetPressureModifier() const override; void SetPressureModifier(float mod) override; void SetButtonDeadzone(float deadzone) override; void SetAnalogInvertL(bool x, bool y) override; void SetAnalogInvertR(bool x, bool y) override; - u8 GetRawInput(u32 index) override; - std::tuple GetRawLeftAnalog() override; - std::tuple GetRawRightAnalog() override; - u32 GetButtons() override; - u8 GetPressure(u32 index) override; + u8 GetRawInput(u32 index) const override; + std::tuple GetRawLeftAnalog() const override; + std::tuple GetRawRightAnalog() const override; + u32 GetButtons() const override; + u8 GetPressure(u32 index) const override; - void Freeze(StateWrapper& sw) override; + bool Freeze(StateWrapper& sw) override; u8 SendCommandByte(u8 commandByte) override; + + static const Pad::ControllerInfo ControllerInfo; }; diff --git a/pcsx2/SIO/Pad/PadDualshock2Types.h b/pcsx2/SIO/Pad/PadDualshock2Types.h deleted file mode 100644 index 08c390a6c7..0000000000 --- a/pcsx2/SIO/Pad/PadDualshock2Types.h +++ /dev/null @@ -1,133 +0,0 @@ -/* PCSX2 - PS2 Emulator for PCs - * Copyright (C) 2002-2023 PCSX2 Dev Team - * - * PCSX2 is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Found- - * ation, either version 3 of the License, or (at your option) any later version. - * - * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with PCSX2. - * If not, see . - */ - -#pragma once - -#include "Config.h" - -namespace Dualshock2 -{ - enum Inputs - { - PAD_UP, // Directional pad up - PAD_RIGHT, // Directional pad right - PAD_DOWN, // Directional pad down - PAD_LEFT, // Directional pad left - PAD_TRIANGLE, // Triangle button - PAD_CIRCLE, // Circle button - PAD_CROSS, // Cross button - PAD_SQUARE, // Square button - PAD_SELECT, // Select button - PAD_START, // Start button - PAD_L1, // L1 button - PAD_L2, // L2 button - PAD_R1, // R1 button - PAD_R2, // R2 button - PAD_L3, // Left joystick button (L3) - PAD_R3, // Right joystick button (R3) - PAD_ANALOG, // Analog mode toggle - PAD_PRESSURE, // Pressure modifier - PAD_L_UP, // Left joystick (Up) - PAD_L_RIGHT, // Left joystick (Right) - PAD_L_DOWN, // Left joystick (Down) - PAD_L_LEFT, // Left joystick (Left) - PAD_R_UP, // Right joystick (Up) - PAD_R_RIGHT, // Right joystick (Right) - PAD_R_DOWN, // Right joystick (Down) - PAD_R_LEFT, // Right joystick (Left) - LENGTH, - }; - - static constexpr u32 PRESSURE_BUTTONS = 12; - static constexpr u8 VIBRATION_MOTORS = 2; - - struct Analogs - { - u8 lx = 0x7f; - u8 ly = 0x7f; - u8 rx = 0x7f; - u8 ry = 0x7f; - u8 lxInvert = 0x7f; - u8 lyInvert = 0x7f; - u8 rxInvert = 0x7f; - u8 ryInvert = 0x7f; - }; - - static const InputBindingInfo defaultBindings[] = { - {"Up", "D-Pad Up", InputBindingInfo::Type::Button, Dualshock2::Inputs::PAD_UP, GenericInputBinding::DPadUp}, - {"Right", "D-Pad Right", InputBindingInfo::Type::Button, Dualshock2::Inputs::PAD_RIGHT, GenericInputBinding::DPadRight}, - {"Down", "D-Pad Down", InputBindingInfo::Type::Button, Dualshock2::Inputs::PAD_DOWN, GenericInputBinding::DPadDown}, - {"Left", "D-Pad Left", InputBindingInfo::Type::Button, Dualshock2::Inputs::PAD_LEFT, GenericInputBinding::DPadLeft}, - {"Triangle", "Triangle", InputBindingInfo::Type::Button, Dualshock2::Inputs::PAD_TRIANGLE, GenericInputBinding::Triangle}, - {"Circle", "Circle", InputBindingInfo::Type::Button, Dualshock2::Inputs::PAD_CIRCLE, GenericInputBinding::Circle}, - {"Cross", "Cross", InputBindingInfo::Type::Button, Dualshock2::Inputs::PAD_CROSS, GenericInputBinding::Cross}, - {"Square", "Square", InputBindingInfo::Type::Button, Dualshock2::Inputs::PAD_SQUARE, GenericInputBinding::Square}, - {"Select", "Select", InputBindingInfo::Type::Button, Dualshock2::Inputs::PAD_SELECT, GenericInputBinding::Select}, - {"Start", "Start", InputBindingInfo::Type::Button, Dualshock2::Inputs::PAD_START, GenericInputBinding::Start}, - {"L1", "L1 (Left Bumper)", InputBindingInfo::Type::Button, Dualshock2::Inputs::PAD_L1, GenericInputBinding::L1}, - {"L2", "L2 (Left Trigger)", InputBindingInfo::Type::HalfAxis, Dualshock2::Inputs::PAD_L2, GenericInputBinding::L2}, - {"R1", "R1 (Right Bumper)", InputBindingInfo::Type::Button, Dualshock2::Inputs::PAD_R1, GenericInputBinding::R1}, - {"R2", "R2 (Right Trigger)", InputBindingInfo::Type::HalfAxis, Dualshock2::Inputs::PAD_R2, GenericInputBinding::R2}, - {"L3", "L3 (Left Stick Button)", InputBindingInfo::Type::Button, Dualshock2::Inputs::PAD_L3, GenericInputBinding::L3}, - {"R3", "R3 (Right Stick Button)", InputBindingInfo::Type::Button, Dualshock2::Inputs::PAD_R3, GenericInputBinding::R3}, - {"Analog", "Analog Toggle", InputBindingInfo::Type::Button, Dualshock2::Inputs::PAD_ANALOG, GenericInputBinding::System}, - {"Pressure", "Apply Pressure", InputBindingInfo::Type::Button, Dualshock2::Inputs::PAD_PRESSURE, GenericInputBinding::Unknown}, - {"LUp", "Left Stick Up", InputBindingInfo::Type::HalfAxis, Dualshock2::Inputs::PAD_L_UP, GenericInputBinding::LeftStickUp}, - {"LRight", "Left Stick Right", InputBindingInfo::Type::HalfAxis, Dualshock2::Inputs::PAD_L_RIGHT, GenericInputBinding::LeftStickRight}, - {"LDown", "Left Stick Down", InputBindingInfo::Type::HalfAxis, Dualshock2::Inputs::PAD_L_DOWN, GenericInputBinding::LeftStickDown}, - {"LLeft", "Left Stick Left", InputBindingInfo::Type::HalfAxis, Dualshock2::Inputs::PAD_L_LEFT, GenericInputBinding::LeftStickLeft}, - {"RUp", "Right Stick Up", InputBindingInfo::Type::HalfAxis, Dualshock2::Inputs::PAD_R_UP, GenericInputBinding::RightStickUp}, - {"RRight", "Right Stick Right", InputBindingInfo::Type::HalfAxis, Dualshock2::Inputs::PAD_R_RIGHT, GenericInputBinding::RightStickRight}, - {"RDown", "Right Stick Down", InputBindingInfo::Type::HalfAxis, Dualshock2::Inputs::PAD_R_DOWN, GenericInputBinding::RightStickDown}, - {"RLeft", "Right Stick Left", InputBindingInfo::Type::HalfAxis, Dualshock2::Inputs::PAD_R_LEFT, GenericInputBinding::RightStickLeft}, - {"LargeMotor", "Large (Low Frequency) Motor", InputBindingInfo::Type::Motor, 0, GenericInputBinding::LargeMotor}, - {"SmallMotor", "Small (High Frequency) Motor", InputBindingInfo::Type::Motor, 0, GenericInputBinding::SmallMotor}, - }; - - static const char* invertOptions[] = { - "Not Inverted", - "Invert Left/Right", - "Invert Up/Down", - "Invert Left/Right + Up/Down", - nullptr}; - - static const SettingInfo defaultSettings[] = { - {SettingInfo::Type::IntegerList, "InvertL", "Invert Left Stick", - "Inverts the direction of the left analog stick.", - "0", "0", "3", nullptr, nullptr, invertOptions, nullptr, 0.0f}, - {SettingInfo::Type::IntegerList, "InvertR", "Invert Right Stick", - "Inverts the direction of the right analog stick.", - "0", "0", "3", nullptr, nullptr, invertOptions, nullptr, 0.0f}, - {SettingInfo::Type::Float, "Deadzone", "Analog Deadzone", - "Sets the analog stick deadzone, i.e. the fraction of the stick movement which will be ignored.", - "0.00", "0.00", "1.00", "0.01", "%.0f%%", nullptr, nullptr, 100.0f}, - {SettingInfo::Type::Float, "AxisScale", "Analog Sensitivity", - "Sets the analog stick axis scaling factor. A value between 1.30 and 1.40 is recommended when using recent " - "controllers, e.g. DualShock 4, Xbox One Controller.", - "1.33", "0.01", "2.00", "0.01", "%.0f%%", nullptr, nullptr, 100.0f}, - {SettingInfo::Type::Float, "LargeMotorScale", "Large Motor Vibration Scale", - "Increases or decreases the intensity of low frequency vibration sent by the game.", - "1.00", "0.00", "2.00", "0.01", "%.0f%%", nullptr, nullptr, 100.0f}, - {SettingInfo::Type::Float, "SmallMotorScale", "Small Motor Vibration Scale", - "Increases or decreases the intensity of high frequency vibration sent by the game.", - "1.00", "0.00", "2.00", "0.01", "%.0f%%", nullptr, nullptr, 100.0f}, - {SettingInfo::Type::Float, "ButtonDeadzone", "Button/Trigger Deadzone", - "Sets the deadzone for activating buttons/triggers, i.e. the fraction of the trigger which will be ignored.", - "0.00", "0.00", "1.00", "0.01", "%.0f%%", nullptr, nullptr, 100.0f}, - {SettingInfo::Type::Float, "PressureModifier", "Modifier Pressure", - "Sets the pressure when the modifier button is held.", - "0.50", "0.01", "1.00", "0.01", "%.0f%%", nullptr, nullptr, 100.0f}, - }; -} // namespace Dualshock2 diff --git a/pcsx2/SIO/Pad/PadGuitar.cpp b/pcsx2/SIO/Pad/PadGuitar.cpp index c849726d05..1a88ee25e6 100644 --- a/pcsx2/SIO/Pad/PadGuitar.cpp +++ b/pcsx2/SIO/Pad/PadGuitar.cpp @@ -16,12 +16,40 @@ #include "PrecompiledHeader.h" #include "SIO/Pad/PadGuitar.h" - -#include "SIO/Pad/PadManager.h" -#include "SIO/Pad/PadGuitarTypes.h" +#include "SIO/Pad/Pad.h" #include "SIO/Sio.h" -#include "Common.h" +#include "Host.h" + +// The generic input bindings on this might seem bizarre, but they are intended to match what DS2 buttons +// would do what actions, if you played Guitar Hero on a PS2 with a DS2 instead of a controller. +static const InputBindingInfo s_bindings[] = { + // clang-format off + {"Up", TRANSLATE_NOOP("Pad", "Strum Up"), InputBindingInfo::Type::Button, PadGuitar::Inputs::STRUM_UP, GenericInputBinding::DPadUp}, + {"Down", TRANSLATE_NOOP("Pad", "Strum Down"), InputBindingInfo::Type::Button, PadGuitar::Inputs::STRUM_DOWN, GenericInputBinding::DPadDown}, + {"Select", TRANSLATE_NOOP("Pad", "Select"), InputBindingInfo::Type::Button, PadGuitar::Inputs::SELECT, GenericInputBinding::Select}, + {"Start", TRANSLATE_NOOP("Pad", "Start"), InputBindingInfo::Type::Button, PadGuitar::Inputs::START, GenericInputBinding::Start}, + {"Green", TRANSLATE_NOOP("Pad", "Green Fret"), InputBindingInfo::Type::Button, PadGuitar::Inputs::GREEN, GenericInputBinding::R2}, + {"Red", TRANSLATE_NOOP("Pad", "Red Fret"), InputBindingInfo::Type::Button, PadGuitar::Inputs::RED, GenericInputBinding::Circle}, + {"Yellow", TRANSLATE_NOOP("Pad", "Yellow Fret"), InputBindingInfo::Type::Button, PadGuitar::Inputs::YELLOW, GenericInputBinding::Triangle}, + {"Blue", TRANSLATE_NOOP("Pad", "Blue Fret"), InputBindingInfo::Type::Button, PadGuitar::Inputs::BLUE, GenericInputBinding::Cross}, + {"Orange", TRANSLATE_NOOP("Pad", "Orange Fret"), InputBindingInfo::Type::Button, PadGuitar::Inputs::ORANGE, GenericInputBinding::Square}, + {"Whammy", TRANSLATE_NOOP("Pad", "Whammy Bar"), InputBindingInfo::Type::HalfAxis, PadGuitar::Inputs::WHAMMY, GenericInputBinding::LeftStickUp}, + {"Tilt", TRANSLATE_NOOP("Pad", "Tilt Up"), InputBindingInfo::Type::Button, PadGuitar::Inputs::TILT, GenericInputBinding::L2}, + // clang-format on +}; + +static const SettingInfo s_settings[] = { + {SettingInfo::Type::Float, "Deadzone", TRANSLATE_NOOP("Pad", "Whammy Bar Deadzone"), + TRANSLATE_NOOP("Pad", "Sets the whammy bar deadzone. Inputs below this value will not be sent to the PS2."), + "0.00", "0.00", "1.00", "0.01", "%.0f%%", nullptr, nullptr, 100.0f}, + {SettingInfo::Type::Float, "AxisScale", TRANSLATE_NOOP("Pad", "Whammy Bar Sensitivity"), + TRANSLATE_NOOP("Pad", "Sets the whammy bar axis scaling factor."), "1.0", "0.01", "2.00", "0.01", "%.0f%%", + nullptr, nullptr, 100.0f}, +}; + +const Pad::ControllerInfo PadGuitar::ControllerInfo = {Pad::ControllerType::Guitar, "Guitar", + TRANSLATE_NOOP("Pad", "Guitar"), s_bindings, s_settings, Pad::VibrationCapabilities::NoVibration}; u8 PadGuitar::Mystery(u8 commandByte) { @@ -54,8 +82,7 @@ u8 PadGuitar::ButtonQuery(u8 commandByte) u8 PadGuitar::Poll(u8 commandByte) { - PadBase* pad = g_PadManager.GetPad(this->unifiedSlot); - const u32 buttons = pad->GetButtons(); + const u32 buttons = GetButtons(); switch (this->commandBytesReceived) { @@ -70,7 +97,7 @@ u8 PadGuitar::Poll(u8 commandByte) case 7: return 0x7f; case 8: - return pad->GetPressure(Guitar::Inputs::WHAMMY); + return GetPressure(Inputs::WHAMMY); } Console.Warning("%s(%02X) Did not reach a valid return path! Returning zero as a failsafe!", __FUNCTION__, commandByte); @@ -98,11 +125,11 @@ u8 PadGuitar::Config(u8 commandByte) { this->isInConfig = false; const auto [port, slot] = sioConvertPadToPortAndSlot(unifiedSlot); - Console.WriteLn(StringUtil::StdStringFromFormat("[Pad] Game finished pad setup for port %d / slot %d - Analogs: %s - Analog Button: %s - Pressure: Not available on guitars", + Console.WriteLn("[Pad] Game finished pad setup for port %d / slot %d - Analogs: %s - Analog Button: %s - Pressure: Not available on guitars", port + 1, slot + 1, (this->analogLight ? "On" : "Off"), - (this->analogLocked ? "Locked" : "Usable"))); + (this->analogLocked ? "Locked" : "Usable")); } else { @@ -163,21 +190,19 @@ u8 PadGuitar::StatusInfo(u8 commandByte) u8 PadGuitar::Constant1(u8 commandByte) { - static bool stage; - switch (this->commandBytesReceived) { case 3: - stage = commandByte; + commandStage = (commandByte != 0); return 0x00; case 5: return 0x01; case 6: - return (!stage ? 0x02 : 0x01); + return (!commandStage ? 0x02 : 0x01); case 7: - return (!stage ? 0x00 : 0x01); + return (!commandStage ? 0x00 : 0x01); case 8: - return (stage ? 0x0a : 0x14); + return (commandStage ? 0x0a : 0x14); default: return 0x00; } @@ -198,15 +223,13 @@ u8 PadGuitar::Constant2(u8 commandByte) u8 PadGuitar::Constant3(u8 commandByte) { - static bool stage; - switch (this->commandBytesReceived) { case 3: - stage = commandByte; + commandStage = (commandByte != 0); return 0x00; case 6: - return (!stage ? 0x04 : 0x07); + return (!commandStage ? 0x04 : 0x07); default: return 0x00; } @@ -214,11 +237,7 @@ u8 PadGuitar::Constant3(u8 commandByte) u8 PadGuitar::VibrationMap(u8 commandByte) { - switch (this->commandBytesReceived) - { - default: - return 0xff; - } + return 0xff; } PadGuitar::PadGuitar(u8 unifiedSlot) @@ -240,14 +259,19 @@ void PadGuitar::Init() this->whammyDeadzone = 0.0f; } -Pad::ControllerType PadGuitar::GetType() +Pad::ControllerType PadGuitar::GetType() const { return Pad::ControllerType::Guitar; } +const Pad::ControllerInfo& PadGuitar::GetInfo() const +{ + return ControllerInfo; +} + void PadGuitar::Set(u32 index, float value) { - if (index > Guitar::Inputs::LENGTH) + if (index > Inputs::LENGTH) { return; } @@ -255,7 +279,7 @@ void PadGuitar::Set(u32 index, float value) // The whammy bar is a special kind of weird in that rather than resting at 0 and going to 255, // they chose to rest it at 127 like a normal analog, but then also make its full press 0, as if // it were the negative Y component of a normal analog. Fun! - if (index == Guitar::Inputs::WHAMMY) + if (index == Inputs::WHAMMY) { this->whammy = static_cast(std::clamp(127 - (value * this->whammyAxisScale) * 255.0f, 0.0f, 127.0f)); @@ -279,7 +303,7 @@ void PadGuitar::Set(u32 index, float value) this->rawInputs[index] = static_cast(std::clamp(dzValue * 255.0f, 0.0f, 255.0f)); // Since we reordered the buttons for better UI, we need to remap them here. - static constexpr std::array bitmaskMapping = {{ + static constexpr std::array bitmaskMapping = {{ 12, // STRUM_UP 14, // STRUM_DOWN 8, // SELECT @@ -318,7 +342,7 @@ void PadGuitar::SetTriggerScale(float deadzone, float scale) } -float PadGuitar::GetVibrationScale(u32 motor) +float PadGuitar::GetVibrationScale(u32 motor) const { return 0; } @@ -327,7 +351,7 @@ void PadGuitar::SetVibrationScale(u32 motor, float scale) { } -float PadGuitar::GetPressureModifier() +float PadGuitar::GetPressureModifier() const { return 0; } @@ -349,54 +373,49 @@ void PadGuitar::SetAnalogInvertR(bool x, bool y) { } -u8 PadGuitar::GetRawInput(u32 index) +u8 PadGuitar::GetRawInput(u32 index) const { - return this->rawInputs[index]; + return rawInputs[index]; } -std::tuple PadGuitar::GetRawLeftAnalog() +std::tuple PadGuitar::GetRawLeftAnalog() const { return std::tuple{0x7f, 0x7f}; } -std::tuple PadGuitar::GetRawRightAnalog() +std::tuple PadGuitar::GetRawRightAnalog() const { return std::tuple{0x7f, 0x7f}; } -u32 PadGuitar::GetButtons() +u32 PadGuitar::GetButtons() const { - return this->buttons; + return buttons; } -u8 PadGuitar::GetPressure(u32 index) +u8 PadGuitar::GetPressure(u32 index) const { - if (index == Guitar::Inputs::WHAMMY) - { - return this->whammy; - } + if (index == Inputs::WHAMMY) + return whammy; return 0; } -void PadGuitar::Freeze(StateWrapper& sw) +bool PadGuitar::Freeze(StateWrapper& sw) { - // Protected PadBase members - sw.Do(&rawInputs); - sw.Do(&unifiedSlot); - sw.Do(&isInConfig); - sw.Do(¤tMode); - sw.Do(¤tCommand); - sw.Do(&commandBytesReceived); + if (!PadBase::Freeze(sw) || !sw.DoMarker("PadGuitar")) + return false; // Private PadGuitar members sw.Do(&buttons); sw.Do(&whammy); sw.Do(&analogLight); sw.Do(&analogLocked); + sw.Do(&commandStage); sw.Do(&whammyAxisScale); sw.Do(&whammyDeadzone); sw.Do(&buttonDeadzone); + return !sw.HasError(); } u8 PadGuitar::SendCommandByte(u8 commandByte) diff --git a/pcsx2/SIO/Pad/PadGuitar.h b/pcsx2/SIO/Pad/PadGuitar.h index 756f38f59a..31c3da71f5 100644 --- a/pcsx2/SIO/Pad/PadGuitar.h +++ b/pcsx2/SIO/Pad/PadGuitar.h @@ -17,8 +17,25 @@ #include "SIO/Pad/PadBase.h" -class PadGuitar : public PadBase +class PadGuitar final : public PadBase { +public: + enum Inputs + { + STRUM_UP, // Strum bar + STRUM_DOWN, // Strum bar down + SELECT, // Select button + START, // Start button + GREEN, // Green fret + RED, // Red fret + YELLOW, // Yellow fret + BLUE, // Blue fret + ORANGE, // Orange fret + WHAMMY, // Whammy bar axis + TILT, // Tilt sensor + LENGTH, + }; + private: u32 buttons; u8 whammy; @@ -27,6 +44,7 @@ private: bool analogLight = false; // Guitars are also instructed to "lock" their "analog light", despite not having one. bool analogLocked = false; + bool commandStage = false; float whammyAxisScale; // Guitars only have 1 axis on the whammy bar. float whammyDeadzone; float buttonDeadzone; // Button deadzone is still a good idea, in case a host analog stick is bound to a guitar button @@ -44,28 +62,31 @@ private: public: PadGuitar(u8 unifiedSlot); - virtual ~PadGuitar(); + ~PadGuitar() override; void Init() override; - Pad::ControllerType GetType() override; + Pad::ControllerType GetType() const override; + const Pad::ControllerInfo& GetInfo() const override; void Set(u32 index, float value) override; void SetRawAnalogs(const std::tuple left, const std::tuple right) override; void SetAxisScale(float deadzone, float scale) override; void SetTriggerScale(float deadzone, float scale) override; - float GetVibrationScale(u32 motor) override; + float GetVibrationScale(u32 motor) const override; void SetVibrationScale(u32 motor, float scale) override; - float GetPressureModifier() override; + float GetPressureModifier() const override; void SetPressureModifier(float mod) override; void SetButtonDeadzone(float deadzone) override; void SetAnalogInvertL(bool x, bool y) override; void SetAnalogInvertR(bool x, bool y) override; - u8 GetRawInput(u32 index) override; - std::tuple GetRawLeftAnalog() override; - std::tuple GetRawRightAnalog() override; - u32 GetButtons() override; - u8 GetPressure(u32 index) override; + u8 GetRawInput(u32 index) const override; + std::tuple GetRawLeftAnalog() const override; + std::tuple GetRawRightAnalog() const override; + u32 GetButtons() const override; + u8 GetPressure(u32 index) const override; - void Freeze(StateWrapper& sw) override; + bool Freeze(StateWrapper& sw) override; u8 SendCommandByte(u8 commandByte) override; + + static const Pad::ControllerInfo ControllerInfo; }; diff --git a/pcsx2/SIO/Pad/PadGuitarTypes.h b/pcsx2/SIO/Pad/PadGuitarTypes.h deleted file mode 100644 index a326fc6617..0000000000 --- a/pcsx2/SIO/Pad/PadGuitarTypes.h +++ /dev/null @@ -1,62 +0,0 @@ -/* PCSX2 - PS2 Emulator for PCs - * Copyright (C) 2002-2023 PCSX2 Dev Team - * - * PCSX2 is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Found- - * ation, either version 3 of the License, or (at your option) any later version. - * - * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with PCSX2. - * If not, see . - */ - -#pragma once - -#include "Config.h" - -namespace Guitar -{ - enum Inputs - { - STRUM_UP, // Strum bar - STRUM_DOWN, // Strum bar down - SELECT, // Select button - START, // Start button - GREEN, // Green fret - RED, // Red fret - YELLOW, // Yellow fret - BLUE, // Blue fret - ORANGE, // Orange fret - WHAMMY, // Whammy bar axis - TILT, // Tilt sensor - LENGTH, - }; - - // The generic input bindings on this might seem bizarre, but they are intended to match what DS2 buttons - // would do what actions, if you played Guitar Hero on a PS2 with a DS2 instead of a controller. - static const InputBindingInfo defaultBindings[] = { - {"Up", "Strum Up", InputBindingInfo::Type::Button, Guitar::Inputs::STRUM_UP, GenericInputBinding::DPadUp}, - {"Down", "Strum Down", InputBindingInfo::Type::Button, Guitar::Inputs::STRUM_DOWN, GenericInputBinding::DPadDown}, - {"Select", "Select", InputBindingInfo::Type::Button, Guitar::Inputs::SELECT, GenericInputBinding::Select}, - {"Start", "Start", InputBindingInfo::Type::Button, Guitar::Inputs::START, GenericInputBinding::Start}, - {"Green", "Green Fret", InputBindingInfo::Type::Button, Guitar::Inputs::GREEN, GenericInputBinding::R2}, - {"Red", "Red Fret", InputBindingInfo::Type::Button, Guitar::Inputs::RED, GenericInputBinding::Circle}, - {"Yellow", "Yellow Fret", InputBindingInfo::Type::Button, Guitar::Inputs::YELLOW, GenericInputBinding::Triangle}, - {"Blue", "Blue Fret", InputBindingInfo::Type::Button, Guitar::Inputs::BLUE, GenericInputBinding::Cross}, - {"Orange", "Orange Fret", InputBindingInfo::Type::Button, Guitar::Inputs::ORANGE, GenericInputBinding::Square}, - {"Whammy", "Whammy Bar", InputBindingInfo::Type::HalfAxis, Guitar::Inputs::WHAMMY, GenericInputBinding::LeftStickUp}, - {"Tilt", "Tilt Up", InputBindingInfo::Type::Button, Guitar::Inputs::TILT, GenericInputBinding::L2}, - }; - - static const SettingInfo defaultSettings[] = { - {SettingInfo::Type::Float, "Deadzone", "Whammy Bar Deadzone", - "Sets the whammy bar deadzone. Inputs below this value will not be sent to the PS2.", - "0.00", "0.00", "1.00", "0.01", "%.0f%%", nullptr, nullptr, 100.0f}, - {SettingInfo::Type::Float, "AxisScale", "Whammy Bar Sensitivity", - "Sets the whammy bar axis scaling factor.", - "1.0", "0.01", "2.00", "0.01", "%.0f%%", nullptr, nullptr, 100.0f}, - }; -} // namespace Guitar diff --git a/pcsx2/SIO/Pad/PadMacros.cpp b/pcsx2/SIO/Pad/PadMacros.cpp deleted file mode 100644 index c43ee092bf..0000000000 --- a/pcsx2/SIO/Pad/PadMacros.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* PCSX2 - PS2 Emulator for PCs - * Copyright (C) 2002-2023 PCSX2 Dev Team - * - * PCSX2 is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Found- - * ation, either version 3 of the License, or (at your option) any later version. - * - * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with PCSX2. - * If not, see . - */ - -#include "PrecompiledHeader.h" - -#include "SIO/Pad/PadMacros.h" - -#include "SIO/Pad/PadManager.h" -#include "SIO/Pad/PadBase.h" - -PadMacros g_PadMacros; - -PadMacros::PadMacros() = default; -PadMacros::~PadMacros() = default; - -void PadMacros::ClearMacros() -{ - this->s_macro_buttons = {}; -} - -PadMacros::MacroButton& PadMacros::GetMacroButton(u32 pad, u32 index) -{ - return this->s_macro_buttons.at(pad).at(index); -} - -void PadMacros::SetMacroButtonState(u32 pad, u32 index, bool state) -{ - if (pad >= Pad::NUM_CONTROLLER_PORTS || index >= NUM_MACRO_BUTTONS_PER_CONTROLLER) - return; - - PadMacros::MacroButton& mb = s_macro_buttons[pad][index]; - if (mb.buttons.empty() || mb.trigger_state == state) - return; - - mb.toggle_counter = mb.toggle_frequency; - mb.trigger_state = state; - if (mb.toggle_state != state) - { - mb.toggle_state = state; - ApplyMacroButton(pad, mb); - } -} - -void PadMacros::ApplyMacroButton(u32 controller, const PadMacros::MacroButton& mb) -{ - const float value = mb.toggle_state ? 1.0f : 0.0f; - PadBase* pad = g_PadManager.GetPad(controller); - - for (const u32 btn : mb.buttons) - pad->Set(btn, value); -} - -void PadMacros::UpdateMacroButtons() -{ - for (u32 pad = 0; pad < Pad::NUM_CONTROLLER_PORTS; pad++) - { - for (u32 index = 0; index < NUM_MACRO_BUTTONS_PER_CONTROLLER; index++) - { - PadMacros::MacroButton& mb = this->s_macro_buttons[pad][index]; - - if (!mb.trigger_state || mb.toggle_frequency == 0) - { - continue; - } - - mb.toggle_counter--; - - if (mb.toggle_counter > 0) - { - continue; - } - - mb.toggle_counter = mb.toggle_frequency; - mb.toggle_state = !mb.toggle_state; - ApplyMacroButton(pad, mb); - } - } -} \ No newline at end of file diff --git a/pcsx2/SIO/Pad/PadMacros.h b/pcsx2/SIO/Pad/PadMacros.h deleted file mode 100644 index 393979f476..0000000000 --- a/pcsx2/SIO/Pad/PadMacros.h +++ /dev/null @@ -1,53 +0,0 @@ -/* PCSX2 - PS2 Emulator for PCs - * Copyright (C) 2002-2023 PCSX2 Dev Team - * - * PCSX2 is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Found- - * ation, either version 3 of the License, or (at your option) any later version. - * - * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with PCSX2. - * If not, see . - */ - -#pragma once - -#include "SIO/Pad/PadTypes.h" - -#include -#include - -class PadMacros -{ -public: // Constants - struct MacroButton - { - std::vector buttons; ///< Buttons to activate. - u32 toggle_frequency; ///< Interval at which the buttons will be toggled, if not 0. - u32 toggle_counter; ///< When this counter reaches zero, buttons will be toggled. - bool toggle_state; ///< Current state for turbo. - bool trigger_state; ///< Whether the macro button is active. - }; - - // Number of macro buttons per controller. - static constexpr u32 NUM_MACRO_BUTTONS_PER_CONTROLLER = 16; - -private: // Private members - std::array, Pad::NUM_CONTROLLER_PORTS> s_macro_buttons; - -public: // Public members - PadMacros(); - ~PadMacros(); - - // Sets the state of the specified macro button. - void ClearMacros(); - PadMacros::MacroButton& GetMacroButton(u32 pad, u32 index); - void SetMacroButtonState(u32 pad, u32 index, bool state); - void ApplyMacroButton(u32 controller, const PadMacros::MacroButton& mb); - void UpdateMacroButtons(); -}; - -extern PadMacros g_PadMacros; diff --git a/pcsx2/SIO/Pad/PadManager.cpp b/pcsx2/SIO/Pad/PadManager.cpp deleted file mode 100644 index 7359fd3807..0000000000 --- a/pcsx2/SIO/Pad/PadManager.cpp +++ /dev/null @@ -1,139 +0,0 @@ -/* PCSX2 - PS2 Emulator for PCs - * Copyright (C) 2002-2023 PCSX2 Dev Team - * - * PCSX2 is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Found- - * ation, either version 3 of the License, or (at your option) any later version. - * - * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with PCSX2. - * If not, see . - */ - -#include "PrecompiledHeader.h" - -#include "SIO/Pad/PadManager.h" - -#include "SIO/Pad/PadNotConnected.h" -#include "SIO/Pad/PadDualshock2.h" -#include "SIO/Pad/PadGuitar.h" - -PadManager g_PadManager; - -// Convert the PS2's port/slot addressing to a single value. -// Physical ports 0 and 1 still correspond to unified slots 0 and 1. -// The remaining unified slots are for multitapped slots. -// Port 0's three multitap slots then occupy unified slots 2, 3 and 4. -// Port 1's three multitap slots then occupy unified slots 5, 6 and 7. -u8 PadManager::GetUnifiedSlot(u8 port, u8 slot) -{ - if (slot == 0) - { - return port; - } - else if (port == 0) // slot=[0,1] - { - return slot + 1; - } - else - { - return slot + 4; - } -} - -PadManager::PadManager() = default; -PadManager::~PadManager() = default; - -bool PadManager::Initialize() -{ - return true; -} - -bool PadManager::Shutdown() -{ - for (u8 i = 0; i < 8; i++) - { - this->ps2Controllers.at(i) = nullptr; - } - - return true; -} - -PadBase* PadManager::ChangePadType(u8 unifiedSlot, Pad::ControllerType controllerType) -{ - switch (controllerType) - { - case Pad::ControllerType::DualShock2: - this->ps2Controllers.at(unifiedSlot) = std::make_unique(unifiedSlot); - break; - case Pad::ControllerType::Guitar: - this->ps2Controllers.at(unifiedSlot) = std::make_unique(unifiedSlot); - break; - default: - this->ps2Controllers.at(unifiedSlot) = std::make_unique(unifiedSlot); - break; - } - - return this->ps2Controllers.at(unifiedSlot).get(); -} - -PadBase* PadManager::GetPad(u8 port, u8 slot) -{ - const u8 unifiedSlot = this->GetUnifiedSlot(port, slot); - return this->ps2Controllers.at(unifiedSlot).get(); -} - -PadBase* PadManager::GetPad(const u8 unifiedSlot) -{ - return this->ps2Controllers.at(unifiedSlot).get(); -} - -void PadManager::SetControllerState(u32 controller, u32 bind, float value) -{ - if (controller >= Pad::NUM_CONTROLLER_PORTS) - return; - - PadBase* pad = g_PadManager.GetPad(controller); - pad->Set(bind, value); -} - -bool PadManager::PadFreeze(StateWrapper& sw) -{ - if (sw.IsReading()) - { - if (!sw.DoMarker("PAD")) - { - Console.Error("PAD state is invalid! Leaving the current state in place."); - return false; - } - - for (u32 unifiedSlot = 0; unifiedSlot < Pad::NUM_CONTROLLER_PORTS; unifiedSlot++) - { - Pad::ControllerType type; - sw.Do(&type); - - PadBase* pad = this->ChangePadType(unifiedSlot, type); - pad->Freeze(sw); - } - } - else - { - if (!sw.DoMarker("PAD")) - { - return false; - } - - for (u32 unifiedSlot = 0; unifiedSlot < Pad::NUM_CONTROLLER_PORTS; unifiedSlot++) - { - PadBase* pad = this->GetPad(unifiedSlot); - Pad::ControllerType type = pad->GetType(); - sw.Do(&type); - pad->Freeze(sw); - } - } - - return true; -} diff --git a/pcsx2/SIO/Pad/PadManager.h b/pcsx2/SIO/Pad/PadManager.h deleted file mode 100644 index 00a027db85..0000000000 --- a/pcsx2/SIO/Pad/PadManager.h +++ /dev/null @@ -1,46 +0,0 @@ -/* PCSX2 - PS2 Emulator for PCs - * Copyright (C) 2002-2023 PCSX2 Dev Team - * - * PCSX2 is free software: you can redistribute it and/or modify it under the terms - * of the GNU Lesser General Public License as published by the Free Software Found- - * ation, either version 3 of the License, or (at your option) any later version. - * - * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with PCSX2. - * If not, see . - */ - -#pragma once - -#include "SIO/Pad/PadBase.h" - -#include - -class PadManager -{ -private: - std::array, 8> ps2Controllers; - - u8 GetUnifiedSlot(u8 port, u8 slot); - -public: - PadManager(); - ~PadManager(); - - bool Initialize(); - bool Shutdown(); - - PadBase* ChangePadType(u8 unifiedSlot, Pad::ControllerType controllerType); - PadBase* GetPad(u8 port, u8 slot); - PadBase* GetPad(const u8 unifiedSlot); - - // Sets the specified bind on a controller to the specified pressure (normalized to 0..1). - void SetControllerState(u32 controller, u32 bind, float value); - - bool PadFreeze(StateWrapper& sw); -}; - -extern PadManager g_PadManager; diff --git a/pcsx2/SIO/Pad/PadNotConnected.cpp b/pcsx2/SIO/Pad/PadNotConnected.cpp index f585634cab..e9cfc9a0a8 100644 --- a/pcsx2/SIO/Pad/PadNotConnected.cpp +++ b/pcsx2/SIO/Pad/PadNotConnected.cpp @@ -17,6 +17,11 @@ #include "SIO/Pad/PadNotConnected.h" +#include "Host.h" + +const Pad::ControllerInfo PadNotConnected::ControllerInfo = {Pad::ControllerType::NotConnected, "None", + TRANSLATE_NOOP("Pad", "Not Connected"), {}, {}, Pad::VibrationCapabilities::NoVibration }; + PadNotConnected::PadNotConnected(u8 unifiedSlot) : PadBase(unifiedSlot) { @@ -30,11 +35,16 @@ void PadNotConnected::Init() } -Pad::ControllerType PadNotConnected::GetType() +Pad::ControllerType PadNotConnected::GetType() const { return Pad::ControllerType::NotConnected; } +const Pad::ControllerInfo& PadNotConnected::GetInfo() const +{ + return ControllerInfo; +} + void PadNotConnected::Set(u32 index, float value) { @@ -55,7 +65,7 @@ void PadNotConnected::SetTriggerScale(float deadzone, float scale) } -float PadNotConnected::GetVibrationScale(u32 motor) +float PadNotConnected::GetVibrationScale(u32 motor) const { return 0; } @@ -65,7 +75,7 @@ void PadNotConnected::SetVibrationScale(u32 motor, float scale) } -float PadNotConnected::GetPressureModifier() +float PadNotConnected::GetPressureModifier() const { return 0; } @@ -90,42 +100,31 @@ void PadNotConnected::SetAnalogInvertR(bool x, bool y) } -u8 PadNotConnected::GetRawInput(u32 index) +u8 PadNotConnected::GetRawInput(u32 index) const { return 0; } -std::tuple PadNotConnected::GetRawLeftAnalog() +std::tuple PadNotConnected::GetRawLeftAnalog() const { return std::tuple{0, 0}; } -std::tuple PadNotConnected::GetRawRightAnalog() +std::tuple PadNotConnected::GetRawRightAnalog() const { return std::tuple{0, 0}; } -u32 PadNotConnected::GetButtons() +u32 PadNotConnected::GetButtons() const { return 0; } -u8 PadNotConnected::GetPressure(u32 index) +u8 PadNotConnected::GetPressure(u32 index) const { return 0; } -void PadNotConnected::Freeze(StateWrapper& sw) -{ - // Protected PadBase members - sw.Do(&rawInputs); - sw.Do(&unifiedSlot); - sw.Do(&isInConfig); - sw.Do(¤tMode); - sw.Do(¤tCommand); - sw.Do(&commandBytesReceived); -} - u8 PadNotConnected::SendCommandByte(u8 commandByte) { return 0xff; diff --git a/pcsx2/SIO/Pad/PadNotConnected.h b/pcsx2/SIO/Pad/PadNotConnected.h index 56e204096c..814f354c94 100644 --- a/pcsx2/SIO/Pad/PadNotConnected.h +++ b/pcsx2/SIO/Pad/PadNotConnected.h @@ -17,32 +17,33 @@ #include "SIO/Pad/PadBase.h" -class PadNotConnected : public PadBase +class PadNotConnected final : public PadBase { public: PadNotConnected(u8 unifiedSlot); - virtual ~PadNotConnected(); + ~PadNotConnected() override; - void Init(); - Pad::ControllerType GetType(); - void Set(u32 index, float value); - void SetRawAnalogs(const std::tuple left, const std::tuple right); - void SetAxisScale(float deadzone, float scale); + void Init() override; + Pad::ControllerType GetType() const override; + const Pad::ControllerInfo& GetInfo() const override; + void Set(u32 index, float value) override; + void SetRawAnalogs(const std::tuple left, const std::tuple right) override; + void SetAxisScale(float deadzone, float scale) override; void SetTriggerScale(float deadzone, float scale) override; - float GetVibrationScale(u32 motor); - void SetVibrationScale(u32 motor, float scale); - float GetPressureModifier(); - void SetPressureModifier(float mod); - void SetButtonDeadzone(float deadzone); - void SetAnalogInvertL(bool x, bool y); - void SetAnalogInvertR(bool x, bool y); - u8 GetRawInput(u32 index); - std::tuple GetRawLeftAnalog(); - std::tuple GetRawRightAnalog(); - u32 GetButtons(); - u8 GetPressure(u32 index); - - void Freeze(StateWrapper& sw) override; + float GetVibrationScale(u32 motor) const override; + void SetVibrationScale(u32 motor, float scale) override; + float GetPressureModifier() const override; + void SetPressureModifier(float mod) override; + void SetButtonDeadzone(float deadzone) override; + void SetAnalogInvertL(bool x, bool y) override; + void SetAnalogInvertR(bool x, bool y) override; + u8 GetRawInput(u32 index) const override; + std::tuple GetRawLeftAnalog() const override; + std::tuple GetRawRightAnalog() const override; + u32 GetButtons() const override; + u8 GetPressure(u32 index) const override; u8 SendCommandByte(u8 commandByte) override; + + static const Pad::ControllerInfo ControllerInfo; }; diff --git a/pcsx2/SIO/Pad/PadTypes.h b/pcsx2/SIO/Pad/PadTypes.h index 20732b9c8f..690b900814 100644 --- a/pcsx2/SIO/Pad/PadTypes.h +++ b/pcsx2/SIO/Pad/PadTypes.h @@ -15,6 +15,10 @@ #pragma once +#include "Config.h" + +#include + namespace Pad { enum class Command : u8 @@ -82,6 +86,19 @@ namespace Pad Count }; + struct ControllerInfo + { + ControllerType type; + const char* name; + const char* display_name; + std::span bindings; + std::span settings; + VibrationCapabilities vibration_caps; + + // Returns localized controller type name. + const char* GetLocalizedName() const; + }; + // Total number of pad ports, across both multitaps. static constexpr u32 NUM_CONTROLLER_PORTS = 8; @@ -93,4 +110,7 @@ namespace Pad static constexpr float DEFAULT_MOTOR_SCALE = 1.0f; static constexpr float DEFAULT_PRESSURE_MODIFIER = 0.5f; static constexpr float DEFAULT_BUTTON_DEADZONE = 0.0f; + + // Number of macro buttons per controller. + static constexpr u32 NUM_MACRO_BUTTONS_PER_CONTROLLER = 16; } // namespace Pad diff --git a/pcsx2/SIO/Sio.h b/pcsx2/SIO/Sio.h index 00e008adb3..9bc6d0cec9 100644 --- a/pcsx2/SIO/Sio.h +++ b/pcsx2/SIO/Sio.h @@ -109,7 +109,11 @@ extern void sioNextFrame(); /// Converts a global pad index to a multitap port and slot. extern std::tuple sioConvertPadToPortAndSlot(u32 index); -/// Converts a multitap port and slot to a global pad index. +/// Convert the PS2's port/slot addressing to a single value. +/// Physical ports 0 and 1 still correspond to unified slots 0 and 1. +/// The remaining unified slots are for multitapped slots. +/// Port 0's three multitap slots then occupy unified slots 2, 3 and 4. +/// Port 1's three multitap slots then occupy unified slots 5, 6 and 7. extern u32 sioConvertPortAndSlotToPad(u32 port, u32 slot); /// Returns true if the given pad index is a multitap slot. diff --git a/pcsx2/SIO/Sio0.cpp b/pcsx2/SIO/Sio0.cpp index 873fd1348c..218c66d73a 100644 --- a/pcsx2/SIO/Sio0.cpp +++ b/pcsx2/SIO/Sio0.cpp @@ -18,7 +18,8 @@ #include "SIO/Sio0.h" #include "SIO/Sio.h" -#include "SIO/Pad/PadManager.h" +#include "SIO/Pad/Pad.h" +#include "SIO/Pad/PadBase.h" #include "SIO/Memcard/MemoryCardProtocol.h" #include "Common.h" @@ -162,7 +163,7 @@ void Sio0::SetTxData(u8 cmd) stat |= SIO0_STAT::TX_READY | SIO0_STAT::TX_EMPTY; stat |= (SIO0_STAT::RX_FIFO_NOT_EMPTY); - if (!ctrl & SIO0_CTRL::TX_ENABLE) + if (!(ctrl & SIO0_CTRL::TX_ENABLE)) { Console.Warning("%s(%02X) CTRL in illegal state, exiting instantly", __FUNCTION__, cmd); return; @@ -176,13 +177,13 @@ void Sio0::SetTxData(u8 cmd) { case SioMode::NOT_SET: sioMode = cmd; - currentPad = g_PadManager.GetPad(port, slot); + currentPad = Pad::GetPad(port, slot); currentPad->SoftReset(); mcd = &mcds[port][slot]; SetAcknowledge(true); break; case SioMode::PAD: - currentPad = g_PadManager.GetPad(port, slot); + currentPad = Pad::GetPad(port, slot); pxAssertMsg(currentPad != nullptr, "Got nullptr when looking up pad"); // Set ACK in advance of sending the command to the pad. // The pad will, if the command is done, set ACK to false. diff --git a/pcsx2/SIO/Sio2.cpp b/pcsx2/SIO/Sio2.cpp index 7a9ebe7160..2b8609ea7f 100644 --- a/pcsx2/SIO/Sio2.cpp +++ b/pcsx2/SIO/Sio2.cpp @@ -19,7 +19,8 @@ #include "SIO/Sio.h" #include "SIO/SioTypes.h" -#include "SIO/Pad/PadManager.h" +#include "SIO/Pad/Pad.h" +#include "SIO/Pad/PadBase.h" #include "SIO/Memcard/MemoryCardProtocol.h" #include "SIO/Multitap/MultitapProtocol.h" @@ -45,13 +46,13 @@ bool Sio2::Initialize() for (size_t i = 0; i < send3.size(); i++) { - send3.at(i) = 0; + send3[i] = 0; } for (size_t i = 0; i < send1.size(); i++) { - send1.at(i) = 0; - send2.at(i) = 0; + send1[i] = 0; + send2[i] = 0; } dataIn = 0; @@ -127,7 +128,7 @@ void Sio2::SetCtrl(u32 value) void Sio2::SetSend3(size_t position, u32 value) { - this->send3.at(position) = value; + this->send3[position] = value; if (position == 0) { @@ -143,7 +144,7 @@ void Sio2::SetRecv1(u32 value) void Sio2::Pad() { // Send PAD our current port, and get back whatever it says the first response byte should be. - std::optional padPtr = g_PadManager.GetPad(port, slot); + PadBase* pad = Pad::GetPad(port, slot); // RECV1 is set once per DMA; if any device is present at all, it should be set to connected. // For now, we will always report connected for pads. @@ -151,17 +152,14 @@ void Sio2::Pad() g_Sio2FifoOut.push_back(0xff); // Then for every byte in g_Sio2FifoIn, pass to PAD and see what it kicks back to us. - if (padPtr.has_value()) - { - padPtr.value()->SoftReset(); + pad->SoftReset(); - while (!g_Sio2FifoIn.empty()) - { - const u8 commandByte = g_Sio2FifoIn.front(); - g_Sio2FifoIn.pop_front(); - const u8 responseByte = padPtr.value()->SendCommandByte(commandByte); - g_Sio2FifoOut.push_back(responseByte); - } + while (!g_Sio2FifoIn.empty()) + { + const u8 commandByte = g_Sio2FifoIn.front(); + g_Sio2FifoIn.pop_front(); + const u8 responseByte = pad->SendCommandByte(commandByte); + g_Sio2FifoOut.push_back(responseByte); } } @@ -355,7 +353,7 @@ void Sio2::Write(u8 data) return; } - const u32 currentSend3 = send3.at(send3Position); + const u32 currentSend3 = send3[send3Position]; port = currentSend3 & Send3::PORT; commandLength = (currentSend3 >> 8) & Send3::COMMAND_LENGTH_MASK; send3Read = true; diff --git a/pcsx2/SaveState.cpp b/pcsx2/SaveState.cpp index 24df4356e7..0f4a813d62 100644 --- a/pcsx2/SaveState.cpp +++ b/pcsx2/SaveState.cpp @@ -28,7 +28,7 @@ #include "Host.h" #include "MTGS.h" #include "MTVU.h" -#include "SIO/Pad/PadManager.h" +#include "SIO/Pad/Pad.h" #include "Patch.h" #include "R3000A.h" #include "SPU2/spu2.h" @@ -314,11 +314,6 @@ static int SysState_MTGSFreeze(FreezeAction mode, freezeData* fP) return sstate.retval; } -static bool SysState_PadFreeze(StateWrapper& sw) -{ - return g_PadManager.PadFreeze(sw); -} - static constexpr SysState_Component SPU2_{ "SPU2", SPU2freeze }; static constexpr SysState_Component GS{ "GS", SysState_MTGSFreeze }; @@ -604,8 +599,8 @@ public: ~SavestateEntry_PAD() override = default; const char* GetFilename() const override { return "PAD.bin"; } - bool FreezeIn(zip_file_t* zf) const override { return SysState_ComponentFreezeInNew(zf, "PAD", &SysState_PadFreeze); } - bool FreezeOut(SaveStateBase& writer) const override { return SysState_ComponentFreezeOutNew(writer, "PAD", 16 * 1024, &SysState_PadFreeze); } + bool FreezeIn(zip_file_t* zf) const override { return SysState_ComponentFreezeInNew(zf, "PAD", &Pad::Freeze); } + bool FreezeOut(SaveStateBase& writer) const override { return SysState_ComponentFreezeOutNew(writer, "PAD", 16 * 1024, &Pad::Freeze); } bool IsRequired() const override { return true; } }; diff --git a/pcsx2/VMManager.cpp b/pcsx2/VMManager.cpp index a5589d5a3a..bafedceee4 100644 --- a/pcsx2/VMManager.cpp +++ b/pcsx2/VMManager.cpp @@ -1,5 +1,5 @@ /* PCSX2 - PS2 Emulator for PCs - * Copyright (C) 2002-2022 PCSX2 Dev Team + * Copyright (C) 2002-2023 PCSX2 Dev Team * * PCSX2 is free software: you can redistribute it and/or modify it under the terms * of the GNU Lesser General Public License as published by the Free Software Found- @@ -44,6 +44,11 @@ #include "R5900.h" #include "Recording/InputRecording.h" #include "Recording/InputRecordingControls.h" +#include "SIO/Memcard/MemoryCardFile.h" +#include "SIO/Pad/Pad.h" +#include "SIO/Sio.h" +#include "SIO/Sio0.h" +#include "SIO/Sio2.h" #include "SPU2/spu2.h" #include "USB/USB.h" #include "VMManager.h" @@ -58,13 +63,6 @@ #include "common/Threading.h" #include "common/Timer.h" #include "common/emitter/tools.h" -#include "SIO/Sio.h" -#include "SIO/Sio0.h" -#include "SIO/Sio2.h" -#include "SIO/Pad/PadManager.h" -#include "SIO/Pad/PadConfig.h" -#include "SIO/Memcard/MemoryCardFile.h" - #include "IconsFontAwesome5.h" #include "fmt/core.h" @@ -451,10 +449,12 @@ void VMManager::SetDefaultSettings( LogSink::SetDefaultLoggingSettings(si); } if (controllers) - g_PadConfig.SetDefaultControllerConfig(si); + { + Pad::SetDefaultControllerConfig(si); USB::SetDefaultConfiguration(&si); + } if (hotkeys) - g_PadConfig.SetDefaultHotkeyConfig(si); + Pad::SetDefaultHotkeyConfig(si); if (ui) Host::SetDefaultUISettings(si); } @@ -464,7 +464,7 @@ void VMManager::LoadSettings() std::unique_lock lock = Host::GetSettingsLock(); SettingsInterface* si = Host::GetSettingsInterface(); LoadCoreSettings(si); - g_PadConfig.LoadConfig(*si); + Pad::LoadConfig(*si); Host::LoadSettings(*si, lock); InputManager::ReloadSources(*si, lock); InputManager::ReloadBindings(*si, *Host::GetSettingsInterfaceForBindings()); @@ -1208,15 +1208,13 @@ bool VMManager::Initialize(VMBootParameters boot_params) ScopedGuard close_spu2(&SPU2::Close); - Console.WriteLn("Initializing PAD..."); - if (!g_PadManager.Initialize()) + Console.WriteLn("Initializing Pad..."); + if (!Pad::Initialize()) { Host::ReportErrorAsync("Startup Error", "Failed to initialize PAD"); return false; } - ScopedGuard close_pad = [](){ - g_PadManager.Shutdown(); - }; + ScopedGuard close_pad = &Pad::Shutdown; Console.WriteLn("Initializing SIO2..."); if (!g_Sio2.Initialize()) @@ -1368,7 +1366,7 @@ void VMManager::Shutdown(bool save_resume_state) vtlb_Shutdown(); USBclose(); SPU2::Close(); - g_PadManager.Shutdown(); + Pad::Shutdown(); g_Sio2.Shutdown(); g_Sio0.Shutdown(); DEV9close(); @@ -1984,7 +1982,8 @@ void VMManager::Internal::EntryPointCompilingOnCPUThread() void VMManager::Internal::VSyncOnCPUThread() { - // TODO: Move frame limiting here to reduce CPU usage after sleeping... + Pad::UpdateMacroButtons(); + Patch::ApplyLoadedPatches(Patch::PPT_CONTINUOUSLY); Patch::ApplyLoadedPatches(Patch::PPT_COMBINED_0_1); diff --git a/pcsx2/pcsx2.vcxproj b/pcsx2/pcsx2.vcxproj index df8ec161bc..6eeb579ea2 100644 --- a/pcsx2/pcsx2.vcxproj +++ b/pcsx2/pcsx2.vcxproj @@ -243,11 +243,9 @@ - + - - @@ -599,14 +597,10 @@ - - - + - - diff --git a/pcsx2/pcsx2.vcxproj.filters b/pcsx2/pcsx2.vcxproj.filters index 4edf71e27b..82850ba53b 100644 --- a/pcsx2/pcsx2.vcxproj.filters +++ b/pcsx2/pcsx2.vcxproj.filters @@ -1418,9 +1418,6 @@ System\Ps2\Iop\SIO\PAD - - System\Ps2\Iop\SIO\PAD - System\Ps2\Iop\SIO\PAD @@ -1433,10 +1430,7 @@ System\Ps2\Iop\SIO - - System\Ps2\Iop\SIO\PAD - - + System\Ps2\Iop\SIO\PAD @@ -2345,12 +2339,6 @@ System\Ps2\Iop\SIO\Memcard - - System\Ps2\Iop\SIO\PAD - - - System\Ps2\Iop\SIO\PAD - System\Ps2\Iop\SIO\PAD @@ -2360,9 +2348,6 @@ System\Ps2\Iop\SIO\PAD - - System\Ps2\Iop\SIO\PAD - System\Ps2\Iop\SIO\PAD @@ -2381,10 +2366,7 @@ System\Ps2\Iop\SIO - - System\Ps2\Iop\SIO\PAD - - + System\Ps2\Iop\SIO\PAD diff --git a/pcsx2/ps2/Iop/IopHwRead.cpp b/pcsx2/ps2/Iop/IopHwRead.cpp index 3a1d0efb1a..18021e68cc 100644 --- a/pcsx2/ps2/Iop/IopHwRead.cpp +++ b/pcsx2/ps2/Iop/IopHwRead.cpp @@ -436,7 +436,7 @@ mem32_t iopHwRead32_Page8( u32 addr ) if( masked_addr < 0x240 ) { const int parm = (masked_addr-0x200) / 4; - ret = g_Sio2.send3.at(parm); + ret = g_Sio2.send3[parm]; Sio2Log.WriteLn("%s(%08X) SIO2 SEND3 Read (%08X)", __FUNCTION__, addr, ret); } else if( masked_addr < 0x260 ) @@ -444,7 +444,7 @@ mem32_t iopHwRead32_Page8( u32 addr ) // SIO2 Send commands alternate registers. First reg maps to Send1, second // to Send2, third to Send1, etc. And the following clever code does this: const int parm = (masked_addr-0x240) / 8; - ret = (masked_addr & 4) ? g_Sio2.send2.at(parm) : g_Sio2.send1.at(parm); + ret = (masked_addr & 4) ? g_Sio2.send2[parm] : g_Sio2.send1[parm]; Sio2Log.WriteLn("%s(%08X) SIO2 SEND1/2 Read (%08X)", __FUNCTION__, addr, ret); } else if( masked_addr <= 0x280 ) diff --git a/pcsx2/ps2/Iop/IopHwWrite.cpp b/pcsx2/ps2/Iop/IopHwWrite.cpp index 92b2961f51..791447e3ac 100644 --- a/pcsx2/ps2/Iop/IopHwWrite.cpp +++ b/pcsx2/ps2/Iop/IopHwWrite.cpp @@ -615,12 +615,12 @@ void iopHwWrite32_Page8( u32 addr, mem32_t val ) if (masked_addr & 4) { Sio2Log.WriteLn("%s(%08X, %08X) SIO2 SEND2 Write", __FUNCTION__, addr, val); - g_Sio2.send2.at(parm) = val; + g_Sio2.send2[parm] = val; } else { Sio2Log.WriteLn("%s(%08X, %08X) SIO2 SEND1 Write", __FUNCTION__, addr, val); - g_Sio2.send1.at(parm) = val; + g_Sio2.send1[parm] = val; } } else if( masked_addr <= 0x280 )