Qt/input/cellpad: enable product choice

This commit is contained in:
Megamouse 2020-04-24 22:49:36 +02:00
parent 256c74def2
commit 4e6d95c5b8
12 changed files with 306 additions and 43 deletions

View File

@ -5,6 +5,7 @@
#include "Emu/Io/pad_types.h"
#include "Input/pad_thread.h"
#include "Input/product_info.h"
#include "cellPad.h"
LOG_CHANNEL(sys_io);
@ -636,43 +637,40 @@ error_code cellPadGetInfo(vm::ptr<CellPadInfo> info)
pads[i]->m_port_status &= ~CELL_PAD_STATUS_ASSIGN_CHANGES; // TODO: should ASSIGN flags be cleared here?
info->status[i] = pads[i]->m_port_status;
// TODO: Allow selecting different product IDs
switch (pads[i]->m_class_type)
if (pads[i]->m_vendor_id == 0 || pads[i]->m_product_id == 0)
{
case CELL_PAD_PCLASS_TYPE_GUITAR:
// Sony Computer Entertainment America
info->vendor_id[i] = 0x12BA;
// RedOctane Guitar (Guitar Hero)
info->product_id[i] = 0x0100;
// Harmonix Guitar (Rock Band)
// info->product_id[i] = 0x0200;
break;
case CELL_PAD_PCLASS_TYPE_DRUM:
// Sony Computer Entertainment America
info->vendor_id[i] = 0x12BA;
// RedOctane Drum Kit (Guitar Hero)
info->product_id[i] = 0x0120;
// Harmonix Drum Kit (Rock Band)
// info->product_id[i] = 0x0210;
break;
case CELL_PAD_PCLASS_TYPE_DJ:
// Sony Computer Entertainment America
info->vendor_id[i] = 0x12BA;
// DJ Hero Turntable
info->product_id[i] = 0x0140;
break;
case CELL_PAD_PCLASS_TYPE_DANCEMAT:
// Konami Digital Entertainment
info->vendor_id[i] = 0x1CCF;
// Dance Dance Revolution Mat
info->product_id[i] = 0x0140;
break;
default:
// Sony Corp.
info->vendor_id[i] = 0x054C;
// PlayStation 3 Controller
info->product_id[i] = 0x0268;
break;
// Fallback to defaults
input::product_info product;
switch (pads[i]->m_class_type)
{
case CELL_PAD_PCLASS_TYPE_GUITAR:
product = input::get_product_info(input::product_type::red_octane_gh_guitar);
break;
case CELL_PAD_PCLASS_TYPE_DRUM:
product = input::get_product_info(input::product_type::red_octane_gh_drum_kit);
break;
case CELL_PAD_PCLASS_TYPE_DJ:
product = input::get_product_info(input::product_type::dj_hero_turntable);
break;
case CELL_PAD_PCLASS_TYPE_DANCEMAT:
product = input::get_product_info(input::product_type::dance_dance_revolution_mat);
break;
case CELL_PAD_PCLASS_TYPE_NAVIGATION:
case CELL_PAD_PCLASS_TYPE_STANDARD:
default:
product = input::get_product_info(input::product_type::playstation_3_controller);
break;
}
info->vendor_id[i] = product.vendor_id;
info->product_id[i] = product.product_id;
}
else
{
info->vendor_id[i] = pads[i]->m_vendor_id;
info->product_id[i] = pads[i]->m_product_id;
}
}
@ -927,8 +925,18 @@ error_code cellPadLddRegisterController()
if (handle < 0)
return CELL_PAD_ERROR_TOO_MANY_DEVICES;
const auto product = input::get_product_info(input::product_type::playstation_3_controller);
auto& pads = handler->GetPads();
pads[handle]->Init(CELL_PAD_STATUS_CONNECTED | CELL_PAD_STATUS_ASSIGN_CHANGES | CELL_PAD_STATUS_CUSTOM_CONTROLLER, CELL_PAD_CAPABILITY_PS3_CONFORMITY, CELL_PAD_DEV_TYPE_LDD, 0);
pads[handle]->Init
(
CELL_PAD_STATUS_CONNECTED | CELL_PAD_STATUS_ASSIGN_CHANGES | CELL_PAD_STATUS_CUSTOM_CONTROLLER,
CELL_PAD_CAPABILITY_PS3_CONFORMITY,
CELL_PAD_DEV_TYPE_LDD,
CELL_PAD_PCLASS_TYPE_STANDARD,
product.vendor_id,
product.product_id
);
config->port_setting[handle] = 0;
return not_an_error(handle);

View File

@ -434,7 +434,9 @@ bool PadHandlerBase::bindPadToDevice(std::shared_ptr<Pad> pad, const std::string
CELL_PAD_STATUS_DISCONNECTED,
CELL_PAD_CAPABILITY_PS3_CONFORMITY | CELL_PAD_CAPABILITY_PRESS_MODE | CELL_PAD_CAPABILITY_HP_ANALOG_STICK | CELL_PAD_CAPABILITY_ACTUATOR | CELL_PAD_CAPABILITY_SENSOR_MODE,
CELL_PAD_DEV_TYPE_STANDARD,
profile->device_class_type
profile->device_class_type,
profile->vendor_id,
profile->product_id
);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, mapping[button::up], CELL_PAD_CTRL_UP);

View File

@ -94,6 +94,8 @@ struct pad_config final : cfg::node
cfg::_int<0, 100> trigger_lerp_factor{ this, "Trigger Lerp Factor", 100 };
cfg::_int<0, 5> device_class_type{ this, "Device Class Type", 0 };
cfg::_int<0, 65535> vendor_id{ this, "Vendor ID", 0 };
cfg::_int<0, 65535> product_id{ this, "Product ID", 0 };
bool exist();
bool load();

View File

@ -181,6 +181,9 @@ struct Pad
u32 m_device_type;
u32 m_class_type;
u16 m_vendor_id;
u16 m_product_id;
// Cable State: 0 - 1 plugged in ?
u8 m_cable_state;
@ -226,12 +229,14 @@ struct Pad
bool ldd = false;
u8 ldd_data[132] = {};
void Init(u32 port_status, u32 device_capability, u32 device_type, u32 class_type)
void Init(u32 port_status, u32 device_capability, u32 device_type, u32 class_type, u16 vendor_id, u16 product_id)
{
m_port_status = port_status;
m_device_capability = device_capability;
m_device_type = device_type;
m_class_type = class_type;
m_vendor_id = vendor_id;
m_product_id = product_id;
}
Pad(u32 port_status, u32 device_capability, u32 device_type)
@ -240,6 +245,8 @@ struct Pad
, m_device_capability(device_capability)
, m_device_type(device_type)
, m_class_type(0)
, m_vendor_id(0)
, m_product_id(0)
, m_cable_state(0)
, m_battery_level(0)

View File

@ -927,7 +927,9 @@ bool evdev_joystick_handler::bindPadToDevice(std::shared_ptr<Pad> pad, const std
CELL_PAD_STATUS_DISCONNECTED,
CELL_PAD_CAPABILITY_PS3_CONFORMITY | CELL_PAD_CAPABILITY_PRESS_MODE | CELL_PAD_CAPABILITY_HP_ANALOG_STICK | CELL_PAD_CAPABILITY_ACTUATOR | CELL_PAD_CAPABILITY_SENSOR_MODE,
CELL_PAD_DEV_TYPE_STANDARD,
p_profile->device_class_type
p_profile->device_class_type,
p_profile->vendor_id,
p_profile->product_id
);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL2, find_key(p_profile->triangle), CELL_PAD_CTRL_TRIANGLE);

View File

@ -612,7 +612,9 @@ bool keyboard_pad_handler::bindPadToDevice(std::shared_ptr<Pad> pad, const std::
CELL_PAD_STATUS_DISCONNECTED,
CELL_PAD_CAPABILITY_PS3_CONFORMITY | CELL_PAD_CAPABILITY_PRESS_MODE | CELL_PAD_CAPABILITY_HP_ANALOG_STICK | CELL_PAD_CAPABILITY_ACTUATOR | CELL_PAD_CAPABILITY_SENSOR_MODE,
CELL_PAD_DEV_TYPE_STANDARD,
p_profile->device_class_type
p_profile->device_class_type,
p_profile->vendor_id,
p_profile->product_id
);
pad->m_buttons.emplace_back(CELL_PAD_BTN_OFFSET_DIGITAL1, find_key(p_profile->left), CELL_PAD_CTRL_LEFT);

130
rpcs3/Input/product_info.h Normal file
View File

@ -0,0 +1,130 @@
#pragma once
#include <vector>
namespace input
{
enum class product_type
{
playstation_3_controller,
red_octane_gh_guitar,
red_octane_gh_drum_kit,
dance_dance_revolution_mat,
dj_hero_turntable,
harmonix_rockband_guitar,
harmonix_rockband_drum_kit,
};
enum vendor_id
{
sony_corp = 0x054C, // Sony Corp.
sony_cea = 0x12BA, // Sony Computer Entertainment America
konami_de = 0x1CCF, // Konami Digital Entertainment
};
enum product_id
{
red_octane_gh_guitar = 0x0100, // RedOctane Guitar (Guitar Hero)
red_octane_gh_drum_kit = 0x0120, // RedOctane Drum Kit (Guitar Hero)
dance_dance_revolution_mat = 0x0140, // Dance Dance Revolution Mat
dj_hero_turntable = 0x0140, // DJ Hero Turntable
harmonix_rockband_guitar = 0x0200, // Harmonix Guitar (Rock Band)
harmonix_rockband_drum_kit = 0x0210, // Harmonix Drum Kit (Rock Band)
playstation_3_controller = 0x0268, // PlayStation 3 Controller
};
struct product_info
{
product_type type;
uint16_t vendor_id;
uint16_t product_id;
};
static product_info get_product_info(product_type type)
{
switch (type)
{
default:
case product_type::playstation_3_controller:
{
return product_info{ type, vendor_id::sony_corp, product_id::playstation_3_controller };
}
case product_type::dance_dance_revolution_mat:
{
return product_info{ type, vendor_id::konami_de, product_id::dance_dance_revolution_mat };
}
case product_type::dj_hero_turntable:
{
return product_info{ type, vendor_id::sony_cea, product_id::dj_hero_turntable };
}
case product_type::harmonix_rockband_drum_kit:
{
return product_info{ type, vendor_id::sony_cea, product_id::harmonix_rockband_drum_kit };
}
case product_type::harmonix_rockband_guitar:
{
return product_info{ type, vendor_id::sony_cea, product_id::harmonix_rockband_guitar };
}
case product_type::red_octane_gh_drum_kit:
{
return product_info{ type, vendor_id::sony_cea, product_id::red_octane_gh_drum_kit };
}
case product_type::red_octane_gh_guitar:
{
return product_info{ type, vendor_id::sony_cea, product_id::red_octane_gh_guitar };
}
}
}
static std::vector<product_info> get_products_by_class(int class_id)
{
switch (class_id)
{
default:
case 0: // CELL_PAD_PCLASS_TYPE_STANDARD
{
return
{
get_product_info(product_type::playstation_3_controller)
};
}
case 1: // CELL_PAD_PCLASS_TYPE_GUITAR
{
return
{
get_product_info(product_type::red_octane_gh_guitar),
get_product_info(product_type::harmonix_rockband_guitar)
};
}
case 2: // CELL_PAD_PCLASS_TYPE_DRUM
{
return
{
get_product_info(product_type::red_octane_gh_drum_kit),
get_product_info(product_type::harmonix_rockband_drum_kit)
};
}
case 3: // CELL_PAD_PCLASS_TYPE_DJ
{
return
{
get_product_info(product_type::dj_hero_turntable)
};
}
case 4: // CELL_PAD_PCLASS_TYPE_DANCEMAT
{
return
{
get_product_info(product_type::dance_dance_revolution_mat)
};
}
case 5: // CELL_PAD_PCLASS_TYPE_NAVIGATION
{
return
{
get_product_info(product_type::playstation_3_controller)
};
}
}
}
};

View File

@ -1904,6 +1904,7 @@
<Command Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\wolfssl" "-I.\..\3rdparty\curl\include" "-I.\..\3rdparty\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\XAudio2Redist\include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtCore" "-I.\debug" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent"</Command>
</CustomBuild>
<ClInclude Include="Input\pad_thread.h" />
<ClInclude Include="Input\product_info.h" />
<ClInclude Include="QTGeneratedFiles\ui_about_dialog.h" />
<ClInclude Include="QTGeneratedFiles\ui_main_window.h" />
<ClInclude Include="QTGeneratedFiles\ui_pad_led_settings_dialog.h" />

View File

@ -1140,6 +1140,9 @@
<ClInclude Include="rpcs3qt\gui_save.h">
<Filter>Gui\settings</Filter>
</ClInclude>
<ClInclude Include="Input\product_info.h">
<Filter>Io</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="debug\moc_predefs.h.cbt">

View File

@ -15,6 +15,7 @@
#include "Emu/Io/Null/NullPadHandler.h"
#include "Input/product_info.h"
#include "Input/keyboard_pad_handler.h"
#include "Input/ds3_pad_handler.h"
#include "Input/ds4_pad_handler.h"
@ -187,6 +188,8 @@ pad_settings_dialog::pad_settings_dialog(QWidget *parent, const GameInfo *game)
ui->chooseClass->addItem(tr("Dance Mat")); // CELL_PAD_PCLASS_TYPE_DANCEMAT = 0x04,
ui->chooseClass->addItem(tr("Navigation")); // CELL_PAD_PCLASS_TYPE_NAVIGATION = 0x05,
connect(ui->chooseClass, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &pad_settings_dialog::HandleDeviceClassChange);
// Initialize configurable buttons
InitButtons();
@ -527,6 +530,20 @@ void pad_settings_dialog::ReloadButtons()
ui->chooseClass->setCurrentIndex(m_handler_cfg.device_class_type);
// Trigger the change manually in case that the class dropdown didn't fire an event
HandleDeviceClassChange(ui->chooseClass->currentIndex());
const auto products = input::get_products_by_class(m_handler_cfg.device_class_type);
for (size_t i = 0; i < products.size(); i++)
{
if (products[i].vendor_id == m_handler_cfg.vendor_id && products[i].product_id == m_handler_cfg.product_id)
{
ui->chooseProduct->setCurrentIndex(static_cast<int>(i));
break;
}
}
// Enable Mouse Deadzones
std::vector<std::string> mouse_dz_range_x = m_handler_cfg.mouse_deadzone_x.to_list();
ui->mouse_dz_x->setRange(std::stoi(mouse_dz_range_x.front()), std::stoi(mouse_dz_range_x.back()));
@ -620,6 +637,7 @@ void pad_settings_dialog::ReactivateButtons()
ui->chooseHandler->setFocusPolicy(Qt::WheelFocus);
ui->chooseDevice->setFocusPolicy(Qt::WheelFocus);
ui->chooseClass->setFocusPolicy(Qt::WheelFocus);
ui->chooseProduct->setFocusPolicy(Qt::WheelFocus);
}
void pad_settings_dialog::RepaintPreviewLabel(QLabel* l, int deadzone, int desired_width, int x, int y)
@ -926,6 +944,7 @@ void pad_settings_dialog::OnPadButtonClicked(int id)
ui->chooseHandler->setFocusPolicy(Qt::ClickFocus);
ui->chooseDevice->setFocusPolicy(Qt::ClickFocus);
ui->chooseClass->setFocusPolicy(Qt::ClickFocus);
ui->chooseProduct->setFocusPolicy(Qt::ClickFocus);
m_last_pos = QCursor::pos();
@ -1086,6 +1105,7 @@ void pad_settings_dialog::ChangeInputType()
bool config_enabled = force_enable || (m_handler->m_type != pad_handler::null && ui->chooseDevice->count() > 0);
ui->chooseDevice->setEnabled(config_enabled);
ui->chooseClass->setEnabled(config_enabled);
ui->chooseProduct->setEnabled(config_enabled);
if (config_enabled)
{
@ -1212,6 +1232,59 @@ void pad_settings_dialog::ChangeProfile()
}
}
void pad_settings_dialog::HandleDeviceClassChange(int index)
{
if (index < 0)
{
return;
}
ui->chooseProduct->clear();
for (const auto& product : input::get_products_by_class(index))
{
switch (product.type)
{
default:
case input::product_type::playstation_3_controller:
{
ui->chooseProduct->addItem(tr("PS3 Controller", "PlayStation 3 Controller"), static_cast<int>(product.type));
break;
}
case input::product_type::dance_dance_revolution_mat:
{
ui->chooseProduct->addItem(tr("Dance Dance Revolution", "Dance Dance Revolution Mat"), static_cast<int>(product.type));
break;
}
case input::product_type::dj_hero_turntable:
{
ui->chooseProduct->addItem(tr("DJ Hero Turntable", "DJ Hero Turntable"), static_cast<int>(product.type));
break;
}
case input::product_type::harmonix_rockband_drum_kit:
{
ui->chooseProduct->addItem(tr("Rockband", "Harmonix Rockband Drum Kit"), static_cast<int>(product.type));
break;
}
case input::product_type::harmonix_rockband_guitar:
{
ui->chooseProduct->addItem(tr("Rockband", "Harmonix Rockband Guitar"), static_cast<int>(product.type));
break;
}
case input::product_type::red_octane_gh_drum_kit:
{
ui->chooseProduct->addItem(tr("Guitar Hero", "RedOctane Guitar Hero Drum Kit"), static_cast<int>(product.type));
break;
}
case input::product_type::red_octane_gh_guitar:
{
ui->chooseProduct->addItem(tr("Guitar Hero", "RedOctane Guitar Hero Guitar"), static_cast<int>(product.type));
break;
}
}
}
}
void pad_settings_dialog::RefreshInputTypes()
{
const auto& handler = g_cfg_input.player[m_tabs->currentIndex()]->handler;
@ -1264,6 +1337,11 @@ void pad_settings_dialog::SaveProfile()
m_handler_cfg.device_class_type.set(ui->chooseClass->currentIndex());
const auto info = input::get_product_info(static_cast<input::product_type>(ui->chooseProduct->currentData().toInt()));
m_handler_cfg.vendor_id.set(info.vendor_id);
m_handler_cfg.product_id.set(info.product_id);
m_handler_cfg.save();
}

View File

@ -98,6 +98,7 @@ private Q_SLOTS:
void OnTabChanged(int index);
void RefreshInputTypes();
void ChangeInputType();
void HandleDeviceClassChange(int index);
/** Save the Pad Configuration to the current Pad Handler Config File */
void SaveProfile();
void SaveExit();

View File

@ -1471,10 +1471,25 @@
<property name="title">
<string>Device Class:</string>
</property>
<layout class="QVBoxLayout" name="gb_choose_class_layout">
<item alignment="Qt::AlignVCenter">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>5</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<item>
<widget class="QComboBox" name="chooseClass"/>
</item>
<item>
<widget class="QComboBox" name="chooseProduct"/>
</item>
</layout>
</widget>
</item>
@ -1490,6 +1505,18 @@
<string>Battery status and LED</string>
</property>
<layout class="QHBoxLayout" name="gb_battery_layout" stretch="1,1">
<property name="leftMargin">
<number>5</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<item>
<widget class="QProgressBar" name="pb_battery">
<property name="maximumSize">