From 5b70495e652e2d6320c333356523d0cbfef8f209 Mon Sep 17 00:00:00 2001 From: deeebug <77402236+deeebug@users.noreply.github.com> Date: Wed, 3 May 2023 22:24:57 +0545 Subject: [PATCH 1/2] Add SOCD resolution with fixes to dual directional --- headers/addons/dualdirectional.h | 1 + headers/gamepad.h | 6 ++++++ headers/gamepad/GamepadEnums.h | 4 +++- src/addons/dualdirectional.cpp | 33 ++++++++++++++++++++++++-------- src/addons/i2cdisplay.cpp | 3 ++- src/gamepad.cpp | 3 ++- 6 files changed, 39 insertions(+), 11 deletions(-) diff --git a/headers/addons/dualdirectional.h b/headers/addons/dualdirectional.h index 221445c7e..91e867a73 100644 --- a/headers/addons/dualdirectional.h +++ b/headers/addons/dualdirectional.h @@ -59,6 +59,7 @@ class DualDirectionalInput : public GPAddon { uint8_t SOCDCombine(SOCDMode, uint8_t); uint8_t SOCDGamepadClean(uint8_t, bool isLastWin); void OverrideGamepad(Gamepad *, DpadMode, uint8_t); + const SOCDMode getSOCDMode(GamepadOptions&); uint8_t dDebState; // Debounce State (stored) uint8_t dualState; // Dual Directional State DpadDirection lastGPUD; // Gamepad Last Up-Down diff --git a/headers/gamepad.h b/headers/gamepad.h index a21c60301..6368b906c 100644 --- a/headers/gamepad.h +++ b/headers/gamepad.h @@ -157,6 +157,12 @@ class Gamepad { GamepadButtonMapping *mapButtonA2; GamepadButtonMapping **gamepadMappings; + inline static const SOCDMode resolveSOCDMode(const GamepadOptions& options) { + return ((options.socdMode == SOCD_MODE_BYPASS) && + (options.inputMode == INPUT_MODE_HID || options.inputMode == INPUT_MODE_SWITCH || options.inputMode == INPUT_MODE_PS4)) ? + SOCD_MODE_NEUTRAL : options.socdMode; + }; + private: void releaseAllKeys(void); void pressKey(uint8_t code); diff --git a/headers/gamepad/GamepadEnums.h b/headers/gamepad/GamepadEnums.h index 3947c9439..2c41037c4 100644 --- a/headers/gamepad/GamepadEnums.h +++ b/headers/gamepad/GamepadEnums.h @@ -34,6 +34,7 @@ typedef enum SOCD_MODE_NEUTRAL, // U+D=N, L+R=N SOCD_MODE_SECOND_INPUT_PRIORITY, // U>D=D, L>R=R (Last Input Priority, aka Last Win) SOCD_MODE_FIRST_INPUT_PRIORITY, // U>D=U, L>R=L (First Input Priority, aka First Win) + SOCD_MODE_BYPASS, // U+D=UD, L+R=LR (No cleaning applied) } SOCDMode; // Enum for tracking last direction state of Second Input SOCD method @@ -60,5 +61,6 @@ typedef enum HOTKEY_SOCD_LAST_INPUT, HOTKEY_INVERT_X_AXIS, HOTKEY_INVERT_Y_AXIS, - HOTKEY_SOCD_FIRST_INPUT + HOTKEY_SOCD_FIRST_INPUT, + HOTKEY_SOCD_BYPASS } GamepadHotkey; diff --git a/src/addons/dualdirectional.cpp b/src/addons/dualdirectional.cpp index b6023ac15..a31dfe3f1 100644 --- a/src/addons/dualdirectional.cpp +++ b/src/addons/dualdirectional.cpp @@ -86,15 +86,16 @@ void DualDirectionalInput::preprocess() // Convert gamepad from process() output to uint8 value uint8_t gamepadState = gamepad->state.dpad; + const SOCDMode& socdMode = getSOCDMode(gamepad->options); // Combined Mode if ( combineMode == DUAL_COMBINE_MODE_MIXED ) { - SOCDDualClean(gamepad->options.socdMode); // Clean up Dual SOCD based on the mode + SOCDDualClean(socdMode); // Clean up Dual SOCD based on the mode // Second Input (Last Input Priority) needs to happen before we MPG clean - if ( gamepad->options.socdMode == SOCD_MODE_SECOND_INPUT_PRIORITY || - gamepad->options.socdMode == SOCD_MODE_FIRST_INPUT_PRIORITY ) { - gamepadState = SOCDGamepadClean(gamepadState, gamepad->options.socdMode == SOCD_MODE_SECOND_INPUT_PRIORITY) | dualState; + if ( socdMode == SOCD_MODE_SECOND_INPUT_PRIORITY || + socdMode == SOCD_MODE_FIRST_INPUT_PRIORITY ) { + gamepadState = SOCDGamepadClean(gamepadState, socdMode == SOCD_MODE_SECOND_INPUT_PRIORITY) | dualState; } } // Gamepad Overwrite Mode @@ -117,21 +118,24 @@ void DualDirectionalInput::process() { Gamepad * gamepad = Storage::getInstance().GetGamepad(); uint8_t dualOut = dualState; + const SOCDMode& socdMode = getSOCDMode(gamepad->options); // If we're in mixed mode if (combineMode == DUAL_COMBINE_MODE_MIXED) { uint8_t gamepadDpad = gpadToBinary(gamepad->options.dpadMode, gamepad->state); // Up-Win or Neutral Modify AFTER SOCD(gamepad), Last-Win Modifies BEFORE SOCD(gamepad) - if ( gamepad->options.socdMode == SOCD_MODE_UP_PRIORITY || - gamepad->options.socdMode == SOCD_MODE_NEUTRAL ) { + if ( socdMode == SOCD_MODE_UP_PRIORITY || + socdMode == SOCD_MODE_NEUTRAL ) { // Up-Win or Neutral: SOCD(gamepad) *already done* | SOCD(dual) *done in preprocess()* - dualOut = SOCDCombine(gamepad->options.socdMode, gamepadDpad); + dualOut = SOCDCombine(socdMode, gamepadDpad); // Modify Gamepad if we're in mixed Up-Win or Neutral and dual != gamepad if ( dualOut != gamepadDpad ) { OverrideGamepad(gamepad, gamepad->options.dpadMode, dualOut); } + } else if (socdMode == SOCD_MODE_BYPASS) { + OverrideGamepad(gamepad, gamepad->options.dpadMode, dualOut | gamepad->state.dpad); } } else { // We are not mixed mode, don't change dual output dualOut = dualState; @@ -204,6 +208,11 @@ uint8_t DualDirectionalInput::SOCDGamepadClean(uint8_t gamepadState, bool isLast uint8_t DualDirectionalInput::SOCDCombine(SOCDMode mode, uint8_t gamepadState) { uint8_t outState = dualState | gamepadState; + + if (mode == SOCD_MODE_BYPASS) { + return outState; + } + switch (outState & (GAMEPAD_MASK_UP | GAMEPAD_MASK_DOWN)) { case (GAMEPAD_MASK_UP | GAMEPAD_MASK_DOWN): // If last state was Up or Down, exclude it from our gamepad if ( mode == SOCD_MODE_NEUTRAL ) @@ -225,7 +234,11 @@ uint8_t DualDirectionalInput::SOCDCombine(SOCDMode mode, uint8_t gamepadState) { return outState; } -void DualDirectionalInput::SOCDDualClean(SOCDMode socdMode) { +void DualDirectionalInput::SOCDDualClean(SOCDMode socdMode) { + if (socdMode == SOCD_MODE_BYPASS) { + return; + } + // Dual SOCD Last-Win Clean switch (dualState & (GAMEPAD_MASK_UP | GAMEPAD_MASK_DOWN)) { case (GAMEPAD_MASK_UP | GAMEPAD_MASK_DOWN): // If last state was Up or Down, exclude it from our gamepad @@ -310,3 +323,7 @@ uint8_t DualDirectionalInput::gpadToBinary(DpadMode dpadMode, GamepadState state return out; } + +const SOCDMode DualDirectionalInput::getSOCDMode(GamepadOptions& options) { + return Gamepad::resolveSOCDMode(options); +} diff --git a/src/addons/i2cdisplay.cpp b/src/addons/i2cdisplay.cpp index 84de68fa6..0445ad1da 100644 --- a/src/addons/i2cdisplay.cpp +++ b/src/addons/i2cdisplay.cpp @@ -945,12 +945,13 @@ void I2CDisplayAddon::drawStatusBar(Gamepad * gamepad) case DPAD_MODE_RIGHT_ANALOG: statusBar += " RS"; break; } - switch (gamepad->options.socdMode) + switch (Gamepad::resolveSOCDMode(gamepad->options)) { case SOCD_MODE_NEUTRAL: statusBar += " SOCD-N"; break; case SOCD_MODE_UP_PRIORITY: statusBar += " SOCD-U"; break; case SOCD_MODE_SECOND_INPUT_PRIORITY: statusBar += " SOCD-L"; break; case SOCD_MODE_FIRST_INPUT_PRIORITY: statusBar += " SOCD-F"; break; + case SOCD_MODE_BYPASS: statusBar += " "; break; } drawText(0, 0, statusBar); } diff --git a/src/gamepad.cpp b/src/gamepad.cpp index 9d7fd935b..70f261f28 100644 --- a/src/gamepad.cpp +++ b/src/gamepad.cpp @@ -148,7 +148,7 @@ void Gamepad::process() { memcpy(&rawState, &state, sizeof(GamepadState)); - state.dpad = runSOCDCleaner(options.socdMode, state.dpad); + state.dpad = runSOCDCleaner(resolveSOCDMode(options), state.dpad); switch (options.dpadMode) { @@ -283,6 +283,7 @@ GamepadHotkey Gamepad::hotkey() case HOTKEY_SOCD_NEUTRAL : options.socdMode = SOCD_MODE_NEUTRAL; break; case HOTKEY_SOCD_LAST_INPUT : options.socdMode = SOCD_MODE_SECOND_INPUT_PRIORITY; break; case HOTKEY_SOCD_FIRST_INPUT : options.socdMode = SOCD_MODE_FIRST_INPUT_PRIORITY; break; + case HOTKEY_SOCD_BYPASS : options.socdMode = SOCD_MODE_BYPASS; break; case HOTKEY_INVERT_X_AXIS : break; case HOTKEY_INVERT_Y_AXIS : if (lastAction != HOTKEY_INVERT_Y_AXIS) From 63dc9b78f139c4d03e9480864ded3012803c50ca Mon Sep 17 00:00:00 2001 From: deeebug <77402236+deeebug@users.noreply.github.com> Date: Sat, 6 May 2023 09:57:25 +0545 Subject: [PATCH 2/2] Add missing SOCD check --- headers/gamepad/GamepadState.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/headers/gamepad/GamepadState.h b/headers/gamepad/GamepadState.h index 8538dda49..91b4c7bea 100644 --- a/headers/gamepad/GamepadState.h +++ b/headers/gamepad/GamepadState.h @@ -153,6 +153,10 @@ inline uint16_t dpadToAnalogY(uint8_t dpad) */ inline uint8_t runSOCDCleaner(SOCDMode mode, uint8_t dpad) { + if (mode == SOCD_MODE_BYPASS) { + return dpad; + } + static DpadDirection lastUD = DIRECTION_NONE; static DpadDirection lastLR = DIRECTION_NONE; uint8_t newDpad = 0;