diff --git a/aurora-main/include/dolphin/pad.h b/aurora-main/include/dolphin/pad.h index df5f358..69dfcd3 100644 --- a/aurora-main/include/dolphin/pad.h +++ b/aurora-main/include/dolphin/pad.h @@ -181,6 +181,8 @@ constexpr u32 PADEncodeAxisButton(u32 axis, bool negative, u32 threshold = 50) { } constexpr bool PADIsAxisButton(u32 binding) { return (binding & 0xffff0000u) == 0x10000u; } constexpr u32 PADAxisButtonThreshold(u32 binding) { return (binding >> 8) & 0xffu; } +constexpr u32 PADAxisButtonAxis(u32 binding) { return binding & 0x7fu; } +constexpr bool PADAxisButtonNegative(u32 binding) { return (binding & 0x80u) != 0; } constexpr u32 PADAxisButtonIdentity(u32 binding) { return PADIsAxisButton(binding) ? (binding & ~0xff00u) : binding; } diff --git a/aurora-main/lib/dolphin/pad/pad.cpp b/aurora-main/lib/dolphin/pad/pad.cpp index 61deb3f..75ef372 100644 --- a/aurora-main/lib/dolphin/pad/pad.cpp +++ b/aurora-main/lib/dolphin/pad/pad.cpp @@ -321,11 +321,11 @@ std::array g_suppressRightTrigger{}; bool is_mouse_scancode(const s32 scancode) { return scancode < PAD_KEY_INVALID; } bool is_native_binding_pressed(SDL_Gamepad* gamepad, u32 binding) { if (PADIsAxisButton(binding)) { - const u32 axis = binding & 0x7fu; + const u32 axis = PADAxisButtonAxis(binding); const u32 threshold = PADAxisButtonThreshold(binding); if (axis >= SDL_GAMEPAD_AXIS_COUNT || threshold < 1 || threshold > 100) return false; int value = SDL_GetGamepadAxis(gamepad, static_cast(axis)); - if ((binding & 0x80u) != 0) value = -value; + if (PADAxisButtonNegative(binding)) value = -value; return value > 0 && value * 100 >= static_cast(threshold) * 32767; } return binding < SDL_GAMEPAD_BUTTON_COUNT && @@ -962,7 +962,9 @@ u32 PADRead(PADStatus* status) { // An explicit button binding must drive both, otherwise the original // L2/R2 axis still activates L/R even when it was rebound to L1/R1. // Real GC pads retain independent analog travel and end-stop clicks. - if (!controller->m_isGameCube) { + if (!(controller->m_isGameCube || + (SDL_GetGamepadType(controller->m_controller) == SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO && + controller->m_pid == 0x2073))) { if (leftTriggerSet) tl = (status[i].button & PAD_TRIGGER_L) != 0 ? 32767 : 0; if (rightTriggerSet) tr = (status[i].button & PAD_TRIGGER_R) != 0 ? 32767 : 0; } diff --git a/runtime/include/controller_button_names.h b/runtime/include/controller_button_names.h index 8dcd5d8..ab61c03 100644 --- a/runtime/include/controller_button_names.h +++ b/runtime/include/controller_button_names.h @@ -48,7 +48,7 @@ struct NativeButtonItem { uint32_t nativeButton; }; -inline constexpr std::array kNativeButtons = {{ +inline constexpr auto kNativeButtons = std::to_array({ {"disabled", "Unmapped", PAD_NATIVE_BUTTON_DISABLED}, {"left_trigger", "Left trigger (LT / L2)", PADEncodeAxisButton(SDL_GAMEPAD_AXIS_LEFT_TRIGGER, false)}, {"right_trigger", "Right trigger (RT / R2)", PADEncodeAxisButton(SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, false)}, @@ -87,7 +87,7 @@ inline constexpr std::array kNa {"misc4", "Misc 4 / GC R click", SDL_GAMEPAD_BUTTON_MISC4}, {"misc5", "Misc 5", SDL_GAMEPAD_BUTTON_MISC5}, {"misc6", "Misc 6", SDL_GAMEPAD_BUTTON_MISC6}, -}}; +}); inline std::string TrimToken(std::string_view token) { const size_t begin = token.find_first_not_of(" \t"); diff --git a/runtime/src/input_bindings.cpp b/runtime/src/input_bindings.cpp index f81a16b..03d2456 100644 --- a/runtime/src/input_bindings.cpp +++ b/runtime/src/input_bindings.cpp @@ -95,8 +95,8 @@ double ReadInput(SDL_Gamepad* gamepad, const std::string& name) { // here does not have to use Dolphin vocabulary. if (const auto* native = ControllerNames::FindNativeButton(name)) { if (PADIsAxisButton(native->nativeButton)) { - const auto axis = static_cast(native->nativeButton & 0x7fu); - const double sign = (native->nativeButton & 0x80u) != 0 ? -1.0 : 1.0; + const auto axis = static_cast(PADAxisButtonAxis(native->nativeButton)); + const double sign = PADAxisButtonNegative(native->nativeButton) ? -1.0 : 1.0; return std::clamp(SDL_GetGamepadAxis(gamepad, axis) / 32767.0 * sign, 0.0, 1.0); } if (native->nativeButton < SDL_GAMEPAD_BUTTON_COUNT) { diff --git a/runtime/src/settings_overlay.cpp b/runtime/src/settings_overlay.cpp index b0572b7..8c55479 100644 --- a/runtime/src/settings_overlay.cpp +++ b/runtime/src/settings_overlay.cpp @@ -509,13 +509,16 @@ void DrawRebindPrompt() { ImGui::OpenPopup("Rebind input"); g_rebind.openPopup = false; } - if (!ImGui::BeginPopupModal("Rebind input", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) return; + if (!ImGui::BeginPopupModal("Rebind input", &g_rebind.active, ImGuiWindowFlags_AlwaysAutoResize)) { + g_rebind.active = false; + return; + } if (g_rebind.active) { ImGui::Text("Rebind: %s", g_rebind.label.c_str()); ImGui::TextUnformatted(g_rebind.kind == RebindKind::Controller ? "Press a controller button, pull a trigger, or move a stick." : "Press a keyboard key or click a mouse button."); - ImGui::TextUnformatted("Release any held input first. F10 is reserved for settings."); + ImGui::TextUnformatted("Release any held input first. Escape cancels. F10 is reserved for settings."); const float remaining = std::chrono::duration(g_rebind.deadline - Clock::now()).count(); ImGui::Text("Unmapped in %d seconds", std::max(0, static_cast(std::ceil(remaining)))); if (remaining <= 0.0f) { @@ -867,6 +870,8 @@ void DrawControllerSettings() { }; if (secondary) PADSetAltButtonMapping(selectedGamePort, updated); else PADSetButtonMapping(selectedGamePort, updated); + } + if (ImGui::IsItemDeactivatedAfterEdit()) { writeBinding(i, mappingIt->nativeButton, altIt != nullptr ? altIt->nativeButton : PAD_NATIVE_BUTTON_INVALID); PADSerializeMappings(); @@ -1306,6 +1311,9 @@ void HandleEvents(const AuroraEvent* events) noexcept { continue; } controller_mapping_wizard::HandleSdlEvent(ev->sdl); + if (g_rebind.active && IsToggleKey(ev->sdl, SDL_SCANCODE_ESCAPE)) { + g_rebind.active = false; + } if (!g_rebind.active && IsToggleKey(ev->sdl, SDL_SCANCODE_F10)) { SetTopBarVisible(!g_topBarVisible); }