mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-03 21:41:26 +12:00
USB: Top Shot Fearmaster device emulation
This commit is contained in:
parent
088b594fa8
commit
33d2b27b91
15 changed files with 593 additions and 5 deletions
|
@ -418,6 +418,7 @@ target_sources(rpcs3_emu PRIVATE
|
||||||
Io/recording_config.cpp
|
Io/recording_config.cpp
|
||||||
Io/Skylander.cpp
|
Io/Skylander.cpp
|
||||||
Io/TopShotElite.cpp
|
Io/TopShotElite.cpp
|
||||||
|
Io/TopShotFearmaster.cpp
|
||||||
Io/Turntable.cpp
|
Io/Turntable.cpp
|
||||||
Io/usb_device.cpp
|
Io/usb_device.cpp
|
||||||
Io/usb_vfs.cpp
|
Io/usb_vfs.cpp
|
||||||
|
|
|
@ -22,11 +22,13 @@
|
||||||
#include "Emu/Io/ghltar_config.h"
|
#include "Emu/Io/ghltar_config.h"
|
||||||
#include "Emu/Io/guncon3_config.h"
|
#include "Emu/Io/guncon3_config.h"
|
||||||
#include "Emu/Io/topshotelite_config.h"
|
#include "Emu/Io/topshotelite_config.h"
|
||||||
|
#include "Emu/Io/topshotfearmaster_config.h"
|
||||||
#include "Emu/Io/Buzz.h"
|
#include "Emu/Io/Buzz.h"
|
||||||
#include "Emu/Io/buzz_config.h"
|
#include "Emu/Io/buzz_config.h"
|
||||||
#include "Emu/Io/GameTablet.h"
|
#include "Emu/Io/GameTablet.h"
|
||||||
#include "Emu/Io/GunCon3.h"
|
#include "Emu/Io/GunCon3.h"
|
||||||
#include "Emu/Io/TopShotElite.h"
|
#include "Emu/Io/TopShotElite.h"
|
||||||
|
#include "Emu/Io/TopShotFearmaster.h"
|
||||||
#include "Emu/Io/Turntable.h"
|
#include "Emu/Io/Turntable.h"
|
||||||
#include "Emu/Io/turntable_config.h"
|
#include "Emu/Io/turntable_config.h"
|
||||||
#include "Emu/Io/RB3MidiKeyboard.h"
|
#include "Emu/Io/RB3MidiKeyboard.h"
|
||||||
|
@ -47,6 +49,7 @@ cfg_turntables g_cfg_turntable;
|
||||||
cfg_usios g_cfg_usio;
|
cfg_usios g_cfg_usio;
|
||||||
cfg_guncon3 g_cfg_guncon3;
|
cfg_guncon3 g_cfg_guncon3;
|
||||||
cfg_topshotelite g_cfg_topshotelite;
|
cfg_topshotelite g_cfg_topshotelite;
|
||||||
|
cfg_topshotfearmaster g_cfg_topshotfearmaster;
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void fmt_class_string<libusb_transfer>::format(std::string& out, u64 arg)
|
void fmt_class_string<libusb_transfer>::format(std::string& out, u64 arg)
|
||||||
|
@ -891,6 +894,18 @@ void connect_usb_controller(u8 index, input::product_type type)
|
||||||
usbh->connect_usb_device(dev, true);
|
usbh->connect_usb_device(dev, true);
|
||||||
usbh->pad_to_usb.emplace(index, std::pair(type, dev));
|
usbh->pad_to_usb.emplace(index, std::pair(type, dev));
|
||||||
}
|
}
|
||||||
|
if (type == input::product_type::top_shot_fearmaster)
|
||||||
|
{
|
||||||
|
if (!g_cfg_topshotfearmaster.load())
|
||||||
|
{
|
||||||
|
sys_usbd.notice("Could not load Top Shot Fearmaster config. Using defaults.");
|
||||||
|
}
|
||||||
|
|
||||||
|
sys_usbd.success("Adding emulated Top Shot Fearmaster (controller %d)", index);
|
||||||
|
std::shared_ptr<usb_device> dev = std::make_shared<usb_device_topshotfearmaster>(index, usbh->get_new_location());
|
||||||
|
usbh->connect_usb_device(dev, true);
|
||||||
|
usbh->pad_to_usb.emplace(index, std::pair(type, dev));
|
||||||
|
}
|
||||||
if (type == input::product_type::udraw_gametablet)
|
if (type == input::product_type::udraw_gametablet)
|
||||||
{
|
{
|
||||||
sys_usbd.success("Adding emulated uDraw GameTablet (controller %d)", index);
|
sys_usbd.success("Adding emulated uDraw GameTablet (controller %d)", index);
|
||||||
|
|
425
rpcs3/Emu/Io/TopShotFearmaster.cpp
Normal file
425
rpcs3/Emu/Io/TopShotFearmaster.cpp
Normal file
|
@ -0,0 +1,425 @@
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "TopShotFearmaster.h"
|
||||||
|
#include "MouseHandler.h"
|
||||||
|
#include "Emu/IdManager.h"
|
||||||
|
#include "Emu/Io/topshotfearmaster_config.h"
|
||||||
|
#include "Emu/Cell/lv2/sys_usbd.h"
|
||||||
|
#include "Emu/system_config.h"
|
||||||
|
#include "Input/pad_thread.h"
|
||||||
|
|
||||||
|
LOG_CHANNEL(topshotfearmaster_log);
|
||||||
|
|
||||||
|
#define TSF_CALIB_LOG false
|
||||||
|
// 0 < Calib_Top < Calib_Bottom < 0x2ff
|
||||||
|
// 0 < Calib_Right < Calib_Left < 0x3ff
|
||||||
|
constexpr u16 TSF_CALIB_TOP = 20;
|
||||||
|
constexpr u16 TSF_CALIB_BOTTOM = 840;
|
||||||
|
constexpr u16 TSF_CALIB_LEFT = 900;
|
||||||
|
constexpr u16 TSF_CALIB_RIGHT = 120;
|
||||||
|
constexpr u16 TSF_CALIB_DIST = 95;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
void fmt_class_string<topshotfearmaster_btn>::format(std::string& out, u64 arg)
|
||||||
|
{
|
||||||
|
format_enum(out, arg, [](topshotfearmaster_btn value)
|
||||||
|
{
|
||||||
|
switch (value)
|
||||||
|
{
|
||||||
|
case topshotfearmaster_btn::trigger: return "Trigger";
|
||||||
|
case topshotfearmaster_btn::heartrate: return "Heartrate";
|
||||||
|
case topshotfearmaster_btn::square: return "Square";
|
||||||
|
case topshotfearmaster_btn::cross: return "Cross";
|
||||||
|
case topshotfearmaster_btn::circle: return "Circle";
|
||||||
|
case topshotfearmaster_btn::triangle: return "Triangle";
|
||||||
|
case topshotfearmaster_btn::select: return "Select";
|
||||||
|
case topshotfearmaster_btn::start: return "Start";
|
||||||
|
case topshotfearmaster_btn::l3: return "L3";
|
||||||
|
case topshotfearmaster_btn::ps: return "PS";
|
||||||
|
case topshotfearmaster_btn::dpad_up: return "D-Pad Up";
|
||||||
|
case topshotfearmaster_btn::dpad_down: return "D-Pad Down";
|
||||||
|
case topshotfearmaster_btn::dpad_left: return "D-Pad Left";
|
||||||
|
case topshotfearmaster_btn::dpad_right: return "D-Pad Right";
|
||||||
|
case topshotfearmaster_btn::ls_x: return "Left Stick X-Axis";
|
||||||
|
case topshotfearmaster_btn::ls_y: return "Left Stick Y-Axis";
|
||||||
|
case topshotfearmaster_btn::count: return "Count";
|
||||||
|
}
|
||||||
|
|
||||||
|
return unknown;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
struct TopShotFearmaster_data
|
||||||
|
{
|
||||||
|
uint8_t btn_square : 1;
|
||||||
|
uint8_t btn_cross : 1;
|
||||||
|
uint8_t btn_circle : 1;
|
||||||
|
uint8_t btn_triangle : 1;
|
||||||
|
uint8_t : 1;
|
||||||
|
uint8_t btn_trigger: 1;
|
||||||
|
uint8_t : 2;
|
||||||
|
|
||||||
|
uint8_t btn_select : 1;
|
||||||
|
uint8_t btn_start : 1;
|
||||||
|
uint8_t btn_l3 : 1;
|
||||||
|
uint8_t btn_heartrate : 1;
|
||||||
|
uint8_t btn_ps: 1;
|
||||||
|
uint8_t : 3;
|
||||||
|
|
||||||
|
uint8_t dpad;
|
||||||
|
uint8_t stick_lx;
|
||||||
|
uint8_t stick_ly;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint8_t stick_rx;
|
||||||
|
uint8_t stick_ry;
|
||||||
|
};
|
||||||
|
uint16_t heartrate;
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t led_lx_hi : 8;
|
||||||
|
uint8_t led_ly_hi : 6;
|
||||||
|
uint8_t led_lx_lo : 2;
|
||||||
|
uint8_t detect_l : 4;
|
||||||
|
uint8_t led_ly_lo : 4;
|
||||||
|
|
||||||
|
uint8_t led_rx_hi : 8;
|
||||||
|
uint8_t led_ry_hi : 6;
|
||||||
|
uint8_t led_rx_lo : 2;
|
||||||
|
uint8_t detect_r : 4;
|
||||||
|
uint8_t led_ry_lo : 4;
|
||||||
|
|
||||||
|
uint8_t : 8;
|
||||||
|
uint8_t : 8;
|
||||||
|
uint8_t : 8;
|
||||||
|
|
||||||
|
uint8_t trigger;
|
||||||
|
uint8_t : 8;
|
||||||
|
uint8_t : 8;
|
||||||
|
uint16_t unk[4];
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
Dpad_North,
|
||||||
|
Dpad_NE,
|
||||||
|
Dpad_East,
|
||||||
|
Dpad_SE,
|
||||||
|
Dpad_South,
|
||||||
|
Dpad_SW,
|
||||||
|
Dpad_West,
|
||||||
|
Dpad_NW,
|
||||||
|
Dpad_None = 0x0f
|
||||||
|
};
|
||||||
|
|
||||||
|
usb_device_topshotfearmaster::usb_device_topshotfearmaster(u32 controller_index, const std::array<u8, 7>& location)
|
||||||
|
: usb_device_emulated(location)
|
||||||
|
, m_controller_index(controller_index)
|
||||||
|
, m_mode(0)
|
||||||
|
{
|
||||||
|
device = UsbDescriptorNode(USB_DESCRIPTOR_DEVICE,
|
||||||
|
UsbDeviceDescriptor {
|
||||||
|
.bcdUSB = 0x0100,
|
||||||
|
.bDeviceClass = 0x00,
|
||||||
|
.bDeviceSubClass = 0x00,
|
||||||
|
.bDeviceProtocol = 0x00,
|
||||||
|
.bMaxPacketSize0 = 0x20,
|
||||||
|
.idVendor = 0x12ba,
|
||||||
|
.idProduct = 0x04a1,
|
||||||
|
.bcdDevice = 0x0108,
|
||||||
|
.iManufacturer = 0x01,
|
||||||
|
.iProduct = 0x02,
|
||||||
|
.iSerialNumber = 0x03,
|
||||||
|
.bNumConfigurations = 0x01});
|
||||||
|
auto& config0 = device.add_node(UsbDescriptorNode(USB_DESCRIPTOR_CONFIG,
|
||||||
|
UsbDeviceConfiguration {
|
||||||
|
.wTotalLength = 0x0029,
|
||||||
|
.bNumInterfaces = 0x01,
|
||||||
|
.bConfigurationValue = 0x01,
|
||||||
|
.iConfiguration = 0x00,
|
||||||
|
.bmAttributes = 0x80,
|
||||||
|
.bMaxPower = 0x32}));
|
||||||
|
config0.add_node(UsbDescriptorNode(USB_DESCRIPTOR_INTERFACE,
|
||||||
|
UsbDeviceInterface {
|
||||||
|
.bInterfaceNumber = 0x00,
|
||||||
|
.bAlternateSetting = 0x00,
|
||||||
|
.bNumEndpoints = 0x02,
|
||||||
|
.bInterfaceClass = 0x03,
|
||||||
|
.bInterfaceSubClass = 0x00,
|
||||||
|
.bInterfaceProtocol = 0x00,
|
||||||
|
.iInterface = 0x00}));
|
||||||
|
config0.add_node(UsbDescriptorNode(USB_DESCRIPTOR_HID,
|
||||||
|
UsbDeviceHID {
|
||||||
|
.bcdHID = 0x0110,
|
||||||
|
.bCountryCode = 0x00,
|
||||||
|
.bNumDescriptors = 0x01,
|
||||||
|
.bDescriptorType = 0x22,
|
||||||
|
.wDescriptorLength = 0x0089}));
|
||||||
|
config0.add_node(UsbDescriptorNode(USB_DESCRIPTOR_ENDPOINT,
|
||||||
|
UsbDeviceEndpoint {
|
||||||
|
.bEndpointAddress = 0x81,
|
||||||
|
.bmAttributes = 0x03,
|
||||||
|
.wMaxPacketSize = 0x0040,
|
||||||
|
.bInterval = 0x0a}));
|
||||||
|
config0.add_node(UsbDescriptorNode(USB_DESCRIPTOR_ENDPOINT,
|
||||||
|
UsbDeviceEndpoint {
|
||||||
|
.bEndpointAddress = 0x02,
|
||||||
|
.bmAttributes = 0x03,
|
||||||
|
.wMaxPacketSize = 0x0040,
|
||||||
|
.bInterval = 0x0a}));
|
||||||
|
|
||||||
|
add_string("Dangerous Hunts for Playstation (R) 3");
|
||||||
|
add_string("Dangerous Hunts for Playstation (R) 3");
|
||||||
|
}
|
||||||
|
|
||||||
|
usb_device_topshotfearmaster::~usb_device_topshotfearmaster()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void usb_device_topshotfearmaster::control_transfer(u8 bmRequestType, u8 bRequest, u16 wValue, u16 wIndex, u16 wLength, u32 buf_size, u8* buf, UsbTransfer* transfer)
|
||||||
|
{
|
||||||
|
transfer->fake = true;
|
||||||
|
transfer->expected_count = buf_size;
|
||||||
|
transfer->expected_result = HC_CC_NOERR;
|
||||||
|
transfer->expected_time = get_timestamp() + 100;
|
||||||
|
|
||||||
|
switch (bmRequestType)
|
||||||
|
{
|
||||||
|
case 0U /*silences warning*/ | LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE: // 0x21
|
||||||
|
switch (bRequest)
|
||||||
|
{
|
||||||
|
case 0x09: // SET_REPORT
|
||||||
|
ensure(buf_size >= 8);
|
||||||
|
switch (buf[0])
|
||||||
|
{
|
||||||
|
case 0x01:
|
||||||
|
topshotfearmaster_log.trace("Leds: %s/%s/%s/%s",
|
||||||
|
buf[2] & 1 ? "ON" : "OFF",
|
||||||
|
buf[2] & 2 ? "ON" : "OFF",
|
||||||
|
buf[2] & 4 ? "ON" : "OFF",
|
||||||
|
buf[2] & 8 ? "ON" : "OFF");
|
||||||
|
break;
|
||||||
|
case 0x82:
|
||||||
|
m_mode = buf[2];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
topshotfearmaster_log.error("Unhandled SET_REPORT packet : %x", buf[0]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
topshotfearmaster_log.error("Unhandled Request: 0x%02X/0x%02X", bmRequestType, bRequest);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
usb_device_emulated::control_transfer(bmRequestType, bRequest, wValue, wIndex, wLength, buf_size, buf, transfer);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern bool is_input_allowed();
|
||||||
|
|
||||||
|
static int get_heartrate_sensor_value(u8 heartrate)
|
||||||
|
{
|
||||||
|
static const uint16_t sensor_data[] = {
|
||||||
|
0x7af, 0x771, 0x737, 0x6ff, 0x6cb, 0x69a, 0x66c, 0x640, 0x616, 0x5ef, // 30-39
|
||||||
|
0x5ca, 0x5a6, 0x584, 0x563, 0x544, 0x527, 0x50a, 0x4ef, 0x4d5, 0x4bc, // 40-49
|
||||||
|
0x4a4, 0x48d, 0x477, 0x462, 0x44d, 0x439, 0x426, 0x413, 0x401, 0x3f0, // 50-59
|
||||||
|
0x3e0, 0x3cf, 0x3c0, 0x3b1, 0x3a2, 0x394, 0x386, 0x379, 0x36c, 0x35f, // 60-69
|
||||||
|
0x353, 0x347, 0x33b, 0x330, 0x325, 0x31b, 0x310, 0x306, 0x2fc, 0x2f3, // 70-79
|
||||||
|
0x2e9, 0x2e0, 0x2d7, 0x2ce, 0x2c6, 0x2bd, 0x2b5, 0x2ad, 0x2a6, 0x29e, // 80-89
|
||||||
|
0x297, 0x290, 0x289, 0x282, 0x27b, 0x274, 0x26e, 0x267, 0x261, 0x25b, // 90-99
|
||||||
|
0x255, 0x24f, 0x249, 0x243, 0x23e, 0x239, 0x233, 0x22e, 0x229, 0x224, // 100-109
|
||||||
|
0x21f, 0x21a, 0x215, 0x210, 0x20c, 0x207, 0x203, 0x1fe, 0x1fa, 0x1f6, // 110-119
|
||||||
|
0x1f2, 0x1ed, 0x1e9, 0x1e5, 0x1e2, 0x1de, 0x1da, 0x1d6, 0x1d3, 0x1cf, // 120-129
|
||||||
|
0x1cc, 0x1c8, 0x1c5, 0x1c1, 0x1be, 0x1bb, 0x1b7, 0x1b4, 0x1b1, 0x1ae // 130-139
|
||||||
|
};
|
||||||
|
|
||||||
|
if (heartrate < 30 || heartrate > 139)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sensor_data[heartrate - 30];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_sensor_pos(struct TopShotFearmaster_data* ts, s32 led_lx, s32 led_ly, s32 led_rx, s32 led_ry, s32 detect_l, s32 detect_r)
|
||||||
|
{
|
||||||
|
ts->led_lx_hi = led_lx >> 2;
|
||||||
|
ts->led_lx_lo = led_lx & 0x3;
|
||||||
|
ts->led_ly_hi = led_ly >> 4;
|
||||||
|
ts->led_ly_lo = led_ly & 0xf;
|
||||||
|
|
||||||
|
ts->led_rx_hi = led_rx >> 2;
|
||||||
|
ts->led_rx_lo = led_rx & 0x3;
|
||||||
|
ts->led_ry_hi = led_ry >> 4;
|
||||||
|
ts->led_ry_lo = led_ry & 0xf;
|
||||||
|
|
||||||
|
ts->detect_l = detect_l;
|
||||||
|
ts->detect_r = detect_r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void prepare_data(const TopShotFearmaster_data* ts, u8* data)
|
||||||
|
{
|
||||||
|
std::memcpy(data, ts, sizeof(TopShotFearmaster_data));
|
||||||
|
topshotfearmaster_log.trace("interrupt_transfer: %s", fmt::buf_to_hexstring(data, sizeof(TopShotFearmaster_data)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void usb_device_topshotfearmaster::interrupt_transfer(u32 buf_size, u8* buf, u32 /*endpoint*/, UsbTransfer* transfer)
|
||||||
|
{
|
||||||
|
ensure(buf_size >= sizeof(TopShotFearmaster_data));
|
||||||
|
|
||||||
|
transfer->fake = true;
|
||||||
|
transfer->expected_count = sizeof(TopShotFearmaster_data);
|
||||||
|
transfer->expected_result = HC_CC_NOERR;
|
||||||
|
transfer->expected_time = get_timestamp() + 4000;
|
||||||
|
|
||||||
|
struct TopShotFearmaster_data ts{};
|
||||||
|
ts.dpad = Dpad_None;
|
||||||
|
ts.stick_lx = ts.stick_ly = ts.stick_rx = ts.stick_ry = 0x7f;
|
||||||
|
if (m_mode)
|
||||||
|
{
|
||||||
|
set_sensor_pos(&ts, 0x3ff, 0x3ff, 0x3ff, 0x3ff, 0xf, 0xf);
|
||||||
|
}
|
||||||
|
ts.unk[0] = ts.unk[1] = ts.unk[2] = ts.unk[3] = 0x0200;
|
||||||
|
|
||||||
|
if (!is_input_allowed())
|
||||||
|
{
|
||||||
|
prepare_data(&ts, buf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_cfg.io.mouse == mouse_handler::null)
|
||||||
|
{
|
||||||
|
topshotfearmaster_log.warning("Top Shot Fearmaster requires a Mouse Handler enabled");
|
||||||
|
prepare_data(&ts, buf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_controller_index >= g_cfg_topshotfearmaster.players.size())
|
||||||
|
{
|
||||||
|
topshotfearmaster_log.warning("Top Shot Fearmaster controllers are only supported for Player1 to Player%d", g_cfg_topshotfearmaster.players.size());
|
||||||
|
prepare_data(&ts, buf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool up = false, right = false, down = false, left = false;
|
||||||
|
const auto input_callback = [&ts, &up, &down, &left, &right](topshotfearmaster_btn btn, u16 value, bool pressed)
|
||||||
|
{
|
||||||
|
if (!pressed)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (btn)
|
||||||
|
{
|
||||||
|
case topshotfearmaster_btn::trigger: ts.btn_trigger |= 1; break;
|
||||||
|
case topshotfearmaster_btn::heartrate: ts.btn_heartrate |= 1; break;
|
||||||
|
case topshotfearmaster_btn::square: ts.btn_square |= 1; break;
|
||||||
|
case topshotfearmaster_btn::cross: ts.btn_cross |= 1; break;
|
||||||
|
case topshotfearmaster_btn::circle: ts.btn_circle |= 1; break;
|
||||||
|
case topshotfearmaster_btn::triangle: ts.btn_triangle |= 1; break;
|
||||||
|
case topshotfearmaster_btn::select: ts.btn_select |= 1; break;
|
||||||
|
case topshotfearmaster_btn::start: ts.btn_start |= 1; break;
|
||||||
|
case topshotfearmaster_btn::l3: ts.btn_l3 |= 1; break;
|
||||||
|
case topshotfearmaster_btn::ps: ts.btn_ps |= 1; break;
|
||||||
|
case topshotfearmaster_btn::dpad_up: up = true; break;
|
||||||
|
case topshotfearmaster_btn::dpad_down: down = true; break;
|
||||||
|
case topshotfearmaster_btn::dpad_left: left = true; break;
|
||||||
|
case topshotfearmaster_btn::dpad_right: right = true; break;
|
||||||
|
case topshotfearmaster_btn::ls_x: ts.stick_lx = static_cast<uint8_t>(value); break;
|
||||||
|
case topshotfearmaster_btn::ls_y: ts.stick_ly = static_cast<uint8_t>(value); break;
|
||||||
|
case topshotfearmaster_btn::count: break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto& cfg = ::at32(g_cfg_topshotfearmaster.players, m_controller_index);
|
||||||
|
|
||||||
|
{
|
||||||
|
std::lock_guard lock(pad::g_pad_mutex);
|
||||||
|
const auto gamepad_handler = pad::get_current_handler();
|
||||||
|
const auto& pads = gamepad_handler->GetPads();
|
||||||
|
const auto& pad = ::at32(pads, m_controller_index);
|
||||||
|
if (pad->m_port_status & CELL_PAD_STATUS_CONNECTED)
|
||||||
|
{
|
||||||
|
cfg->handle_input(pad, true, input_callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!up && !right && !down && !left)
|
||||||
|
ts.dpad = Dpad_None;
|
||||||
|
else if (up && !left && !right)
|
||||||
|
ts.dpad = Dpad_North;
|
||||||
|
else if (up && right)
|
||||||
|
ts.dpad = Dpad_NE;
|
||||||
|
else if (right && !up && !down)
|
||||||
|
ts.dpad = Dpad_East;
|
||||||
|
else if (down && right)
|
||||||
|
ts.dpad = Dpad_SE;
|
||||||
|
else if (down && !left && !right)
|
||||||
|
ts.dpad = Dpad_South;
|
||||||
|
else if (down && left)
|
||||||
|
ts.dpad = Dpad_SW;
|
||||||
|
else if (left && !up && !down)
|
||||||
|
ts.dpad = Dpad_West;
|
||||||
|
else if (up && left)
|
||||||
|
ts.dpad = Dpad_NW;
|
||||||
|
|
||||||
|
if (m_mode)
|
||||||
|
{
|
||||||
|
auto& mouse_handler = g_fxo->get<MouseHandlerBase>();
|
||||||
|
std::lock_guard mouse_lock(mouse_handler.mutex);
|
||||||
|
|
||||||
|
mouse_handler.Init(4);
|
||||||
|
|
||||||
|
const u32 mouse_index = g_cfg.io.mouse == mouse_handler::basic ? 0 : m_controller_index;
|
||||||
|
if (mouse_index >= mouse_handler.GetMice().size())
|
||||||
|
{
|
||||||
|
prepare_data(&ts, buf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Mouse& mouse_data = ::at32(mouse_handler.GetMice(), mouse_index);
|
||||||
|
cfg->handle_input(mouse_data, input_callback);
|
||||||
|
ts.trigger = ts.btn_trigger ? 0xff : 0x00;
|
||||||
|
ts.heartrate = ts.btn_heartrate ? get_heartrate_sensor_value(60) : 0;
|
||||||
|
|
||||||
|
if (mouse_data.x_max <= 0 || mouse_data.y_max <= 0)
|
||||||
|
{
|
||||||
|
prepare_data(&ts, buf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 led_lx = 0x3ff - (TSF_CALIB_RIGHT + (mouse_data.x_pos * (TSF_CALIB_LEFT - TSF_CALIB_RIGHT) / mouse_data.x_max) + TSF_CALIB_DIST);
|
||||||
|
s32 led_rx = 0x3ff - (TSF_CALIB_RIGHT + (mouse_data.x_pos * (TSF_CALIB_LEFT - TSF_CALIB_RIGHT) / mouse_data.x_max) - TSF_CALIB_DIST);
|
||||||
|
|
||||||
|
s32 led_ly = TSF_CALIB_TOP + (mouse_data.y_pos * (TSF_CALIB_BOTTOM - TSF_CALIB_TOP) / mouse_data.y_max);
|
||||||
|
s32 led_ry = TSF_CALIB_TOP + (mouse_data.y_pos * (TSF_CALIB_BOTTOM - TSF_CALIB_TOP) / mouse_data.y_max);
|
||||||
|
|
||||||
|
u8 detect_l = 0x2, detect_r = 0x2; // 0x2 = led detected / 0xf = undetected
|
||||||
|
|
||||||
|
if (led_lx < 0 || led_lx > 0x3ff || led_ly < 0 || led_ly > 0x3ff)
|
||||||
|
{
|
||||||
|
led_lx = 0x3ff;
|
||||||
|
led_ly = 0x3ff;
|
||||||
|
detect_l = 0xf;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (led_rx < 0 || led_rx > 0x3ff || led_ry < 0 || led_ry > 0x3ff)
|
||||||
|
{
|
||||||
|
led_rx = 0x3ff;
|
||||||
|
led_ry = 0x3ff;
|
||||||
|
detect_r = 0xf;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_sensor_pos(&ts, led_lx, led_ly, led_rx, led_ry, detect_l, detect_r);
|
||||||
|
|
||||||
|
#if TSF_CALIB_LOG
|
||||||
|
topshotfearmaster_log.error("L: %d x %d, R: %d x %d", led_lx + TSF_CALIB_DIST, led_ly, led_rx - TSF_CALIB_DIST, led_ry);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
prepare_data(&ts, buf);
|
||||||
|
}
|
17
rpcs3/Emu/Io/TopShotFearmaster.h
Normal file
17
rpcs3/Emu/Io/TopShotFearmaster.h
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Emu/Io/usb_device.h"
|
||||||
|
|
||||||
|
class usb_device_topshotfearmaster: public usb_device_emulated
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
usb_device_topshotfearmaster(u32 controller_index, const std::array<u8, 7>& location);
|
||||||
|
~usb_device_topshotfearmaster();
|
||||||
|
|
||||||
|
void control_transfer(u8 bmRequestType, u8 bRequest, u16 wValue, u16 wIndex, u16 wLength, u32 buf_size, u8* buf, UsbTransfer* transfer) override;
|
||||||
|
void interrupt_transfer(u32 buf_size, u8* buf, u32 endpoint, UsbTransfer* transfer) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
u32 m_controller_index;
|
||||||
|
u8 m_mode;
|
||||||
|
};
|
|
@ -146,10 +146,11 @@ enum
|
||||||
CELL_PAD_PCLASS_TYPE_SKATEBOARD = 0x8001,
|
CELL_PAD_PCLASS_TYPE_SKATEBOARD = 0x8001,
|
||||||
|
|
||||||
// these are used together with pad->is_fake_pad to capture input events for usbd/gem/move without conflicting with cellPad
|
// these are used together with pad->is_fake_pad to capture input events for usbd/gem/move without conflicting with cellPad
|
||||||
CELL_PAD_FAKE_TYPE_FIRST = 0xa000,
|
CELL_PAD_FAKE_TYPE_FIRST = 0xa000,
|
||||||
CELL_PAD_FAKE_TYPE_GUNCON3 = 0xa000,
|
CELL_PAD_FAKE_TYPE_GUNCON3 = 0xa000,
|
||||||
CELL_PAD_FAKE_TYPE_TOP_SHOT_ELITE = 0xa001,
|
CELL_PAD_FAKE_TYPE_TOP_SHOT_ELITE = 0xa001,
|
||||||
CELL_PAD_FAKE_TYPE_GAMETABLET = 0xa003,
|
CELL_PAD_FAKE_TYPE_TOP_SHOT_FEARMASTER = 0xa002,
|
||||||
|
CELL_PAD_FAKE_TYPE_GAMETABLET = 0xa003,
|
||||||
CELL_PAD_FAKE_TYPE_LAST,
|
CELL_PAD_FAKE_TYPE_LAST,
|
||||||
|
|
||||||
CELL_PAD_PCLASS_TYPE_MAX // last item
|
CELL_PAD_PCLASS_TYPE_MAX // last item
|
||||||
|
|
56
rpcs3/Emu/Io/topshotfearmaster_config.h
Normal file
56
rpcs3/Emu/Io/topshotfearmaster_config.h
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "emulated_pad_config.h"
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
enum class topshotfearmaster_btn
|
||||||
|
{
|
||||||
|
trigger,
|
||||||
|
heartrate,
|
||||||
|
square,
|
||||||
|
cross,
|
||||||
|
circle,
|
||||||
|
triangle,
|
||||||
|
select,
|
||||||
|
start,
|
||||||
|
l3,
|
||||||
|
ps,
|
||||||
|
dpad_up,
|
||||||
|
dpad_down,
|
||||||
|
dpad_left,
|
||||||
|
dpad_right,
|
||||||
|
ls_x,
|
||||||
|
ls_y,
|
||||||
|
|
||||||
|
count
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cfg_tsf final : public emulated_pad_config<topshotfearmaster_btn>
|
||||||
|
{
|
||||||
|
cfg_tsf(node* owner, const std::string& name) : emulated_pad_config(owner, name) {}
|
||||||
|
|
||||||
|
cfg_pad_btn<topshotfearmaster_btn> trigger{this, "Trigger", topshotfearmaster_btn::trigger, pad_button::mouse_button_1};
|
||||||
|
cfg_pad_btn<topshotfearmaster_btn> heartrate{this, "Heartrate", topshotfearmaster_btn::heartrate, pad_button::mouse_button_2};
|
||||||
|
cfg_pad_btn<topshotfearmaster_btn> square{this, "Square", topshotfearmaster_btn::square, pad_button::square};
|
||||||
|
cfg_pad_btn<topshotfearmaster_btn> cross{this, "Cross", topshotfearmaster_btn::cross, pad_button::cross};
|
||||||
|
cfg_pad_btn<topshotfearmaster_btn> circle{this, "Circle", topshotfearmaster_btn::circle, pad_button::circle};
|
||||||
|
cfg_pad_btn<topshotfearmaster_btn> triangle{this, "Triangle", topshotfearmaster_btn::triangle, pad_button::triangle};
|
||||||
|
cfg_pad_btn<topshotfearmaster_btn> select{this, "Select", topshotfearmaster_btn::select, pad_button::select};
|
||||||
|
cfg_pad_btn<topshotfearmaster_btn> start{this, "Start", topshotfearmaster_btn::start, pad_button::start};
|
||||||
|
cfg_pad_btn<topshotfearmaster_btn> l3{this, "L3", topshotfearmaster_btn::l3, pad_button::L3};
|
||||||
|
cfg_pad_btn<topshotfearmaster_btn> ps{this, "PS", topshotfearmaster_btn::ps, pad_button::ps};
|
||||||
|
cfg_pad_btn<topshotfearmaster_btn> dpad_up{this, "D-Pad Up", topshotfearmaster_btn::dpad_up, pad_button::dpad_up};
|
||||||
|
cfg_pad_btn<topshotfearmaster_btn> dpad_down{this, "D-Pad Down", topshotfearmaster_btn::dpad_down, pad_button::dpad_down};
|
||||||
|
cfg_pad_btn<topshotfearmaster_btn> dpad_left{this, "D-Pad Left", topshotfearmaster_btn::dpad_left, pad_button::dpad_left};
|
||||||
|
cfg_pad_btn<topshotfearmaster_btn> dpad_right{this, "D-Pad Right", topshotfearmaster_btn::dpad_right, pad_button::dpad_right};
|
||||||
|
cfg_pad_btn<topshotfearmaster_btn> ls_x{this, "Left Stick X-Axis", topshotfearmaster_btn::ls_x, pad_button::ls_x};
|
||||||
|
cfg_pad_btn<topshotfearmaster_btn> ls_y{this, "Left Stick Y-Axis", topshotfearmaster_btn::ls_y, pad_button::ls_y};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cfg_topshotfearmaster final : public emulated_pads_config<cfg_tsf, 4>
|
||||||
|
{
|
||||||
|
cfg_topshotfearmaster() : emulated_pads_config<cfg_tsf, 4>("topshotfearmaster") {};
|
||||||
|
};
|
||||||
|
|
||||||
|
extern cfg_topshotfearmaster g_cfg_topshotfearmaster;
|
|
@ -216,6 +216,17 @@ namespace input
|
||||||
.capabilites = 0x0
|
.capabilites = 0x0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
product_type::top_shot_fearmaster,
|
||||||
|
{
|
||||||
|
.type = product_type::top_shot_fearmaster,
|
||||||
|
.class_id = CELL_PAD_FAKE_TYPE_TOP_SHOT_FEARMASTER,
|
||||||
|
.vendor_id = vendor_id::sony_cea,
|
||||||
|
.product_id = product_id::top_shot_fearmaster,
|
||||||
|
.pclass_profile = 0x0,
|
||||||
|
.capabilites = 0x0
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
product_type::udraw_gametablet,
|
product_type::udraw_gametablet,
|
||||||
{
|
{
|
||||||
|
|
|
@ -20,6 +20,7 @@ namespace input
|
||||||
ride_skateboard,
|
ride_skateboard,
|
||||||
guncon_3,
|
guncon_3,
|
||||||
top_shot_elite,
|
top_shot_elite,
|
||||||
|
top_shot_fearmaster,
|
||||||
udraw_gametablet,
|
udraw_gametablet,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -46,6 +47,7 @@ namespace input
|
||||||
dance_dance_revolution_mat = 0x1010, // Dance Dance Revolution Dance Mat Controller
|
dance_dance_revolution_mat = 0x1010, // Dance Dance Revolution Dance Mat Controller
|
||||||
ride_skateboard = 0x0400, // Tony Hawk RIDE Skateboard Controller
|
ride_skateboard = 0x0400, // Tony Hawk RIDE Skateboard Controller
|
||||||
top_shot_elite = 0x04A0, // Top Shot Elite Controller
|
top_shot_elite = 0x04A0, // Top Shot Elite Controller
|
||||||
|
top_shot_fearmaster = 0x04A1, // Top Shot Fearmaster Controller
|
||||||
guncon_3 = 0x0800, // GunCon 3 Controller
|
guncon_3 = 0x0800, // GunCon 3 Controller
|
||||||
udraw_gametablet = 0xCB17, // uDraw GameTablet Controller
|
udraw_gametablet = 0xCB17, // uDraw GameTablet Controller
|
||||||
};
|
};
|
||||||
|
|
|
@ -85,6 +85,7 @@
|
||||||
<ClCompile Include="Emu\Io\RB3MidiKeyboard.cpp" />
|
<ClCompile Include="Emu\Io\RB3MidiKeyboard.cpp" />
|
||||||
<ClCompile Include="Emu\Io\recording_config.cpp" />
|
<ClCompile Include="Emu\Io\recording_config.cpp" />
|
||||||
<ClCompile Include="Emu\Io\TopShotElite.cpp" />
|
<ClCompile Include="Emu\Io\TopShotElite.cpp" />
|
||||||
|
<ClCompile Include="Emu\Io\TopShotFearmaster.cpp" />
|
||||||
<ClCompile Include="Emu\Io\Turntable.cpp" />
|
<ClCompile Include="Emu\Io\Turntable.cpp" />
|
||||||
<ClCompile Include="Emu\Io\usio.cpp" />
|
<ClCompile Include="Emu\Io\usio.cpp" />
|
||||||
<ClCompile Include="Emu\Audio\AudioBackend.cpp" />
|
<ClCompile Include="Emu\Audio\AudioBackend.cpp" />
|
||||||
|
@ -564,6 +565,8 @@
|
||||||
<ClInclude Include="Emu\Io\recording_config.h" />
|
<ClInclude Include="Emu\Io\recording_config.h" />
|
||||||
<ClInclude Include="Emu\Io\TopShotElite.h" />
|
<ClInclude Include="Emu\Io\TopShotElite.h" />
|
||||||
<ClInclude Include="Emu\Io\topshotelite_config.h" />
|
<ClInclude Include="Emu\Io\topshotelite_config.h" />
|
||||||
|
<ClInclude Include="Emu\Io\TopShotFearmaster.h" />
|
||||||
|
<ClInclude Include="Emu\Io\topshotfearmaster_config.h" />
|
||||||
<ClInclude Include="Emu\Io\Turntable.h" />
|
<ClInclude Include="Emu\Io\Turntable.h" />
|
||||||
<ClInclude Include="Emu\Io\turntable_config.h" />
|
<ClInclude Include="Emu\Io\turntable_config.h" />
|
||||||
<ClInclude Include="Emu\Io\usio.h" />
|
<ClInclude Include="Emu\Io\usio.h" />
|
||||||
|
|
|
@ -1041,6 +1041,9 @@
|
||||||
<ClCompile Include="Emu\Io\TopShotElite.cpp">
|
<ClCompile Include="Emu\Io\TopShotElite.cpp">
|
||||||
<Filter>Emu\Io</Filter>
|
<Filter>Emu\Io</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="Emu\Io\TopShotFearmaster.cpp">
|
||||||
|
<Filter>Emu\Io</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="Emu\Io\Turntable.cpp">
|
<ClCompile Include="Emu\Io\Turntable.cpp">
|
||||||
<Filter>Emu\Io</Filter>
|
<Filter>Emu\Io</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -2187,6 +2190,9 @@
|
||||||
<ClInclude Include="Emu\Io\TopShotElite.h">
|
<ClInclude Include="Emu\Io\TopShotElite.h">
|
||||||
<Filter>Emu\Io</Filter>
|
<Filter>Emu\Io</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="Emu\Io\TopShotFearmaster.h">
|
||||||
|
<Filter>Emu\Io</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="Emu\Io\Turntable.h">
|
<ClInclude Include="Emu\Io\Turntable.h">
|
||||||
<Filter>Emu\Io</Filter>
|
<Filter>Emu\Io</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
@ -2470,6 +2476,9 @@
|
||||||
<ClInclude Include="Emu\Io\topshotelite_config.h">
|
<ClInclude Include="Emu\Io\topshotelite_config.h">
|
||||||
<Filter>Emu\Io</Filter>
|
<Filter>Emu\Io</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="Emu\Io\topshotfearmaster_config.h">
|
||||||
|
<Filter>Emu\Io</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="Emu\Io\usio_config.h">
|
<ClInclude Include="Emu\Io\usio_config.h">
|
||||||
<Filter>Emu\Io</Filter>
|
<Filter>Emu\Io</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "Emu/Io/ghltar_config.h"
|
#include "Emu/Io/ghltar_config.h"
|
||||||
#include "Emu/Io/guncon3_config.h"
|
#include "Emu/Io/guncon3_config.h"
|
||||||
#include "Emu/Io/topshotelite_config.h"
|
#include "Emu/Io/topshotelite_config.h"
|
||||||
|
#include "Emu/Io/topshotfearmaster_config.h"
|
||||||
#include "Emu/Io/turntable_config.h"
|
#include "Emu/Io/turntable_config.h"
|
||||||
#include "Emu/Io/usio_config.h"
|
#include "Emu/Io/usio_config.h"
|
||||||
#include "util/asm.hpp"
|
#include "util/asm.hpp"
|
||||||
|
@ -95,6 +96,10 @@ emulated_pad_settings_dialog::emulated_pad_settings_dialog(pad_type type, QWidge
|
||||||
setWindowTitle(tr("Configure Emulated Top Shot Elite"));
|
setWindowTitle(tr("Configure Emulated Top Shot Elite"));
|
||||||
add_tabs<topshotelite_btn>(tabs);
|
add_tabs<topshotelite_btn>(tabs);
|
||||||
break;
|
break;
|
||||||
|
case emulated_pad_settings_dialog::pad_type::topshotfearmaster:
|
||||||
|
setWindowTitle(tr("Configure Emulated Top Shot Fearmaster"));
|
||||||
|
add_tabs<topshotfearmaster_btn>(tabs);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
v_layout->addWidget(tabs);
|
v_layout->addWidget(tabs);
|
||||||
|
@ -139,6 +144,9 @@ void emulated_pad_settings_dialog::add_tabs(QTabWidget* tabs)
|
||||||
case pad_type::topshotelite:
|
case pad_type::topshotelite:
|
||||||
players = g_cfg_topshotelite.players.size();
|
players = g_cfg_topshotelite.players.size();
|
||||||
break;
|
break;
|
||||||
|
case pad_type::topshotfearmaster:
|
||||||
|
players = g_cfg_topshotfearmaster.players.size();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_combos.resize(players);
|
m_combos.resize(players);
|
||||||
|
@ -166,7 +174,7 @@ void emulated_pad_settings_dialog::add_tabs(QTabWidget* tabs)
|
||||||
combo->setItemData(index, i, button_role::emulated_button);
|
combo->setItemData(index, i, button_role::emulated_button);
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr (std::is_same_v<T, guncon3_btn> || std::is_same_v<T, topshotelite_btn>)
|
if constexpr (std::is_same_v<T, guncon3_btn> || std::is_same_v<T, topshotelite_btn> || std::is_same_v<T, topshotfearmaster_btn>)
|
||||||
{
|
{
|
||||||
for (int p = static_cast<int>(pad_button::mouse_button_1); p <= static_cast<int>(pad_button::mouse_button_8); p++)
|
for (int p = static_cast<int>(pad_button::mouse_button_1); p <= static_cast<int>(pad_button::mouse_button_8); p++)
|
||||||
{
|
{
|
||||||
|
@ -202,6 +210,9 @@ void emulated_pad_settings_dialog::add_tabs(QTabWidget* tabs)
|
||||||
case pad_type::topshotelite:
|
case pad_type::topshotelite:
|
||||||
saved_btn_id = ::at32(g_cfg_topshotelite.players, player)->get_pad_button(static_cast<topshotelite_btn>(id));
|
saved_btn_id = ::at32(g_cfg_topshotelite.players, player)->get_pad_button(static_cast<topshotelite_btn>(id));
|
||||||
break;
|
break;
|
||||||
|
case pad_type::topshotfearmaster:
|
||||||
|
saved_btn_id = ::at32(g_cfg_topshotfearmaster.players, player)->get_pad_button(static_cast<topshotfearmaster_btn>(id));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
combo->setCurrentIndex(combo->findData(static_cast<int>(saved_btn_id)));
|
combo->setCurrentIndex(combo->findData(static_cast<int>(saved_btn_id)));
|
||||||
|
@ -240,6 +251,9 @@ void emulated_pad_settings_dialog::add_tabs(QTabWidget* tabs)
|
||||||
case pad_type::topshotelite:
|
case pad_type::topshotelite:
|
||||||
::at32(g_cfg_topshotelite.players, player)->set_button(static_cast<topshotelite_btn>(id), btn_id);
|
::at32(g_cfg_topshotelite.players, player)->set_button(static_cast<topshotelite_btn>(id), btn_id);
|
||||||
break;
|
break;
|
||||||
|
case pad_type::topshotfearmaster:
|
||||||
|
::at32(g_cfg_topshotfearmaster.players, player)->set_button(static_cast<topshotfearmaster_btn>(id), btn_id);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -306,6 +320,12 @@ void emulated_pad_settings_dialog::load_config()
|
||||||
cfg_log.notice("Could not load topshotelite config. Using defaults.");
|
cfg_log.notice("Could not load topshotelite config. Using defaults.");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case emulated_pad_settings_dialog::pad_type::topshotfearmaster:
|
||||||
|
if (!g_cfg_topshotfearmaster.load())
|
||||||
|
{
|
||||||
|
cfg_log.notice("Could not load topshotfearmaster config. Using defaults.");
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,6 +354,9 @@ void emulated_pad_settings_dialog::save_config()
|
||||||
case emulated_pad_settings_dialog::pad_type::topshotelite:
|
case emulated_pad_settings_dialog::pad_type::topshotelite:
|
||||||
g_cfg_topshotelite.save();
|
g_cfg_topshotelite.save();
|
||||||
break;
|
break;
|
||||||
|
case emulated_pad_settings_dialog::pad_type::topshotfearmaster:
|
||||||
|
g_cfg_topshotfearmaster.save();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,6 +385,9 @@ void emulated_pad_settings_dialog::reset_config()
|
||||||
case emulated_pad_settings_dialog::pad_type::topshotelite:
|
case emulated_pad_settings_dialog::pad_type::topshotelite:
|
||||||
g_cfg_topshotelite.from_default();
|
g_cfg_topshotelite.from_default();
|
||||||
break;
|
break;
|
||||||
|
case emulated_pad_settings_dialog::pad_type::topshotfearmaster:
|
||||||
|
g_cfg_topshotfearmaster.from_default();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (usz player = 0; player < m_combos.size(); player++)
|
for (usz player = 0; player < m_combos.size(); player++)
|
||||||
|
@ -399,6 +425,9 @@ void emulated_pad_settings_dialog::reset_config()
|
||||||
case pad_type::topshotelite:
|
case pad_type::topshotelite:
|
||||||
def_btn_id = ::at32(g_cfg_topshotelite.players, player)->default_pad_button(static_cast<topshotelite_btn>(data.toInt()));
|
def_btn_id = ::at32(g_cfg_topshotelite.players, player)->default_pad_button(static_cast<topshotelite_btn>(data.toInt()));
|
||||||
break;
|
break;
|
||||||
|
case pad_type::topshotfearmaster:
|
||||||
|
def_btn_id = ::at32(g_cfg_topshotfearmaster.players, player)->default_pad_button(static_cast<topshotfearmaster_btn>(data.toInt()));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
combo->setCurrentIndex(combo->findData(static_cast<int>(def_btn_id)));
|
combo->setCurrentIndex(combo->findData(static_cast<int>(def_btn_id)));
|
||||||
|
|
|
@ -22,6 +22,7 @@ public:
|
||||||
ds3gem,
|
ds3gem,
|
||||||
guncon3,
|
guncon3,
|
||||||
topshotelite,
|
topshotelite,
|
||||||
|
topshotfearmaster,
|
||||||
};
|
};
|
||||||
|
|
||||||
emulated_pad_settings_dialog(pad_type type, QWidget* parent = nullptr);
|
emulated_pad_settings_dialog(pad_type type, QWidget* parent = nullptr);
|
||||||
|
|
|
@ -2784,6 +2784,12 @@ void main_window::CreateConnects()
|
||||||
dlg->show();
|
dlg->show();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
connect(ui->confTopShotFearmasterAct, &QAction::triggered, this, [this]
|
||||||
|
{
|
||||||
|
emulated_pad_settings_dialog* dlg = new emulated_pad_settings_dialog(emulated_pad_settings_dialog::pad_type::topshotfearmaster, this);
|
||||||
|
dlg->show();
|
||||||
|
});
|
||||||
|
|
||||||
connect(ui->actionBasic_Mouse, &QAction::triggered, this, [this]
|
connect(ui->actionBasic_Mouse, &QAction::triggered, this, [this]
|
||||||
{
|
{
|
||||||
basic_mouse_settings_dialog* dlg = new basic_mouse_settings_dialog(this);
|
basic_mouse_settings_dialog* dlg = new basic_mouse_settings_dialog(this);
|
||||||
|
|
|
@ -242,6 +242,7 @@
|
||||||
<addaction name="confPSMoveDS3Act"/>
|
<addaction name="confPSMoveDS3Act"/>
|
||||||
<addaction name="confGunCon3Act"/>
|
<addaction name="confGunCon3Act"/>
|
||||||
<addaction name="confTopShotEliteAct"/>
|
<addaction name="confTopShotEliteAct"/>
|
||||||
|
<addaction name="confTopShotFearmasterAct"/>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QMenu" name="menuMice">
|
<widget class="QMenu" name="menuMice">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
|
@ -1350,6 +1351,11 @@
|
||||||
<string>Top Shot Elite</string>
|
<string>Top Shot Elite</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="confTopShotFearmasterAct">
|
||||||
|
<property name="text">
|
||||||
|
<string>Top Shot Fearmaster</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
<action name="actionBasic_Mouse">
|
<action name="actionBasic_Mouse">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Basic Mouse</string>
|
<string>Basic Mouse</string>
|
||||||
|
|
|
@ -183,6 +183,7 @@ pad_settings_dialog::pad_settings_dialog(std::shared_ptr<gui_settings> gui_setti
|
||||||
ui->chooseClass->addItem(tr("Skateboard"), u32{CELL_PAD_PCLASS_TYPE_SKATEBOARD});
|
ui->chooseClass->addItem(tr("Skateboard"), u32{CELL_PAD_PCLASS_TYPE_SKATEBOARD});
|
||||||
ui->chooseClass->addItem(tr("GunCon 3"), u32{CELL_PAD_FAKE_TYPE_GUNCON3});
|
ui->chooseClass->addItem(tr("GunCon 3"), u32{CELL_PAD_FAKE_TYPE_GUNCON3});
|
||||||
ui->chooseClass->addItem(tr("Top Shot Elite"), u32{CELL_PAD_FAKE_TYPE_TOP_SHOT_ELITE});
|
ui->chooseClass->addItem(tr("Top Shot Elite"), u32{CELL_PAD_FAKE_TYPE_TOP_SHOT_ELITE});
|
||||||
|
ui->chooseClass->addItem(tr("Top Shot Fearmaster"),u32{CELL_PAD_FAKE_TYPE_TOP_SHOT_FEARMASTER});
|
||||||
ui->chooseClass->addItem(tr("uDraw GameTablet"), u32{CELL_PAD_FAKE_TYPE_GAMETABLET});
|
ui->chooseClass->addItem(tr("uDraw GameTablet"), u32{CELL_PAD_FAKE_TYPE_GAMETABLET});
|
||||||
|
|
||||||
connect(ui->chooseClass, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [this](int index)
|
connect(ui->chooseClass, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [this](int index)
|
||||||
|
@ -1731,6 +1732,11 @@ void pad_settings_dialog::HandleDeviceClassChange(u32 class_id) const
|
||||||
ui->chooseProduct->addItem(tr("Top Shot Elite", "Top Shot Elite Controller"), static_cast<int>(product.type));
|
ui->chooseProduct->addItem(tr("Top Shot Elite", "Top Shot Elite Controller"), static_cast<int>(product.type));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case input::product_type::top_shot_fearmaster:
|
||||||
|
{
|
||||||
|
ui->chooseProduct->addItem(tr("Top Shot Fearmaster", "Top Shot Fearmaster Controller"), static_cast<int>(product.type));
|
||||||
|
break;
|
||||||
|
}
|
||||||
case input::product_type::udraw_gametablet:
|
case input::product_type::udraw_gametablet:
|
||||||
{
|
{
|
||||||
ui->chooseProduct->addItem(tr("uDraw GameTablet", "uDraw GameTablet Controller"), static_cast<int>(product.type));
|
ui->chooseProduct->addItem(tr("uDraw GameTablet", "uDraw GameTablet Controller"), static_cast<int>(product.type));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue