mirror of https://github.com/PCSX2/pcsx2.git
USB: Gametrak/RealPlay emulation
This commit is contained in:
parent
2fa85c56c2
commit
2bff3579e5
|
@ -24,8 +24,10 @@
|
||||||
#include "SettingWidgetBinder.h"
|
#include "SettingWidgetBinder.h"
|
||||||
|
|
||||||
#include "ui_USBBindingWidget_DrivingForce.h"
|
#include "ui_USBBindingWidget_DrivingForce.h"
|
||||||
|
#include "ui_USBBindingWidget_Gametrak.h"
|
||||||
#include "ui_USBBindingWidget_GTForce.h"
|
#include "ui_USBBindingWidget_GTForce.h"
|
||||||
#include "ui_USBBindingWidget_GunCon2.h"
|
#include "ui_USBBindingWidget_GunCon2.h"
|
||||||
|
#include "ui_USBBindingWidget_RealPlay.h"
|
||||||
|
|
||||||
ControllerBindingWidget::ControllerBindingWidget(QWidget* parent, ControllerSettingsWindow* dialog, u32 port)
|
ControllerBindingWidget::ControllerBindingWidget(QWidget* parent, ControllerSettingsWindow* dialog, u32 port)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
|
@ -1322,11 +1324,21 @@ USBBindingWidget* USBBindingWidget::createInstance(
|
||||||
has_template = true;
|
has_template = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (type == "Gametrak")
|
||||||
|
{
|
||||||
|
Ui::USBBindingWidget_Gametrak().setupUi(widget);
|
||||||
|
has_template = true;
|
||||||
|
}
|
||||||
else if (type == "guncon2")
|
else if (type == "guncon2")
|
||||||
{
|
{
|
||||||
Ui::USBBindingWidget_GunCon2().setupUi(widget);
|
Ui::USBBindingWidget_GunCon2().setupUi(widget);
|
||||||
has_template = true;
|
has_template = true;
|
||||||
}
|
}
|
||||||
|
else if (type == "RealPlay")
|
||||||
|
{
|
||||||
|
Ui::USBBindingWidget_RealPlay().setupUi(widget);
|
||||||
|
has_template = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (has_template)
|
if (has_template)
|
||||||
widget->bindWidgets(bindings);
|
widget->bindWidgets(bindings);
|
||||||
|
|
|
@ -0,0 +1,436 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>USBBindingWidget_Gametrak</class>
|
||||||
|
<widget class="QWidget" name="USBBindingWidget_Gametrak">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>1100</width>
|
||||||
|
<height>500</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<spacer name="horizontalSpacer0">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout1">
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox1">
|
||||||
|
<property name="title">
|
||||||
|
<string>Left Hand</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout1">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QGroupBox" name="groupBox1_X">
|
||||||
|
<property name="title">
|
||||||
|
<string>X Axis</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout1_X">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="InputBindingWidget" name="LeftX">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>130</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>130</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>PushButton</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label1_X">
|
||||||
|
<property name="text">
|
||||||
|
<string>Left=0 / Right=0x3ff</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QGroupBox" name="groupBox1_Y">
|
||||||
|
<property name="title">
|
||||||
|
<string>Y Axis</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout1_Y">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="InputBindingWidget" name="LeftY">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>130</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>130</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>PushButton</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label1_Y">
|
||||||
|
<property name="text">
|
||||||
|
<string>Back=0 / Front=0x3ff</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QGroupBox" name="groupBox1_Z">
|
||||||
|
<property name="title">
|
||||||
|
<string>Z Axis</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout1_Z">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="InputBindingWidget" name="LeftZ">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>130</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>130</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>PushButton</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label1_Z">
|
||||||
|
<property name="text">
|
||||||
|
<string>Top=0 / Bottom=0xfff</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="2">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout2">
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox2">
|
||||||
|
<property name="title">
|
||||||
|
<string>Foot Pedal</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout2">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="InputBindingWidget" name="FootPedal">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>130</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>130</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>PushButton</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="3">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout3">
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox3">
|
||||||
|
<property name="title">
|
||||||
|
<string>Right Hand</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout3">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QGroupBox" name="groupBox3_X">
|
||||||
|
<property name="title">
|
||||||
|
<string>X Axis</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout3_X">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="InputBindingWidget" name="RightX">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>130</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>130</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>PushButton</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label3_X">
|
||||||
|
<property name="text">
|
||||||
|
<string>Left=0 / Right=0x3ff</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QGroupBox" name="groupBox3_Y">
|
||||||
|
<property name="title">
|
||||||
|
<string>Y Axis</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout3_Y">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="InputBindingWidget" name="RightY">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>130</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>130</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>PushButton</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label3_Y">
|
||||||
|
<property name="text">
|
||||||
|
<string>Back=0 / Front=0x3ff</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QGroupBox" name="groupBox3_Z">
|
||||||
|
<property name="title">
|
||||||
|
<string>Z Axis</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout3_Z">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="InputBindingWidget" name="RightZ">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>130</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>130</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>PushButton</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label3_Z">
|
||||||
|
<property name="text">
|
||||||
|
<string>Top=0 / Bottom=0xfff</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="4">
|
||||||
|
<spacer name="horizontalSpacer4">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1" colspan="3">
|
||||||
|
<spacer name="verticalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>InputBindingWidget</class>
|
||||||
|
<extends>QPushButton</extends>
|
||||||
|
<header>Settings/InputBindingWidget.h</header>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
|
<resources>
|
||||||
|
<include location="../resources/resources.qrc"/>
|
||||||
|
</resources>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
|
@ -0,0 +1,506 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>USBBindingWidget_RealPlay</class>
|
||||||
|
<widget class="QWidget" name="USBBindingWidget_RealPlay">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>1100</width>
|
||||||
|
<height>500</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item row="0" column="2">
|
||||||
|
<widget class="QGroupBox" name="groupBoxDPadUp">
|
||||||
|
<property name="title">
|
||||||
|
<string>D-Pad Up</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayoutDPadUp">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="InputBindingWidget" name="DPadUp">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>130</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>130</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>PushButton</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="2">
|
||||||
|
<widget class="QGroupBox" name="groupBoxDPadDown">
|
||||||
|
<property name="title">
|
||||||
|
<string>D-Pad Down</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayoutDPadDown">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="InputBindingWidget" name="DPadDown">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>130</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>130</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>PushButton</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QGroupBox" name="groupBoxDPadLeft">
|
||||||
|
<property name="title">
|
||||||
|
<string>D-Pad Left</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayoutDPadLeft">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="InputBindingWidget" name="DPadLeft">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>130</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>130</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>PushButton</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="3">
|
||||||
|
<widget class="QGroupBox" name="groupBoxDPadRight">
|
||||||
|
<property name="title">
|
||||||
|
<string>D-Pad Right</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayoutDPadRight">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="InputBindingWidget" name="DPadRight">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>130</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>130</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>PushButton</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="6">
|
||||||
|
<widget class="QGroupBox" name="groupBoxBtnRed">
|
||||||
|
<property name="title">
|
||||||
|
<string>Red</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayoutBtnRed">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="InputBindingWidget" name="Red">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>130</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>130</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>PushButton</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="6">
|
||||||
|
<widget class="QGroupBox" name="groupBoxBtnGreen">
|
||||||
|
<property name="title">
|
||||||
|
<string>Green</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayoutBtnGreen">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="InputBindingWidget" name="Green">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>130</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>130</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>PushButton</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="5">
|
||||||
|
<widget class="QGroupBox" name="groupBoxBtnYellow">
|
||||||
|
<property name="title">
|
||||||
|
<string>Yellow</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayoutBtnYellow">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="InputBindingWidget" name="Yellow">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>130</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>130</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>PushButton</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="7">
|
||||||
|
<widget class="QGroupBox" name="groupBoxBtnBlue">
|
||||||
|
<property name="title">
|
||||||
|
<string>Blue</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayoutBtnBlue">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="InputBindingWidget" name="Blue">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>130</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>130</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>PushButton</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="3">
|
||||||
|
<widget class="QGroupBox" name="groupBoxAccelX">
|
||||||
|
<property name="title">
|
||||||
|
<string>Accel X</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayoutAccelX">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="InputBindingWidget" name="AccelX">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>130</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>130</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>PushButton</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="4">
|
||||||
|
<widget class="QGroupBox" name="groupBoxAccelY">
|
||||||
|
<property name="title">
|
||||||
|
<string>Accel Y</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayoutAccelY">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="InputBindingWidget" name="AccelY">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>130</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>130</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>PushButton</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="5">
|
||||||
|
<widget class="QGroupBox" name="groupBoxAccelZ">
|
||||||
|
<property name="title">
|
||||||
|
<string>Accel Z</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayoutAccelZ">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="InputBindingWidget" name="AccelZ">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>130</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>130</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>PushButton</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0" rowspan="4">
|
||||||
|
<spacer name="horizontalSpacer0">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="8" rowspan="4">
|
||||||
|
<spacer name="horizontalSpacer8">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="1" colspan="7">
|
||||||
|
<spacer name="verticalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>InputBindingWidget</class>
|
||||||
|
<extends>QPushButton</extends>
|
||||||
|
<header>Settings/InputBindingWidget.h</header>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
|
<resources>
|
||||||
|
<include location="../resources/resources.qrc"/>
|
||||||
|
</resources>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
|
@ -395,9 +395,6 @@
|
||||||
</QtUi>
|
</QtUi>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<QtUi Include="Settings\USBBindingWidget_GunCon2.ui">
|
|
||||||
<FileType>Document</FileType>
|
|
||||||
</QtUi>
|
|
||||||
<QtUi Include="SetupWizardDialog.ui">
|
<QtUi Include="SetupWizardDialog.ui">
|
||||||
<FileType>Document</FileType>
|
<FileType>Document</FileType>
|
||||||
</QtUi>
|
</QtUi>
|
||||||
|
@ -422,9 +419,18 @@
|
||||||
<QtUi Include="Settings\USBBindingWidget_DrivingForce.ui">
|
<QtUi Include="Settings\USBBindingWidget_DrivingForce.ui">
|
||||||
<FileType>Document</FileType>
|
<FileType>Document</FileType>
|
||||||
</QtUi>
|
</QtUi>
|
||||||
|
<QtUi Include="Settings\USBBindingWidget_Gametrak.ui">
|
||||||
|
<FileType>Document</FileType>
|
||||||
|
</QtUi>
|
||||||
<QtUi Include="Settings\USBBindingWidget_GTForce.ui">
|
<QtUi Include="Settings\USBBindingWidget_GTForce.ui">
|
||||||
<FileType>Document</FileType>
|
<FileType>Document</FileType>
|
||||||
</QtUi>
|
</QtUi>
|
||||||
|
<QtUi Include="Settings\USBBindingWidget_GunCon2.ui">
|
||||||
|
<FileType>Document</FileType>
|
||||||
|
</QtUi>
|
||||||
|
<QtUi Include="Settings\USBBindingWidget_RealPlay.ui">
|
||||||
|
<FileType>Document</FileType>
|
||||||
|
</QtUi>
|
||||||
<QtUi Include="Settings\USBDeviceWidget.ui">
|
<QtUi Include="Settings\USBDeviceWidget.ui">
|
||||||
<FileType>Document</FileType>
|
<FileType>Document</FileType>
|
||||||
</QtUi>
|
</QtUi>
|
||||||
|
|
|
@ -660,12 +660,18 @@
|
||||||
<QtUi Include="Settings\USBBindingWidget_DrivingForce.ui">
|
<QtUi Include="Settings\USBBindingWidget_DrivingForce.ui">
|
||||||
<Filter>Settings</Filter>
|
<Filter>Settings</Filter>
|
||||||
</QtUi>
|
</QtUi>
|
||||||
|
<QtUi Include="Settings\USBBindingWidget_Gametrak.ui">
|
||||||
|
<Filter>Settings</Filter>
|
||||||
|
</QtUi>
|
||||||
<QtUi Include="Settings\USBBindingWidget_GTForce.ui">
|
<QtUi Include="Settings\USBBindingWidget_GTForce.ui">
|
||||||
<Filter>Settings</Filter>
|
<Filter>Settings</Filter>
|
||||||
</QtUi>
|
</QtUi>
|
||||||
<QtUi Include="Settings\USBBindingWidget_GunCon2.ui">
|
<QtUi Include="Settings\USBBindingWidget_GunCon2.ui">
|
||||||
<Filter>Settings</Filter>
|
<Filter>Settings</Filter>
|
||||||
</QtUi>
|
</QtUi>
|
||||||
|
<QtUi Include="Settings\USBBindingWidget_RealPlay.ui">
|
||||||
|
<Filter>Settings</Filter>
|
||||||
|
</QtUi>
|
||||||
<QtUi Include="Settings\AudioExpansionSettingsDialog.ui">
|
<QtUi Include="Settings\AudioExpansionSettingsDialog.ui">
|
||||||
<Filter>Settings</Filter>
|
<Filter>Settings</Filter>
|
||||||
</QtUi>
|
</QtUi>
|
||||||
|
|
|
@ -383,6 +383,8 @@ set(pcsx2USBSources
|
||||||
USB/usb-mic/usb-mic-singstar.cpp
|
USB/usb-mic/usb-mic-singstar.cpp
|
||||||
USB/usb-msd/usb-msd.cpp
|
USB/usb-msd/usb-msd.cpp
|
||||||
USB/usb-pad/lg/lg_ff.cpp
|
USB/usb-pad/lg/lg_ff.cpp
|
||||||
|
USB/usb-pad/usb-gametrak.cpp
|
||||||
|
USB/usb-pad/usb-realplay.cpp
|
||||||
USB/usb-pad/usb-pad-ff.cpp
|
USB/usb-pad/usb-pad-ff.cpp
|
||||||
USB/usb-pad/usb-pad-sdl-ff.cpp
|
USB/usb-pad/usb-pad-sdl-ff.cpp
|
||||||
USB/usb-pad/usb-pad.cpp
|
USB/usb-pad/usb-pad.cpp
|
||||||
|
@ -417,6 +419,8 @@ set(pcsx2USBHeaders
|
||||||
USB/usb-mic/usb-mic-singstar.h
|
USB/usb-mic/usb-mic-singstar.h
|
||||||
USB/usb-msd/usb-msd.h
|
USB/usb-msd/usb-msd.h
|
||||||
USB/usb-pad/lg/lg_ff.h
|
USB/usb-pad/lg/lg_ff.h
|
||||||
|
USB/usb-pad/usb-gametrak.h
|
||||||
|
USB/usb-pad/usb-realplay.h
|
||||||
USB/usb-pad/usb-pad-sdl-ff.h
|
USB/usb-pad/usb-pad-sdl-ff.h
|
||||||
USB/usb-pad/usb-pad.h
|
USB/usb-pad/usb-pad.h
|
||||||
USB/usb-printer/usb-printer.h
|
USB/usb-printer/usb-printer.h
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
#include "deviceproxy.h"
|
#include "deviceproxy.h"
|
||||||
#include "usb-eyetoy/usb-eyetoy-webcam.h"
|
#include "usb-eyetoy/usb-eyetoy-webcam.h"
|
||||||
|
#include "usb-pad/usb-gametrak.h"
|
||||||
|
#include "usb-pad/usb-realplay.h"
|
||||||
#include "usb-hid/usb-hid.h"
|
#include "usb-hid/usb-hid.h"
|
||||||
#include "usb-mic/usb-headset.h"
|
#include "usb-mic/usb-headset.h"
|
||||||
#include "usb-mic/usb-mic-singstar.h"
|
#include "usb-mic/usb-mic-singstar.h"
|
||||||
|
@ -78,6 +80,8 @@ void RegisterDevice::Register()
|
||||||
inst.Add(DEVTYPE_PRINTER, new usb_printer::PrinterDevice());
|
inst.Add(DEVTYPE_PRINTER, new usb_printer::PrinterDevice());
|
||||||
inst.Add(DEVTYPE_KEYBOARDMANIA, new usb_pad::KeyboardmaniaDevice());
|
inst.Add(DEVTYPE_KEYBOARDMANIA, new usb_pad::KeyboardmaniaDevice());
|
||||||
inst.Add(DEVTYPE_GUNCON2, new usb_lightgun::GunCon2Device());
|
inst.Add(DEVTYPE_GUNCON2, new usb_lightgun::GunCon2Device());
|
||||||
|
inst.Add(DEVTYPE_GAMETRAK, new usb_pad::GametrakDevice());
|
||||||
|
inst.Add(DEVTYPE_REALPLAY, new usb_pad::RealPlayDevice());
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegisterDevice::Unregister()
|
void RegisterDevice::Unregister()
|
||||||
|
|
|
@ -39,7 +39,9 @@ enum DeviceType : s32
|
||||||
DEVTYPE_PRINTER,
|
DEVTYPE_PRINTER,
|
||||||
DEVTYPE_KEYBOARDMANIA,
|
DEVTYPE_KEYBOARDMANIA,
|
||||||
DEVTYPE_GUNCON2,
|
DEVTYPE_GUNCON2,
|
||||||
DEVTYPE_DJ
|
DEVTYPE_DJ,
|
||||||
|
DEVTYPE_GAMETRAK,
|
||||||
|
DEVTYPE_REALPLAY,
|
||||||
};
|
};
|
||||||
|
|
||||||
class DeviceProxy
|
class DeviceProxy
|
||||||
|
|
|
@ -0,0 +1,408 @@
|
||||||
|
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0+
|
||||||
|
|
||||||
|
#include "Host.h"
|
||||||
|
#include "Input/InputManager.h"
|
||||||
|
#include "StateWrapper.h"
|
||||||
|
#include "USB/USB.h"
|
||||||
|
#include "USB/deviceproxy.h"
|
||||||
|
#include "USB/qemu-usb/USBinternal.h"
|
||||||
|
#include "USB/qemu-usb/desc.h"
|
||||||
|
#include "USB/usb-pad/usb-gametrak.h"
|
||||||
|
#include "USB/usb-pad/usb-pad.h"
|
||||||
|
#include <common/Console.h>
|
||||||
|
|
||||||
|
namespace usb_pad
|
||||||
|
{
|
||||||
|
static const USBDescStrings desc_strings = {
|
||||||
|
"",
|
||||||
|
"In2Games Ltd.",
|
||||||
|
"Game-Trak V1.3"};
|
||||||
|
|
||||||
|
static uint8_t dev_descriptor[] = {
|
||||||
|
0x12, // bLength
|
||||||
|
0x01, // bDescriptorType (Device)
|
||||||
|
0x10, 0x01, // bcdUSB 1.10
|
||||||
|
0x00, // bDeviceClass (Use class information in the Interface Descriptors)
|
||||||
|
0x00, // bDeviceSubClass
|
||||||
|
0x00, // bDeviceProtocol
|
||||||
|
0x08, // bMaxPacketSize0 8
|
||||||
|
0xB7, 0x14, // idVendor 0x14B7
|
||||||
|
0x82, 0x09, // idProduct 0x0982
|
||||||
|
0x01, 0x00, // bcdDevice 0.01
|
||||||
|
0x01, // iManufacturer (String Index)
|
||||||
|
0x02, // iProduct (String Index)
|
||||||
|
0x00, // iSerialNumber (String Index)
|
||||||
|
0x01, // bNumConfigurations 1
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t config_descriptor[] = {
|
||||||
|
0x09, // bLength
|
||||||
|
0x02, // bDescriptorType (Configuration)
|
||||||
|
0x22, 0x00, // wTotalLength 34
|
||||||
|
0x01, // bNumInterfaces 1
|
||||||
|
0x01, // bConfigurationValue
|
||||||
|
0x00, // iConfiguration (String Index)
|
||||||
|
0x80, // bmAttributes
|
||||||
|
0x0A, // bMaxPower 20mA
|
||||||
|
|
||||||
|
0x09, // bLength
|
||||||
|
0x04, // bDescriptorType (Interface)
|
||||||
|
0x00, // bInterfaceNumber 0
|
||||||
|
0x00, // bAlternateSetting
|
||||||
|
0x01, // bNumEndpoints 1
|
||||||
|
0x03, // bInterfaceClass
|
||||||
|
0x00, // bInterfaceSubClass
|
||||||
|
0x00, // bInterfaceProtocol
|
||||||
|
0x00, // iInterface (String Index)
|
||||||
|
|
||||||
|
0x09, // bLength
|
||||||
|
0x21, // bDescriptorType (HID)
|
||||||
|
0x01, 0x01, // bcdHID 1.01
|
||||||
|
0x00, // bCountryCode
|
||||||
|
0x01, // bNumDescriptors
|
||||||
|
0x22, // bDescriptorType[0] (HID)
|
||||||
|
0x7A, 0x00, // wDescriptorLength[0] 122
|
||||||
|
|
||||||
|
0x07, // bLength
|
||||||
|
0x05, // bDescriptorType (Endpoint)
|
||||||
|
0x81, // bEndpointAddress (IN/D2H)
|
||||||
|
0x03, // bmAttributes (Interrupt)
|
||||||
|
0x10, 0x00, // wMaxPacketSize 16
|
||||||
|
0x0A, // bInterval 10 (unit depends on device speed)
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t hid_report_descriptor[] = {
|
||||||
|
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
|
||||||
|
0x09, 0x04, // Usage (Joystick)
|
||||||
|
0xA1, 0x01, // Collection (Application)
|
||||||
|
0x09, 0x01, // Usage (Pointer)
|
||||||
|
0xA1, 0x00, // Collection (Physical)
|
||||||
|
0x09, 0x30, // Usage (X)
|
||||||
|
0x09, 0x31, // Usage (Y)
|
||||||
|
0x09, 0x32, // Usage (Z)
|
||||||
|
0x09, 0x33, // Usage (Rx)
|
||||||
|
0x09, 0x34, // Usage (Ry)
|
||||||
|
0x09, 0x35, // Usage (Rz)
|
||||||
|
0x16, 0x00, 0x00, // Logical Minimum (0)
|
||||||
|
0x26, 0xFF, 0x0F, // Logical Maximum (4095)
|
||||||
|
0x36, 0x00, 0x00, // Physical Minimum (0)
|
||||||
|
0x46, 0xFF, 0x0F, // Physical Maximum (4095)
|
||||||
|
0x66, 0x00, 0x00, // Unit (None)
|
||||||
|
0x75, 0x10, // Report Size (16)
|
||||||
|
0x95, 0x06, // Report Count (6)
|
||||||
|
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||||
|
0xC0, // End Collection
|
||||||
|
0x09, 0x39, // Usage (Hat switch)
|
||||||
|
0x15, 0x01, // Logical Minimum (1)
|
||||||
|
0x25, 0x08, // Logical Maximum (8)
|
||||||
|
0x35, 0x00, // Physical Minimum (0)
|
||||||
|
0x46, 0x3B, 0x01, // Physical Maximum (315)
|
||||||
|
0x65, 0x14, // Unit (System: English Rotation, Length: Centimeter)
|
||||||
|
0x75, 0x04, // Report Size (4)
|
||||||
|
0x95, 0x01, // Report Count (1)
|
||||||
|
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||||
|
0x05, 0x09, // Usage Page (Button)
|
||||||
|
0x19, 0x01, // Usage Minimum (0x01)
|
||||||
|
0x29, 0x0C, // Usage Maximum (0x0C)
|
||||||
|
0x15, 0x00, // Logical Minimum (0)
|
||||||
|
0x25, 0x01, // Logical Maximum (1)
|
||||||
|
0x75, 0x01, // Report Size (1)
|
||||||
|
0x95, 0x0C, // Report Count (12)
|
||||||
|
0x55, 0x00, // Unit Exponent (0)
|
||||||
|
0x65, 0x00, // Unit (None)
|
||||||
|
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||||
|
0x75, 0x08, // Report Size (8)
|
||||||
|
0x95, 0x02, // Report Count (2)
|
||||||
|
0x81, 0x01, // Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||||
|
0x05, 0x08, // Usage Page (LEDs)
|
||||||
|
0x09, 0x43, // Usage (Slow Blink On Time)
|
||||||
|
0x15, 0x00, // Logical Minimum (0)
|
||||||
|
0x26, 0xFF, 0x00, // Logical Maximum (255)
|
||||||
|
0x35, 0x00, // Physical Minimum (0)
|
||||||
|
0x46, 0xFF, 0x00, // Physical Maximum (255)
|
||||||
|
0x75, 0x08, // Report Size (8)
|
||||||
|
0x95, 0x01, // Report Count (1)
|
||||||
|
0x91, 0x82, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Volatile)
|
||||||
|
0x09, 0x44, // Usage (Slow Blink Off Time)
|
||||||
|
0x91, 0x82, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Volatile)
|
||||||
|
0x09, 0x45, // Usage (Fast Blink On Time)
|
||||||
|
0x91, 0x82, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Volatile)
|
||||||
|
0x09, 0x46, // Usage (Fast Blink Off Time)
|
||||||
|
0x91, 0x82, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Volatile)
|
||||||
|
0xC0, // End Collection
|
||||||
|
};
|
||||||
|
|
||||||
|
GametrakState::GametrakState(u32 port_)
|
||||||
|
: port(port_)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
GametrakState::~GametrakState() = default;
|
||||||
|
|
||||||
|
static u32 gametrak_compute_key(u32* key)
|
||||||
|
{
|
||||||
|
u32 ret = 0;
|
||||||
|
ret = *key << 2 & 0xFC0000;
|
||||||
|
ret |= *key << 17 & 0x020000;
|
||||||
|
ret ^= *key << 16 & 0xFE0000;
|
||||||
|
ret |= *key & 0x010000;
|
||||||
|
ret |= *key >> 9 & 0x007F7F;
|
||||||
|
ret |= *key << 7 & 0x008080;
|
||||||
|
*key = ret;
|
||||||
|
return ret >> 16;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void gametrak_handle_control(USBDevice* dev, USBPacket* p,
|
||||||
|
int request, int value, int index, int length, uint8_t* data)
|
||||||
|
{
|
||||||
|
GametrakState* s = USB_CONTAINER_OF(dev, GametrakState, dev);
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
switch (request)
|
||||||
|
{
|
||||||
|
case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
|
||||||
|
switch (value >> 8)
|
||||||
|
{
|
||||||
|
case USB_DT_REPORT:
|
||||||
|
ret = sizeof(hid_report_descriptor);
|
||||||
|
memcpy(data, hid_report_descriptor, ret);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SET_REPORT:
|
||||||
|
{
|
||||||
|
constexpr u8 secret[] = "Gametrak";
|
||||||
|
if (length == 8 && std::memcmp(data, secret, sizeof(secret)) == 0)
|
||||||
|
{
|
||||||
|
s->state = 0;
|
||||||
|
s->key = 0;
|
||||||
|
}
|
||||||
|
else if (length == 2)
|
||||||
|
{
|
||||||
|
if (data[0] == 0x45)
|
||||||
|
{
|
||||||
|
s->key = data[1] << 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((s->key >> 16) == data[1])
|
||||||
|
{
|
||||||
|
gametrak_compute_key(&s->key);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ERROR_LOG("gametrak error : own key = {}, recv key = {}", s->key >> 16, data[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SET_IDLE:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
|
||||||
|
if (ret >= 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
p->status = USB_RET_STALL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gametrak_handle_data(USBDevice* dev, USBPacket* p)
|
||||||
|
{
|
||||||
|
GametrakState* s = USB_CONTAINER_OF(dev, GametrakState, dev);
|
||||||
|
|
||||||
|
switch (p->pid)
|
||||||
|
{
|
||||||
|
case USB_TOKEN_IN:
|
||||||
|
if (p->ep->nr == 1)
|
||||||
|
{
|
||||||
|
pxAssert(p->buffer_size >= sizeof(s->data));
|
||||||
|
|
||||||
|
if (s->state == 0)
|
||||||
|
{
|
||||||
|
s->state = 1;
|
||||||
|
constexpr u8 secret[] = "Gametrak\0\0\0\0\0\0\0\0";
|
||||||
|
std::memcpy(p->buffer_ptr, secret, sizeof(secret));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
s->data.k1 = s->key >> 16 & 1;
|
||||||
|
s->data.k2 = s->key >> 17 & 1;
|
||||||
|
s->data.k3 = s->key >> 18 & 1;
|
||||||
|
s->data.k4 = s->key >> 19 & 1;
|
||||||
|
s->data.k5 = s->key >> 20 & 1;
|
||||||
|
s->data.k6 = s->key >> 21 & 1;
|
||||||
|
|
||||||
|
auto time = std::chrono::steady_clock::now();
|
||||||
|
if (std::chrono::duration_cast<std::chrono::milliseconds>(time - s->last_log).count() > 500)
|
||||||
|
{
|
||||||
|
Log::Write(LOGLEVEL_INFO, Color_Green, "{} LX={} LY={} LZ={} RX={} RY={} RZ={} Btn={}",
|
||||||
|
__FUNCTION__,
|
||||||
|
(u16)s->data.left_x, (u16)s->data.left_y, (u16)s->data.left_z,
|
||||||
|
(u16)s->data.right_x, (u16)s->data.right_y, (u16)s->data.right_z,
|
||||||
|
(u8)s->data.button);
|
||||||
|
s->last_log = time;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::memcpy(p->buffer_ptr, &s->data, sizeof(s->data));
|
||||||
|
}
|
||||||
|
|
||||||
|
p->actual_length += sizeof(s->data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case USB_TOKEN_OUT:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fail:
|
||||||
|
p->status = USB_RET_STALL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gametrak_unrealize(USBDevice* dev)
|
||||||
|
{
|
||||||
|
GametrakState* s = USB_CONTAINER_OF(dev, GametrakState, dev);
|
||||||
|
delete s;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* GametrakDevice::Name() const
|
||||||
|
{
|
||||||
|
return TRANSLATE_NOOP("USB", "Gametrak Device");
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* GametrakDevice::TypeName() const
|
||||||
|
{
|
||||||
|
return "Gametrak";
|
||||||
|
}
|
||||||
|
|
||||||
|
USBDevice* GametrakDevice::CreateDevice(SettingsInterface& si, u32 port, u32 subtype) const
|
||||||
|
{
|
||||||
|
GametrakState* s = new GametrakState(port);
|
||||||
|
|
||||||
|
s->desc.full = &s->desc_dev;
|
||||||
|
s->desc.str = desc_strings;
|
||||||
|
|
||||||
|
if (usb_desc_parse_dev(dev_descriptor, sizeof(dev_descriptor), s->desc, s->desc_dev) < 0)
|
||||||
|
goto fail;
|
||||||
|
if (usb_desc_parse_config(config_descriptor, sizeof(config_descriptor), s->desc_dev) < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
s->dev.speed = USB_SPEED_FULL;
|
||||||
|
s->dev.klass.handle_attach = usb_desc_attach;
|
||||||
|
s->dev.klass.handle_reset = nullptr;
|
||||||
|
s->dev.klass.handle_control = gametrak_handle_control;
|
||||||
|
s->dev.klass.handle_data = gametrak_handle_data;
|
||||||
|
s->dev.klass.unrealize = gametrak_unrealize;
|
||||||
|
s->dev.klass.usb_desc = &s->desc;
|
||||||
|
s->dev.klass.product_desc = nullptr;
|
||||||
|
|
||||||
|
usb_desc_init(&s->dev);
|
||||||
|
usb_ep_init(&s->dev);
|
||||||
|
|
||||||
|
return &s->dev;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
gametrak_unrealize(&s->dev);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GametrakDevice::Freeze(USBDevice* dev, StateWrapper& sw) const
|
||||||
|
{
|
||||||
|
GametrakState* s = USB_CONTAINER_OF(dev, GametrakState, dev);
|
||||||
|
|
||||||
|
if (!sw.DoMarker("GametrakDevice"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
sw.Do(&s->state);
|
||||||
|
sw.Do(&s->key);
|
||||||
|
return !sw.HasError();
|
||||||
|
}
|
||||||
|
|
||||||
|
float GametrakDevice::GetBindingValue(const USBDevice* dev, u32 bind_index) const
|
||||||
|
{
|
||||||
|
GametrakState* s = USB_CONTAINER_OF(dev, GametrakState, dev);
|
||||||
|
if (bind_index == CID_GT_BUTTON)
|
||||||
|
return s->data.button;
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GametrakDevice::SetBindingValue(USBDevice* dev, u32 bind_index, float value) const
|
||||||
|
{
|
||||||
|
GametrakState* s = USB_CONTAINER_OF(dev, GametrakState, dev);
|
||||||
|
switch (bind_index)
|
||||||
|
{
|
||||||
|
case CID_GT_BUTTON:
|
||||||
|
s->data.button = (value >= 0.5f);
|
||||||
|
break;
|
||||||
|
case CID_GT_LEFT_X:
|
||||||
|
s->data.left_x = static_cast<u16>(std::clamp<long>(std::lroundf(value * 2047.f), 0, 2047));
|
||||||
|
s->data.left_x = s->invert_x_axis ? 2047 - s->data.left_x : s->data.left_x;
|
||||||
|
break;
|
||||||
|
case CID_GT_LEFT_Y:
|
||||||
|
s->data.left_y = static_cast<u16>(std::clamp<long>(std::lroundf(value * 2047.f), 0, 2047));
|
||||||
|
s->data.left_y = s->invert_y_axis ? 2047 - s->data.left_y : s->data.left_y;
|
||||||
|
break;
|
||||||
|
case CID_GT_LEFT_Z:
|
||||||
|
s->data.left_z = static_cast<u32>(std::clamp<long>(std::lroundf(value * s->limit_z_axis), 0, s->limit_z_axis));
|
||||||
|
s->data.left_z = s->invert_z_axis ? s->limit_z_axis - s->data.left_z : s->data.left_z;
|
||||||
|
break;
|
||||||
|
case CID_GT_RIGHT_X:
|
||||||
|
s->data.right_x = static_cast<u16>(std::clamp<long>(std::lroundf(value * 2047.f), 0, 2047));
|
||||||
|
s->data.right_x = s->invert_x_axis ? 2047 - s->data.right_x : s->data.right_x;
|
||||||
|
break;
|
||||||
|
case CID_GT_RIGHT_Y:
|
||||||
|
s->data.right_y = static_cast<u16>(std::clamp<long>(std::lroundf(value * 2047.f), 0, 2047));
|
||||||
|
s->data.right_y = s->invert_y_axis ? 2047 - s->data.right_y : s->data.right_y;
|
||||||
|
break;
|
||||||
|
case CID_GT_RIGHT_Z:
|
||||||
|
s->data.right_z = static_cast<u32>(std::clamp<long>(std::lroundf(value * s->limit_z_axis), 0, s->limit_z_axis));
|
||||||
|
s->data.right_z = s->invert_z_axis ? s->limit_z_axis - s->data.right_z : s->data.right_z;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GametrakDevice::UpdateSettings(USBDevice* dev, SettingsInterface& si) const
|
||||||
|
{
|
||||||
|
GametrakState* s = USB_CONTAINER_OF(dev, GametrakState, dev);
|
||||||
|
s->invert_x_axis = USB::GetConfigBool(si, s->port, TypeName(), "invert_x_axis", false);
|
||||||
|
s->invert_y_axis = USB::GetConfigBool(si, s->port, TypeName(), "invert_y_axis", false);
|
||||||
|
s->invert_z_axis = USB::GetConfigBool(si, s->port, TypeName(), "invert_z_axis", false);
|
||||||
|
s->limit_z_axis = USB::GetConfigInt(si, s->port, TypeName(), "limit_z_axis", 4095);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::span<const InputBindingInfo> GametrakDevice::Bindings(u32 subtype) const
|
||||||
|
{
|
||||||
|
static constexpr const InputBindingInfo bindings[] = {
|
||||||
|
{"FootPedal", TRANSLATE_NOOP("USB", "Foot Pedal"), nullptr, InputBindingInfo::Type::Button, CID_GT_BUTTON, GenericInputBinding::Cross},
|
||||||
|
{"LeftX", TRANSLATE_NOOP("USB", "Left X"), nullptr, InputBindingInfo::Type::Axis, CID_GT_LEFT_X, GenericInputBinding::Unknown},
|
||||||
|
{"LeftY", TRANSLATE_NOOP("USB", "Left Y"), nullptr, InputBindingInfo::Type::Axis, CID_GT_LEFT_Y, GenericInputBinding::Unknown},
|
||||||
|
{"LeftZ", TRANSLATE_NOOP("USB", "Left Z"), nullptr, InputBindingInfo::Type::Axis, CID_GT_LEFT_Z, GenericInputBinding::Unknown},
|
||||||
|
{"RightX", TRANSLATE_NOOP("USB", "Right X"), nullptr, InputBindingInfo::Type::Axis, CID_GT_RIGHT_X, GenericInputBinding::Unknown},
|
||||||
|
{"RightY", TRANSLATE_NOOP("USB", "Right Y"), nullptr, InputBindingInfo::Type::Axis, CID_GT_RIGHT_Y, GenericInputBinding::Unknown},
|
||||||
|
{"RightZ", TRANSLATE_NOOP("USB", "Right Z"), nullptr, InputBindingInfo::Type::Axis, CID_GT_RIGHT_Z, GenericInputBinding::Unknown},
|
||||||
|
};
|
||||||
|
|
||||||
|
return bindings;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::span<const SettingInfo> GametrakDevice::Settings(u32 subtype) const
|
||||||
|
{
|
||||||
|
static constexpr const SettingInfo info[] = {
|
||||||
|
{SettingInfo::Type::Boolean, "invert_x_axis", TRANSLATE_NOOP("USB", "Invert X axis"), TRANSLATE_NOOP("USB", "Invert X axis"), "false"},
|
||||||
|
{SettingInfo::Type::Boolean, "invert_y_axis", TRANSLATE_NOOP("USB", "Invert Y axis"), TRANSLATE_NOOP("USB", "Invert Y axis"), "false"},
|
||||||
|
{SettingInfo::Type::Boolean, "invert_z_axis", TRANSLATE_NOOP("USB", "Invert Z axis"), TRANSLATE_NOOP("USB", "Invert Z axis"), "false"},
|
||||||
|
{SettingInfo::Type::Integer, "limit_z_axis", TRANSLATE_NOOP("USB", "Limit Z axis [100-4095]"),
|
||||||
|
TRANSLATE_NOOP("USB", "- 4095 for original Gametrak controllers\n- 1790 for standard gamepads"),
|
||||||
|
"4095", "100", "4095", "1", TRANSLATE_NOOP("USB", "%d"), nullptr, nullptr, 1.0f},
|
||||||
|
};
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
} // namespace usb_pad
|
|
@ -0,0 +1,86 @@
|
||||||
|
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0+
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "SaveState.h"
|
||||||
|
#include "USB/qemu-usb/desc.h"
|
||||||
|
#include <list>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace usb_pad
|
||||||
|
{
|
||||||
|
enum GametrakControlID
|
||||||
|
{
|
||||||
|
CID_GT_BUTTON,
|
||||||
|
CID_GT_LEFT_X,
|
||||||
|
CID_GT_LEFT_Y,
|
||||||
|
CID_GT_LEFT_Z,
|
||||||
|
CID_GT_RIGHT_X,
|
||||||
|
CID_GT_RIGHT_Y,
|
||||||
|
CID_GT_RIGHT_Z,
|
||||||
|
CID_GT_COUNT,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GametrakState
|
||||||
|
{
|
||||||
|
GametrakState(u32 port_);
|
||||||
|
~GametrakState();
|
||||||
|
|
||||||
|
USBDevice dev{};
|
||||||
|
USBDesc desc{};
|
||||||
|
USBDescDevice desc_dev{};
|
||||||
|
|
||||||
|
u32 port = 0;
|
||||||
|
u8 state = 0;
|
||||||
|
u32 key = 0;
|
||||||
|
|
||||||
|
// Settings
|
||||||
|
bool invert_x_axis = false;
|
||||||
|
bool invert_y_axis = false;
|
||||||
|
bool invert_z_axis = false;
|
||||||
|
u16 limit_z_axis = 0xfff;
|
||||||
|
|
||||||
|
std::chrono::steady_clock::time_point last_log;
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
u16 k1 : 1;
|
||||||
|
u16 left_x : 15;
|
||||||
|
u16 k2 : 1;
|
||||||
|
u16 left_y : 15;
|
||||||
|
u16 k3 : 1;
|
||||||
|
u16 left_z : 15;
|
||||||
|
u16 k4 : 1;
|
||||||
|
u16 right_x : 15;
|
||||||
|
u16 k5 : 1;
|
||||||
|
u16 right_y : 15;
|
||||||
|
u16 k6 : 1;
|
||||||
|
u16 right_z : 15;
|
||||||
|
|
||||||
|
u8 : 4;
|
||||||
|
u8 button : 1;
|
||||||
|
u8 : 3;
|
||||||
|
|
||||||
|
u8 : 8;
|
||||||
|
u8 : 8;
|
||||||
|
u8 : 8;
|
||||||
|
} data = {};
|
||||||
|
#pragma pack(pop)
|
||||||
|
};
|
||||||
|
|
||||||
|
class GametrakDevice final : public DeviceProxy
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const char* Name() const override;
|
||||||
|
const char* TypeName() const override;
|
||||||
|
float GetBindingValue(const USBDevice* dev, u32 bind_index) const override;
|
||||||
|
void SetBindingValue(USBDevice* dev, u32 bind_index, float value) const override;
|
||||||
|
bool Freeze(USBDevice* dev, StateWrapper& sw) const override;
|
||||||
|
void UpdateSettings(USBDevice* dev, SettingsInterface& si) const override;
|
||||||
|
std::span<const InputBindingInfo> Bindings(u32 subtype) const override;
|
||||||
|
std::span<const SettingInfo> Settings(u32 subtype) const override;
|
||||||
|
USBDevice* CreateDevice(SettingsInterface& si, u32 port, u32 subtype) const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace usb_pad
|
|
@ -0,0 +1,466 @@
|
||||||
|
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0+
|
||||||
|
|
||||||
|
#include "Host.h"
|
||||||
|
#include "Input/InputManager.h"
|
||||||
|
#include "StateWrapper.h"
|
||||||
|
#include "USB/USB.h"
|
||||||
|
#include "USB/deviceproxy.h"
|
||||||
|
#include "USB/qemu-usb/USBinternal.h"
|
||||||
|
#include "USB/qemu-usb/desc.h"
|
||||||
|
#include "USB/usb-pad/usb-realplay.h"
|
||||||
|
#include "USB/usb-pad/usb-pad.h"
|
||||||
|
#include <common/Console.h>
|
||||||
|
|
||||||
|
namespace usb_pad
|
||||||
|
{
|
||||||
|
static const USBDescStrings desc_strings = {
|
||||||
|
"",
|
||||||
|
"In2Games",
|
||||||
|
"Real Play"};
|
||||||
|
|
||||||
|
static const uint8_t realplay_racing_dev_descriptor[] = {
|
||||||
|
0x12, // bLength
|
||||||
|
0x01, // bDescriptorType (Device)
|
||||||
|
0x00, 0x02, // bcdUSB 2.00
|
||||||
|
0x00, // bDeviceClass (Use class information in the Interface Descriptors)
|
||||||
|
0x00, // bDeviceSubClass
|
||||||
|
0x00, // bDeviceProtocol
|
||||||
|
0x40, // bMaxPacketSize0 64
|
||||||
|
0xB7, 0x14, // idVendor 0x14B7
|
||||||
|
0xB2, 0x09, // idProduct 0x09B2
|
||||||
|
0x00, 0x01, // bcdDevice 2.00
|
||||||
|
0x01, // iManufacturer (String Index)
|
||||||
|
0x02, // iProduct (String Index)
|
||||||
|
0x00, // iSerialNumber (String Index)
|
||||||
|
0x01, // bNumConfigurations 1
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t realplay_sphere_dev_descriptor[] = {
|
||||||
|
0x12, // bLength
|
||||||
|
0x01, // bDescriptorType (Device)
|
||||||
|
0x00, 0x02, // bcdUSB 2.00
|
||||||
|
0x00, // bDeviceClass (Use class information in the Interface Descriptors)
|
||||||
|
0x00, // bDeviceSubClass
|
||||||
|
0x00, // bDeviceProtocol
|
||||||
|
0x40, // bMaxPacketSize0 64
|
||||||
|
0xB7, 0x14, // idVendor 0x14B7
|
||||||
|
0xB3, 0x09, // idProduct 0x09B3
|
||||||
|
0x00, 0x01, // bcdDevice 2.00
|
||||||
|
0x01, // iManufacturer (String Index)
|
||||||
|
0x02, // iProduct (String Index)
|
||||||
|
0x00, // iSerialNumber (String Index)
|
||||||
|
0x01, // bNumConfigurations 1
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t realplay_golf_dev_descriptor[] = {
|
||||||
|
0x12, // bLength
|
||||||
|
0x01, // bDescriptorType (Device)
|
||||||
|
0x00, 0x02, // bcdUSB 2.00
|
||||||
|
0x00, // bDeviceClass (Use class information in the Interface Descriptors)
|
||||||
|
0x00, // bDeviceSubClass
|
||||||
|
0x00, // bDeviceProtocol
|
||||||
|
0x40, // bMaxPacketSize0 64
|
||||||
|
0xB7, 0x14, // idVendor 0x14B7
|
||||||
|
0xB5, 0x09, // idProduct 0x09B5
|
||||||
|
0x00, 0x01, // bcdDevice 2.00
|
||||||
|
0x01, // iManufacturer (String Index)
|
||||||
|
0x02, // iProduct (String Index)
|
||||||
|
0x00, // iSerialNumber (String Index)
|
||||||
|
0x01, // bNumConfigurations 1
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t realplay_pool_dev_descriptor[] = {
|
||||||
|
0x12, // bLength
|
||||||
|
0x01, // bDescriptorType (Device)
|
||||||
|
0x00, 0x02, // bcdUSB 2.00
|
||||||
|
0x00, // bDeviceClass (Use class information in the Interface Descriptors)
|
||||||
|
0x00, // bDeviceSubClass
|
||||||
|
0x00, // bDeviceProtocol
|
||||||
|
0x40, // bMaxPacketSize0 64
|
||||||
|
0xB7, 0x14, // idVendor 0x14B7
|
||||||
|
0xB6, 0x09, // idProduct 0x09B6
|
||||||
|
0x00, 0x01, // bcdDevice 2.00
|
||||||
|
0x01, // iManufacturer (String Index)
|
||||||
|
0x02, // iProduct (String Index)
|
||||||
|
0x00, // iSerialNumber (String Index)
|
||||||
|
0x01, // bNumConfigurations 1
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t config_descriptor[] = {
|
||||||
|
0x09, // bLength
|
||||||
|
0x02, // bDescriptorType (Configuration)
|
||||||
|
0x29, 0x00, // wTotalLength 41
|
||||||
|
0x01, // bNumInterfaces 1
|
||||||
|
0x01, // bConfigurationValue
|
||||||
|
0x00, // iConfiguration (String Index)
|
||||||
|
0x80, // bmAttributes
|
||||||
|
0x32, // bMaxPower 100mA
|
||||||
|
|
||||||
|
0x09, // bLength
|
||||||
|
0x04, // bDescriptorType (Interface)
|
||||||
|
0x00, // bInterfaceNumber 0
|
||||||
|
0x00, // bAlternateSetting
|
||||||
|
0x02, // bNumEndpoints 2
|
||||||
|
0x03, // bInterfaceClass
|
||||||
|
0x00, // bInterfaceSubClass
|
||||||
|
0x00, // bInterfaceProtocol
|
||||||
|
0x00, // iInterface (String Index)
|
||||||
|
|
||||||
|
0x09, // bLength
|
||||||
|
0x21, // bDescriptorType (HID)
|
||||||
|
0x11, 0x01, // bcdHID 1.11
|
||||||
|
0x00, // bCountryCode
|
||||||
|
0x01, // bNumDescriptors
|
||||||
|
0x22, // bDescriptorType[0] (HID)
|
||||||
|
0x85, 0x00, // wDescriptorLength[0] 133
|
||||||
|
|
||||||
|
0x07, // bLength
|
||||||
|
0x05, // bDescriptorType (Endpoint)
|
||||||
|
0x02, // bEndpointAddress (OUT/H2D)
|
||||||
|
0x03, // bmAttributes (Interrupt)
|
||||||
|
0x40, 0x00, // wMaxPacketSize 64
|
||||||
|
0x0A, // bInterval 10 (unit depends on device speed)
|
||||||
|
|
||||||
|
0x07, // bLength
|
||||||
|
0x05, // bDescriptorType (Endpoint)
|
||||||
|
0x81, // bEndpointAddress (IN/D2H)
|
||||||
|
0x03, // bmAttributes (Interrupt)
|
||||||
|
0x40, 0x00, // wMaxPacketSize 64
|
||||||
|
0x0A, // bInterval 10 (unit depends on device speed)
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t hid_report_descriptor[] = {
|
||||||
|
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
|
||||||
|
0x09, 0x05, // Usage (Game Pad)
|
||||||
|
0xA1, 0x01, // Collection (Application)
|
||||||
|
0x15, 0x00, // Logical Minimum (0)
|
||||||
|
0x26, 0xFF, 0x0F, // Logical Maximum (4095)
|
||||||
|
0x35, 0x00, // Physical Minimum (0)
|
||||||
|
0x46, 0xFF, 0x0F, // Physical Maximum (4095)
|
||||||
|
0x09, 0x30, // Usage (X)
|
||||||
|
0x75, 0x0C, // Report Size (12)
|
||||||
|
0x95, 0x01, // Report Count (1)
|
||||||
|
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||||
|
0x75, 0x01, // Report Size (1)
|
||||||
|
0x95, 0x04, // Report Count (4)
|
||||||
|
0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||||
|
0x09, 0x31, // Usage (Y)
|
||||||
|
0x75, 0x0C, // Report Size (12)
|
||||||
|
0x95, 0x01, // Report Count (1)
|
||||||
|
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||||
|
0x75, 0x01, // Report Size (1)
|
||||||
|
0x95, 0x04, // Report Count (4)
|
||||||
|
0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||||
|
0x09, 0x32, // Usage (Z)
|
||||||
|
0x75, 0x0C, // Report Size (12)
|
||||||
|
0x95, 0x01, // Report Count (1)
|
||||||
|
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||||
|
0x75, 0x01, // Report Size (1)
|
||||||
|
0x95, 0x04, // Report Count (4)
|
||||||
|
0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||||
|
0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00)
|
||||||
|
0x09, 0x20, // Usage (0x20)
|
||||||
|
0x09, 0x21, // Usage (0x21)
|
||||||
|
0x09, 0x22, // Usage (0x22)
|
||||||
|
0x09, 0x23, // Usage (0x23)
|
||||||
|
0x09, 0x24, // Usage (0x24)
|
||||||
|
0x09, 0x25, // Usage (0x25)
|
||||||
|
0x09, 0x26, // Usage (0x26)
|
||||||
|
0x09, 0x27, // Usage (0x27)
|
||||||
|
0x26, 0xFF, 0x00, // Logical Maximum (255)
|
||||||
|
0x46, 0xFF, 0x00, // Physical Maximum (255)
|
||||||
|
0x75, 0x08, // Report Size (8)
|
||||||
|
0x95, 0x08, // Report Count (8)
|
||||||
|
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||||
|
0x15, 0x00, // Logical Minimum (0)
|
||||||
|
0x25, 0x01, // Logical Maximum (1)
|
||||||
|
0x35, 0x00, // Physical Minimum (0)
|
||||||
|
0x45, 0x01, // Physical Maximum (1)
|
||||||
|
0x75, 0x01, // Report Size (1)
|
||||||
|
0x95, 0x08, // Report Count (8)
|
||||||
|
0x05, 0x09, // Usage Page (Button)
|
||||||
|
0x19, 0x01, // Usage Minimum (0x01)
|
||||||
|
0x29, 0x08, // Usage Maximum (0x08)
|
||||||
|
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||||
|
0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00)
|
||||||
|
0x09, 0x28, // Usage (0x28)
|
||||||
|
0x09, 0x29, // Usage (0x29)
|
||||||
|
0x09, 0x2A, // Usage (0x2A)
|
||||||
|
0x09, 0x2B, // Usage (0x2B)
|
||||||
|
0x26, 0xFF, 0x00, // Logical Maximum (255)
|
||||||
|
0x46, 0xFF, 0x00, // Physical Maximum (255)
|
||||||
|
0x75, 0x08, // Report Size (8)
|
||||||
|
0x95, 0x04, // Report Count (4)
|
||||||
|
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||||
|
0xC0, // End Collection
|
||||||
|
};
|
||||||
|
|
||||||
|
RealPlayState::RealPlayState(u32 port_, u32 type_)
|
||||||
|
: port(port_)
|
||||||
|
, type(type_)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
RealPlayState::~RealPlayState() = default;
|
||||||
|
|
||||||
|
static void realplay_handle_control(USBDevice* dev, USBPacket* p,
|
||||||
|
int request, int value, int index, int length, uint8_t* data)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
switch (request)
|
||||||
|
{
|
||||||
|
case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
|
||||||
|
switch (value >> 8)
|
||||||
|
{
|
||||||
|
case USB_DT_REPORT:
|
||||||
|
ret = sizeof(hid_report_descriptor);
|
||||||
|
memcpy(data, hid_report_descriptor, ret);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SET_REPORT:
|
||||||
|
break;
|
||||||
|
case SET_IDLE:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
|
||||||
|
if (ret >= 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
p->status = USB_RET_STALL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void realplay_handle_data(USBDevice* dev, USBPacket* p)
|
||||||
|
{
|
||||||
|
RealPlayState* s = USB_CONTAINER_OF(dev, RealPlayState, dev);
|
||||||
|
|
||||||
|
switch (p->pid)
|
||||||
|
{
|
||||||
|
case USB_TOKEN_IN:
|
||||||
|
if (p->ep->nr == 1)
|
||||||
|
{
|
||||||
|
pxAssert(p->buffer_size >= sizeof(s->data));
|
||||||
|
|
||||||
|
std::memcpy(p->buffer_ptr, &s->data, sizeof(s->data));
|
||||||
|
|
||||||
|
// simulate a slight move to avoid a game "protection" : controller disconnected
|
||||||
|
p->buffer_ptr[0] ^= s->state;
|
||||||
|
s->state ^= 1;
|
||||||
|
|
||||||
|
p->actual_length += sizeof(s->data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case USB_TOKEN_OUT:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fail:
|
||||||
|
p->status = USB_RET_STALL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void realplay_unrealize(USBDevice* dev)
|
||||||
|
{
|
||||||
|
RealPlayState* s = USB_CONTAINER_OF(dev, RealPlayState, dev);
|
||||||
|
delete s;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* RealPlayDevice::Name() const
|
||||||
|
{
|
||||||
|
return TRANSLATE_NOOP("USB", "RealPlay Device");
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* RealPlayDevice::TypeName() const
|
||||||
|
{
|
||||||
|
return "RealPlay";
|
||||||
|
}
|
||||||
|
|
||||||
|
USBDevice* RealPlayDevice::CreateDevice(SettingsInterface& si, u32 port, u32 type) const
|
||||||
|
{
|
||||||
|
RealPlayState* s = new RealPlayState(port, type);
|
||||||
|
|
||||||
|
s->desc.full = &s->desc_dev;
|
||||||
|
s->desc.str = desc_strings;
|
||||||
|
|
||||||
|
const uint8_t* dev_desc = nullptr;
|
||||||
|
int dev_desc_len = 0;
|
||||||
|
|
||||||
|
switch (s->type)
|
||||||
|
{
|
||||||
|
case REALPLAY_RACING:
|
||||||
|
dev_desc = realplay_racing_dev_descriptor;
|
||||||
|
dev_desc_len = sizeof(realplay_racing_dev_descriptor);
|
||||||
|
break;
|
||||||
|
case REALPLAY_SPHERE:
|
||||||
|
dev_desc = realplay_sphere_dev_descriptor;
|
||||||
|
dev_desc_len = sizeof(realplay_sphere_dev_descriptor);
|
||||||
|
break;
|
||||||
|
case REALPLAY_GOLF:
|
||||||
|
dev_desc = realplay_golf_dev_descriptor;
|
||||||
|
dev_desc_len = sizeof(realplay_golf_dev_descriptor);
|
||||||
|
break;
|
||||||
|
case REALPLAY_POOL:
|
||||||
|
dev_desc = realplay_pool_dev_descriptor;
|
||||||
|
dev_desc_len = sizeof(realplay_pool_dev_descriptor);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
pxAssertMsg(false, "Unhandled type");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (usb_desc_parse_dev(dev_desc, dev_desc_len, s->desc, s->desc_dev) < 0)
|
||||||
|
goto fail;
|
||||||
|
if (usb_desc_parse_config(config_descriptor, sizeof(config_descriptor), s->desc_dev) < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
s->dev.speed = USB_SPEED_FULL;
|
||||||
|
s->dev.klass.handle_attach = usb_desc_attach;
|
||||||
|
s->dev.klass.handle_reset = nullptr;
|
||||||
|
s->dev.klass.handle_control = realplay_handle_control;
|
||||||
|
s->dev.klass.handle_data = realplay_handle_data;
|
||||||
|
s->dev.klass.unrealize = realplay_unrealize;
|
||||||
|
s->dev.klass.usb_desc = &s->desc;
|
||||||
|
s->dev.klass.product_desc = nullptr;
|
||||||
|
|
||||||
|
usb_desc_init(&s->dev);
|
||||||
|
usb_ep_init(&s->dev);
|
||||||
|
|
||||||
|
return &s->dev;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
realplay_unrealize(&s->dev);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RealPlayDevice::Freeze(USBDevice* dev, StateWrapper& sw) const
|
||||||
|
{
|
||||||
|
RealPlayState* s = USB_CONTAINER_OF(dev, RealPlayState, dev);
|
||||||
|
|
||||||
|
if (!sw.DoMarker("RealPlayDevice"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
sw.Do(&s->type);
|
||||||
|
sw.Do(&s->state);
|
||||||
|
return !sw.HasError();
|
||||||
|
}
|
||||||
|
|
||||||
|
float RealPlayDevice::GetBindingValue(const USBDevice* dev, u32 bind_index) const
|
||||||
|
{
|
||||||
|
RealPlayState* s = USB_CONTAINER_OF(dev, RealPlayState, dev);
|
||||||
|
switch (bind_index)
|
||||||
|
{
|
||||||
|
case CID_RP_DPAD_UP: return s->data.dpad_up;
|
||||||
|
case CID_RP_DPAD_DOWN: return s->data.dpad_down;
|
||||||
|
case CID_RP_DPAD_LEFT: return s->data.dpad_left;
|
||||||
|
case CID_RP_DPAD_RIGHT: return s->data.dpad_right;
|
||||||
|
case CID_RP_RED: return s->data.btn_red;
|
||||||
|
case CID_RP_GREEN: return s->data.btn_green;
|
||||||
|
case CID_RP_YELLOW: return s->data.btn_yellow;
|
||||||
|
case CID_RP_BLUE: return s->data.btn_blue;
|
||||||
|
default: return 0.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RealPlayDevice::SetBindingValue(USBDevice* dev, u32 bind_index, float value) const
|
||||||
|
{
|
||||||
|
RealPlayState* s = USB_CONTAINER_OF(dev, RealPlayState, dev);
|
||||||
|
switch (bind_index)
|
||||||
|
{
|
||||||
|
case CID_RP_DPAD_UP:
|
||||||
|
s->data.dpad_up = (value >= 0.5f);
|
||||||
|
break;
|
||||||
|
case CID_RP_DPAD_DOWN:
|
||||||
|
s->data.dpad_down = (value >= 0.5f);
|
||||||
|
break;
|
||||||
|
case CID_RP_DPAD_LEFT:
|
||||||
|
s->data.dpad_left = (value >= 0.5f);
|
||||||
|
break;
|
||||||
|
case CID_RP_DPAD_RIGHT:
|
||||||
|
s->data.dpad_right = (value >= 0.5f);
|
||||||
|
break;
|
||||||
|
case CID_RP_RED:
|
||||||
|
s->data.btn_red = (value >= 0.5f);
|
||||||
|
break;
|
||||||
|
case CID_RP_GREEN:
|
||||||
|
s->data.btn_green = (value >= 0.5f);
|
||||||
|
break;
|
||||||
|
case CID_RP_YELLOW:
|
||||||
|
s->data.btn_yellow = (value >= 0.5f);
|
||||||
|
break;
|
||||||
|
case CID_RP_BLUE:
|
||||||
|
s->data.btn_blue = (value >= 0.5f);
|
||||||
|
break;
|
||||||
|
case CID_RP_ACC_X:
|
||||||
|
s->data.acc_x = static_cast<u16>(std::clamp<long>(std::lroundf(value * 4095.f), 0, 4095));
|
||||||
|
s->data.acc_x = s->invert_x_axis ? 4095 - s->data.acc_x : s->data.acc_x;
|
||||||
|
break;
|
||||||
|
case CID_RP_ACC_Y:
|
||||||
|
s->data.acc_y = static_cast<u16>(std::clamp<long>(std::lroundf(value * 4095.f), 0, 4095));
|
||||||
|
s->data.acc_y = s->invert_x_axis ? 4095 - s->data.acc_y : s->data.acc_y;
|
||||||
|
break;
|
||||||
|
case CID_RP_ACC_Z:
|
||||||
|
s->data.acc_z = static_cast<u16>(std::clamp<long>(std::lroundf(value * 4095.f), 0, 4095));
|
||||||
|
s->data.acc_z = s->invert_x_axis ? 4095 - s->data.acc_z : s->data.acc_z;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::span<const char*> RealPlayDevice::SubTypes() const
|
||||||
|
{
|
||||||
|
static const char* subtypes[] = {
|
||||||
|
TRANSLATE_NOOP("USB", "RealPlay Racing"),
|
||||||
|
TRANSLATE_NOOP("USB", "RealPlay Sphere"),
|
||||||
|
TRANSLATE_NOOP("USB", "RealPlay Golf"),
|
||||||
|
TRANSLATE_NOOP("USB", "RealPlay Pool"),
|
||||||
|
};
|
||||||
|
return subtypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RealPlayDevice::UpdateSettings(USBDevice* dev, SettingsInterface& si) const
|
||||||
|
{
|
||||||
|
RealPlayState* s = USB_CONTAINER_OF(dev, RealPlayState, dev);
|
||||||
|
s->invert_x_axis = USB::GetConfigBool(si, s->port, TypeName(), "invert_x_axis", false);
|
||||||
|
s->invert_y_axis = USB::GetConfigBool(si, s->port, TypeName(), "invert_y_axis", false);
|
||||||
|
s->invert_z_axis = USB::GetConfigBool(si, s->port, TypeName(), "invert_z_axis", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::span<const InputBindingInfo> RealPlayDevice::Bindings(u32 subtype) const
|
||||||
|
{
|
||||||
|
static constexpr const InputBindingInfo bindings[] = {
|
||||||
|
{"DPadUp", TRANSLATE_NOOP("USB", "D-Pad Up"), nullptr, InputBindingInfo::Type::Button, CID_RP_DPAD_UP, GenericInputBinding::DPadUp},
|
||||||
|
{"DPadDown", TRANSLATE_NOOP("USB", "D-Pad Down"), nullptr, InputBindingInfo::Type::Button, CID_RP_DPAD_DOWN, GenericInputBinding::DPadDown},
|
||||||
|
{"DPadLeft", TRANSLATE_NOOP("USB", "D-Pad Left"), nullptr, InputBindingInfo::Type::Button, CID_RP_DPAD_LEFT, GenericInputBinding::DPadLeft},
|
||||||
|
{"DPadRight", TRANSLATE_NOOP("USB", "D-Pad Right"), nullptr, InputBindingInfo::Type::Button, CID_RP_DPAD_RIGHT, GenericInputBinding::DPadRight},
|
||||||
|
{"Red", TRANSLATE_NOOP("USB", "Red"), nullptr, InputBindingInfo::Type::Button, CID_RP_RED, GenericInputBinding::Triangle},
|
||||||
|
{"Green", TRANSLATE_NOOP("USB", "Green"), nullptr, InputBindingInfo::Type::Button, CID_RP_GREEN, GenericInputBinding::Cross},
|
||||||
|
{"Yellow", TRANSLATE_NOOP("USB", "Yellow"), nullptr, InputBindingInfo::Type::Button, CID_RP_YELLOW, GenericInputBinding::Square},
|
||||||
|
{"Blue", TRANSLATE_NOOP("USB", "Blue"), nullptr, InputBindingInfo::Type::Button, CID_RP_BLUE, GenericInputBinding::Circle},
|
||||||
|
{"AccelX", TRANSLATE_NOOP("USB", "Accel X"), nullptr, InputBindingInfo::Type::Axis, CID_RP_ACC_X, GenericInputBinding::Unknown},
|
||||||
|
{"AccelY", TRANSLATE_NOOP("USB", "Accel Y"), nullptr, InputBindingInfo::Type::Axis, CID_RP_ACC_Y, GenericInputBinding::Unknown},
|
||||||
|
{"AccelZ", TRANSLATE_NOOP("USB", "Accel Z"), nullptr, InputBindingInfo::Type::Axis, CID_RP_ACC_Z, GenericInputBinding::Unknown},
|
||||||
|
};
|
||||||
|
|
||||||
|
return bindings;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::span<const SettingInfo> RealPlayDevice::Settings(u32 subtype) const
|
||||||
|
{
|
||||||
|
static constexpr const SettingInfo info[] = {
|
||||||
|
{SettingInfo::Type::Boolean, "invert_x_axis", TRANSLATE_NOOP("USB", "Invert X axis"), TRANSLATE_NOOP("USB", "Invert X axis"), "false"},
|
||||||
|
{SettingInfo::Type::Boolean, "invert_y_axis", TRANSLATE_NOOP("USB", "Invert Y axis"), TRANSLATE_NOOP("USB", "Invert Y axis"), "false"},
|
||||||
|
{SettingInfo::Type::Boolean, "invert_z_axis", TRANSLATE_NOOP("USB", "Invert Z axis"), TRANSLATE_NOOP("USB", "Invert Z axis"), "false"},
|
||||||
|
};
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
} // namespace usb_pad
|
|
@ -0,0 +1,92 @@
|
||||||
|
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0+
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "SaveState.h"
|
||||||
|
#include "USB/qemu-usb/desc.h"
|
||||||
|
#include <list>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace usb_pad
|
||||||
|
{
|
||||||
|
enum RealPlayControlID
|
||||||
|
{
|
||||||
|
CID_RP_DPAD_UP,
|
||||||
|
CID_RP_DPAD_DOWN,
|
||||||
|
CID_RP_DPAD_LEFT,
|
||||||
|
CID_RP_DPAD_RIGHT,
|
||||||
|
CID_RP_RED,
|
||||||
|
CID_RP_GREEN,
|
||||||
|
CID_RP_YELLOW,
|
||||||
|
CID_RP_BLUE,
|
||||||
|
CID_RP_ACC_X,
|
||||||
|
CID_RP_ACC_Y,
|
||||||
|
CID_RP_ACC_Z,
|
||||||
|
CID_RP_COUNT,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum RealPlayType
|
||||||
|
{
|
||||||
|
REALPLAY_RACING,
|
||||||
|
REALPLAY_SPHERE,
|
||||||
|
REALPLAY_GOLF,
|
||||||
|
REALPLAY_POOL,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RealPlayState
|
||||||
|
{
|
||||||
|
RealPlayState(u32 port_, u32 type_);
|
||||||
|
~RealPlayState();
|
||||||
|
|
||||||
|
USBDevice dev{};
|
||||||
|
USBDesc desc{};
|
||||||
|
USBDescDevice desc_dev{};
|
||||||
|
|
||||||
|
u32 port = 0;
|
||||||
|
u32 type = 0;
|
||||||
|
u8 state = 0;
|
||||||
|
|
||||||
|
// Settings
|
||||||
|
bool invert_x_axis = false;
|
||||||
|
bool invert_y_axis = false;
|
||||||
|
bool invert_z_axis = false;
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
u16 acc_x;
|
||||||
|
u16 acc_y;
|
||||||
|
u16 acc_z;
|
||||||
|
|
||||||
|
u32 : 32;
|
||||||
|
u32 : 32;
|
||||||
|
|
||||||
|
u8 dpad_up : 1;
|
||||||
|
u8 dpad_down : 1;
|
||||||
|
u8 dpad_left : 1;
|
||||||
|
u8 dpad_right : 1;
|
||||||
|
u8 btn_red : 1;
|
||||||
|
u8 btn_green: 1;
|
||||||
|
u8 btn_yellow : 1;
|
||||||
|
u8 btn_blue : 1;
|
||||||
|
|
||||||
|
u32 : 32;
|
||||||
|
} data = {};
|
||||||
|
#pragma pack(pop)
|
||||||
|
};
|
||||||
|
|
||||||
|
class RealPlayDevice final : public DeviceProxy
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const char* Name() const override;
|
||||||
|
const char* TypeName() const override;
|
||||||
|
float GetBindingValue(const USBDevice* dev, u32 bind_index) const override;
|
||||||
|
void SetBindingValue(USBDevice* dev, u32 bind_index, float value) const override;
|
||||||
|
bool Freeze(USBDevice* dev, StateWrapper& sw) const override;
|
||||||
|
void UpdateSettings(USBDevice* dev, SettingsInterface& si) const override;
|
||||||
|
std::span<const char*> SubTypes() const override;
|
||||||
|
std::span<const InputBindingInfo> Bindings(u32 subtype) const override;
|
||||||
|
std::span<const SettingInfo> Settings(u32 subtype) const override;
|
||||||
|
USBDevice* CreateDevice(SettingsInterface& si, u32 port, u32 subtype) const override;
|
||||||
|
};
|
||||||
|
} // namespace usb_pad
|
|
@ -392,6 +392,8 @@
|
||||||
<ClCompile Include="USB\usb-mic\usb-mic-singstar.cpp" />
|
<ClCompile Include="USB\usb-mic\usb-mic-singstar.cpp" />
|
||||||
<ClCompile Include="USB\usb-msd\usb-msd.cpp" />
|
<ClCompile Include="USB\usb-msd\usb-msd.cpp" />
|
||||||
<ClCompile Include="USB\usb-pad\lg\lg_ff.cpp" />
|
<ClCompile Include="USB\usb-pad\lg\lg_ff.cpp" />
|
||||||
|
<ClCompile Include="USB\usb-pad\usb-gametrak.cpp" />
|
||||||
|
<ClCompile Include="USB\usb-pad\usb-realplay.cpp" />
|
||||||
<ClCompile Include="USB\usb-pad\usb-pad-ff.cpp" />
|
<ClCompile Include="USB\usb-pad\usb-pad-ff.cpp" />
|
||||||
<ClCompile Include="USB\usb-pad\usb-pad-sdl-ff.cpp" />
|
<ClCompile Include="USB\usb-pad\usb-pad-sdl-ff.cpp" />
|
||||||
<ClCompile Include="USB\usb-pad\usb-pad.cpp" />
|
<ClCompile Include="USB\usb-pad\usb-pad.cpp" />
|
||||||
|
@ -839,6 +841,8 @@
|
||||||
<ClInclude Include="USB\usb-mic\usb-mic-singstar.h" />
|
<ClInclude Include="USB\usb-mic\usb-mic-singstar.h" />
|
||||||
<ClInclude Include="USB\usb-msd\usb-msd.h" />
|
<ClInclude Include="USB\usb-msd\usb-msd.h" />
|
||||||
<ClInclude Include="USB\usb-pad\lg\lg_ff.h" />
|
<ClInclude Include="USB\usb-pad\lg\lg_ff.h" />
|
||||||
|
<ClInclude Include="USB\usb-pad\usb-gametrak.h" />
|
||||||
|
<ClInclude Include="USB\usb-pad\usb-realplay.h" />
|
||||||
<ClInclude Include="USB\usb-pad\usb-pad-sdl-ff.h" />
|
<ClInclude Include="USB\usb-pad\usb-pad-sdl-ff.h" />
|
||||||
<ClInclude Include="USB\usb-pad\usb-pad.h" />
|
<ClInclude Include="USB\usb-pad\usb-pad.h" />
|
||||||
<ClInclude Include="USB\usb-pad\usb-turntable.h" />
|
<ClInclude Include="USB\usb-pad\usb-turntable.h" />
|
||||||
|
|
|
@ -1187,6 +1187,12 @@
|
||||||
<ClCompile Include="USB\usb-hid\usb-hid.cpp">
|
<ClCompile Include="USB\usb-hid\usb-hid.cpp">
|
||||||
<Filter>System\Ps2\USB\usb-hid</Filter>
|
<Filter>System\Ps2\USB\usb-hid</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="USB\usb-pad\usb-gametrak.cpp">
|
||||||
|
<Filter>System\Ps2\USB\usb-pad</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="USB\usb-pad\usb-realplay.cpp">
|
||||||
|
<Filter>System\Ps2\USB\usb-pad</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="USB\usb-pad\usb-pad.cpp">
|
<ClCompile Include="USB\usb-pad\usb-pad.cpp">
|
||||||
<Filter>System\Ps2\USB\usb-pad</Filter>
|
<Filter>System\Ps2\USB\usb-pad</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -2121,6 +2127,12 @@
|
||||||
<ClInclude Include="USB\usb-hid\usb-hid.h">
|
<ClInclude Include="USB\usb-hid\usb-hid.h">
|
||||||
<Filter>System\Ps2\USB\usb-hid</Filter>
|
<Filter>System\Ps2\USB\usb-hid</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="USB\usb-pad\usb-gametrak.h">
|
||||||
|
<Filter>System\Ps2\USB\usb-pad</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="USB\usb-pad\usb-realplay.h">
|
||||||
|
<Filter>System\Ps2\USB\usb-pad</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="USB\usb-pad\usb-pad.h">
|
<ClInclude Include="USB\usb-pad\usb-pad.h">
|
||||||
<Filter>System\Ps2\USB\usb-pad</Filter>
|
<Filter>System\Ps2\USB\usb-pad</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
|
Loading…
Reference in New Issue