Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cellPad/input: prepare some peripheral data code #14559

Merged
merged 2 commits into from Aug 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
164 changes: 128 additions & 36 deletions rpcs3/Emu/Cell/Modules/cellPad.cpp
Expand Up @@ -260,39 +260,7 @@ error_code cellPadClearBuf(u32 port_no)
return CELL_OK;
}

void pad_get_data(u32 port_no, CellPadData* data);

error_code cellPadGetData(u32 port_no, vm::ptr<CellPadData> data)
{
sys_io.trace("cellPadGetData(port_no=%d, data=*0x%x)", port_no, data);

std::lock_guard lock(pad::g_pad_mutex);

auto& config = g_fxo->get<pad_info>();

if (!config.max_connect)
return CELL_PAD_ERROR_UNINITIALIZED;

const auto handler = pad::get_current_handler();

if (port_no >= CELL_MAX_PADS || !data)
return CELL_PAD_ERROR_INVALID_PARAMETER;

const auto& pads = handler->GetPads();

if (port_no >= config.get_max_connect())
return CELL_PAD_ERROR_NO_DEVICE;

const auto& pad = pads[port_no];

if (!config.is_reportedly_connected(port_no) || !(pad->m_port_status & CELL_PAD_STATUS_CONNECTED))
return not_an_error(CELL_PAD_ERROR_NO_DEVICE);

pad_get_data(port_no, data.get_ptr());
return CELL_OK;
}

void pad_get_data(u32 port_no, CellPadData* data)
void pad_get_data(u32 port_no, CellPadData* data, bool get_periph_data = false)
{
auto& config = g_fxo->get<pad_info>();
const auto handler = pad::get_current_handler();
Expand All @@ -305,7 +273,7 @@ void pad_get_data(u32 port_no, CellPadData* data)
return;
}

const auto setting = config.port_setting[port_no];
const u32 setting = config.port_setting[port_no];
bool btnChanged = false;

if (rinfo.ignore_input || !is_input_allowed())
Expand Down Expand Up @@ -492,6 +460,131 @@ void pad_get_data(u32 port_no, CellPadData* data)
data->button[CELL_PAD_BTN_OFFSET_SENSOR_G] = pad->m_sensor_g;
}
}

if (!get_periph_data || data->len <= CELL_PAD_LEN_CHANGE_SENSOR_ON)
{
return;
}

const auto get_pressure_value = [setting](u16 val, u16 min, u16 max) -> u16
{
if (setting & CELL_PAD_SETTING_PRESS_ON)
{
return std::clamp(val, min, max);
}

if (val > 0)
{
return max;
}

return 0;
};

// TODO: support for 'unique' controllers, which goes in offsets 24+ in padData (CELL_PAD_PCLASS_BTN_OFFSET)
// TODO: update data->len accordingly

switch (pad->m_class_profile)
{
default:
case CELL_PAD_PCLASS_TYPE_STANDARD:
case CELL_PAD_PCLASS_TYPE_NAVIGATION:
{
break;
}
case CELL_PAD_PCLASS_TYPE_GUITAR:
{
data->button[CELL_PAD_PCLASS_BTN_OFFSET_GUITAR_FRET_1] = get_pressure_value(0, 0x0, 0xFF);
data->button[CELL_PAD_PCLASS_BTN_OFFSET_GUITAR_FRET_2] = get_pressure_value(0, 0x0, 0xFF);
data->button[CELL_PAD_PCLASS_BTN_OFFSET_GUITAR_FRET_3] = get_pressure_value(0, 0x0, 0xFF);
data->button[CELL_PAD_PCLASS_BTN_OFFSET_GUITAR_FRET_4] = get_pressure_value(0, 0x0, 0xFF);
data->button[CELL_PAD_PCLASS_BTN_OFFSET_GUITAR_FRET_5] = get_pressure_value(0, 0x0, 0xFF);
data->button[CELL_PAD_PCLASS_BTN_OFFSET_GUITAR_STRUM_UP] = get_pressure_value(0, 0x0, 0xFF);
data->button[CELL_PAD_PCLASS_BTN_OFFSET_GUITAR_STRUM_DOWN] = get_pressure_value(0, 0x0, 0xFF);
data->button[CELL_PAD_PCLASS_BTN_OFFSET_GUITAR_WHAMMYBAR] = 0x80; // 0x80 – 0xFF
data->button[CELL_PAD_PCLASS_BTN_OFFSET_GUITAR_FRET_H1] = get_pressure_value(0, 0x0, 0xFF);
data->button[CELL_PAD_PCLASS_BTN_OFFSET_GUITAR_FRET_H2] = get_pressure_value(0, 0x0, 0xFF);
data->button[CELL_PAD_PCLASS_BTN_OFFSET_GUITAR_FRET_H3] = get_pressure_value(0, 0x0, 0xFF);
data->button[CELL_PAD_PCLASS_BTN_OFFSET_GUITAR_FRET_H4] = get_pressure_value(0, 0x0, 0xFF);
data->button[CELL_PAD_PCLASS_BTN_OFFSET_GUITAR_FRET_H5] = get_pressure_value(0, 0x0, 0xFF);
data->button[CELL_PAD_PCLASS_BTN_OFFSET_GUITAR_5WAY_EFFECT] = 0x0019; // One of 5 values: 0x0019, 0x004C, 0x007F (or 0x0096), 0x00B2, 0x00E5 (or 0x00E2)
data->button[CELL_PAD_PCLASS_BTN_OFFSET_GUITAR_TILT_SENS] = get_pressure_value(0, 0x0, 0xFF);
break;
}
case CELL_PAD_PCLASS_TYPE_DRUM:
{
data->button[CELL_PAD_PCLASS_BTN_OFFSET_DRUM_SNARE] = get_pressure_value(0, 0x0, 0xFF);
data->button[CELL_PAD_PCLASS_BTN_OFFSET_DRUM_TOM] = get_pressure_value(0, 0x0, 0xFF);
data->button[CELL_PAD_PCLASS_BTN_OFFSET_DRUM_TOM2] = get_pressure_value(0, 0x0, 0xFF);
data->button[CELL_PAD_PCLASS_BTN_OFFSET_DRUM_TOM_FLOOR] = get_pressure_value(0, 0x0, 0xFF);
data->button[CELL_PAD_PCLASS_BTN_OFFSET_DRUM_KICK] = get_pressure_value(0, 0x0, 0xFF);
data->button[CELL_PAD_PCLASS_BTN_OFFSET_DRUM_CYM_HiHAT] = get_pressure_value(0, 0x0, 0xFF);
data->button[CELL_PAD_PCLASS_BTN_OFFSET_DRUM_CYM_CRASH] = get_pressure_value(0, 0x0, 0xFF);
data->button[CELL_PAD_PCLASS_BTN_OFFSET_DRUM_CYM_RIDE] = get_pressure_value(0, 0x0, 0xFF);
data->button[CELL_PAD_PCLASS_BTN_OFFSET_DRUM_KICK2] = get_pressure_value(0, 0x0, 0xFF);
break;
}
case CELL_PAD_PCLASS_TYPE_DJ:
{
// First deck
data->button[CELL_PAD_PCLASS_BTN_OFFSET_DJ_MIXER_ATTACK] = 0; // 0x0 or 0xFF
data->button[CELL_PAD_PCLASS_BTN_OFFSET_DJ_MIXER_CROSSFADER] = 0; // 0x0 - 0x3FF
data->button[CELL_PAD_PCLASS_BTN_OFFSET_DJ_MIXER_DSP_DIAL] = 0; // 0x0 - 0x3FF
data->button[CELL_PAD_PCLASS_BTN_OFFSET_DJ_DECK1_STREAM1] = 0; // 0x0 or 0xFF
data->button[CELL_PAD_PCLASS_BTN_OFFSET_DJ_DECK1_STREAM2] = 0; // 0x0 or 0xFF
data->button[CELL_PAD_PCLASS_BTN_OFFSET_DJ_DECK1_STREAM3] = 0; // 0x0 or 0xFF
data->button[CELL_PAD_PCLASS_BTN_OFFSET_DJ_DECK1_PLATTER] = 0x80; // 0x0 - 0xFF (neutral: 0x80)

// Second deck
data->button[CELL_PAD_PCLASS_BTN_OFFSET_DJ_DECK2_STREAM1] = 0; // 0x0 or 0xFF
data->button[CELL_PAD_PCLASS_BTN_OFFSET_DJ_DECK2_STREAM2] = 0; // 0x0 or 0xFF
data->button[CELL_PAD_PCLASS_BTN_OFFSET_DJ_DECK2_STREAM3] = 0; // 0x0 or 0xFF
data->button[CELL_PAD_PCLASS_BTN_OFFSET_DJ_DECK2_PLATTER] = 0x80; // 0x0 - 0xFF (neutral: 0x80)
break;
}
case CELL_PAD_PCLASS_TYPE_DANCEMAT:
{
data->button[CELL_PAD_PCLASS_BTN_OFFSET_DANCEMAT_CIRCLE] = 0; // 0x0 or 0xFF
data->button[CELL_PAD_PCLASS_BTN_OFFSET_DANCEMAT_CROSS] = 0; // 0x0 or 0xFF
data->button[CELL_PAD_PCLASS_BTN_OFFSET_DANCEMAT_TRIANGLE] = 0; // 0x0 or 0xFF
data->button[CELL_PAD_PCLASS_BTN_OFFSET_DANCEMAT_SQUARE] = 0; // 0x0 or 0xFF
data->button[CELL_PAD_PCLASS_BTN_OFFSET_DANCEMAT_RIGHT] = 0; // 0x0 or 0xFF
data->button[CELL_PAD_PCLASS_BTN_OFFSET_DANCEMAT_LEFT] = 0; // 0x0 or 0xFF
data->button[CELL_PAD_PCLASS_BTN_OFFSET_DANCEMAT_UP] = 0; // 0x0 or 0xFF
data->button[CELL_PAD_PCLASS_BTN_OFFSET_DANCEMAT_DOWN] = 0; // 0x0 or 0xFF
break;
}
}
}

error_code cellPadGetData(u32 port_no, vm::ptr<CellPadData> data)
{
sys_io.trace("cellPadGetData(port_no=%d, data=*0x%x)", port_no, data);

std::lock_guard lock(pad::g_pad_mutex);

auto& config = g_fxo->get<pad_info>();

if (!config.max_connect)
return CELL_PAD_ERROR_UNINITIALIZED;

const auto handler = pad::get_current_handler();

if (port_no >= CELL_MAX_PADS || !data)
return CELL_PAD_ERROR_INVALID_PARAMETER;

const auto& pads = handler->GetPads();

if (port_no >= config.get_max_connect())
return CELL_PAD_ERROR_NO_DEVICE;

const auto& pad = pads[port_no];

if (!config.is_reportedly_connected(port_no) || !(pad->m_port_status & CELL_PAD_STATUS_CONNECTED))
return not_an_error(CELL_PAD_ERROR_NO_DEVICE);

pad_get_data(port_no, data.get_ptr());
return CELL_OK;
}

error_code cellPadPeriphGetInfo(vm::ptr<CellPadPeriphInfo> info)
Expand Down Expand Up @@ -573,12 +666,11 @@ error_code cellPadPeriphGetData(u32 port_no, vm::ptr<CellPadPeriphData> data)
if (!config.is_reportedly_connected(port_no) || !(pad->m_port_status & CELL_PAD_STATUS_CONNECTED))
return not_an_error(CELL_PAD_ERROR_NO_DEVICE);

pad_get_data(port_no, &data->cellpad_data);
pad_get_data(port_no, &data->cellpad_data, true);

data->pclass_type = pad->m_class_type;
data->pclass_profile = pad->m_class_profile;

// TODO: support for 'unique' controllers, which goes in offsets 24+ in padData (CELL_PAD_PCLASS_BTN_OFFSET)
return CELL_OK;
}

Expand Down
4 changes: 2 additions & 2 deletions rpcs3/Emu/Io/pad_config.h
@@ -1,6 +1,6 @@
#pragma once

#include "pad_config_types.h"
#include "pad_types.h"

#include "Utilities/Config.h"

Expand Down Expand Up @@ -97,7 +97,7 @@ struct cfg_pad final : cfg::node
cfg::uint<0, 100> analog_lerp_factor{ this, "Analog Button Lerp Factor", 100 };
cfg::uint<0, 100> trigger_lerp_factor{ this, "Trigger Lerp Factor", 100 };

cfg::uint<0, 5> device_class_type{ this, "Device Class Type", 0 };
cfg::uint<CELL_PAD_PCLASS_TYPE_STANDARD, CELL_PAD_PCLASS_TYPE_NAVIGATION> device_class_type{ this, "Device Class Type", 0 };
cfg::uint<0, 65535> vendor_id{ this, "Vendor ID", 0 };
cfg::uint<0, 65535> product_id{ this, "Product ID", 0 };
};
Expand Down
34 changes: 17 additions & 17 deletions rpcs3/rpcs3qt/pad_settings_dialog.cpp
Expand Up @@ -174,14 +174,18 @@ pad_settings_dialog::pad_settings_dialog(std::shared_ptr<gui_settings> gui_setti
// Refresh Button
connect(ui->b_refresh, &QPushButton::clicked, this, &pad_settings_dialog::RefreshHandlers);

ui->chooseClass->addItem(tr("Standard (Pad)")); // CELL_PAD_PCLASS_TYPE_STANDARD = 0x00,
ui->chooseClass->addItem(tr("Guitar")); // CELL_PAD_PCLASS_TYPE_GUITAR = 0x01,
ui->chooseClass->addItem(tr("Drum")); // CELL_PAD_PCLASS_TYPE_DRUM = 0x02,
ui->chooseClass->addItem(tr("DJ")); // CELL_PAD_PCLASS_TYPE_DJ = 0x03,
ui->chooseClass->addItem(tr("Dance Mat")); // CELL_PAD_PCLASS_TYPE_DANCEMAT = 0x04,
ui->chooseClass->addItem(tr("Navigation")); // CELL_PAD_PCLASS_TYPE_NAVIGATION = 0x05,
ui->chooseClass->addItem(tr("Standard (Pad)"), u32{CELL_PAD_PCLASS_TYPE_STANDARD});
ui->chooseClass->addItem(tr("Guitar"), u32{CELL_PAD_PCLASS_TYPE_GUITAR});
ui->chooseClass->addItem(tr("Drum"), u32{CELL_PAD_PCLASS_TYPE_DRUM});
ui->chooseClass->addItem(tr("DJ"), u32{CELL_PAD_PCLASS_TYPE_DJ});
ui->chooseClass->addItem(tr("Dance Mat"), u32{CELL_PAD_PCLASS_TYPE_DANCEMAT});
ui->chooseClass->addItem(tr("Navigation"), u32{CELL_PAD_PCLASS_TYPE_NAVIGATION});

connect(ui->chooseClass, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &pad_settings_dialog::HandleDeviceClassChange);
connect(ui->chooseClass, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [this](int index)
{
if (index < 0) return;
HandleDeviceClassChange(ui->chooseClass->currentData().toUInt());
});

ui->chb_show_emulated_values->setChecked(m_gui_settings->GetValue(gui::pads_show_emulated).toBool());

Expand Down Expand Up @@ -1075,10 +1079,11 @@ void pad_settings_dialog::UpdateLabels(bool is_reset)
const cfg_pad& cfg = GetPlayerConfig();

// Update device class
ui->chooseClass->setCurrentIndex(cfg.device_class_type);
const int index = ui->chooseClass->findData(cfg.device_class_type.get());
ui->chooseClass->setCurrentIndex(index);

// Trigger the change manually in case that the class dropdown didn't fire an event
HandleDeviceClassChange(ui->chooseClass->currentIndex());
HandleDeviceClassChange(cfg.device_class_type);

const auto products = input::get_products_by_class(cfg.device_class_type);

Expand Down Expand Up @@ -1608,16 +1613,11 @@ void pad_settings_dialog::ChangeDevice(int index)
}
}

void pad_settings_dialog::HandleDeviceClassChange(int index) const
void pad_settings_dialog::HandleDeviceClassChange(u32 class_id) const
{
if (index < 0)
{
return;
}

ui->chooseProduct->clear();

for (const input::product_info& product : input::get_products_by_class(index))
for (const input::product_info& product : input::get_products_by_class(class_id))
{
switch (product.type)
{
Expand Down Expand Up @@ -1833,7 +1833,7 @@ void pad_settings_dialog::ApplyCurrentPlayerConfig(int new_player_id)
cfg.r_stick_lerp_factor.set(ui->right_stick_lerp->value() * 100);
}

cfg.device_class_type.set(ui->chooseClass->currentIndex());
cfg.device_class_type.set(ui->chooseClass->currentData().toUInt());

const auto info = input::get_product_info(static_cast<input::product_type>(ui->chooseProduct->currentData().toInt()));

Expand Down
2 changes: 1 addition & 1 deletion rpcs3/rpcs3qt/pad_settings_dialog.h
Expand Up @@ -99,7 +99,7 @@ private Q_SLOTS:
void ChangeHandler();
void ChangeProfile(const QString& profile);
void ChangeDevice(int index);
void HandleDeviceClassChange(int index) const;
void HandleDeviceClassChange(u32 class_id) const;
void AddProfile();
/** Update the current player config with the GUI values. */
void ApplyCurrentPlayerConfig(int new_player_id);
Expand Down