Stop the pre-boot gate persisting its pointer switch, and repair already-broken installs - #4
Open
bward-dev1 wants to merge 1 commit into
Open
bward-dev1 wants to merge 1 commit into
bward-dev1 wants to merge 1 commit into
Conversation
…alls Builds on fix/device-only-play, which fixes the *defaults* (display-derived + persisted) so a handheld player is no longer pushed into "Point at TV". This covers three things that change doesn't reach. 1. The switch was persisted, and still is on that branch. switchToMotionPointingIfNeeded used Config::SetBaseOrCurrent, which writes the *Base* layer -> Dolphin.ini. So every Wii boot under the old defaults permanently wrote TouchPadIRMode = None (shipped default is 2 = Drag). Deriving better defaults only stops new damage: anyone who has already run a build from master still has touch pointing disabled on disk and stays broken. Split into switchToMotionPointingIfNeededPersisting: -- the automatic pre-game path now writes LayerType::CurrentRun (dropped by BootManager::RestoreConfig, never saved), while the Motion menu's explicit Calibrate/Recenter actions still persist as their alert text promises. Added a one-time repair (DOLDidRepairForcedMotionPointingV1) that restores the shipped default for already-clobbered installs. Why this is the regression Brandon reported: TCWiiPad.handleLongPress returns immediately when mode == .none, so the on-screen touch pointer emits nothing at all. Pointing then falls to the gyro, which has no drift correction left (IMUIR/Accelerometer Influence = 0 from a57ce46, IMUGyroscope/Calibration Period = 0 from 96f567b, so EmulateIMUCursor runs a zero-weight complementary filter over raw integrated gyro). Every Mario Kart Wii menu is pointer-driven, so they became unclickable. Note the tilt-steering half of the earlier hypothesis does NOT hold: GetTotalAcceleration -> GetAcceleration uses GetTransformation() with an identity extra rotation, and m_imu_cursor_state.rotation is applied only in GetTotalTransformation (the IR camera path). IMUAccelerometer ::GetState is gated on AreInputsBound alone, independent of the IMUPoint enable this code toggles. Racing was never affected -- which is exactly why it read as "almost impossible to play" rather than "won't launch". 2. calibrateFlat could hang the boot forever. Its completion only ever fired from inside the gyro handler, and the gate blocks startEmulation on it behind a non-cancellable full-screen modal -- no usable gyro, or motion access denied, meant the game simply never started. Now guards on isGyroAvailable with a 3s watchdog, and averaging zero samples no longer produces NaN biases. Calibration state moved behind a lock since two threads can now finish it. 3. The gate ran before GameCube titles. Every question on it is about the emulated Wii Remote's pointer. Added EmulationBootParameter.targetsWii (System Menu yes, GC IPL no, file boot from the GameFile's DiscIO::Platform) and skip straight to startEmulation otherwise. Subtitle restored to "every Wii game" to match. Not verified on device -- only Brandon can confirm the gameplay fix. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
bward-dev1
force-pushed
the
fix/landscape-wii-pointer-regression
branch
from
August 10, 2026 22:45
7a0244a to
3a78003
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #5 (
fix/device-only-play) — merge that first. Base is set to it so this diff shows only the increment.The regression
Reported: "ever since improvements; it's almost impossible to play Mario Kart Wii and other landscape-controller games like it don't work."
Cause:
effbb0924e— "Add mandatory pre-game pointer calibration screen", which I found independently before seeing #5. We agree on the trigger; #5 fixes the defaults, this fixes the damage and two other hard failures in the same commit.Verified chain:
PreGameCalibrationPreferences.calibrationModedefaulted to.pointAtTV, on a screen that is mandatory, full-screen andmodalInPresentation = true. Tapping Calibrate & Continue is the only way to reach a game.updateVisibleTouchPadToWiithen callsswitchToMotionPointingIfNeeded→Config::SetBaseOrCurrent(MAIN_TOUCH_PAD_IR_MODE, None).SetBaseOrCurrentwrites the Base layer, i.e. straight intoDolphin.ini, overwriting the shipped default (2= Drag).TCWiiPad.handleLongPress(TCWiiPad.swift:69) returns immediately whenmode == .none— the on-screen touch pointer emits nothing at all.IMUIR/Accelerometer Influence = 0(a57ce46dc5) andIMUGyroscope/Calibration Period = 0(96f567bca7), soEmulateIMUCursor(Dynamics.cpp:325-328) runs a zero-weight complementary filter over unbounded integrated gyro.Every menu in Mario Kart Wii — license, mode, character, kart, course — is pointer-driven, so they became unclickable.
Correction to the earlier hypothesis: tilt steering was never affected
Worth stating plainly, because it changes what to test. The claim that this breaks MKWii's motion steering does not hold:
Wiimote::GetTotalAcceleration()(WiimoteEmu.cpp:944) →GetAcceleration()(:841), which callsGetTransformation()with its default identityextra_rotation.m_imu_cursor_state.rotation— what the recenter pulse and gyro integration produce — is applied only inGetTotalTransformation()(:960), used at:507for the IR camera data, not at:497where the accelerometer report is built.IMUAccelerometer::GetState()(IMUAccelerometer.cpp:31) is gated onAreInputsBound()alone, entirely independent of theIMUPointenable flag this code toggles.So the recenter pulse cannot move the steering. Racing itself always worked — which is precisely why Brandon said "almost impossible to play" rather than "won't launch", and why the fix should be judged on menus, not on handling.
What #5 already fixes, and what it doesn't
#5's display-derived, persisted defaults are a better answer to the default problem than my original one-line flip, so I dropped mine and rebased onto it. Three things remain:
1. The switch is persisted — so #5 alone leaves Brandon still broken
SetBaseOrCurrentwritesDolphin.ini. Better defaults only prevent new damage; anyone who has already run a build frommasterhasTouchPadIRMode = 0on disk and stays broken after #5. (The brief that reached me said the gate "persists nothing" — the answers persist nothing, but the consequence is written to disk permanently.) #5 also addspromptHandheldRecenter, which calls the same persisting path.Fix: split into
switchToMotionPointingIfNeededPersisting:. The automatic pre-game path writesLayerType::CurrentRun(dropped byBootManager::RestoreConfig(), never saved — the layer has no loader). The Motion menu's explicit Calibrate/Recenter actions still persist, as their alert text promises.SetBaseOrCurrentkeeps targetingCurrentRunafterwards, so the in-game menu still works on top of it. Plus a one-time repair (DOLDidRepairForcedMotionPointingV1) restoring the shipped default for clobbered installs.2.
calibrateFlatcould hang the boot foreverIts completion only ever fired from inside the gyro handler, and the gate blocks
startEmulationon it behind a non-cancellable modal. No usable gyro, or motion access denied → the game never boots, with no way out. Now guards onisGyroAvailablewith a 3s watchdog; averaging zero samples no longer yields NaN biases. Calibration state moved behind a lock since two threads can now finish it.3. The gate ran before GameCube titles
No Wii Remote exists in a GameCube boot for any of those questions to affect. Added
EmulationBootParameter.targetsWii(System Menu → yes, GC IPL → no, file boot → from the GameFile'sDiscIO::Platform, defaulting to yes for any path that doesn't set it) and skip tostartEmulationotherwise.What to test on device
CI-compiled only — not verified on hardware.
Motion > Recenter Pointer (Handheld)should switch to motion pointing and stick across boots.Suspicious, deliberately not changed
IMUIR/Accelerometer Influence = 0andIMUGyroscope/Calibration Period = 0inTouchscreen.ini. Together these remove all drift correction from motion pointing. Both were deliberate fixes for a different symptom (calibration decaying in ~15s); re-tuning needs device testing, and a small non-zero influence is probably right rather than 0.effbb0924e. Once-per-install or a "Don't ask again" is the obvious next step.holdOrientation,flatFacing,isPlayingOnTV,tvScreenSize,tvScreenType) — Stop assuming a TV is attached when playing on the device alone #5 noted this too. Wire them up or drop them.TCJoystick.sharedInit'sguard let ... else { return }(3694061dbd) bails before attaching the pan recognizer, so a badjoystickTypeyields a silently dead stick. Not reachable with current XIBs.TCDeviceMotion.portdefaults to 0 and the gate enables motion beforesetPort:4runs, so Wii accel axes are briefly written to controller port 0. Harmless pre-boot, but a real ordering smell.Emulation.storyboard— flagged by Stop assuming a TV is attached when playing on the device alone #5, left alone; agreed it's separate.Ruled out as causes, for the record: supported interface orientations (unchanged, landscape still allowed both idioms); the
touchPadsoutlet-collection order (still matchesDOLEmulationVisibleTouchPad);47f7c75e18's tag-based row dispatch (correct — segue rows are tag 0 and correctly fall through); the D-pad/joystick skin wiring in835c5bf9ea(hit regions come from the view frame, not the image); built-in skin seeding (never activates a skin); and the core input additions indb05493f5b(purely additive).🤖 Generated with Claude Code