mirror of https://github.com/PCSX2/pcsx2.git
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
This commit is contained in:
parent
d4cb35469d
commit
ab5c03b1d9
|
@ -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<int>::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<const SettingInfo> 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<const InputBindingInfo*> new_binds;
|
||||
for (u32 i = 0, bind_index = 0; i < cinfo->num_bindings; i++)
|
||||
for (u32 i = 0, bind_index = 0; i < static_cast<u32>(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)
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "pcsx2/SIO/Pad/PadMacros.h"
|
||||
#include "pcsx2/SIO/Pad/PadTypes.h"
|
||||
|
||||
#include <QtWidgets/QWidget>
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>691</width>
|
||||
<height>547</height>
|
||||
<height>433</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
@ -83,6 +83,9 @@
|
|||
<property name="tickPosition">
|
||||
<enum>QSlider::TicksBelow</enum>
|
||||
</property>
|
||||
<property name="tickInterval">
|
||||
<number>10</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
|
@ -123,6 +126,46 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<layout class="QHBoxLayout" name="deadzoneLayout" stretch="0,1,0">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Deadzone:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="deadzone">
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="tickPosition">
|
||||
<enum>QSlider::TicksBelow</enum>
|
||||
</property>
|
||||
<property name="tickInterval">
|
||||
<number>10</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="deadzoneValue">
|
||||
<property name="text">
|
||||
<string>100%</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
|
@ -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<std::string> names(g_PadConfig.GetInputProfileNames());
|
||||
const std::vector<std::string> names = Pad::GetInputProfileNames();
|
||||
|
||||
QSignalBlocker sb(m_ui.currentProfile);
|
||||
m_ui.currentProfile->clear();
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<std::string> profiles(g_PadConfig.GetInputProfileNames());
|
||||
std::vector<std::string> 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<std::string> profiles(g_PadConfig.GetInputProfileNames());
|
||||
std::vector<std::string> 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<std::pair<const char*, const char*>> raw_options = g_PadConfig.GetControllerTypeNames();
|
||||
const std::vector<std::pair<const char*, const char*>> 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<std::string_view> 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<const SettingInfo> settings(USB::GetDeviceSettings(type, subtype));
|
||||
|
|
|
@ -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<PadBase*> 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<PadBase*> 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<u32>(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<float>(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<float>(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<float>(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<float>(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++)
|
||||
|
|
|
@ -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<std::string> 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;
|
||||
|
|
|
@ -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 <fmt/core.h>
|
||||
|
@ -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<u8, 18> data)
|
||||
|
@ -81,54 +81,54 @@ PadData::PadData(const int port, const int slot, const std::array<u8, 18> 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<bool, u8> buttonInfo)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 <vector>
|
||||
|
||||
PadConfig::PadConfig() = default;
|
||||
PadConfig::~PadConfig() = default;
|
||||
|
||||
void PadConfig::LoadConfig(const SettingsInterface& si)
|
||||
namespace Pad
|
||||
{
|
||||
g_PadMacros.ClearMacros();
|
||||
struct MacroButton
|
||||
{
|
||||
std::vector<u32> 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<PadBase> 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<std::array<MacroButton, NUM_MACRO_BUTTONS_PER_CONTROLLER>, NUM_CONTROLLER_PORTS> s_macro_buttons;
|
||||
static std::array<std::unique_ptr<PadBase>, 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<std::pair<const char*, const char*>> 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<std::pair<const char*, const char*>> Pad::GetControllerTypeNames()
|
||||
{
|
||||
std::vector<std::pair<const char*, const char*>> 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<std::string> PadConfig::GetControllerBinds(const std::string_view& type)
|
||||
std::vector<std::string> Pad::GetControllerBinds(const std::string_view& type)
|
||||
{
|
||||
std::vector<std::string> 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<std::pair<GenericInputBinding, std::string>>& 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<std::string> PadConfig::GetInputProfileNames()
|
||||
std::vector<std::string> Pad::GetInputProfileNames()
|
||||
{
|
||||
FileSystem::FindResultsArray results;
|
||||
FileSystem::FindFiles(EmuFolders::InputProfiles.c_str(), "*.ini",
|
||||
|
@ -465,17 +495,123 @@ std::vector<std::string> 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<PadBase> Pad::CreatePad(u8 unifiedSlot, ControllerType controllerType)
|
||||
{
|
||||
switch (controllerType)
|
||||
{
|
||||
case ControllerType::DualShock2:
|
||||
return std::make_unique<PadDualshock2>(unifiedSlot);
|
||||
case ControllerType::Guitar:
|
||||
return std::make_unique<PadGuitar>(unifiedSlot);
|
||||
default:
|
||||
return std::make_unique<PadNotConnected>(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<PadBase> 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<std::string> 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<u32> bind_indices;
|
||||
std::vector<std::string_view> 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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,58 +15,69 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "Config.h"
|
||||
#include "SIO/Pad/PadTypes.h"
|
||||
|
||||
#include "Config.h"
|
||||
#include <memory>
|
||||
|
||||
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<std::pair<const char*, const char*>> GetControllerTypeNames();
|
||||
|
||||
// Returns the list of binds for the specified controller type.
|
||||
std::vector<std::string> 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<std::pair<GenericInputBinding, std::string>>& mapping);
|
||||
bool MapController(
|
||||
SettingsInterface& si, u32 controller, const std::vector<std::pair<GenericInputBinding, std::string>>& mapping);
|
||||
|
||||
// Returns a list of input profiles available.
|
||||
std::vector<std::string> 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
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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<u8, u8> left, const std::tuple<u8, u8> 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<u8, u8> GetRawLeftAnalog() = 0;
|
||||
virtual std::tuple<u8, u8> GetRawRightAnalog() = 0;
|
||||
virtual u32 GetButtons() = 0;
|
||||
virtual u8 GetPressure(u32 index) = 0;
|
||||
virtual u8 GetRawInput(u32 index) const = 0;
|
||||
virtual std::tuple<u8, u8> GetRawLeftAnalog() const = 0;
|
||||
virtual std::tuple<u8, u8> 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;
|
||||
};
|
||||
|
|
|
@ -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<float>(this->vibrationMotors.at(0)) * GetVibrationScale(0) * (1.0f / 255.0f), 1.0f),
|
||||
std::min(static_cast<float>(this->vibrationMotors.at(1)) * GetVibrationScale(1) * (1.0f / 255.0f), 1.0f)
|
||||
std::min(static_cast<float>(this->vibrationMotors[0]) * GetVibrationScale(0) * (1.0f / 255.0f), 1.0f),
|
||||
std::min(static_cast<float>(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<u8, Dualshock2::Inputs::LENGTH> bitmaskMapping = {{
|
||||
static constexpr std::array<u8, Inputs::LENGTH> 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<float>(this->rawInputs[pos]) / 255.0f) : (static_cast<float>(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<u8>(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<u8, u8> PadDualshock2::GetRawLeftAnalog()
|
||||
std::tuple<u8, u8> PadDualshock2::GetRawLeftAnalog() const
|
||||
{
|
||||
return {this->analogs.lx, this->analogs.ly};
|
||||
return {analogs.lx, analogs.ly};
|
||||
}
|
||||
|
||||
std::tuple<u8, u8> PadDualshock2::GetRawRightAnalog()
|
||||
std::tuple<u8, u8> 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)
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "SIO/Pad/PadBase.h"
|
||||
#include "SIO/Pad/PadDualshock2Types.h"
|
||||
|
||||
#include <array>
|
||||
|
||||
|
@ -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<u8, Dualshock2::PRESSURE_BUTTONS> pressures;
|
||||
std::array<u8, Dualshock2::VIBRATION_MOTORS> vibrationMotors;
|
||||
std::array<u8, PRESSURE_BUTTONS> pressures;
|
||||
std::array<u8, VIBRATION_MOTORS> 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<u8, u8> left, const std::tuple<u8, u8> 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<u8, u8> GetRawLeftAnalog() override;
|
||||
std::tuple<u8, u8> GetRawRightAnalog() override;
|
||||
u32 GetButtons() override;
|
||||
u8 GetPressure(u32 index) override;
|
||||
u8 GetRawInput(u32 index) const override;
|
||||
std::tuple<u8, u8> GetRawLeftAnalog() const override;
|
||||
std::tuple<u8, u8> 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;
|
||||
};
|
||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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
|
|
@ -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<u8>(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<u8>(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<u8, Guitar::Inputs::LENGTH> bitmaskMapping = {{
|
||||
static constexpr std::array<u8, Inputs::LENGTH> 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<u8, u8> PadGuitar::GetRawLeftAnalog()
|
||||
std::tuple<u8, u8> PadGuitar::GetRawLeftAnalog() const
|
||||
{
|
||||
return std::tuple<u8, u8>{0x7f, 0x7f};
|
||||
}
|
||||
|
||||
std::tuple<u8, u8> PadGuitar::GetRawRightAnalog()
|
||||
std::tuple<u8, u8> PadGuitar::GetRawRightAnalog() const
|
||||
{
|
||||
return std::tuple<u8, u8>{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)
|
||||
|
|
|
@ -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<u8, u8> left, const std::tuple<u8, u8> 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<u8, u8> GetRawLeftAnalog() override;
|
||||
std::tuple<u8, u8> GetRawRightAnalog() override;
|
||||
u32 GetButtons() override;
|
||||
u8 GetPressure(u32 index) override;
|
||||
u8 GetRawInput(u32 index) const override;
|
||||
std::tuple<u8, u8> GetRawLeftAnalog() const override;
|
||||
std::tuple<u8, u8> 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;
|
||||
};
|
||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "SIO/Pad/PadTypes.h"
|
||||
|
||||
#include <vector>
|
||||
#include <array>
|
||||
|
||||
class PadMacros
|
||||
{
|
||||
public: // Constants
|
||||
struct MacroButton
|
||||
{
|
||||
std::vector<u32> 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<std::array<PadMacros::MacroButton, PadMacros::NUM_MACRO_BUTTONS_PER_CONTROLLER>, 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;
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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<PadDualshock2>(unifiedSlot);
|
||||
break;
|
||||
case Pad::ControllerType::Guitar:
|
||||
this->ps2Controllers.at(unifiedSlot) = std::make_unique<PadGuitar>(unifiedSlot);
|
||||
break;
|
||||
default:
|
||||
this->ps2Controllers.at(unifiedSlot) = std::make_unique<PadNotConnected>(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;
|
||||
}
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "SIO/Pad/PadBase.h"
|
||||
|
||||
#include <array>
|
||||
|
||||
class PadManager
|
||||
{
|
||||
private:
|
||||
std::array<std::unique_ptr<PadBase>, 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;
|
|
@ -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<u8, u8> PadNotConnected::GetRawLeftAnalog()
|
||||
std::tuple<u8, u8> PadNotConnected::GetRawLeftAnalog() const
|
||||
{
|
||||
return std::tuple<u8, u8>{0, 0};
|
||||
}
|
||||
|
||||
std::tuple<u8, u8> PadNotConnected::GetRawRightAnalog()
|
||||
std::tuple<u8, u8> PadNotConnected::GetRawRightAnalog() const
|
||||
{
|
||||
return std::tuple<u8, u8>{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;
|
||||
|
|
|
@ -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<u8, u8> left, const std::tuple<u8, u8> 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<u8, u8> left, const std::tuple<u8, u8> 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<u8, u8> GetRawLeftAnalog();
|
||||
std::tuple<u8, u8> 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<u8, u8> GetRawLeftAnalog() const override;
|
||||
std::tuple<u8, u8> GetRawRightAnalog() const override;
|
||||
u32 GetButtons() const override;
|
||||
u8 GetPressure(u32 index) const override;
|
||||
|
||||
u8 SendCommandByte(u8 commandByte) override;
|
||||
|
||||
static const Pad::ControllerInfo ControllerInfo;
|
||||
};
|
||||
|
|
|
@ -15,6 +15,10 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#include <span>
|
||||
|
||||
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<const InputBindingInfo> bindings;
|
||||
std::span<const SettingInfo> 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
|
||||
|
|
|
@ -109,7 +109,11 @@ extern void sioNextFrame();
|
|||
/// Converts a global pad index to a multitap port and slot.
|
||||
extern std::tuple<u32, u32> 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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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<PadBase*> 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;
|
||||
|
|
|
@ -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; }
|
||||
};
|
||||
|
||||
|
|
|
@ -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<std::mutex> 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);
|
||||
|
||||
|
|
|
@ -243,11 +243,9 @@
|
|||
<ClCompile Include="SIO\Memcard\MemoryCardProtocol.cpp" />
|
||||
<ClCompile Include="SIO\Multitap\MultitapProtocol.cpp" />
|
||||
<ClCompile Include="SIO\Pad\PadBase.cpp" />
|
||||
<ClCompile Include="SIO\Pad\PadConfig.cpp" />
|
||||
<ClCompile Include="SIO\Pad\Pad.cpp" />
|
||||
<ClCompile Include="SIO\Pad\PadDualshock2.cpp" />
|
||||
<ClCompile Include="SIO\Pad\PadGuitar.cpp" />
|
||||
<ClCompile Include="SIO\Pad\PadMacros.cpp" />
|
||||
<ClCompile Include="SIO\Pad\PadManager.cpp" />
|
||||
<ClCompile Include="SIO\Pad\PadNotConnected.cpp" />
|
||||
<ClCompile Include="SIO\Sio.cpp" />
|
||||
<ClCompile Include="SIO\Sio0.cpp" />
|
||||
|
@ -599,14 +597,10 @@
|
|||
<ClInclude Include="SIO\Memcard\MemoryCardFolder.h" />
|
||||
<ClInclude Include="SIO\Memcard\MemoryCardProtocol.h" />
|
||||
<ClInclude Include="SIO\Multitap\MultitapProtocol.h" />
|
||||
<ClInclude Include="SIO\Pad\PadDualshock2Types.h" />
|
||||
<ClInclude Include="SIO\Pad\PadGuitarTypes.h" />
|
||||
<ClInclude Include="SIO\Pad\PadBase.h" />
|
||||
<ClInclude Include="SIO\Pad\PadConfig.h" />
|
||||
<ClInclude Include="SIO\Pad\Pad.h" />
|
||||
<ClInclude Include="SIO\Pad\PadDualshock2.h" />
|
||||
<ClInclude Include="SIO\Pad\PadGuitar.h" />
|
||||
<ClInclude Include="SIO\Pad\PadMacros.h" />
|
||||
<ClInclude Include="SIO\Pad\PadManager.h" />
|
||||
<ClInclude Include="SIO\Pad\PadNotConnected.h" />
|
||||
<ClInclude Include="SIO\Pad\PadTypes.h" />
|
||||
<ClInclude Include="SIO\Sio.h" />
|
||||
|
|
|
@ -1418,9 +1418,6 @@
|
|||
<ClCompile Include="SIO\Pad\PadGuitar.cpp">
|
||||
<Filter>System\Ps2\Iop\SIO\PAD</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SIO\Pad\PadManager.cpp">
|
||||
<Filter>System\Ps2\Iop\SIO\PAD</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SIO\Pad\PadNotConnected.cpp">
|
||||
<Filter>System\Ps2\Iop\SIO\PAD</Filter>
|
||||
</ClCompile>
|
||||
|
@ -1433,10 +1430,7 @@
|
|||
<ClCompile Include="SIO\Sio2.cpp">
|
||||
<Filter>System\Ps2\Iop\SIO</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SIO\Pad\PadMacros.cpp">
|
||||
<Filter>System\Ps2\Iop\SIO\PAD</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SIO\Pad\PadConfig.cpp">
|
||||
<ClCompile Include="SIO\Pad\Pad.cpp">
|
||||
<Filter>System\Ps2\Iop\SIO\PAD</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
|
@ -2345,12 +2339,6 @@
|
|||
<ClInclude Include="SIO\Memcard\MemoryCardProtocol.h">
|
||||
<Filter>System\Ps2\Iop\SIO\Memcard</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SIO\Pad\PadDualshock2Types.h">
|
||||
<Filter>System\Ps2\Iop\SIO\PAD</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SIO\Pad\PadGuitarTypes.h">
|
||||
<Filter>System\Ps2\Iop\SIO\PAD</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SIO\Pad\PadBase.h">
|
||||
<Filter>System\Ps2\Iop\SIO\PAD</Filter>
|
||||
</ClInclude>
|
||||
|
@ -2360,9 +2348,6 @@
|
|||
<ClInclude Include="SIO\Pad\PadGuitar.h">
|
||||
<Filter>System\Ps2\Iop\SIO\PAD</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SIO\Pad\PadManager.h">
|
||||
<Filter>System\Ps2\Iop\SIO\PAD</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SIO\Pad\PadNotConnected.h">
|
||||
<Filter>System\Ps2\Iop\SIO\PAD</Filter>
|
||||
</ClInclude>
|
||||
|
@ -2381,10 +2366,7 @@
|
|||
<ClInclude Include="SIO\SioTypes.h">
|
||||
<Filter>System\Ps2\Iop\SIO</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SIO\Pad\PadMacros.h">
|
||||
<Filter>System\Ps2\Iop\SIO\PAD</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SIO\Pad\PadConfig.h">
|
||||
<ClInclude Include="SIO\Pad\Pad.h">
|
||||
<Filter>System\Ps2\Iop\SIO\PAD</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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 )
|
||||
|
|
Loading…
Reference in New Issue