diff --git a/rpcs3/Emu/Cell/Modules/cellPad.cpp b/rpcs3/Emu/Cell/Modules/cellPad.cpp index 107be92a9d..249bbfaef1 100644 --- a/rpcs3/Emu/Cell/Modules/cellPad.cpp +++ b/rpcs3/Emu/Cell/Modules/cellPad.cpp @@ -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 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(); - - 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(); const auto handler = pad::get_current_handler(); @@ -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()) @@ -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 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(); + + 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 info) @@ -573,12 +666,11 @@ error_code cellPadPeriphGetData(u32 port_no, vm::ptr 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; }