Skip to content

Commit

Permalink
cellGem: implement real ps move handler
Browse files Browse the repository at this point in the history
  • Loading branch information
Megamouse committed Jul 19, 2024
1 parent a253426 commit 338ff5a
Show file tree
Hide file tree
Showing 34 changed files with 3,623 additions and 127 deletions.
625 changes: 538 additions & 87 deletions rpcs3/Emu/Cell/Modules/cellGem.cpp

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion rpcs3/Emu/Cell/Modules/cellGem.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,8 @@ enum CellGemVideoConvertFormatEnum : s32
// External device IDs (types)
enum
{
SHARP_SHOOTER_DEVICE_ID = 0x8081
SHARP_SHOOTER_DEVICE_ID = 0x8081,
RACING_WHEEL_DEVICE_ID = 0x8101
};

struct CellGemAttribute
Expand Down
7 changes: 4 additions & 3 deletions rpcs3/Emu/Cell/Modules/cellPad.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,9 +211,10 @@ void clear_pad_buffer(const std::shared_ptr<Pad>& pad)
pad->m_press_triangle = pad->m_press_circle = pad->m_press_cross = pad->m_press_square = 0;
pad->m_press_L1 = pad->m_press_L2 = pad->m_press_R1 = pad->m_press_R2 = 0;

// ~399 on sensor y is a level non moving controller
pad->m_sensor_y = 399;
pad->m_sensor_x = pad->m_sensor_z = pad->m_sensor_g = 512;
pad->m_sensor_x = DEFAULT_MOTION_X;
pad->m_sensor_y = DEFAULT_MOTION_Y;
pad->m_sensor_z = DEFAULT_MOTION_Z;
pad->m_sensor_g = DEFAULT_MOTION_G;
}

error_code cellPadClearBuf(u32 port_no)
Expand Down
28 changes: 24 additions & 4 deletions rpcs3/Emu/Io/PadHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,21 @@ PadHandlerBase::connection PadHandlerBase::get_next_button_press(const std::stri
return status;
}

if (m_type == pad_handler::move)
{
// Keep the pad cached to reduce expensive one time requests
if (!m_pad_for_pad_settings || m_pad_for_pad_settings->m_pad_handler != m_type)
{
const pad_preview_values preview_values{};
m_pad_for_pad_settings = std::make_shared<Pad>(m_type, 0, 0, 0, 0);
m_pad_for_pad_settings->m_sensors.resize(preview_values.size(), AnalogSensor(0, 0, 0, 0, 0));
}

// Get extended device ID
pad_ensemble binding{m_pad_for_pad_settings, device, nullptr};
get_extended_info(binding);
}

// Get the current button values
auto data = get_button_values(device);

Expand Down Expand Up @@ -321,15 +336,20 @@ void PadHandlerBase::get_motion_sensors(const std::string& pad_id, const motion_
return;
}

// Keep the pad cached to reduce expensive one time requests
if (!m_pad_for_pad_settings || m_pad_for_pad_settings->m_pad_handler != m_type)
{
m_pad_for_pad_settings = std::make_shared<Pad>(m_type, 0, 0, 0, 0);
m_pad_for_pad_settings->m_sensors.resize(preview_values.size(), AnalogSensor(0, 0, 0, 0, 0));
}

// Get the current motion values
std::shared_ptr<Pad> pad = std::make_shared<Pad>(m_type, 0, 0, 0, 0);
pad->m_sensors.resize(preview_values.size(), AnalogSensor(0, 0, 0, 0, 0));
pad_ensemble binding{pad, device, nullptr};
pad_ensemble binding{m_pad_for_pad_settings, device, nullptr};
get_extended_info(binding);

for (usz i = 0; i < preview_values.size(); i++)
{
preview_values[i] = pad->m_sensors[i].m_value;
preview_values[i] = m_pad_for_pad_settings->m_sensors[i].m_value;
}

callback(pad_id, std::move(preview_values));
Expand Down
11 changes: 11 additions & 0 deletions rpcs3/Emu/Io/PadHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,15 @@ class PadDevice
std::set<u64> trigger_code_right{};
std::array<std::set<u64>, 4> axis_code_left{};
std::array<std::set<u64>, 4> axis_code_right{};

struct color
{
u8 r{};
u8 g{};
u8 b{};
};
color color_override{};
bool color_override_active{};
};

struct pad_ensemble
Expand Down Expand Up @@ -134,6 +143,8 @@ class PadHandlerBase
std::unordered_map<u32, std::string> button_list;
std::set<u32> blacklist;

std::shared_ptr<Pad> m_pad_for_pad_settings;

static std::set<u32> narrow_set(const std::set<u64>& src);

// Search an unordered map for a string value and return found keycode
Expand Down
7 changes: 7 additions & 0 deletions rpcs3/Emu/Io/camera_handler_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ class camera_handler_base

camera_handler_state get_state() const { return m_state.load(); };

bool mirrored() const { return m_mirrored; };
s32 format() const { return m_format; };
u32 bytesize() const { return m_bytesize; };
u32 width() const { return m_width; };
u32 height() const { return m_height; };
u32 frame_rate() const { return m_frame_rate; };

protected:
std::mutex m_mutex;
atomic_t<camera_handler_state> m_state = camera_handler_state::closed;
Expand Down
28 changes: 24 additions & 4 deletions rpcs3/Emu/Io/gem_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ enum class gem_btn
count
};

struct cfg_gem final : public emulated_pad_config<gem_btn>
struct cfg_fake_gem final : public emulated_pad_config<gem_btn>
{
cfg_gem(node* owner, const std::string& name) : emulated_pad_config(owner, name) {}
cfg_fake_gem(node* owner, const std::string& name) : emulated_pad_config(owner, name) {}

cfg_pad_btn<gem_btn> start{ this, "Start", gem_btn::start, pad_button::start };
cfg_pad_btn<gem_btn> select{ this, "Select", gem_btn::select, pad_button::select };
Expand All @@ -36,9 +36,29 @@ struct cfg_gem final : public emulated_pad_config<gem_btn>
cfg_pad_btn<gem_btn> y_axis{ this, "Y-Axis", gem_btn::y_axis, pad_button::ls_y };
};

struct cfg_fake_gems final : public emulated_pads_config<cfg_fake_gem, 4>
{
cfg_fake_gems() : emulated_pads_config<cfg_fake_gem, 4>("gem") {};
};

struct cfg_gem final : public emulated_pad_config<gem_btn>
{
cfg_gem(node* owner, const std::string& name) : emulated_pad_config(owner, name) {}

cfg_pad_btn<gem_btn> start{ this, "Start", gem_btn::start, pad_button::start };
cfg_pad_btn<gem_btn> select{ this, "Select", gem_btn::select, pad_button::select };
cfg_pad_btn<gem_btn> triangle{ this, "Triangle", gem_btn::triangle, pad_button::triangle };
cfg_pad_btn<gem_btn> circle{ this, "Circle", gem_btn::circle, pad_button::circle };
cfg_pad_btn<gem_btn> cross{ this, "Cross", gem_btn::cross, pad_button::cross };
cfg_pad_btn<gem_btn> square{ this, "Square", gem_btn::square, pad_button::square };
cfg_pad_btn<gem_btn> move{ this, "Move", gem_btn::move, pad_button::R1 };
cfg_pad_btn<gem_btn> t{ this, "T", gem_btn::t, pad_button::R2 };
};

struct cfg_gems final : public emulated_pads_config<cfg_gem, 4>
{
cfg_gems() : emulated_pads_config<cfg_gem, 4>("gem") {};
cfg_gems() : emulated_pads_config<cfg_gem, 4>("gem_real") {};
};

extern cfg_gems g_cfg_gem;
extern cfg_gems g_cfg_gem_real;
extern cfg_fake_gems g_cfg_gem_fake;
1 change: 1 addition & 0 deletions rpcs3/Emu/Io/pad_config_types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ void fmt_class_string<pad_handler>::format(std::string& out, u64 arg)
case pad_handler::ds4: return "DualShock 4";
case pad_handler::dualsense: return "DualSense";
case pad_handler::skateboard: return "Skateboard";
case pad_handler::move: return "PS Move";
#ifdef _WIN32
case pad_handler::xinput: return "XInput";
case pad_handler::mm: return "MMJoystick";
Expand Down
1 change: 1 addition & 0 deletions rpcs3/Emu/Io/pad_config_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ enum class pad_handler
ds4,
dualsense,
skateboard,
move,
#ifdef _WIN32
xinput,
mm,
Expand Down
25 changes: 23 additions & 2 deletions rpcs3/Emu/Io/pad_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -334,8 +334,9 @@ struct CellPadData
be_t<u16> button[CELL_PAD_MAX_CODES];
};

static constexpr u16 MOTION_ONE_G = 113;
static constexpr u16 DEFAULT_MOTION_X = 512;
static constexpr u16 DEFAULT_MOTION_Y = 399;
static constexpr u16 DEFAULT_MOTION_Y = 399; // 512 - 113 (113 is 1G gravity)
static constexpr u16 DEFAULT_MOTION_Z = 512;
static constexpr u16 DEFAULT_MOTION_G = 512;

Expand Down Expand Up @@ -449,6 +450,25 @@ struct VibrateMotor
{}
};

struct ps_move_data
{
bool external_device_connected = false;
u32 external_device_id = 0;
std::array<u8, 5> external_device_data{};
std::array<u8, 38> external_device_read{}; // CELL_GEM_EXTERNAL_PORT_DEVICE_INFO_SIZE
std::array<u8, 40> external_device_write{}; // CELL_GEM_EXTERNAL_PORT_OUTPUT_SIZE
bool external_device_read_requested = false;
bool external_device_write_requested = false;

s16 accelerometer_x = 0;
s16 accelerometer_y = 0;
s16 accelerometer_z = 0;
s16 gyro_x = 0;
s16 gyro_y = 0;
s16 gyro_z = 0;
s16 temperature = 0;
};

struct Pad
{
const pad_handler m_pad_handler;
Expand Down Expand Up @@ -507,7 +527,6 @@ struct Pad
u16 m_press_R2{0};

// Except for these...0-1023
// ~399 on sensor y is a level non moving controller
u16 m_sensor_x{DEFAULT_MOTION_X};
u16 m_sensor_y{DEFAULT_MOTION_Y};
u16 m_sensor_z{DEFAULT_MOTION_Z};
Expand All @@ -518,6 +537,8 @@ struct Pad

bool is_fake_pad = false;

ps_move_data move_data{};

explicit Pad(pad_handler handler, u32 player_id, u32 port_status, u32 device_capability, u32 device_type)
: m_pad_handler(handler)
, m_player_id(player_id)
Expand Down
1 change: 1 addition & 0 deletions rpcs3/Emu/system_config_types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,7 @@ void fmt_class_string<move_handler>::format(std::string& out, u64 arg)
switch (value)
{
case move_handler::null: return "Null";
case move_handler::real: return "Real";
case move_handler::fake: return "Fake";
case move_handler::mouse: return "Mouse";
case move_handler::raw_mouse: return "Raw Mouse";
Expand Down
1 change: 1 addition & 0 deletions rpcs3/Emu/system_config_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ enum class fake_camera_type
enum class move_handler
{
null,
real,
fake,
mouse,
raw_mouse,
Expand Down
1 change: 1 addition & 0 deletions rpcs3/Input/gui_pad_thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ std::shared_ptr<PadHandlerBase> gui_pad_thread::GetHandler(pad_handler type)
{
case pad_handler::null:
case pad_handler::keyboard:
case pad_handler::move:
// Makes no sense to use this if we are in the GUI anyway
return nullptr;
case pad_handler::ds3:
Expand Down
59 changes: 54 additions & 5 deletions rpcs3/Input/hid_pad_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "ds4_pad_handler.h"
#include "dualsense_pad_handler.h"
#include "skateboard_pad_handler.h"
#include "ps_move_handler.h"
#include "util/logs.hpp"
#include "Utilities/Timer.h"
#include "Emu/System.h"
Expand All @@ -27,6 +28,13 @@ void HidDevice::close()
hid_close(hidDevice);
hidDevice = nullptr;
}
#ifdef _WIN32
if (bt_device)
{
hid_close(bt_device);
bt_device = nullptr;
}
#endif
}

template <class Device>
Expand Down Expand Up @@ -149,9 +157,19 @@ void hid_pad_handler<Device>::enumerate_devices()
hid_log.error("Skipping enumeration of device with empty path.");
continue;
}
device_paths.insert(dev_info->path);
serials[dev_info->path] = dev_info->serial_number ? std::wstring(dev_info->serial_number) : std::wstring();
dev_info = dev_info->next;

const std::string path = dev_info->path;
device_paths.insert(path);

#ifdef _WIN32
// Only add serials for col01 ps move device
if (m_type == pad_handler::move && path.find("&Col01#") != umax)
#endif
{
serials[path] = dev_info->serial_number ? std::wstring(dev_info->serial_number) : std::wstring();
}

dev_info = dev_info->next;
}
hid_free_enumeration(head);
}
Expand All @@ -160,6 +178,29 @@ void hid_pad_handler<Device>::enumerate_devices()
std::lock_guard lock(m_enumeration_mutex);
m_new_enumerated_devices = device_paths;
m_enumerated_serials = std::move(serials);

#ifdef _WIN32
if (m_type == pad_handler::move)
{
// Windows enumerates 3 ps move devices: Col01, Col02, and Col03.
// We use Col01 for data and Col02 for bluetooth.

// Filter paths. We only want the Col01 paths.
std::set<std::string> col01_paths;

for (const std::string& path : m_new_enumerated_devices)
{
hid_log.trace("Found ps move device: %s", path);

if (path.find("&Col01#") != umax)
{
col01_paths.insert(path);
}
}

m_new_enumerated_devices = std::move(col01_paths);
}
#endif
}

template <class Device>
Expand Down Expand Up @@ -199,8 +240,15 @@ void hid_pad_handler<Device>::update_devices()
if (std::any_of(m_controllers.cbegin(), m_controllers.cend(), [&path](const auto& c) { return c.second && c.second->path == path; }))
continue;

hid_device* dev = hid_open_path(path.c_str());
if (dev)
#ifdef _WIN32
if (m_type == pad_handler::move)
{
check_add_device(nullptr, path, m_enumerated_serials[path]);
continue;
}
#endif

if (hid_device* dev = hid_open_path(path.c_str()))
{
if (const hid_device_info* info = hid_get_device_info(dev))
{
Expand Down Expand Up @@ -278,3 +326,4 @@ template class hid_pad_handler<ds3_device>;
template class hid_pad_handler<DS4Device>;
template class hid_pad_handler<DualSenseDevice>;
template class hid_pad_handler<skateboard_device>;
template class hid_pad_handler<ps_move_device>;
3 changes: 3 additions & 0 deletions rpcs3/Input/hid_pad_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ class HidDevice : public PadDevice
void close();

hid_device* hidDevice{nullptr};
#ifdef _WIN32
hid_device* bt_device{nullptr}; // Used in ps move handler
#endif
std::string path;
bool new_output_data{true};
bool enable_player_leds{false};
Expand Down
5 changes: 4 additions & 1 deletion rpcs3/Input/pad_thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "ds4_pad_handler.h"
#include "dualsense_pad_handler.h"
#include "skateboard_pad_handler.h"
#include "ps_move_handler.h"
#ifdef _WIN32
#include "xinput_pad_handler.h"
#include "mm_joystick_handler.h"
Expand Down Expand Up @@ -190,7 +191,7 @@ void pad_thread::Init()
i, cfg->device.to_string(), m_pads[i]->m_pad_handler, m_pads[i]->m_vendor_id, m_pads[i]->m_product_id, m_pads[i]->m_class_type, m_pads[i]->m_class_profile);
}

m_pads[i]->is_fake_pad = (g_cfg.io.move == move_handler::fake && i >= (static_cast<u32>(CELL_PAD_MAX_PORT_NUM) - static_cast<u32>(CELL_GEM_MAX_NUM)))
m_pads[i]->is_fake_pad = ((g_cfg.io.move == move_handler::real || g_cfg.io.move == move_handler::fake) && i >= (static_cast<u32>(CELL_PAD_MAX_PORT_NUM) - static_cast<u32>(CELL_GEM_MAX_NUM)))
|| (m_pads[i]->m_class_type >= CELL_PAD_FAKE_TYPE_FIRST && m_pads[i]->m_class_type < CELL_PAD_FAKE_TYPE_LAST);
connect_usb_controller(i, input::get_product_by_vid_pid(m_pads[i]->m_vendor_id, m_pads[i]->m_product_id));
}
Expand Down Expand Up @@ -614,6 +615,8 @@ std::shared_ptr<PadHandlerBase> pad_thread::GetHandler(pad_handler type)
return std::make_shared<dualsense_pad_handler>();
case pad_handler::skateboard:
return std::make_shared<skateboard_pad_handler>();
case pad_handler::move:
return std::make_shared<ps_move_handler>();
#ifdef _WIN32
case pad_handler::xinput:
return std::make_shared<xinput_pad_handler>();
Expand Down
Loading

0 comments on commit 338ff5a

Please sign in to comment.