Skip to content

fix(input): keep camera inversion out of stick rest detection - #2286

Merged
hckrman101 merged 1 commit into
NotRexed:mainfrom
Arkex-ai:fix/stick-rest-inversion
Nov 11, 2026
Merged

hckrman101 merged 1 commit into
NotRexed:mainfrom
Arkex-ai:fix/stick-rest-inversion

Conversation

@Arkex-ai

@Arkex-ai Arkex-ai commented Nov 11, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Changing camera X/Y inversion can make the camera spin again after the held-stick protection blocked a phantom axis. The setting flips the sign used to recognize a physical crossing, permanently admitting the unchanged held input; reversing the setting then reverses the spin instead of stopping it.

Fixes #2273 by keeping rest detection independent of configurable output inversion.

Technical changes

  • Admit each SDL axis in a stable orientation, then apply camera X/Y inversion to its output.
  • Preserve genuine neutral/crossing recovery, the selected dead zone, independently tracked devices/axes and immediate inversion of already-admitted input.
  • Add a game-free test that compiles the actual SDL conversion/rest/output block with production axis conversion helpers and authored samples. No binding, camera-speed, XInput or renderer change.

Validation

Tested 8f572915 on main 49f75dc8:

  • 108 scenarios pass on Windows and Linux: repeated inversion toggles, both right axes/signs, endpoints and just-outside-dead-zone input, all six dead zones, two independent devices, genuine crossings, neutral recovery and unchanged left-axis mapping.
  • The original source fails. Five mutations are rejected on both OSes: inversion before filtering, missing gating, missing output inversion, missing physical-crossing recovery and shared device state.
  • Existing stick-rest and exhaustive dead-zone checks pass on both OSes. The entire changed pad_sdl.c translation unit also compiles on both, using runtime model headers generated solely from tracked recompiler source, without game instructions.
  • Full Linux: 352 passed / 0 failed / 23 skipped, versus exact base 351/0/23; jq supplied for the release-script checks.
  • Full Windows: 342 passed / 3 failed / 30 skipped, versus exact base 341/3/30. The same three checks fail: NUP file-link privilege fixtures, missing windows.h for the compute-guard fixture, and the recorder destructor negative control. One new source check passes; no new failures.

These are authored device samples and real compiled host code. A physical controller and game runtime have not been tested; no gameplay or performance result is claimed. Hosted exact-head checks are pending.

Claimed before implementation in dev-work and on the issue. Severity S2; reach1.0 is an upper bound, since the affected SDL/phantom-device subset is unknown; confidence1.0 refers to the authored source regression.

Current-head workflow Result
Linux AppImage Needs attention
Game-free source regressions Passed
PR title Passed
Windows builder Passed

Apply configurable inversion only after admitting an axis, preserving physical rest and crossing recovery across settings changes.

Assisted-by: OpenAI Codex

@hckrman101 hckrman101 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. The fix is small and right: the rest detector now always sees the stick in one fixed orientation (right X as 0, right Y as 1), and camera inversion is applied to the admitted output afterwards. That is the same output as before for every admitted input (the old inv_y ? 0 : 1 and the new -v on top of the fixed flip cancel exactly), and it stops the setting from flipping the sign the rest/crossing check sees. Neutral and worn-stick crossing recovery are untouched.

CI: the source regressions, Windows builder and Vulkan jobs pass. The AppImage job timed out at 1h, which is unrelated to a 6-line change in pad_sdl.c.

Overlap: #1600 (stick direction outside the dead zone) edits the same block in pads_poll and drops stick_value, so whichever lands second needs a rebase. They don't disagree, though: #1600 also does the inversion after filtering (if (inv_x) v[2] = -v[2]), just with the Y flip folded in differently, and it would need to keep this PR's placement after the rest gating. #1945 (camera speed) doesn't touch pad_sdl.c, so no conflict.

Nit: a physical controller has not been tried (the PR says so), so a quick in-game check of a toggle with a real pad would be nice, but not blocking.

@hckrman101
hckrman101 merged commit b29967b into NotRexed:main Nov 11, 2026
14 of 15 checks passed
hckrman101 pushed a commit that referenced this pull request Nov 12, 2026
The worklist was behind the forum and the merges. Since v2.1.0, many fix
PRs have merged, several rows already shipped, and the most-reported
problems in Discord #bug-reporting had no row. This PR brings
`docs/worklist.md` back in line, following the rules in the worklist and
in `docs/workflow.md`.

## Method
- **Forum snapshot.** All 409 #bug-reporting posts as of Nov 11, ~11:10
PM ET (Nov 7-11). Each post is dated by its thread ID, so the submit
time is in ET.
- **How dates were used.**
- v2.1.0 was cut from `main` at about 8:32 PM ET on Nov 10 and published
at 9:29 PM ET. A PR merged before the cut counts as shipped; I checked
this with `git merge-base --is-ancestor <merge commit> v2.1.0`.
- A report sent before a fix shipped and not repeated after it counts as
fixed.
- A report sent after v2.1.0, or before a fix that merged later, counts
as still open or waiting for a release.
- **Score.** Severity x reach x confidence.
- Reach comes from workflow.md's 2026-11-10 reporter shares. Where the
affected subset is unknown, it is marked as an upper bound.
- Confidence is 0.7 only where the GitHub tracker has logs from several
commenters; otherwise it is 0.4.
- **Owners.** New rows have no owner. Existing owners are kept.

## Changes
- **Added 20 rows (18 Open, 2 Fixed-waiting).**
- Open: RAM/VRAM fill-up to OOM (#993, 5.6; 13 threads after v2.1.0),
shader preparation stalls (3.2), AMD Windows crashes (#996, 2.9),
CPU-bound fps in Castle Town and Hyrule Field (#995), invisible objects
and doors (#1002), build.py stopped on v2.1.0, cutscene audio desync,
shadow artifacts, coloured lighting, HDR black screen and flicker, frame
generation stutter, the block grid around lights and fog, the v2.1.0
update failing, AF outlines, wrong button glyphs, Steam Deck at 6 fps,
Linux AMD slower than Windows, and the FSR 4 tick not rebuilding.
- Fixed-waiting: the pick-up counter above 60 fps (#2006) and RADV
device lost after the intro (#2362).
- **Updated 6 rows.**
- The Link-jump row is now the "above a 60 fps cap" row (#1742),
covering the Scarecrow's Song softlock, Gohma and the item hanging above
Link's head. It goes from S2 to S1 and is re-scored from 1.2 to 3.5.
- New forum links or scores on the antivirus, Intel black screen (0.11
to 0.2, #999 has logs), fairy grotto, voices (#2506) and RX 580 (#2343)
rows.
- **Moved 10 rows to Fixed, waiting for a release.** #2545 (ground
garbling), #2451 (RTX 30 crash), #2286, #2275, #2449, #2096, #2406,
#2515, #1954 and #2367.
- **Deleted 8 rows** whose fix shipped in v2.1.0: #1792, #1922, #1819,
#1863, #1447, #1451, #1769-#1810 and the HDR10 overlay.

## Not done
- PRs listed as "candidate" fixes are matched by title and description
only. None is confirmed against the reports.
- Long forum threads were judged from their summaries.
- `tests/run_all.py` was not run (docs-only change).

Co-authored-by: Joey Magnus <joey.magnus@cxalloy.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Camera spinning still happens once you try changing X/Y inversion.

2 participants