From 632c8872cdd477c5fe7818d05c76fdc76efb9e50 Mon Sep 17 00:00:00 2001 From: jjsat Date: Sun, 24 Sep 2017 20:39:56 +0200 Subject: [PATCH] Respect the controller setting when returning data from cellPadGetData. --- rpcs3/Emu/Cell/Modules/cellPad.cpp | 101 +++++++++++++++++++---------- rpcs3/Emu/Cell/Modules/cellPad.h | 9 +++ 2 files changed, 77 insertions(+), 33 deletions(-) diff --git a/rpcs3/Emu/Cell/Modules/cellPad.cpp b/rpcs3/Emu/Cell/Modules/cellPad.cpp index 11f08bba77..000ec8f969 100644 --- a/rpcs3/Emu/Cell/Modules/cellPad.cpp +++ b/rpcs3/Emu/Cell/Modules/cellPad.cpp @@ -235,43 +235,78 @@ s32 cellPadGetData(u32 port_no, vm::ptr data) btnChanged = true; } - //not sure if this should officially change with capabilities/portsettings :( - data->len = 24; + + // the real hardware only fills the buffer up to "len" elements (16 bit each) + if (pad->m_port_setting & CELL_PAD_SETTING_SENSOR_ON) + { + // report back new data every ~10 ms even if the input doesn't change + // this is observed behaviour when using a Dualshock 3 controller + static std::chrono::time_point last_update[CELL_PAD_MAX_PORT_NUM] = { }; + const std::chrono::time_point now = steady_clock::now(); - if (pad->m_buffer_cleared) - { - pad->m_buffer_cleared = false; + if (btnChanged || pad->m_buffer_cleared || (std::chrono::duration_cast(now - last_update[port_no]).count() >= 10)) + { + data->len = CELL_PAD_LEN_CHANGE_SENSOR_ON; + last_update[port_no] = now; + } + else + { + data->len = CELL_PAD_LEN_NO_CHANGE; + } } - else if (!btnChanged) + else if (btnChanged || pad->m_buffer_cleared) { - data->len = 0; + // only give back valid data if a controller state changed + data->len = (pad->m_port_setting & CELL_PAD_SETTING_PRESS_ON) ? CELL_PAD_LEN_CHANGE_PRESS_ON : CELL_PAD_LEN_CHANGE_DEFAULT; + } + else + { + // report no state changes + data->len = CELL_PAD_LEN_NO_CHANGE; + } + + pad->m_buffer_cleared = false; + + // only update parts of the output struct depending on the controller setting + if (data->len > CELL_PAD_LEN_NO_CHANGE) + { + memset(data->button, 0, sizeof(data->button)); + + data->button[0] = 0x0; // always 0 + // bits 15-8 reserved, 7-4 = 0x7, 3-0: data->len/2; + data->button[1] = (0x7 << 4) | std::min(data->len / 2, 15); + + data->button[CELL_PAD_BTN_OFFSET_DIGITAL1] = pad->m_digital_1; + data->button[CELL_PAD_BTN_OFFSET_DIGITAL2] = pad->m_digital_2; + data->button[CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X] = pad->m_analog_right_x; + data->button[CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y] = pad->m_analog_right_y; + data->button[CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X] = pad->m_analog_left_x; + data->button[CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y] = pad->m_analog_left_y; + data->button[CELL_PAD_BTN_OFFSET_PRESS_RIGHT] = pad->m_press_right; + data->button[CELL_PAD_BTN_OFFSET_PRESS_LEFT] = pad->m_press_left; + data->button[CELL_PAD_BTN_OFFSET_PRESS_UP] = pad->m_press_up; + data->button[CELL_PAD_BTN_OFFSET_PRESS_DOWN] = pad->m_press_down; + } + + if (data->len >= CELL_PAD_LEN_CHANGE_PRESS_ON) + { + data->button[CELL_PAD_BTN_OFFSET_PRESS_TRIANGLE] = pad->m_press_triangle; + data->button[CELL_PAD_BTN_OFFSET_PRESS_CIRCLE] = pad->m_press_circle; + data->button[CELL_PAD_BTN_OFFSET_PRESS_CROSS] = pad->m_press_cross; + data->button[CELL_PAD_BTN_OFFSET_PRESS_SQUARE] = pad->m_press_square; + data->button[CELL_PAD_BTN_OFFSET_PRESS_L1] = pad->m_press_L1; + data->button[CELL_PAD_BTN_OFFSET_PRESS_L2] = pad->m_press_L2; + data->button[CELL_PAD_BTN_OFFSET_PRESS_R1] = pad->m_press_R1; + data->button[CELL_PAD_BTN_OFFSET_PRESS_R2] = pad->m_press_R2; + } + + if (data->len == CELL_PAD_LEN_CHANGE_SENSOR_ON) + { + data->button[CELL_PAD_BTN_OFFSET_SENSOR_X] = pad->m_sensor_x; + data->button[CELL_PAD_BTN_OFFSET_SENSOR_Y] = pad->m_sensor_y; + data->button[CELL_PAD_BTN_OFFSET_SENSOR_Z] = pad->m_sensor_z; + data->button[CELL_PAD_BTN_OFFSET_SENSOR_G] = pad->m_sensor_g; } - data->button[0] = 0x0; // always 0 - // bits 15-8 reserved, 7-4 = 0x7, 3-0: data->len/2; - data->button[1] = (0x7 << 4) | std::min(data->len / 2, 15); - //lets still send new data anyway, not sure whats expected still - data->button[CELL_PAD_BTN_OFFSET_DIGITAL1] = pad->m_digital_1; - data->button[CELL_PAD_BTN_OFFSET_DIGITAL2] = pad->m_digital_2; - data->button[CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X] = pad->m_analog_right_x; - data->button[CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y] = pad->m_analog_right_y; - data->button[CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X] = pad->m_analog_left_x; - data->button[CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y] = pad->m_analog_left_y; - data->button[CELL_PAD_BTN_OFFSET_PRESS_RIGHT] = pad->m_press_right; - data->button[CELL_PAD_BTN_OFFSET_PRESS_LEFT] = pad->m_press_left; - data->button[CELL_PAD_BTN_OFFSET_PRESS_UP] = pad->m_press_up; - data->button[CELL_PAD_BTN_OFFSET_PRESS_DOWN] = pad->m_press_down; - data->button[CELL_PAD_BTN_OFFSET_PRESS_TRIANGLE] = pad->m_press_triangle; - data->button[CELL_PAD_BTN_OFFSET_PRESS_CIRCLE] = pad->m_press_circle; - data->button[CELL_PAD_BTN_OFFSET_PRESS_CROSS] = pad->m_press_cross; - data->button[CELL_PAD_BTN_OFFSET_PRESS_SQUARE] = pad->m_press_square; - data->button[CELL_PAD_BTN_OFFSET_PRESS_L1] = pad->m_press_L1; - data->button[CELL_PAD_BTN_OFFSET_PRESS_L2] = pad->m_press_L2; - data->button[CELL_PAD_BTN_OFFSET_PRESS_R1] = pad->m_press_R1; - data->button[CELL_PAD_BTN_OFFSET_PRESS_R2] = pad->m_press_R2; - data->button[CELL_PAD_BTN_OFFSET_SENSOR_X] = pad->m_sensor_x; - data->button[CELL_PAD_BTN_OFFSET_SENSOR_Y] = pad->m_sensor_y; - data->button[CELL_PAD_BTN_OFFSET_SENSOR_Z] = pad->m_sensor_z; - data->button[CELL_PAD_BTN_OFFSET_SENSOR_G] = pad->m_sensor_g; return CELL_OK; } diff --git a/rpcs3/Emu/Cell/Modules/cellPad.h b/rpcs3/Emu/Cell/Modules/cellPad.h index 3f1d9ae6d4..47deac7c23 100644 --- a/rpcs3/Emu/Cell/Modules/cellPad.h +++ b/rpcs3/Emu/Cell/Modules/cellPad.h @@ -27,6 +27,15 @@ enum CELL_PAD_PCLASS_TYPE_NAVIGATION = 0x05, }; +// Length returned in CellPadData struct +enum +{ + CELL_PAD_LEN_NO_CHANGE = 0, + CELL_PAD_LEN_CHANGE_DEFAULT = 8, + CELL_PAD_LEN_CHANGE_PRESS_ON = 20, + CELL_PAD_LEN_CHANGE_SENSOR_ON = 24, +}; + struct CellPadData { be_t len;