mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-19 20:20:19 +02:00
fix(input): ignore raw face presses when Joy-Con is gamepad
love-nx emits gamepad+raw on one press; NamingScreen saw a+b and always erased. Skip raw when isGamepad(); align NX Y→a/X→b; prefer A if both. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+16
-4
@@ -16,11 +16,13 @@ GamepadMap.RAW_BUTTON_BINDINGS = {
|
|||||||
[7] = "select", [8] = "start", [9] = "select", [10] = "start",
|
[7] = "select", [8] = "start", [9] = "select", [10] = "start",
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Switch OLED probe 2026-08-01: love.joystickpressed indices (1-based).
|
-- Switch OLED: love.joystickpressed indices (1-based). Used only when the
|
||||||
-- Gamepad path still preferred when isGamepad(); raw covers the rest.
|
-- device is NOT a gamepad — love-nx also emits gamepadpressed for Joy-Con,
|
||||||
|
-- and applying both face paths in one frame breaks NamingScreen (a+b).
|
||||||
|
-- Y→a / X→b matches operator OLED naming diagnosis (2026-08-01).
|
||||||
GamepadMap.NX_RAW_BUTTON_BINDINGS = {
|
GamepadMap.NX_RAW_BUTTON_BINDINGS = {
|
||||||
[1] = "a", [2] = "b",
|
[1] = "a", [2] = "b",
|
||||||
[3] = "b", [4] = "a",
|
[3] = "a", [4] = "b",
|
||||||
[9] = "select", [10] = "start",
|
[9] = "select", [10] = "start",
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,7 +34,7 @@ GamepadMap.RAW_TO_GAMEPAD_BUTTON = {
|
|||||||
|
|
||||||
GamepadMap.NX_RAW_TO_GAMEPAD_BUTTON = {
|
GamepadMap.NX_RAW_TO_GAMEPAD_BUTTON = {
|
||||||
[1] = "a", [2] = "b",
|
[1] = "a", [2] = "b",
|
||||||
[3] = "y", [4] = "x",
|
[3] = "a", [4] = "b",
|
||||||
[9] = "back", [10] = "start",
|
[9] = "back", [10] = "start",
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,6 +56,16 @@ function GamepadMap.mapGamepadButton(button)
|
|||||||
return GamepadMap.DEFAULT_GAMEPAD_BINDINGS[button]
|
return GamepadMap.DEFAULT_GAMEPAD_BINDINGS[button]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- love-nx / SDL: when isGamepad(), face+menu already arrive via gamepad*.
|
||||||
|
-- Applying joystickpressed raw on top double-fires GB A/B in one frame.
|
||||||
|
function GamepadMap.ignoreRawForJoystick(joystick)
|
||||||
|
if not joystick then return false end
|
||||||
|
local ok, isPad = pcall(function()
|
||||||
|
return joystick.isGamepad and joystick:isGamepad()
|
||||||
|
end)
|
||||||
|
return ok and isPad == true
|
||||||
|
end
|
||||||
|
|
||||||
function GamepadMap.mapRawButton(index)
|
function GamepadMap.mapRawButton(index)
|
||||||
if nxActive() then
|
if nxActive() then
|
||||||
local nx = GamepadMap.NX_RAW_BUTTON_BINDINGS[index]
|
local nx = GamepadMap.NX_RAW_BUTTON_BINDINGS[index]
|
||||||
|
|||||||
@@ -180,11 +180,13 @@ function Input:gamepadreleased(joystick, button)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function Input:joystickpressed(joystick, button)
|
function Input:joystickpressed(joystick, button)
|
||||||
|
if GamepadMap.ignoreRawForJoystick(joystick) then return end
|
||||||
local btn = GamepadMap.mapRawButton(button)
|
local btn = GamepadMap.mapRawButton(button)
|
||||||
if btn then press(self, btn, "joy:" .. button) end
|
if btn then press(self, btn, "joy:" .. button) end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Input:joystickreleased(joystick, button)
|
function Input:joystickreleased(joystick, button)
|
||||||
|
if GamepadMap.ignoreRawForJoystick(joystick) then return end
|
||||||
local btn = GamepadMap.mapRawButton(button)
|
local btn = GamepadMap.mapRawButton(button)
|
||||||
if btn then release(self, btn, "joy:" .. button) end
|
if btn then release(self, btn, "joy:" .. button) end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1548,11 +1548,13 @@ function RomImporter:gamepadaxis(_, axis, value)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function RomImporter:joystickpressed(joystick, button)
|
function RomImporter:joystickpressed(joystick, button)
|
||||||
|
if GamepadMap.ignoreRawForJoystick(joystick) then return end
|
||||||
local padButton = GamepadMap.mapRawToGamepadButton(button)
|
local padButton = GamepadMap.mapRawToGamepadButton(button)
|
||||||
if padButton then self:gamepadpressed(joystick, padButton) end
|
if padButton then self:gamepadpressed(joystick, padButton) end
|
||||||
end
|
end
|
||||||
|
|
||||||
function RomImporter:joystickreleased(joystick, button)
|
function RomImporter:joystickreleased(joystick, button)
|
||||||
|
if GamepadMap.ignoreRawForJoystick(joystick) then return end
|
||||||
local padButton = GamepadMap.mapRawToGamepadButton(button)
|
local padButton = GamepadMap.mapRawToGamepadButton(button)
|
||||||
if padButton then self:gamepadreleased(joystick, padButton) end
|
if padButton then self:gamepadreleased(joystick, padButton) end
|
||||||
end
|
end
|
||||||
|
|||||||
+22
-15
@@ -153,21 +153,28 @@ function NamingScreen:update(dt)
|
|||||||
if self.row ~= caseRow then
|
if self.row ~= caseRow then
|
||||||
self.col = self.col < #GRID[self.row] and self.col + 1 or 1
|
self.col = self.col < #GRID[self.row] and self.col + 1 or 1
|
||||||
end
|
end
|
||||||
elseif input:wasPressed("b") then
|
else
|
||||||
table.remove(self.glyphs)
|
-- Prefer A over B when both edges fire in one frame (love-nx dual
|
||||||
elseif input:wasPressed("a") then
|
-- gamepad+raw path historically set both; erase must not win).
|
||||||
if self.row == edRow and self.col == edCol then
|
local pressedA = input:wasPressed("a")
|
||||||
self:confirm()
|
local pressedB = input:wasPressed("b")
|
||||||
return
|
if pressedA and pressedB then pressedB = false end
|
||||||
end
|
if pressedB then
|
||||||
if self.row == caseRow then
|
table.remove(self.glyphs)
|
||||||
self.lower = not self.lower
|
elseif pressedA then
|
||||||
return
|
if self.row == edRow and self.col == edCol then
|
||||||
end
|
self:confirm()
|
||||||
if #self.glyphs < self.maxLen then
|
return
|
||||||
Sound.play(self.game.data, "Press_AB")
|
end
|
||||||
table.insert(self.glyphs, GRID[self.row][self.col])
|
if self.row == caseRow then
|
||||||
if #self.glyphs >= self.maxLen then self:jumpToEnd() end
|
self.lower = not self.lower
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if #self.glyphs < self.maxLen then
|
||||||
|
Sound.play(self.game.data, "Press_AB")
|
||||||
|
table.insert(self.glyphs, GRID[self.row][self.col])
|
||||||
|
if #self.glyphs >= self.maxLen then self:jumpToEnd() end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
-- When isGamepad(), raw face presses must not stack on gamepad* (NamingScreen a+b).
|
||||||
|
package.path = "./?.lua;./?/init.lua;" .. package.path
|
||||||
|
if not _G.love then _G.love = require("tests.love_stub") end
|
||||||
|
|
||||||
|
local T = require("tests.harness")
|
||||||
|
local check = T.check
|
||||||
|
local eq = T.eq
|
||||||
|
|
||||||
|
local GamepadMap = require("src.core.GamepadMap")
|
||||||
|
local Input = require("src.core.Input")
|
||||||
|
|
||||||
|
local gamepadJoy = {
|
||||||
|
isGamepad = function() return true end,
|
||||||
|
}
|
||||||
|
local rawJoy = {
|
||||||
|
isGamepad = function() return false end,
|
||||||
|
}
|
||||||
|
|
||||||
|
check(GamepadMap.ignoreRawForJoystick(gamepadJoy), "ignore raw when isGamepad")
|
||||||
|
check(not GamepadMap.ignoreRawForJoystick(rawJoy), "allow raw when not gamepad")
|
||||||
|
check(not GamepadMap.ignoreRawForJoystick(nil), "nil joystick does not ignore raw")
|
||||||
|
|
||||||
|
GamepadMap._setForceNXForTests(true)
|
||||||
|
eq(GamepadMap.mapRawButton(3), "a", "NX raw Y (#3) -> GB A")
|
||||||
|
eq(GamepadMap.mapRawButton(4), "b", "NX raw X (#4) -> GB B")
|
||||||
|
GamepadMap._setForceNXForTests(false)
|
||||||
|
|
||||||
|
Input:init()
|
||||||
|
Input:gamepadpressed(gamepadJoy, "a")
|
||||||
|
Input:joystickpressed(gamepadJoy, 1) -- must no-op
|
||||||
|
Input:joystickpressed(gamepadJoy, 2) -- must no-op (would have set b)
|
||||||
|
Input:step()
|
||||||
|
check(Input:wasPressed("a"), "gamepad A edge present")
|
||||||
|
check(not Input:wasPressed("b"), "raw must not add B alongside gamepad A")
|
||||||
|
check(Input:isDown("a"), "A held from pad source only")
|
||||||
|
|
||||||
|
Input:init()
|
||||||
|
Input:joystickpressed(rawJoy, 1)
|
||||||
|
Input:step()
|
||||||
|
check(Input:wasPressed("a"), "non-gamepad raw #1 still maps to A")
|
||||||
|
|
||||||
|
T.finish()
|
||||||
@@ -9,11 +9,11 @@ local GamepadMap = require("src.core.GamepadMap")
|
|||||||
|
|
||||||
GamepadMap._setForceNXForTests(true)
|
GamepadMap._setForceNXForTests(true)
|
||||||
|
|
||||||
-- Phase 0 probe: Y→#3, X→#4; Nintendo B/A at #1/#2.
|
-- Phase 0 / naming diagnosis: Y→#3→a, X→#4→b; Nintendo B/A at #1/#2.
|
||||||
eq(GamepadMap.mapRawButton(3), "b", "NX raw Y (#3) maps to GB B")
|
eq(GamepadMap.mapRawButton(3), "a", "NX raw Y (#3) maps to GB A")
|
||||||
eq(GamepadMap.mapRawButton(4), "a", "NX raw X (#4) maps to GB A")
|
eq(GamepadMap.mapRawButton(4), "b", "NX raw X (#4) maps to GB B")
|
||||||
eq(GamepadMap.mapRawToGamepadButton(3), "y", "NX raw #3 routes to gamepad y")
|
eq(GamepadMap.mapRawToGamepadButton(3), "a", "NX raw #3 routes to gamepad a")
|
||||||
eq(GamepadMap.mapRawToGamepadButton(4), "x", "NX raw #4 routes to gamepad x")
|
eq(GamepadMap.mapRawToGamepadButton(4), "b", "NX raw #4 routes to gamepad b")
|
||||||
eq(GamepadMap.mapRawButton(9), "select", "NX minus (#9) -> select")
|
eq(GamepadMap.mapRawButton(9), "select", "NX minus (#9) -> select")
|
||||||
eq(GamepadMap.mapRawButton(10), "start", "NX plus (#10) -> start")
|
eq(GamepadMap.mapRawButton(10), "start", "NX plus (#10) -> start")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user