mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-01-30 12:32:43 +00:00
cellGem: Allow to use multiple controllers as fake PS-Move
- Allows to use the last 4 ports/players as PS Move in fake mode - Should in theory react to re/disconnected controllers - Should allow to use player 1-3 as normal controller simultaneously
This commit is contained in:
parent
d5ce4e0f6b
commit
dda0b8af45
@ -114,6 +114,20 @@ void fmt_class_string<CellGemVideoConvertFormatEnum>::format(std::string& out, u
|
||||
});
|
||||
}
|
||||
|
||||
// last 4 out of 7 ports (7,6,5,4). index starts at 1
|
||||
static u32 port_num(u32 gem_num)
|
||||
{
|
||||
ensure(gem_num < CELL_GEM_MAX_NUM);
|
||||
return CELL_PAD_MAX_PORT_NUM - gem_num;
|
||||
}
|
||||
|
||||
// last 4 out of 7 ports (6,5,4,3). index starts at 0
|
||||
static u32 pad_num(u32 gem_num)
|
||||
{
|
||||
ensure(gem_num < CELL_GEM_MAX_NUM);
|
||||
return (CELL_PAD_MAX_PORT_NUM - 1) - gem_num;
|
||||
}
|
||||
|
||||
// **********************
|
||||
// * HLE helper structs *
|
||||
// **********************
|
||||
@ -278,12 +292,38 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
bool is_connected = false;
|
||||
|
||||
switch (g_cfg.io.move)
|
||||
{
|
||||
case move_handler::fake:
|
||||
{
|
||||
connected_controllers = 0;
|
||||
std::lock_guard lock(pad::g_pad_mutex);
|
||||
const auto handler = pad::get_current_handler();
|
||||
for (u32 i = 0; i < std::min<u32>(attribute.max_connect, CELL_GEM_MAX_NUM); i++)
|
||||
{
|
||||
const auto& pad = ::at32(handler->GetPads(), pad_num(i));
|
||||
if (pad && (pad->m_port_status & CELL_PAD_STATUS_CONNECTED))
|
||||
{
|
||||
connected_controllers++;
|
||||
|
||||
if (gem_num == i)
|
||||
{
|
||||
is_connected = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case move_handler::mouse:
|
||||
{
|
||||
connected_controllers = 1;
|
||||
|
||||
if (gem_num == 0)
|
||||
{
|
||||
is_connected = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#ifdef HAVE_LIBEVDEV
|
||||
@ -291,8 +331,13 @@ public:
|
||||
{
|
||||
gun_thread& gun = g_fxo->get<gun_thread>();
|
||||
std::scoped_lock lock(gun.handler.mutex);
|
||||
connected_controllers = gun.handler.init() ? gun.handler.get_num_guns() : 0;
|
||||
gun.num_devices = connected_controllers;
|
||||
gun.num_devices = gun.handler.init() ? gun.handler.get_num_guns() : 0;
|
||||
connected_controllers = std::min<u32>(std::min<u32>(attribute.max_connect, CELL_GEM_MAX_NUM), gun.num_devices);
|
||||
|
||||
if (gem_num < connected_controllers)
|
||||
{
|
||||
is_connected = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
@ -306,10 +351,10 @@ public:
|
||||
controller.sphere_rgb = gem_color::get_default_color(gem_num);
|
||||
|
||||
// Assign status and port number
|
||||
if (gem_num < connected_controllers)
|
||||
if (is_connected)
|
||||
{
|
||||
controller.status = CELL_GEM_STATUS_READY;
|
||||
controller.port = CELL_PAD_MAX_PORT_NUM - gem_num;
|
||||
controller.port = port_num(gem_num);
|
||||
}
|
||||
}
|
||||
|
||||
@ -638,12 +683,12 @@ extern bool is_input_allowed();
|
||||
/**
|
||||
* \brief Maps Move controller data (digital buttons, and analog Trigger data) to DS3 pad input.
|
||||
* Unavoidably buttons conflict with DS3 mappings, which is problematic for some games.
|
||||
* \param port_no DS3 port number to use
|
||||
* \param gem_num gem index to use
|
||||
* \param digital_buttons Bitmask filled with CELL_GEM_CTRL_* values
|
||||
* \param analog_t Analog value of Move's Trigger. Currently mapped to R2.
|
||||
* \return true on success, false if port_no controller is invalid
|
||||
* \return true on success, false if controller is disconnected
|
||||
*/
|
||||
static void ds3_input_to_pad(const u32 port_no, be_t<u16>& digital_buttons, be_t<u16>& analog_t)
|
||||
static void ds3_input_to_pad(const u32 gem_num, be_t<u16>& digital_buttons, be_t<u16>& analog_t)
|
||||
{
|
||||
digital_buttons = 0;
|
||||
analog_t = 0;
|
||||
@ -656,14 +701,14 @@ static void ds3_input_to_pad(const u32 port_no, be_t<u16>& digital_buttons, be_t
|
||||
std::lock_guard lock(pad::g_pad_mutex);
|
||||
|
||||
const auto handler = pad::get_current_handler();
|
||||
const auto& pad = ::at32(handler->GetPads(), port_no);
|
||||
const auto& pad = ::at32(handler->GetPads(), pad_num(gem_num));
|
||||
|
||||
if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& cfg = ::at32(g_cfg_gem.players, port_no);
|
||||
const auto& cfg = ::at32(g_cfg_gem.players, gem_num);
|
||||
cfg->handle_input(pad, true, [&](gem_btn btn, u16 value, bool pressed)
|
||||
{
|
||||
if (!pressed)
|
||||
@ -707,12 +752,12 @@ static void ds3_input_to_pad(const u32 port_no, be_t<u16>& digital_buttons, be_t
|
||||
constexpr u16 ds3_max_x = 255;
|
||||
constexpr u16 ds3_max_y = 255;
|
||||
|
||||
static inline void ds3_get_stick_values(u32 port_no, const std::shared_ptr<Pad>& pad, s32& x_pos, s32& y_pos)
|
||||
static inline void ds3_get_stick_values(u32 gem_num, const std::shared_ptr<Pad>& pad, s32& x_pos, s32& y_pos)
|
||||
{
|
||||
x_pos = 0;
|
||||
y_pos = 0;
|
||||
|
||||
const auto& cfg = ::at32(g_cfg_gem.players, port_no);
|
||||
const auto& cfg = ::at32(g_cfg_gem.players, gem_num);
|
||||
cfg->handle_input(pad, true, [&](gem_btn btn, u16 value, bool pressed)
|
||||
{
|
||||
if (!pressed)
|
||||
@ -733,7 +778,7 @@ static inline void ds3_get_stick_values(u32 port_no, const std::shared_ptr<Pad>&
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void ds3_pos_to_gem_state(const u32 port_no, const gem_config::gem_controller& controller, T& gem_state)
|
||||
static void ds3_pos_to_gem_state(u32 gem_num, const gem_config::gem_controller& controller, T& gem_state)
|
||||
{
|
||||
if (!gem_state || !is_input_allowed())
|
||||
{
|
||||
@ -743,7 +788,7 @@ static void ds3_pos_to_gem_state(const u32 port_no, const gem_config::gem_contro
|
||||
std::lock_guard lock(pad::g_pad_mutex);
|
||||
|
||||
const auto handler = pad::get_current_handler();
|
||||
const auto& pad = ::at32(handler->GetPads(), port_no);
|
||||
const auto& pad = ::at32(handler->GetPads(), pad_num(gem_num));
|
||||
|
||||
if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED))
|
||||
{
|
||||
@ -751,15 +796,15 @@ static void ds3_pos_to_gem_state(const u32 port_no, const gem_config::gem_contro
|
||||
}
|
||||
|
||||
s32 ds3_pos_x, ds3_pos_y;
|
||||
ds3_get_stick_values(port_no, pad, ds3_pos_x, ds3_pos_y);
|
||||
ds3_get_stick_values(gem_num, pad, ds3_pos_x, ds3_pos_y);
|
||||
|
||||
if constexpr (std::is_same<T, vm::ptr<CellGemState>>::value)
|
||||
{
|
||||
pos_to_gem_state(port_no, controller, gem_state, ds3_pos_x, ds3_pos_y, ds3_max_x, ds3_max_y);
|
||||
pos_to_gem_state(gem_num, controller, gem_state, ds3_pos_x, ds3_pos_y, ds3_max_x, ds3_max_y);
|
||||
}
|
||||
else if constexpr (std::is_same<T, vm::ptr<CellGemImageState>>::value)
|
||||
{
|
||||
pos_to_gem_image_state(port_no, controller, gem_state, ds3_pos_x, ds3_pos_y, ds3_max_x, ds3_max_y);
|
||||
pos_to_gem_image_state(gem_num, controller, gem_state, ds3_pos_x, ds3_pos_y, ds3_max_x, ds3_max_y);
|
||||
}
|
||||
}
|
||||
|
||||
@ -767,11 +812,11 @@ static void ds3_pos_to_gem_state(const u32 port_no, const gem_config::gem_contro
|
||||
* \brief Maps external Move controller data to DS3 input. (This can be input from any physical pad, not just the DS3)
|
||||
* Implementation detail: CellGemExtPortData's digital/analog fields map the same way as
|
||||
* libPad, so no translation is needed.
|
||||
* \param port_no DS3 port number to use
|
||||
* \param gem_num gem index to use
|
||||
* \param ext External data to modify
|
||||
* \return true on success, false if port_no controller is invalid
|
||||
* \return true on success, false if controller is disconnected
|
||||
*/
|
||||
static void ds3_input_to_ext(const u32 port_no, const gem_config::gem_controller& controller, CellGemExtPortData& ext)
|
||||
static void ds3_input_to_ext(const u32 gem_num, const gem_config::gem_controller& controller, CellGemExtPortData& ext)
|
||||
{
|
||||
ext = {};
|
||||
|
||||
@ -783,7 +828,7 @@ static void ds3_input_to_ext(const u32 port_no, const gem_config::gem_controller
|
||||
std::lock_guard lock(pad::g_pad_mutex);
|
||||
|
||||
const auto handler = pad::get_current_handler();
|
||||
const auto& pad = ::at32(handler->GetPads(), port_no);
|
||||
const auto& pad = ::at32(handler->GetPads(), pad_num(gem_num));
|
||||
|
||||
if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED))
|
||||
{
|
||||
@ -1460,6 +1505,33 @@ error_code cellGemGetInfo(vm::ptr<CellGemInfo> info)
|
||||
}
|
||||
|
||||
// TODO: Support connecting PlayStation Move controllers
|
||||
|
||||
if (g_cfg.io.move == move_handler::fake)
|
||||
{
|
||||
gem.connected_controllers = 0;
|
||||
|
||||
std::lock_guard lock(pad::g_pad_mutex);
|
||||
const auto handler = pad::get_current_handler();
|
||||
|
||||
for (u32 i = 0; i < CELL_GEM_MAX_NUM; i++)
|
||||
{
|
||||
const auto& pad = ::at32(handler->GetPads(), pad_num(i));
|
||||
const bool connected = (pad && (pad->m_port_status & CELL_PAD_STATUS_CONNECTED) && i < gem.attribute.max_connect);
|
||||
|
||||
if (connected)
|
||||
{
|
||||
gem.connected_controllers++;
|
||||
gem.controllers[i].status = CELL_GEM_STATUS_READY;
|
||||
gem.controllers[i].port = port_num(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
gem.controllers[i].status = CELL_GEM_STATUS_DISCONNECTED;
|
||||
gem.controllers[i].port = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
info->max_connect = gem.attribute.max_connect;
|
||||
info->now_connect = gem.connected_controllers;
|
||||
|
||||
|
@ -36,9 +36,9 @@ 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_gems final : public emulated_pads_config<cfg_gem, 7>
|
||||
struct cfg_gems final : public emulated_pads_config<cfg_gem, 4>
|
||||
{
|
||||
cfg_gems() : emulated_pads_config<cfg_gem, 7>("gem") {};
|
||||
cfg_gems() : emulated_pads_config<cfg_gem, 4>("gem") {};
|
||||
};
|
||||
|
||||
extern cfg_gems g_cfg_gem;
|
||||
|
Loading…
x
Reference in New Issue
Block a user