From edd39dfe08ac6395da54720c23f4c032111d8f2d Mon Sep 17 00:00:00 2001 From: Florin9doi Date: Tue, 23 Jul 2024 10:15:04 +0300 Subject: [PATCH] USB: ASCII Trance Vib emulation --- pcsx2-qt/Settings/ControllerBindingWidget.cpp | 14 ++ .../USBBindingWidget_TranceVibrator.ui | 116 +++++++++++ pcsx2-qt/pcsx2-qt.vcxproj | 3 + pcsx2-qt/pcsx2-qt.vcxproj.filters | 3 + .../icons/black/svg/trance-vibrator-line.svg | 19 ++ .../icons/white/svg/trance-vibrator-line.svg | 19 ++ pcsx2-qt/resources/resources.qrc | 2 + pcsx2/CMakeLists.txt | 2 + pcsx2/Input/InputManager.cpp | 18 ++ pcsx2/Input/InputManager.h | 1 + pcsx2/USB/deviceproxy.cpp | 2 + pcsx2/USB/deviceproxy.h | 1 + pcsx2/USB/usb-pad/usb-trance-vibrator.cpp | 185 ++++++++++++++++++ pcsx2/USB/usb-pad/usb-trance-vibrator.h | 36 ++++ pcsx2/pcsx2.vcxproj | 2 + pcsx2/pcsx2.vcxproj.filters | 6 + 16 files changed, 429 insertions(+) create mode 100644 pcsx2-qt/Settings/USBBindingWidget_TranceVibrator.ui create mode 100644 pcsx2-qt/resources/icons/black/svg/trance-vibrator-line.svg create mode 100644 pcsx2-qt/resources/icons/white/svg/trance-vibrator-line.svg create mode 100644 pcsx2/USB/usb-pad/usb-trance-vibrator.cpp create mode 100644 pcsx2/USB/usb-pad/usb-trance-vibrator.h diff --git a/pcsx2-qt/Settings/ControllerBindingWidget.cpp b/pcsx2-qt/Settings/ControllerBindingWidget.cpp index d061087f8f..1c13e11015 100644 --- a/pcsx2-qt/Settings/ControllerBindingWidget.cpp +++ b/pcsx2-qt/Settings/ControllerBindingWidget.cpp @@ -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 bindings) widget->initialize(sif, bi.bind_type, getConfigSection(), getBindingKey(bi.name)); } + + if (bi.bind_type == InputBindingInfo::Type::Motor) + { + InputVibrationBindingWidget* widget = findChild(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); diff --git a/pcsx2-qt/Settings/USBBindingWidget_TranceVibrator.ui b/pcsx2-qt/Settings/USBBindingWidget_TranceVibrator.ui new file mode 100644 index 0000000000..772ddd21f7 --- /dev/null +++ b/pcsx2-qt/Settings/USBBindingWidget_TranceVibrator.ui @@ -0,0 +1,116 @@ + + + USBBindingWidget_TranceVibrator + + + + 0 + 0 + 1100 + 500 + + + + + 0 + 0 + + + + + 1100 + 500 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Horizontal + + + + + + + + + Motor + + + + 6 + + + 6 + + + 6 + + + 6 + + + + + + 100 + 0 + + + + + 16777215 + 16777215 + + + + PushButton + + + + + + + + + + + + Qt::Horizontal + + + + + + + Qt::Vertical + + + + + + + + InputVibrationBindingWidget + QPushButton +
Settings/InputBindingWidget.h
+
+
+ + + + +
diff --git a/pcsx2-qt/pcsx2-qt.vcxproj b/pcsx2-qt/pcsx2-qt.vcxproj index a70040658b..e8e3d4006c 100644 --- a/pcsx2-qt/pcsx2-qt.vcxproj +++ b/pcsx2-qt/pcsx2-qt.vcxproj @@ -431,6 +431,9 @@ Document + + Document + Document diff --git a/pcsx2-qt/pcsx2-qt.vcxproj.filters b/pcsx2-qt/pcsx2-qt.vcxproj.filters index 8fa5b1fd97..36eeae6e02 100644 --- a/pcsx2-qt/pcsx2-qt.vcxproj.filters +++ b/pcsx2-qt/pcsx2-qt.vcxproj.filters @@ -672,6 +672,9 @@ Settings + + Settings + Settings diff --git a/pcsx2-qt/resources/icons/black/svg/trance-vibrator-line.svg b/pcsx2-qt/resources/icons/black/svg/trance-vibrator-line.svg new file mode 100644 index 0000000000..2b9f9478fd --- /dev/null +++ b/pcsx2-qt/resources/icons/black/svg/trance-vibrator-line.svg @@ -0,0 +1,19 @@ + + + + + diff --git a/pcsx2-qt/resources/icons/white/svg/trance-vibrator-line.svg b/pcsx2-qt/resources/icons/white/svg/trance-vibrator-line.svg new file mode 100644 index 0000000000..6619d170d6 --- /dev/null +++ b/pcsx2-qt/resources/icons/white/svg/trance-vibrator-line.svg @@ -0,0 +1,19 @@ + + + + + diff --git a/pcsx2-qt/resources/resources.qrc b/pcsx2-qt/resources/resources.qrc index d94bd0004c..a2d154d548 100644 --- a/pcsx2-qt/resources/resources.qrc +++ b/pcsx2-qt/resources/resources.qrc @@ -83,6 +83,7 @@ icons/black/svg/shut-down-line.svg icons/black/svg/singstar-line.svg icons/black/svg/tools-line.svg + icons/black/svg/trance-vibrator-line.svg icons/black/svg/trash-fill.svg icons/black/svg/trophy-line.svg icons/black/svg/tv-2-line.svg @@ -180,6 +181,7 @@ icons/white/svg/shut-down-line.svg icons/white/svg/singstar-line.svg icons/white/svg/tools-line.svg + icons/white/svg/trance-vibrator-line.svg icons/white/svg/trash-fill.svg icons/white/svg/trophy-line.svg icons/white/svg/tv-2-line.svg diff --git a/pcsx2/CMakeLists.txt b/pcsx2/CMakeLists.txt index a32632a2ad..552efda4fc 100644 --- a/pcsx2/CMakeLists.txt +++ b/pcsx2/CMakeLists.txt @@ -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 ) diff --git a/pcsx2/Input/InputManager.cpp b/pcsx2/Input/InputManager.cpp index 99f9a4b9bb..d5edf5e263 100644 --- a/pcsx2/Input/InputManager.cpp +++ b/pcsx2/Input/InputManager.cpp @@ -868,6 +868,19 @@ void InputManager::AddUSBBindings(SettingsInterface& si, u32 port) } break; + case InputBindingInfo::Type::Motor: + { + const std::vector 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) diff --git a/pcsx2/Input/InputManager.h b/pcsx2/Input/InputManager.h index c4d6affabf..4acc7c2f0c 100644 --- a/pcsx2/Input/InputManager.h +++ b/pcsx2/Input/InputManager.h @@ -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. diff --git a/pcsx2/USB/deviceproxy.cpp b/pcsx2/USB/deviceproxy.cpp index f93fccf488..78b26a5a3f 100644 --- a/pcsx2/USB/deviceproxy.cpp +++ b/pcsx2/USB/deviceproxy.cpp @@ -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()); diff --git a/pcsx2/USB/deviceproxy.h b/pcsx2/USB/deviceproxy.h index f68e0bb889..41c2b32b86 100644 --- a/pcsx2/USB/deviceproxy.h +++ b/pcsx2/USB/deviceproxy.h @@ -35,6 +35,7 @@ enum DeviceType : s32 DEVTYPE_BUZZ, DEVTYPE_EYETOY, DEVTYPE_BEATMANIA_DADADA, + DEVTYPE_TRANCE_VIBRATOR, DEVTYPE_SEGA_SEAMIC, DEVTYPE_PRINTER, DEVTYPE_KEYBOARDMANIA, diff --git a/pcsx2/USB/usb-pad/usb-trance-vibrator.cpp b/pcsx2/USB/usb-pad/usb-trance-vibrator.cpp new file mode 100644 index 0000000000..d99c763893 --- /dev/null +++ b/pcsx2/USB/usb-pad/usb-trance-vibrator.cpp @@ -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 + +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 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 TranceVibratorDevice::Settings(u32 subtype) const + { + return {}; + } +} // namespace usb_pad diff --git a/pcsx2/USB/usb-pad/usb-trance-vibrator.h b/pcsx2/USB/usb-pad/usb-trance-vibrator.h new file mode 100644 index 0000000000..715edb92c0 --- /dev/null +++ b/pcsx2/USB/usb-pad/usb-trance-vibrator.h @@ -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 +#include + +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 Bindings(u32 subtype) const override; + std::span Settings(u32 subtype) const override; + USBDevice* CreateDevice(SettingsInterface& si, u32 port, u32 subtype) const override; + }; + +} // namespace usb_pad diff --git a/pcsx2/pcsx2.vcxproj b/pcsx2/pcsx2.vcxproj index 39e0939cb7..f9b0f83eab 100644 --- a/pcsx2/pcsx2.vcxproj +++ b/pcsx2/pcsx2.vcxproj @@ -398,6 +398,7 @@ + @@ -845,6 +846,7 @@ + diff --git a/pcsx2/pcsx2.vcxproj.filters b/pcsx2/pcsx2.vcxproj.filters index 0a2bbc9c34..27b0cd06f1 100644 --- a/pcsx2/pcsx2.vcxproj.filters +++ b/pcsx2/pcsx2.vcxproj.filters @@ -1199,6 +1199,9 @@ System\Ps2\USB\usb-pad + + System\Ps2\USB\usb-pad + System\Ps2\USB\usb-pad @@ -2136,6 +2139,9 @@ System\Ps2\USB\usb-pad + + System\Ps2\USB\usb-pad + System\Ps2\USB\usb-pad