Fix issues with input detection due to overloaded ring buffer and fix buffer size being incorrect (#2346)

* Add axis noise filter + only update outputs if a change happened

* Change the ring buffer size to 32 as seen in Ghidra

* Fix merge
This commit is contained in:
kalaposfos13 2025-02-05 19:36:16 +01:00 committed by GitHub
parent 0c3260b1b4
commit f111395044
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 30 additions and 23 deletions

View file

@ -60,7 +60,7 @@ inline int GetAxis(int min, int max, int value) {
return std::clamp((255 * (value - min)) / (max - min), 0, 255); return std::clamp((255 * (value - min)) / (max - min), 0, 255);
} }
constexpr u32 MAX_STATES = 64; constexpr u32 MAX_STATES = 32;
class GameController { class GameController {
public: public:

View file

@ -448,7 +448,6 @@ void ControllerOutput::ResetUpdate() {
*new_param = 0; // bruh *new_param = 0; // bruh
} }
void ControllerOutput::AddUpdate(InputEvent event) { void ControllerOutput::AddUpdate(InputEvent event) {
state_changed = true;
if (button == KEY_TOGGLE) { if (button == KEY_TOGGLE) {
if (event.active) { if (event.active) {
ToggleKeyInList(event.input); ToggleKeyInList(event.input);
@ -465,24 +464,43 @@ void ControllerOutput::AddUpdate(InputEvent event) {
} }
} else if (axis != SDL_GAMEPAD_AXIS_INVALID) { } else if (axis != SDL_GAMEPAD_AXIS_INVALID) {
auto ApplyDeadzone = [](s8* value, std::pair<int, int> deadzone) {
if (std::abs(*value) <= deadzone.first || deadzone.first == deadzone.second) {
*value = 0;
} else {
*value = (*value >= 0 ? 1 : -1) *
std::clamp((int)((128.0 * (std::abs(*value) - deadzone.first)) /
(float)(deadzone.second - deadzone.first)),
0, 128);
}
};
switch (axis) { switch (axis) {
case SDL_GAMEPAD_AXIS_LEFTX:
case SDL_GAMEPAD_AXIS_LEFTY:
ApplyDeadzone(&event.axis_value, leftjoystick_deadzone);
break;
case SDL_GAMEPAD_AXIS_RIGHTX:
case SDL_GAMEPAD_AXIS_RIGHTY:
ApplyDeadzone(&event.axis_value, rightjoystick_deadzone);
break;
case SDL_GAMEPAD_AXIS_LEFT_TRIGGER: case SDL_GAMEPAD_AXIS_LEFT_TRIGGER:
ApplyDeadzone(&event.axis_value, lefttrigger_deadzone);
break;
case SDL_GAMEPAD_AXIS_RIGHT_TRIGGER: case SDL_GAMEPAD_AXIS_RIGHT_TRIGGER:
// if it's a button input, then we know the value to set, so the param is 0. ApplyDeadzone(&event.axis_value, righttrigger_deadzone);
// if it's an analog input, then the param isn't 0
*new_param = (event.active ? event.axis_value : 0) + *new_param;
break; break;
default: default:
*new_param = (event.active ? event.axis_value : 0) + *new_param; UNREACHABLE();
break; break;
} }
*new_param = (event.active ? event.axis_value : 0) + *new_param;
} }
} }
void ControllerOutput::FinalizeUpdate() { void ControllerOutput::FinalizeUpdate() {
state_changed = old_button_state != new_button_state || old_param != *new_param;
if (!state_changed) { if (!state_changed) {
// return; return;
} }
old_button_state = new_button_state; old_button_state = new_button_state;
old_param = *new_param; old_param = *new_param;
float touchpad_x = 0; float touchpad_x = 0;
@ -512,36 +530,21 @@ void ControllerOutput::FinalizeUpdate() {
} else if (axis != SDL_GAMEPAD_AXIS_INVALID && positive_axis) { } else if (axis != SDL_GAMEPAD_AXIS_INVALID && positive_axis) {
// avoid double-updating axes, but don't skip directional button bindings // avoid double-updating axes, but don't skip directional button bindings
float multiplier = 1.0; float multiplier = 1.0;
int deadzone = 0;
auto ApplyDeadzone = [](s16* value, std::pair<int, int> deadzone) {
if (std::abs(*value) <= deadzone.first || deadzone.first == deadzone.second) {
*value = 0;
} else {
*value = (*value >= 0 ? 1 : -1) *
std::clamp((int)((128.0 * (std::abs(*value) - deadzone.first)) /
(float)(deadzone.second - deadzone.first)),
0, 128);
}
};
Axis c_axis = GetAxisFromSDLAxis(axis); Axis c_axis = GetAxisFromSDLAxis(axis);
switch (c_axis) { switch (c_axis) {
case Axis::LeftX: case Axis::LeftX:
case Axis::LeftY: case Axis::LeftY:
ApplyDeadzone(new_param, leftjoystick_deadzone);
multiplier = leftjoystick_halfmode ? 0.5 : 1.0; multiplier = leftjoystick_halfmode ? 0.5 : 1.0;
break; break;
case Axis::RightX: case Axis::RightX:
case Axis::RightY: case Axis::RightY:
ApplyDeadzone(new_param, rightjoystick_deadzone);
multiplier = rightjoystick_halfmode ? 0.5 : 1.0; multiplier = rightjoystick_halfmode ? 0.5 : 1.0;
break; break;
case Axis::TriggerLeft: case Axis::TriggerLeft:
ApplyDeadzone(new_param, lefttrigger_deadzone);
controller->Axis(0, c_axis, GetAxis(0x0, 0x80, *new_param)); controller->Axis(0, c_axis, GetAxis(0x0, 0x80, *new_param));
controller->CheckButton(0, OrbisPadButtonDataOffset::L2, *new_param > 0x20); controller->CheckButton(0, OrbisPadButtonDataOffset::L2, *new_param > 0x20);
return; return;
case Axis::TriggerRight: case Axis::TriggerRight:
ApplyDeadzone(new_param, righttrigger_deadzone);
controller->Axis(0, c_axis, GetAxis(0x0, 0x80, *new_param)); controller->Axis(0, c_axis, GetAxis(0x0, 0x80, *new_param));
controller->CheckButton(0, OrbisPadButtonDataOffset::R2, *new_param > 0x20); controller->CheckButton(0, OrbisPadButtonDataOffset::R2, *new_param > 0x20);
return; return;
@ -572,6 +575,10 @@ bool UpdatePressedKeys(InputEvent event) {
pressed_keys.insert(it, {event, false}); pressed_keys.insert(it, {event, false});
LOG_DEBUG(Input, "Added axis {} to the input list", event.input.sdl_id); LOG_DEBUG(Input, "Added axis {} to the input list", event.input.sdl_id);
} else { } else {
// noise filter
if (std::abs(it->first.axis_value - event.axis_value) <= 1) {
return false;
}
it->first.axis_value = event.axis_value; it->first.axis_value = event.axis_value;
} }
return true; return true;