Skip to content
Open
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
74 changes: 74 additions & 0 deletions UnleashedRecomp/hid/driver/sdl_hid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,18 @@
#define TRANSLATE_INPUT(S, X) SDL_GameControllerGetButton(controller, S) << FirstBitLow(X)
#define VIBRATION_TIMEOUT_MS 5000

static bool IsBoostOnRightTriggerActive()
{
// true if sonic is werehog and right trigger preference is boost
return !App::s_isWerehog && Config::RightTriggerAction == ERightTriggerAction::Boost;
}

static uint32_t GetBoostCancelDurationMs()
{
int32_t fps = Config::FPS > 0 ? Config::FPS : 60;
return static_cast<uint32_t>(2000 / fps);
}

class Controller
{
public:
Expand All @@ -20,6 +32,13 @@ class Controller
XAMINPUT_VIBRATION vibration{ 0, 0 };
int index{};

// for when user sets Config::RightTriggerAction to ERightTriggerAction this
// increases stability to allow square/X to be recognised by the game while
// right trigger is being pressed down especially when the user is moving
// the thumbsticks
bool xWasHeldLastPoll{};
uint32_t xCancelUntilTick{};

Controller() = default;

explicit Controller(int index) : Controller(SDL_GameControllerOpen(index))
Expand Down Expand Up @@ -99,6 +118,33 @@ class Controller

pad.bLeftTrigger = SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_TRIGGERLEFT) >> 7;
pad.bRightTrigger = SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_TRIGGERRIGHT) >> 7;



if (IsBoostOnRightTriggerActive())
{
bool xHeldPhysically = SDL_GameControllerGetButton(controller, SDL_CONTROLLER_BUTTON_X) != 0;
bool xRisingEdge = xHeldPhysically && !xWasHeldLastPoll;
bool rtPulled = pad.bRightTrigger >= 30; // TODO: change this to a pressure preference

// these checks are in place to improve responsiveness of square/X while right trigger is held down
if (xRisingEdge && rtPulled)
xCancelUntilTick = SDL_GetTicks() + GetBoostCancelDurationMs();

bool inCancelWindow = SDL_TICKS_PASSED(xCancelUntilTick, SDL_GetTicks());

if (inCancelWindow)
pad.wButtons &= ~XAMINPUT_GAMEPAD_X;
else if (xHeldPhysically || rtPulled)
pad.wButtons |= XAMINPUT_GAMEPAD_X;
else
pad.wButtons &= ~XAMINPUT_GAMEPAD_X;

if (rtPulled)
pad.bRightTrigger = 0;

xWasHeldLastPoll = xHeldPhysically;
}
}

void Poll()
Expand Down Expand Up @@ -129,6 +175,34 @@ class Controller
pad.wButtons |= TRANSLATE_INPUT(SDL_CONTROLLER_BUTTON_B, XAMINPUT_GAMEPAD_B);
pad.wButtons |= TRANSLATE_INPUT(SDL_CONTROLLER_BUTTON_X, XAMINPUT_GAMEPAD_X);
pad.wButtons |= TRANSLATE_INPUT(SDL_CONTROLLER_BUTTON_Y, XAMINPUT_GAMEPAD_Y);

// when playing day stages keep the right trigger mirrored onto square/X
// so so the game knows the user is boosting. This will remove the actual
// right trigger from the game so sonic wouldn't drift
if (IsBoostOnRightTriggerActive())
{
bool xHeldPhysically = (pad.wButtons & XAMINPUT_GAMEPAD_X) != 0;
bool xRisingEdge = xHeldPhysically && !xWasHeldLastPoll;
uint8_t rtRaw = SDL_GameControllerGetAxis(controller, SDL_CONTROLLER_AXIS_TRIGGERRIGHT) >> 7;
bool rtPulled = rtRaw >= 30; // TODO: change this to a pressure preference

// like in Poll() these checks are in place to improve responsiveness
// of square/X while right trigger is held down
if (xRisingEdge && rtPulled)
xCancelUntilTick = SDL_GetTicks() + GetBoostCancelDurationMs();

bool inCancelWindow = SDL_TICKS_PASSED(xCancelUntilTick, SDL_GetTicks());

if (inCancelWindow)
pad.wButtons &= ~XAMINPUT_GAMEPAD_X;
else if (rtPulled)
pad.wButtons |= XAMINPUT_GAMEPAD_X;

if (rtPulled)
pad.bRightTrigger = 0;

xWasHeldLastPoll = xHeldPhysically;
}
}

void SetVibration(const XAMINPUT_VIBRATION& vibration)
Expand Down
60 changes: 60 additions & 0 deletions UnleashedRecomp/locale/config_locale.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,66 @@ CONFIG_DEFINE_ENUM_LOCALE(ETimeOfDayTransition)
}
};

// Translation required
// Japanese Notes: This localization should include furigana in its description.
CONFIG_DEFINE_LOCALE(RightTriggerAction)
{
{ ELanguage::English, { "Right Trigger Action", "Choose what the right trigger does in day stages." } },
{ ELanguage::Japanese, { "Right Trigger Action", "Choose what the right trigger does in day stages." } }, // Translation required
{ ELanguage::German, { "Right Trigger Action", "Choose what the right trigger does in day stages." } }, // Translation required
{ ELanguage::French, { "Right Trigger Action", "Choose what the right trigger does in day stages." } }, // Translation required
{ ELanguage::Spanish, { "Right Trigger Action", "Choose what the right trigger does in day stages." } }, // Translation required
{ ELanguage::Italian, { "Right Trigger Action", "Choose what the right trigger does in day stages." } } // Translation required
};

// Translation required
// Japanese Notes: This localization should include furigana in its description.
CONFIG_DEFINE_ENUM_LOCALE(ERightTriggerAction)
{
{
ELanguage::English,
{
{ ERightTriggerAction::Drift, { "DRIFT", "Default: the right trigger acts as drift, matching the original Xbox 360/PS3 controls." } },
{ ERightTriggerAction::Boost, { "BOOST/H.A", "EXPERIMENTAL: The right trigger acts as boost or homing attack. Drift is still available on the left trigger and X/Square still triggers boost too." } }
}
},
{
ELanguage::Japanese,
{
{ ERightTriggerAction::Drift, { "DRIFT", "" } },
{ ERightTriggerAction::Boost, { "BOOST", "" } }
}
},
{
ELanguage::German,
{
{ ERightTriggerAction::Drift, { "DRIFT", "" } },
{ ERightTriggerAction::Boost, { "BOOST", "" } }
}
},
{
ELanguage::French,
{
{ ERightTriggerAction::Drift, { "DRIFT", "" } },
{ ERightTriggerAction::Boost, { "BOOST", "" } }
}
},
{
ELanguage::Spanish,
{
{ ERightTriggerAction::Drift, { "DRIFT", "" } },
{ ERightTriggerAction::Boost, { "BOOST", "" } }
}
},
{
ELanguage::Italian,
{
{ ERightTriggerAction::Drift, { "DRIFT", "" } },
{ ERightTriggerAction::Boost, { "BOOST", "" } }
}
}
};

// Japanese Notes: This localization should include furigana.
CONFIG_DEFINE_LOCALE(ControllerIcons)
{
Expand Down
6 changes: 6 additions & 0 deletions UnleashedRecomp/user/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ CONFIG_DEFINE_ENUM_TEMPLATE(ECameraRotationMode)
{ "Reverse", ECameraRotationMode::Reverse },
};

CONFIG_DEFINE_ENUM_TEMPLATE(ERightTriggerAction)
{
{ "Drift", ERightTriggerAction::Drift },
{ "Boost", ERightTriggerAction::Boost }
};

CONFIG_DEFINE_ENUM_TEMPLATE(EControllerIcons)
{
{ "Auto", EControllerIcons::Auto },
Expand Down
6 changes: 6 additions & 0 deletions UnleashedRecomp/user/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ enum class ECameraRotationMode : uint32_t
Reverse
};

enum class ERightTriggerAction : uint32_t
{
Drift,
Boost
};

enum class EControllerIcons : uint32_t
{
Auto,
Expand Down
1 change: 1 addition & 0 deletions UnleashedRecomp/user/config_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ CONFIG_DEFINE("System", bool, ShowConsole, false);

CONFIG_DEFINE_ENUM_LOCALISED("Input", ECameraRotationMode, HorizontalCamera, ECameraRotationMode::Normal);
CONFIG_DEFINE_ENUM_LOCALISED("Input", ECameraRotationMode, VerticalCamera, ECameraRotationMode::Normal);
CONFIG_DEFINE_ENUM_LOCALISED("Input", ERightTriggerAction, RightTriggerAction, ERightTriggerAction::Drift);
CONFIG_DEFINE_LOCALISED("Input", bool, Vibration, true);
CONFIG_DEFINE_LOCALISED("Input", bool, AllowBackgroundInput, false);
CONFIG_DEFINE_ENUM_LOCALISED("Input", EControllerIcons, ControllerIcons, EControllerIcons::Auto);
Expand Down