Skip to content

[pull] master from beyond-all-reason:master - #49

Merged
pull[bot] merged 1 commit into
ExaDev:masterfrom
beyond-all-reason:master
Jul 28, 2026
Merged

[pull] master from beyond-all-reason:master#49
pull[bot] merged 1 commit into
ExaDev:masterfrom
beyond-all-reason:master

Conversation

@pull

@pull pull Bot commented Jul 28, 2026

Copy link
Copy Markdown

See Commits and Changes for more details.


Created by pull[bot] (v2.0.0-alpha.4)

Can you help keep this open source service alive? 💖 Please sponsor : )

…nc) (#3075)

* Sim/COB: avoid UB in float-to-short angle casts (fixes arm64/x86 desync)

Casting a floating-point heading/pitch expression directly to `short` is
undefined behaviour when the truncated value does not fit in `short`, and
this is genuinely reached: `heading * RAD2TAANG` equals +-32768 at
heading = +-pi, one past short's 32767 maximum.

Because the result is UB, arm64 and x86 produced different values at the
angle extremes, which was observed as an arm64/x86 multiplayer desync.
x86 already lowers `short(float)` as float->int->short (cvttss2si into a
32-bit register, then narrow), so making the `int()` step explicit leaves
the already-correct x86 result unchanged while pinning arm64 (whose fcvtzs
saturated differently) to the same value. The int->short narrowing is the
intended 16-bit TA-angle wraparound.

Sites fixed in CobInstance.cpp: WindChanged, StartBuilding, AimWeapon.
Sibling casts were checked and left untouched: UnitScript.cpp:1058 casts
asin(...)*RAD2TAANG (range +-16384, always fits short, no UB) and lines
1095/1099 already route through int; CobThread.cpp has no such casts.

Pure correctness fix to synced simulation code; it does not alter results
on the platform that was already correct. Cross-arch sync validation is
recommended. Origin: discussed in PR #2991's review (credit BambaDamba).

AI assistance: implemented with Claude Code (Anthropic) from a written
plan; reasoning and build verification reviewed by a human.

* address review: extract RadAngleToCobShort helper with explanatory comment

sprunk asked for a comment and a named helper around the float->short angle
cast. Wrap the conversion in RadAngleToCobShort() and document why it exists:
COB angles are circular 16-bit TA units (full turn == COBSCALE), so values
past a half turn intentionally wrap modulo 2^16 via the int->short narrowing.
The float->int step stays because the wrap is the desired behaviour and is
deterministic across arm64/x86; clamping the range (as suggested) would break
angles past a half turn rather than wrapping them. No behavioural change vs the
previous short(int(...)) form.
@pull pull Bot locked and limited conversation to collaborators Jul 28, 2026
@pull pull Bot added the ⤵️ pull label Jul 28, 2026
@pull
pull Bot merged commit 7104ab1 into ExaDev:master Jul 28, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant