Skip to content

iOS: a controller with no gyroscope leaves the phone's gyro in charge (#971) - #975

Open
Haseenesss wants to merge 3 commits into
LNPANDY:mainfrom
Haseenesss:fix/971-ios-phone-gyro-fallback
Open

Haseenesss wants to merge 3 commits into
LNPANDY:mainfrom
Haseenesss:fix/971-ios-phone-gyro-fallback

Conversation

@Haseenesss

@Haseenesss Haseenesss commented Nov 8, 2026 •

Copy link
Copy Markdown
Contributor

Fix or feature

  • Fix
  • Feature

What and why

The iOS part of #971.

Symptom. On an iPhone, Breath of the Wild's gyro works with no controller and with a Pro Controller over USB. With a GameSir X5 Lite, a controller the phone mounts in and which has no gyroscope, motion stops a few seconds after the touch controls disappear. The reporter's log (in the issue) has controller 'GameSir-X5 Lite_S' connected: player 1 (npad 0), with motion (gyro): GameController lists it with a rotation rate.

Cause. The phone's gyro drives player 1 only while no controller supplies fresh motion (DM_PHONE_MOTION=auto, hle_hid.c). The Apple adapter (motion_apple.h) took a controller as a source at its first report that is not all zeroes, so a controller that advertises a gyroscope it does not have, and sends anything else, takes over from the phone. The reporter's DM_MOTION_LOG=1 log (comment) confirms it: all 26 controller lines read acc +0.00 +0.00 -1.04 G, gyro +0.000 +0.003 -0.000 rev/s, the same report every time, and they win over the phone's while it is held and moved. With DM_PHONE_MOTION=1 the phone's gyro works with the X5 Lite attached.

This adapter rule and the phone fallback did not change between v1.2.0 and v1.3.0, upstream or here. The reporter says the controller firmware and iOS did not change either, so why v1.2.0 worked is not explained.

Change.

  • patches/0100-motion-source-once-its-rotation-changes.patch: a controller becomes a motion source once its rotation rate changes from its first report. A real gyroscope's noise changes it within a few reports; a missing one never does. The zero-only reports of Launcher: one size for the hero button, one line for every row control #296 (seedds) are the same case. After that, still or zero samples are taken as before. Upstream-Status: forwarded seedds/nxnative#1877.
  • patches/0101-test-native-motion-primes-the-adapter.patch: the fork's test_native_motion_integration (t_controllers_mac.m, from patch 0081) sends a priming report first.

The numbers follow main's 0097 and 0098 and #972's 0099; they are placeholders until merge.

Checked

  • Tests: python3 tools/engine.py check (66 patches apply to c78d7375). t_motion_apple, t_controllers_mac, t_motion, t_motion_pro_mac, t_hid pass. t_motion_apple.m with motion_apple.h passes -fsyntax-only against the iOS SDK.
  • Test for a fix: t_motion_apple sends a moving accelerometer with a constant rotation rate (zero and not zero): no sample is published until the rotation changes. It fails on the old adapter.
  • Run on a device or Mac: not run on an iPhone, and no GameSir controller here. The values the X5 Lite sends come from the reporter's log; the build with this change has not been tried on the device yet.

Screenshots

None, no visible change.

Scope

  • No engine file (dm/, scripts/, docs/, ref/) is added to the repository: a change there is a patch in patches/ (a commit in engine/, then tools/engine.py export, and tools/engine.py check passes), with its Upstream-Status
  • A fix to the engine or a game profile also goes to seedds/nxnative as a PR in parallel: this PR's patch says forwarded seedds/nxnative#..., or pending until that PR is open
  • A change to a launcher view has before and after screenshots above
  • No keys, game files or data extracted from a game in the change or the attachments

🤖 Generated with Claude Code

…LNPANDY#971)

The GameSir X5 Lite, a controller an iPhone mounts in, has no gyroscope, but
GameController lists it with a rotation rate. The Apple adapter took any report
that is not all zeroes as live motion, so it replaced the phone's gyro a few
seconds after it connected. Patch 0099 takes a controller as a motion source
once its rotation rate changes from its first report. Patch 0100 primes the
fork's native-motion test accordingly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added the patch-queue Changes the patch queue or the upstream pin label Nov 8, 2026
…d 0101

main moved the pin to c78d7375 and added patches 0097 and 0098; LNPANDY#972 takes 0099.
Both patches here apply unchanged on the new pin.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Haseenesss
Haseenesss marked this pull request as ready for review November 8, 2026 23:35
@v0lumehi

v0lumehi commented Nov 9, 2026

Copy link
Copy Markdown
Collaborator

@Haseenesss thanks for the patch. The code and the test look right to me. It has not been tried on an iPhone with the GameSir X5 Lite yet. Please ask the reporter of #971 to try a test build and post the result here. I would merge after that. The patch numbers 0100 and 0101 collide with other open PRs, so whoever merges later renumbers.

@v0lumehi

v0lumehi commented Nov 9, 2026

Copy link
Copy Markdown
Collaborator

Also @Haseenesss, please explain to me, why would you want to use the iPhone's gyro when holding a controller in your hands? Because some games require you to use gyro?

@Haseenesss

Copy link
Copy Markdown
Contributor Author

@v0lumehi The X5 Lite is a controller the phone mounts in: the iPhone sits between its two halves, like a Backbone or a Kishi.

GameSir X5 Lite, with and without an iPhone mounted in it

Holding the controller is holding the phone, as a Switch in handheld mode is held with the Joy-Cons on it. The X5 Lite has no gyroscope, so the phone's is the only one there. Breath of the Wild needs it for motion aiming and for some shrines that can only be solved with motion.

This PR doesn't change when the phone's gyro is used. Since #351 it drives player 1 while no controller supplies fresh motion (DM_PHONE_MOTION=auto), and DM_PHONE_MOTION=0 turns it off. A controller with a real gyroscope, held apart from the phone (DualSense, Pro Controller), still drives the motion itself. What changes is only what counts as a controller supplying motion: the X5 Lite sends the same report every time, and that no longer counts.

@v0lumehi

v0lumehi commented Nov 9, 2026

Copy link
Copy Markdown
Collaborator

@Haseenesss got it, that makes sense

@v0lumehi v0lumehi modified the milestones: v1.4.0, v1.5.0 Nov 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

patch-queue Changes the patch queue or the upstream pin

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants