USB: ASCII Trance Vib emulation

This commit is contained in:
Florin9doi 2024-07-23 10:15:04 +03:00 committed by Ty
parent f5320e201e
commit edd39dfe08
16 changed files with 429 additions and 0 deletions

View File

@ -28,6 +28,7 @@
#include "ui_USBBindingWidget_GTForce.h"
#include "ui_USBBindingWidget_GunCon2.h"
#include "ui_USBBindingWidget_RealPlay.h"
#include "ui_USBBindingWidget_TranceVibrator.h"
ControllerBindingWidget::ControllerBindingWidget(QWidget* parent, ControllerSettingsWindow* dialog, u32 port)
: QWidget(parent)
@ -965,6 +966,7 @@ QIcon USBDeviceWidget::getIcon() const
{"hidmouse", "mouse-line"}, // HID Mouse
{"RBDrumKit", "drum-line"}, // Rock Band Drum Kit
{"BuzzDevice", "buzz-controller-line"}, // Buzz Controller
{"TranceVibrator", "trance-vibrator-line"}, // Trance Vibrator
{"webcam", "eyetoy-line"}, // EyeToy
{"beatmania", "keyboard-2-line"}, // BeatMania Da Da Da!! (Konami Keyboard)
{"seamic", "seamic-line"}, // SEGA Seamic
@ -1302,6 +1304,13 @@ void USBBindingWidget::bindWidgets(std::span<const InputBindingInfo> bindings)
widget->initialize(sif, bi.bind_type, getConfigSection(), getBindingKey(bi.name));
}
if (bi.bind_type == InputBindingInfo::Type::Motor)
{
InputVibrationBindingWidget* widget = findChild<InputVibrationBindingWidget*>(QString::fromUtf8(bi.name));
if (widget)
widget->setKey(getDialog(), getConfigSection(), getBindingKey(bi.name));
}
}
}
@ -1339,6 +1348,11 @@ USBBindingWidget* USBBindingWidget::createInstance(
Ui::USBBindingWidget_RealPlay().setupUi(widget);
has_template = true;
}
else if (type == "TranceVibrator")
{
Ui::USBBindingWidget_TranceVibrator().setupUi(widget);
has_template = true;
}
if (has_template)
widget->bindWidgets(bindings);

View File

@ -0,0 +1,116 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>USBBindingWidget_TranceVibrator</class>
<widget class="QWidget" name="USBBindingWidget_TranceVibrator">
<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>
<property name="minimumSize">
<size>
<width>1100</width>
<height>500</height>
</size>
</property>
<layout class="QGridLayout" name="gridLayout_1">
<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="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Motor</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<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="InputVibrationBindingWidget" name="Motor">
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string notr="true">PushButton</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item row="0" column="2">
<spacer name="horizontalSpacer1">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</spacer>
</item>
<item row="1" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</spacer>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>InputVibrationBindingWidget</class>
<extends>QPushButton</extends>
<header>Settings/InputBindingWidget.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="../resources/resources.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -431,6 +431,9 @@
<QtUi Include="Settings\USBBindingWidget_RealPlay.ui">
<FileType>Document</FileType>
</QtUi>
<QtUi Include="Settings\USBBindingWidget_TranceVibrator.ui">
<FileType>Document</FileType>
</QtUi>
<QtUi Include="Settings\USBDeviceWidget.ui">
<FileType>Document</FileType>
</QtUi>

View File

@ -672,6 +672,9 @@
<QtUi Include="Settings\USBBindingWidget_RealPlay.ui">
<Filter>Settings</Filter>
</QtUi>
<QtUi Include="Settings\USBBindingWidget_TranceVibrator.ui">
<Filter>Settings</Filter>
</QtUi>
<QtUi Include="Settings\AudioExpansionSettingsDialog.ui">
<Filter>Settings</Filter>
</QtUi>

View File

@ -0,0 +1,19 @@
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 -10 100 110" >
<g>
<path
fill="none"
stroke="black"
stroke-width="8"
stroke-miterlimit="5"
d="m 0 50
l 20,0
l 7.5,20
l 15,-45
l 15,55
l 15,-65
l 7.5,35
l 20,0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 332 B

View File

@ -0,0 +1,19 @@
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 -10 100 110" >
<g>
<path
fill="none"
stroke="white"
stroke-width="8"
stroke-miterlimit="5"
d="m 0 50
l 20,0
l 7.5,20
l 15,-45
l 15,55
l 15,-65
l 7.5,35
l 20,0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 332 B

View File

@ -83,6 +83,7 @@
<file>icons/black/svg/shut-down-line.svg</file>
<file>icons/black/svg/singstar-line.svg</file>
<file>icons/black/svg/tools-line.svg</file>
<file>icons/black/svg/trance-vibrator-line.svg</file>
<file>icons/black/svg/trash-fill.svg</file>
<file>icons/black/svg/trophy-line.svg</file>
<file>icons/black/svg/tv-2-line.svg</file>
@ -180,6 +181,7 @@
<file>icons/white/svg/shut-down-line.svg</file>
<file>icons/white/svg/singstar-line.svg</file>
<file>icons/white/svg/tools-line.svg</file>
<file>icons/white/svg/trance-vibrator-line.svg</file>
<file>icons/white/svg/trash-fill.svg</file>
<file>icons/white/svg/trophy-line.svg</file>
<file>icons/white/svg/tv-2-line.svg</file>

View File

@ -389,6 +389,7 @@ set(pcsx2USBSources
USB/usb-pad/usb-pad-sdl-ff.cpp
USB/usb-pad/usb-pad.cpp
USB/usb-pad/usb-seamic.cpp
USB/usb-pad/usb-trance-vibrator.cpp
USB/usb-pad/usb-turntable.cpp
USB/usb-printer/usb-printer.cpp
)
@ -423,6 +424,7 @@ set(pcsx2USBHeaders
USB/usb-pad/usb-realplay.h
USB/usb-pad/usb-pad-sdl-ff.h
USB/usb-pad/usb-pad.h
USB/usb-pad/usb-trance-vibrator.h
USB/usb-printer/usb-printer.h
)

View File

@ -868,6 +868,19 @@ void InputManager::AddUSBBindings(SettingsInterface& si, u32 port)
}
break;
case InputBindingInfo::Type::Motor:
{
const std::vector<std::string> bindings(si.GetStringList(section.c_str(), bind_name.c_str()));
for (const std::string& binding : bindings)
{
PadVibrationBinding vib;
vib.pad_index = Pad::NUM_CONTROLLER_PORTS + port;
ParseBindingAndGetSource(binding, &vib.motors[0].binding, &vib.motors[0].source);
s_pad_vibration_array.push_back(std::move(vib));
}
}
break;
default:
break;
}
@ -1219,6 +1232,11 @@ void InputManager::OnInputDeviceDisconnected(const InputBindingKey key, const st
// Vibration
// ------------------------------------------------------------------------
void InputManager::SetUSBVibrationIntensity(u32 port, float large_or_single_motor_intensity, float small_motor_intensity)
{
SetPadVibrationIntensity(Pad::NUM_CONTROLLER_PORTS + port, large_or_single_motor_intensity, small_motor_intensity);
}
void InputManager::SetPadVibrationIntensity(u32 pad_index, float large_or_single_motor_intensity, float small_motor_intensity)
{
for (PadVibrationBinding& pad : s_pad_vibration_array)

View File

@ -270,6 +270,7 @@ namespace InputManager
/// Internal method used by pads to dispatch vibration updates to input sources.
/// Intensity is normalized from 0 to 1.
void SetUSBVibrationIntensity(u32 port, float large_or_single_motor_intensity, float small_motor_intensity);
void SetPadVibrationIntensity(u32 pad_index, float large_or_single_motor_intensity, float small_motor_intensity);
/// Zeros all vibration intensities. Call when pausing.

View File

@ -10,6 +10,7 @@
#include "usb-mic/usb-mic-singstar.h"
#include "usb-msd/usb-msd.h"
#include "usb-pad/usb-pad.h"
#include "usb-pad/usb-trance-vibrator.h"
#include "usb-pad/usb-turntable.h"
#include "usb-printer/usb-printer.h"
#include "usb-lightgun/guncon2.h"
@ -76,6 +77,7 @@ void RegisterDevice::Register()
inst.Add(DEVTYPE_BUZZ, new usb_pad::BuzzDevice());
inst.Add(DEVTYPE_EYETOY, new usb_eyetoy::EyeToyWebCamDevice());
inst.Add(DEVTYPE_BEATMANIA_DADADA, new usb_hid::BeatManiaDevice());
inst.Add(DEVTYPE_TRANCE_VIBRATOR, new usb_pad::TranceVibratorDevice());
inst.Add(DEVTYPE_SEGA_SEAMIC, new usb_pad::SeamicDevice());
inst.Add(DEVTYPE_PRINTER, new usb_printer::PrinterDevice());
inst.Add(DEVTYPE_KEYBOARDMANIA, new usb_pad::KeyboardmaniaDevice());

View File

@ -35,6 +35,7 @@ enum DeviceType : s32
DEVTYPE_BUZZ,
DEVTYPE_EYETOY,
DEVTYPE_BEATMANIA_DADADA,
DEVTYPE_TRANCE_VIBRATOR,
DEVTYPE_SEGA_SEAMIC,
DEVTYPE_PRINTER,
DEVTYPE_KEYBOARDMANIA,

View File

@ -0,0 +1,185 @@
// 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-trance-vibrator.h"
#include "USB/usb-pad/usb-pad.h"
#include <common/Console.h>
namespace usb_pad
{
static const USBDescStrings desc_strings = {
"",
"ASCII CORPORATION",
"ASCII Vib"};
static uint8_t dev_descriptor[] = {
0x12, // bLength
0x01, // bDescriptorType (Device)
0x00, 0x01, // bcdUSB 1.00
0x00, // bDeviceClass (Use class information in the Interface Descriptors)
0x00, // bDeviceSubClass
0x00, // bDeviceProtocol
0x08, // bMaxPacketSize0 8
0x49, 0x0B, // idVendor 0x0B49
0x4F, 0x06, // idProduct 0x064F
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)
0x22, 0x00, // wTotalLength 34
0x01, // bNumInterfaces 1
0x01, // bConfigurationValue
0x00, // iConfiguration (String Index)
0x80, // bmAttributes
0x31, // bMaxPower 98mA
0x09, // bLength
0x04, // bDescriptorType (Interface)
0x00, // bInterfaceNumber 0
0x00, // bAlternateSetting
0x01, // bNumEndpoints 1
0x00, // bInterfaceClass
0x00, // bInterfaceSubClass
0x00, // bInterfaceProtocol
0x00, // iInterface (String Index)
0x07, // bLength
0x05, // bDescriptorType (Endpoint)
0x81, // bEndpointAddress (IN/D2H)
0x03, // bmAttributes (Interrupt)
0x08, 0x00, // wMaxPacketSize 8
0x0A, // bInterval 10 (unit depends on device speed)
};
TranceVibratorState::TranceVibratorState(u32 port_)
: port(port_)
{
}
TranceVibratorState::~TranceVibratorState() = default;
static void trancevibrator_handle_control(USBDevice* dev, USBPacket* p,
int request, int value, int index, int length, uint8_t* data)
{
TranceVibratorState* s = USB_CONTAINER_OF(dev, TranceVibratorState, dev);
int ret = 0;
switch (request)
{
case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
break;
case SET_IDLE:
break;
case VendorDeviceOutRequest:
// Vibration = wValue
// LED1 = wIndex&1, LED2 = wIndex&2, LED3 = wIndex&4
InputManager::SetUSBVibrationIntensity(s->port, value & 0xff, 0);
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 trancevibrator_handle_data(USBDevice* dev, USBPacket* p)
{
switch (p->pid)
{
case USB_TOKEN_IN:
break;
case USB_TOKEN_OUT:
break;
default:
p->status = USB_RET_STALL;
break;
}
}
static void trancevibrator_unrealize(USBDevice* dev)
{
TranceVibratorState* s = USB_CONTAINER_OF(dev, TranceVibratorState, dev);
delete s;
}
const char* TranceVibratorDevice::Name() const
{
return TRANSLATE_NOOP("USB", "Trance Vibrator (Rez)");
}
const char* TranceVibratorDevice::TypeName() const
{
return "TranceVibrator";
}
USBDevice* TranceVibratorDevice::CreateDevice(SettingsInterface& si, u32 port, u32 subtype) const
{
TranceVibratorState* s = new TranceVibratorState(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 = trancevibrator_handle_control;
s->dev.klass.handle_data = trancevibrator_handle_data;
s->dev.klass.unrealize = trancevibrator_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:
trancevibrator_unrealize(&s->dev);
return nullptr;
}
float TranceVibratorDevice::GetBindingValue(const USBDevice* dev, u32 bind_index) const
{
return 0.0f;
}
void TranceVibratorDevice::SetBindingValue(USBDevice* dev, u32 bind_index, float value) const
{
}
std::span<const InputBindingInfo> TranceVibratorDevice::Bindings(u32 subtype) const
{
static constexpr const InputBindingInfo bindings[] = {
{"Motor", TRANSLATE_NOOP("Pad", "Motor"), nullptr, InputBindingInfo::Type::Motor, 0, GenericInputBinding::LargeMotor},
};
return bindings;
}
std::span<const SettingInfo> TranceVibratorDevice::Settings(u32 subtype) const
{
return {};
}
} // namespace usb_pad

View File

@ -0,0 +1,36 @@
// 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
{
struct TranceVibratorState
{
TranceVibratorState(u32 port_);
~TranceVibratorState();
USBDevice dev{};
USBDesc desc{};
USBDescDevice desc_dev{};
u32 port = 0;
};
class TranceVibratorDevice 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;
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

View File

@ -398,6 +398,7 @@
<ClCompile Include="USB\usb-pad\usb-pad-sdl-ff.cpp" />
<ClCompile Include="USB\usb-pad\usb-pad.cpp" />
<ClCompile Include="USB\usb-pad\usb-seamic.cpp" />
<ClCompile Include="USB\usb-pad\usb-trance-vibrator.cpp" />
<ClCompile Include="USB\usb-pad\usb-turntable.cpp" />
<ClCompile Include="USB\usb-printer\usb-printer.cpp" />
<ClCompile Include="USB\USB.cpp" />
@ -845,6 +846,7 @@
<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.h" />
<ClInclude Include="USB\usb-pad\usb-trance-vibrator.h" />
<ClInclude Include="USB\usb-pad\usb-turntable.h" />
<ClInclude Include="USB\usb-printer\usb-printer.h" />
<ClInclude Include="USB\USB.h" />

View File

@ -1199,6 +1199,9 @@
<ClCompile Include="USB\usb-pad\usb-seamic.cpp">
<Filter>System\Ps2\USB\usb-pad</Filter>
</ClCompile>
<ClCompile Include="USB\usb-pad\usb-trance-vibrator.cpp">
<Filter>System\Ps2\USB\usb-pad</Filter>
</ClCompile>
<ClCompile Include="USB\usb-pad\usb-turntable.cpp">
<Filter>System\Ps2\USB\usb-pad</Filter>
</ClCompile>
@ -2136,6 +2139,9 @@
<ClInclude Include="USB\usb-pad\usb-pad.h">
<Filter>System\Ps2\USB\usb-pad</Filter>
</ClInclude>
<ClInclude Include="USB\usb-pad\usb-trance-vibrator.h">
<Filter>System\Ps2\USB\usb-pad</Filter>
</ClInclude>
<ClInclude Include="USB\usb-pad\usb-turntable.h">
<Filter>System\Ps2\USB\usb-pad</Filter>
</ClInclude>