bugfix: Re-assert FP mode in mouse pick to fix wrong click location with audio active#222
Conversation
…ith audio active screenToTerrain() and pickDrawable() perform screen->world ray/coordinate math without setting the FPU mode the engine relies on (GameLogic::update() calls setFPMode() every frame for its fast float->int conversions). On macOS/ARM the audio thread leaves the floating-point environment in a state that skews these conversions, so clicks resolve to the wrong world tile whenever audio is active. Call setFPMode() at the top of both pick functions. Fixes fbraz3#215 AI-assisted: change authored with Claude; verified in-game by me (clicks and camera-jump freeze fixed with audio on, tested on three displays at native fullscreen). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Tested the CI build from this PR on my M-series mac with Steam assets, works fine. Happy to merge this as a defensive fix for #215. One thing though, the audio thread explanation can't be right. FPU state is per-thread (FPCR on arm64), so more likely some audio work on the main thread is changing the FP env. Could you reword the comments so the audio-thread leak isn't stated as fact? Something like "this math needs the engine FP mode, re-assert it here" is enough. screenToWorldAtZ() and calcCameraAreaOffset() also use getPickRay(), and there are similar paths in W3DMouse.cpp and W3DTerrainVisual.cpp. Putting the guard inside getPickRay() would cover all of them, but that can be a follow-up. I opened #226 to guard the audio entry points since most of MiniAudioManager was unguarded. That's probably closer to the actual cause. If this ever comes back: screenToTerrain caches location requests until the camera moves, which matches the "fixed by moving the camera" symptom. A stale cache would explain that better than FP state. |
Summary
Fixes #215. On macOS/ARM, move orders and building placement resolve to the wrong world location whenever game audio is active — selection/box-drag work (screen-space), but any screen→world terrain pick lands on the wrong tile. Disabling sound makes it disappear entirely.
Root cause
The engine relies on a specific FPU mode for its fast float→int conversions;
GameLogic::update()callssetFPMode()every frame for this. ButW3DView::screenToTerrain()andW3DView::pickDrawable()do their ray/coordinate math with no such guard. On macOS/ARM the OpenAL audio thread leaves the FP environment in a state that skews these conversions, so picks resolve incorrectly while audio plays.Fix
Call the engine's existing
setFPMode()at the top of both pick functions. 12 lines, no behavior change beyond re-asserting the mode the engine already expects. AsW3DView.cppis shared underCore/, this covers both Zero Hour and Generals.Testing
Verified in-game on latest
main(post-Beta-14), audio on, on three displays at native fullscreen (2560×1440, 3440×1440, 5120×1440): move/build clicks land correctly across the whole screen, and an apparently-related camera-jump freeze is also resolved.Note on the mechanism
The audio-thread FP-env leak is inferred from the strong audio-on/off correlation and the fix working, not from instrumenting FP registers. If you'd prefer preventing the audio thread from altering the FP env at its source rather than re-asserting at point-of-use, happy to adjust.
AI disclosure
Per CONTRIBUTING: change was authored with AI assistance (Claude). I reviewed, tested, and verified the code and vouch for its correctness.