Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option to bypass SOCD cleaning for supported input modes #210

Merged
merged 3 commits into from
May 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions headers/addons/dualdirectional.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 6 additions & 0 deletions headers/gamepad.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
4 changes: 3 additions & 1 deletion headers/gamepad/GamepadEnums.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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;
4 changes: 4 additions & 0 deletions headers/gamepad/GamepadState.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
33 changes: 25 additions & 8 deletions src/addons/dualdirectional.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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;
Expand Down Expand Up @@ -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 )
Expand All @@ -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
Expand Down Expand Up @@ -310,3 +323,7 @@ uint8_t DualDirectionalInput::gpadToBinary(DpadMode dpadMode, GamepadState state

return out;
}

const SOCDMode DualDirectionalInput::getSOCDMode(GamepadOptions& options) {
return Gamepad::resolveSOCDMode(options);
}
3 changes: 2 additions & 1 deletion src/addons/i2cdisplay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
3 changes: 2 additions & 1 deletion src/gamepad.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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)
Expand Down