cellPadGetData: clear buttons if input is ignored but not intercepted.

needed in Hotline Miami and NinJa Gaiden Sigma, fixes Gran Turismo 6 regression
This commit is contained in:
Megamouse 2019-10-06 12:35:02 +02:00
parent d402507be2
commit 3455d76970
1 changed files with 154 additions and 137 deletions

View File

@ -64,6 +64,27 @@ error_code cellPadEnd()
return CELL_OK; return CELL_OK;
} }
void clear_pad_buffer(const std::shared_ptr<Pad> pad)
{
if (!pad)
return;
// Set 'm_buffer_cleared' to force a resend of everything
// might as well also reset everything in our pad 'buffer' to nothing as well
pad->m_buffer_cleared = true;
pad->m_analog_left_x = pad->m_analog_left_y = pad->m_analog_right_x = pad->m_analog_right_y = 128;
pad->m_digital_1 = pad->m_digital_2 = 0;
pad->m_press_right = pad->m_press_left = pad->m_press_up = pad->m_press_down = 0;
pad->m_press_triangle = pad->m_press_circle = pad->m_press_cross = pad->m_press_square = 0;
pad->m_press_L1 = pad->m_press_L2 = pad->m_press_R1 = pad->m_press_R2 = 0;
// ~399 on sensor y is a level non moving controller
pad->m_sensor_y = 399;
pad->m_sensor_x = pad->m_sensor_z = pad->m_sensor_g = 512;
}
error_code cellPadClearBuf(u32 port_no) error_code cellPadClearBuf(u32 port_no)
{ {
sys_io.trace("cellPadClearBuf(port_no=%d)", port_no); sys_io.trace("cellPadClearBuf(port_no=%d)", port_no);
@ -90,20 +111,7 @@ error_code cellPadClearBuf(u32 port_no)
if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED)) if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED))
return CELL_PAD_ERROR_NO_DEVICE; return CELL_PAD_ERROR_NO_DEVICE;
// Set 'm_buffer_cleared' to force a resend of everything clear_pad_buffer(pad);
// might as well also reset everything in our pad 'buffer' to nothing as well
pad->m_buffer_cleared = true;
pad->m_analog_left_x = pad->m_analog_left_y = pad->m_analog_right_x = pad->m_analog_right_y = 128;
pad->m_digital_1 = pad->m_digital_2 = 0;
pad->m_press_right = pad->m_press_left = pad->m_press_up = pad->m_press_down = 0;
pad->m_press_triangle = pad->m_press_circle = pad->m_press_cross = pad->m_press_square = 0;
pad->m_press_L1 = pad->m_press_L2 = pad->m_press_R1 = pad->m_press_R2 = 0;
// ~399 on sensor y is a level non moving controller
pad->m_sensor_y = 399;
pad->m_sensor_x = pad->m_sensor_z = pad->m_sensor_g = 512;
return CELL_OK; return CELL_OK;
} }
@ -137,13 +145,21 @@ error_code cellPadGetData(u32 port_no, vm::ptr<CellPadData> data)
const PadInfo& rinfo = handler->GetInfo(); const PadInfo& rinfo = handler->GetInfo();
if (rinfo.ignore_input || (rinfo.system_info & CELL_PAD_INFO_INTERCEPTED)) if (rinfo.system_info & CELL_PAD_INFO_INTERCEPTED)
{ {
data->len = CELL_PAD_LEN_NO_CHANGE; data->len = CELL_PAD_LEN_NO_CHANGE;
return CELL_OK; return CELL_OK;
} }
if (pad->ldd) bool btnChanged = false;
if (rinfo.ignore_input)
{
// Needed for Hotline Miami and Ninja Gaiden Sigma after dialogs were closed and buttons are still pressed.
// Gran Turismo 6 would keep registering the Start button during OSK Dialogs if this wasn't cleared and if we'd return with len as CELL_PAD_LEN_NO_CHANGE.
clear_pad_buffer(pad);
}
else if (pad->ldd)
{ {
memcpy(data.get_ptr(), pad->ldd_data, sizeof(CellPadData)); memcpy(data.get_ptr(), pad->ldd_data, sizeof(CellPadData));
if (setting & CELL_PAD_SETTING_SENSOR_ON) if (setting & CELL_PAD_SETTING_SENSOR_ON)
@ -152,149 +168,150 @@ error_code cellPadGetData(u32 port_no, vm::ptr<CellPadData> data)
data->len = (setting & CELL_PAD_SETTING_PRESS_ON) ? CELL_PAD_LEN_CHANGE_PRESS_ON : CELL_PAD_LEN_CHANGE_DEFAULT; data->len = (setting & CELL_PAD_SETTING_PRESS_ON) ? CELL_PAD_LEN_CHANGE_PRESS_ON : CELL_PAD_LEN_CHANGE_DEFAULT;
return CELL_OK; return CELL_OK;
} }
else
u16 d1Initial = pad->m_digital_1;
u16 d2Initial = pad->m_digital_2;
bool btnChanged = false;
for (Button& button : pad->m_buttons)
{ {
// here we check btns, and set pad accordingly, u16 d1Initial = pad->m_digital_1;
// if something changed, set btnChanged u16 d2Initial = pad->m_digital_2;
if (button.m_offset == CELL_PAD_BTN_OFFSET_DIGITAL1) for (Button& button : pad->m_buttons)
{ {
if (button.m_pressed) // here we check btns, and set pad accordingly,
pad->m_digital_1 |= button.m_outKeyCode; // if something changed, set btnChanged
else
pad->m_digital_1 &= ~button.m_outKeyCode;
switch (button.m_outKeyCode) if (button.m_offset == CELL_PAD_BTN_OFFSET_DIGITAL1)
{ {
case CELL_PAD_CTRL_LEFT: if (button.m_pressed)
if (pad->m_press_left != button.m_value) btnChanged = true; pad->m_digital_1 |= button.m_outKeyCode;
pad->m_press_left = button.m_value; else
break; pad->m_digital_1 &= ~button.m_outKeyCode;
case CELL_PAD_CTRL_DOWN:
if (pad->m_press_down != button.m_value) btnChanged = true; switch (button.m_outKeyCode)
pad->m_press_down = button.m_value; {
break; case CELL_PAD_CTRL_LEFT:
case CELL_PAD_CTRL_RIGHT: if (pad->m_press_left != button.m_value) btnChanged = true;
if (pad->m_press_right != button.m_value) btnChanged = true; pad->m_press_left = button.m_value;
pad->m_press_right = button.m_value; break;
break; case CELL_PAD_CTRL_DOWN:
case CELL_PAD_CTRL_UP: if (pad->m_press_down != button.m_value) btnChanged = true;
if (pad->m_press_up != button.m_value) btnChanged = true; pad->m_press_down = button.m_value;
pad->m_press_up = button.m_value; break;
break; case CELL_PAD_CTRL_RIGHT:
// These arent pressure btns if (pad->m_press_right != button.m_value) btnChanged = true;
case CELL_PAD_CTRL_R3: pad->m_press_right = button.m_value;
case CELL_PAD_CTRL_L3: break;
case CELL_PAD_CTRL_START: case CELL_PAD_CTRL_UP:
case CELL_PAD_CTRL_SELECT: if (pad->m_press_up != button.m_value) btnChanged = true;
default: break; pad->m_press_up = button.m_value;
break;
// These arent pressure btns
case CELL_PAD_CTRL_R3:
case CELL_PAD_CTRL_L3:
case CELL_PAD_CTRL_START:
case CELL_PAD_CTRL_SELECT:
default: break;
}
}
else if (button.m_offset == CELL_PAD_BTN_OFFSET_DIGITAL2)
{
if (button.m_pressed)
pad->m_digital_2 |= button.m_outKeyCode;
else
pad->m_digital_2 &= ~button.m_outKeyCode;
switch (button.m_outKeyCode)
{
case CELL_PAD_CTRL_SQUARE:
if (pad->m_press_square != button.m_value) btnChanged = true;
pad->m_press_square = button.m_value;
break;
case CELL_PAD_CTRL_CROSS:
if (pad->m_press_cross != button.m_value) btnChanged = true;
pad->m_press_cross = button.m_value;
break;
case CELL_PAD_CTRL_CIRCLE:
if (pad->m_press_circle != button.m_value) btnChanged = true;
pad->m_press_circle = button.m_value;
break;
case CELL_PAD_CTRL_TRIANGLE:
if (pad->m_press_triangle != button.m_value) btnChanged = true;
pad->m_press_triangle = button.m_value;
break;
case CELL_PAD_CTRL_R1:
if (pad->m_press_R1 != button.m_value) btnChanged = true;
pad->m_press_R1 = button.m_value;
break;
case CELL_PAD_CTRL_L1:
if (pad->m_press_L1 != button.m_value) btnChanged = true;
pad->m_press_L1 = button.m_value;
break;
case CELL_PAD_CTRL_R2:
if (pad->m_press_R2 != button.m_value) btnChanged = true;
pad->m_press_R2 = button.m_value;
break;
case CELL_PAD_CTRL_L2:
if (pad->m_press_L2 != button.m_value) btnChanged = true;
pad->m_press_L2 = button.m_value;
break;
default: break;
}
} }
} }
else if (button.m_offset == CELL_PAD_BTN_OFFSET_DIGITAL2)
{
if (button.m_pressed)
pad->m_digital_2 |= button.m_outKeyCode;
else
pad->m_digital_2 &= ~button.m_outKeyCode;
switch (button.m_outKeyCode) for (const AnalogStick& stick : pad->m_sticks)
{
switch (stick.m_offset)
{ {
case CELL_PAD_CTRL_SQUARE: case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X:
if (pad->m_press_square != button.m_value) btnChanged = true; if (pad->m_analog_left_x != stick.m_value) btnChanged = true;
pad->m_press_square = button.m_value; pad->m_analog_left_x = stick.m_value;
break; break;
case CELL_PAD_CTRL_CROSS: case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y:
if (pad->m_press_cross != button.m_value) btnChanged = true; if (pad->m_analog_left_y != stick.m_value) btnChanged = true;
pad->m_press_cross = button.m_value; pad->m_analog_left_y = stick.m_value;
break; break;
case CELL_PAD_CTRL_CIRCLE: case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X:
if (pad->m_press_circle != button.m_value) btnChanged = true; if (pad->m_analog_right_x != stick.m_value) btnChanged = true;
pad->m_press_circle = button.m_value; pad->m_analog_right_x = stick.m_value;
break; break;
case CELL_PAD_CTRL_TRIANGLE: case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y:
if (pad->m_press_triangle != button.m_value) btnChanged = true; if (pad->m_analog_right_y != stick.m_value) btnChanged = true;
pad->m_press_triangle = button.m_value; pad->m_analog_right_y = stick.m_value;
break;
case CELL_PAD_CTRL_R1:
if (pad->m_press_R1 != button.m_value) btnChanged = true;
pad->m_press_R1 = button.m_value;
break;
case CELL_PAD_CTRL_L1:
if (pad->m_press_L1 != button.m_value) btnChanged = true;
pad->m_press_L1 = button.m_value;
break;
case CELL_PAD_CTRL_R2:
if (pad->m_press_R2 != button.m_value) btnChanged = true;
pad->m_press_R2 = button.m_value;
break;
case CELL_PAD_CTRL_L2:
if (pad->m_press_L2 != button.m_value) btnChanged = true;
pad->m_press_L2 = button.m_value;
break; break;
default: break; default: break;
} }
} }
}
for (const AnalogStick& stick : pad->m_sticks) if (setting & CELL_PAD_SETTING_SENSOR_ON)
{
switch (stick.m_offset)
{ {
case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X: for (const AnalogSensor& sensor : pad->m_sensors)
if (pad->m_analog_left_x != stick.m_value) btnChanged = true;
pad->m_analog_left_x = stick.m_value;
break;
case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y:
if (pad->m_analog_left_y != stick.m_value) btnChanged = true;
pad->m_analog_left_y = stick.m_value;
break;
case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X:
if (pad->m_analog_right_x != stick.m_value) btnChanged = true;
pad->m_analog_right_x = stick.m_value;
break;
case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y:
if (pad->m_analog_right_y != stick.m_value) btnChanged = true;
pad->m_analog_right_y = stick.m_value;
break;
default: break;
}
}
if (setting & CELL_PAD_SETTING_SENSOR_ON)
{
for (const AnalogSensor& sensor : pad->m_sensors)
{
switch (sensor.m_offset)
{ {
case CELL_PAD_BTN_OFFSET_SENSOR_X: switch (sensor.m_offset)
if (pad->m_sensor_x != sensor.m_value) btnChanged = true; {
pad->m_sensor_x = sensor.m_value; case CELL_PAD_BTN_OFFSET_SENSOR_X:
break; if (pad->m_sensor_x != sensor.m_value) btnChanged = true;
case CELL_PAD_BTN_OFFSET_SENSOR_Y: pad->m_sensor_x = sensor.m_value;
if (pad->m_sensor_y != sensor.m_value) btnChanged = true; break;
pad->m_sensor_y = sensor.m_value; case CELL_PAD_BTN_OFFSET_SENSOR_Y:
break; if (pad->m_sensor_y != sensor.m_value) btnChanged = true;
case CELL_PAD_BTN_OFFSET_SENSOR_Z: pad->m_sensor_y = sensor.m_value;
if (pad->m_sensor_z != sensor.m_value) btnChanged = true; break;
pad->m_sensor_z = sensor.m_value; case CELL_PAD_BTN_OFFSET_SENSOR_Z:
break; if (pad->m_sensor_z != sensor.m_value) btnChanged = true;
case CELL_PAD_BTN_OFFSET_SENSOR_G: pad->m_sensor_z = sensor.m_value;
if (pad->m_sensor_g != sensor.m_value) btnChanged = true; break;
pad->m_sensor_g = sensor.m_value; case CELL_PAD_BTN_OFFSET_SENSOR_G:
break; if (pad->m_sensor_g != sensor.m_value) btnChanged = true;
default: break; pad->m_sensor_g = sensor.m_value;
break;
default: break;
}
} }
} }
}
if (d1Initial != pad->m_digital_1 || d2Initial != pad->m_digital_2) if (d1Initial != pad->m_digital_1 || d2Initial != pad->m_digital_2)
{ {
btnChanged = true; btnChanged = true;
}
} }
if (setting & CELL_PAD_SETTING_SENSOR_ON) if (setting & CELL_PAD_SETTING_SENSOR_ON)