std::uniform_real/int_distribution has UB when min>max. The old "fancy Random"
used interpolate(a,b,t) which tolerated a>b; the migration to
std::uniform_real_distribution did not, and only one inverted call site was
fixed by hand. Swap the bounds inside Random()/Random(int)/LocalRandom() so
every call site is safe, and reorder the two inverted literal calls in
Driver.cpp (fActionTime buzzer / departure delay) for readability.
The dumb3d->glm / utilities-simplification refactor replaced the old custom
clamp() (which tolerated Lo>Hi, returning the upper bound) with std::clamp,
where inverted bounds are undefined behaviour. Only a few sites were patched
afterwards, by hand, with std::minmax plumbing (incl. a stray `static` inside
a per-axle loop). Others silently produced wrong results in the AI braking /
acceleration path.
Add a safe_clamp() helper (normalizes inverted bounds) and use it ONLY where
Lo<=Hi cannot be proven at compile time (config min/max pairs, sign-dependent
expressions, container underflow). Sites with constant bounds or [0, x>=0]
keep std::clamp. Remove the manual std::minmax workarounds and rewrite the
damaged-track jolt code value-first.
Consolidates platform-specific config-directory logic (APPDATA on Windows,
~/Library/Application Support on macOS, ~/.config on Linux) into a single
user_config_path(filename) function in utilities/utilities.{cpp,h}, removing
copy-pasted #ifdef blocks from application.cpp, editor/editorSettings.cpp,
input/{keyboard,gamepad,drivermouse,uart}input.cpp.
Three small source tweaks that let the OpenGL renderer build and run
on Apple Silicon without affecting the Windows/Linux paths:
- stdafx.h: use GLM_FORCE_NEON on ARM64 instead of GLM_FORCE_AVX2.
AVX2 pulls <immintrin.h>, which clang on ARM64 rejects because
the x86 intrinsics are unimplemented.
- utilities/utilities.cpp: provide an Apple libc++ fallback for
Now() using localtime_r + strftime, since
std::chrono::current_zone() is not yet implemented there.
- audio/audio.h: prefer Khronos-style <AL/al.h> headers when they
are on the include path (brew openal-soft) and fall back to the
deprecated Apple OpenAL.framework's <OpenAL/al.h> only otherwise.