* android build support
* Update es_compatibility.h
* Support reporting flags in android
* include pref_path in json v2
* add vulkan headers
* shaderc includes
* remove headers
* force use prebuilt vulkan
* fix vulkan inverted screen
* fix find sdl3 precompiled android
* Update CMakeLists.txt
* replace sdl2 android function names for sdl3 versions
* change sdl includes in osapi
* fix sdl3 includes, again
* rename function to sdl3 name
* remove unused definition
* copy libshaderc_shared.so to output in android
* do not look for vulkan-loader in android
* revert changes to SDL2.cmake
* add comment to vulkan pretransform setup
* cleanup maxsize function
* rename new android functions in osapi
* android trap back button
* Remove calculate_max_resize_max_size
* touch ui opacity control
* change opacity control to int
* fix opacity slider
* Corrected android working folder fallback and set borderless mode as default
* Implement shared helper for JNI calls
* Add version tag and sha256 to android prebuilt libs
* vulkan android check eSuboptimal
* An already requested rebuild also avoids redundant Android surface queries
* add cache bool to cmakelist
* set string ids
* avoid undefined behavior from UNREACHABLE on reachable code paths
UNREACHABLE expands to __assume(false) / __builtin_unreachable() in
release builds, which is undefined behavior if the code is ever actually
reached. Many UNREACHABLE sites only guard against unexpected-but-
possible runtime states (values from tables, mission/save files, network
packets, scripting, or user input), so reaching them should degrade
gracefully rather than invoke UB.
Replace UNREACHABLE with Assertion(false, ...) at all such sites. It
still pops an error in debug builds, but in release it is a harmless
no-op that simply falls through to the following code. Sites that are
genuinely unreachable by local invariants (e.g. a switch over a bounded
random number) are left as UNREACHABLE.
A few converted sites had no safe fall-through -- an uninitialized read,
null dereference, or null call would have followed -- so they also get a
minimal recovery: initialize the value, guard the dereference, return
early, or skip the offending item.
Where the converted site was a simple guard of the form
if (x) { Assertion(false, ...); return; }
hoist the check onto the invariant instead:
Assertion(!x, ...);
if (x) { return; }
This states the expectation directly and shows the offending value in
the debug popup, while keeping the same graceful runtime degradation.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
* addendum
After consultation with Lafiel, use UNREACHABLE in situations that are effectively impossible even if not provably impossible. UNREACHABLE = "this shouldn't ever happen"; Assertion = "if this ever happens, it's a coding error". Also fix a few other sites and change a couple to Warnings.
---------
Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
* add tts support
* correct type
* more robust method binding and hide volume option
* missing ifndef
* thread safe jnienv
* check jni env before use it
* remove opt in volume option and cleanup
* cleanup
* add imgui speech options
* adapt existing windows sapi speech implementation
* adapt existing mac speech integration
* add speech linux stubs
* add speech support in linux
* Add array checks
* Use dlopen for speech-dispatcher
* corrrect lib name
* missing includes and static cast
* do not change mac file type
* fix clang tidy warnings 1
* set tts rate
* set localization ids
* fix clang tidy warnings 2
* correct symbol name
* Remove voice cache and fix win enumerate_voices overriding voice selection
* fix mac rate
Done by notimaginative
* requested changes
* re-add voice cache for linux
* Open connection for linux get flags
* fix missing }
* change voice option combobox to std::pair
* delete duplicated voice id sanitizer on windows set voice
* Use pairs for speech_enumerate_voices() and adapt linux speech
* use reference
* actually free vector memory
* Clear voice cache when ingame options closes
* Use extern to call fsspeech_options_cleanup()
* update localization ids
* Fixing some linux and window speech oversights
* Apply volume and rate after a voice change, correct voice, volume and rate apply order
When a streaming OpenAL source plays through all queued buffers it
transitions to AL_STOPPED. Per the spec, queueing more buffers after
that does not auto-resume playback -- alSourcePlay must be called
again. This is the likely cause of music and briefing voices cutting
out.
To fix this, check for underrun and call alSourcePlay if needed. Also
double MAX_STREAM_BUFFERS from 4 to 8, bumping the margin to ~2s
of queued audio.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
* use std::move() for local variables that are copied but not reused
Addresses ~140 Coverity "Variable copied when it could be moved"
defects across 74 files. Every std::move() targets a local variable
whose value is consumed by push_back, emplace, assignment, lambda
capture, or a function call and is never read again afterward.
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
* clang: use std::make_shared
* clang: use std::make_unique
* address feedback
---------
Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
Add coverity[GLOBAL_INIT_ORDER] annotations to ~50 global variables
across 27 files. These were all analyzed and confirmed safe:
- ~48 OptionBuilder::finish() globals use a Meyers singleton
(OptionsManager::instance()), which guarantees safe init order.
Destruction is also safe due to shared_ptr ref-counting.
- 6 default-constructed container globals (vectors, maps) have no
cross-TU dependencies at construction or destruction time.
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
The `continue` statement in these error checks had no effect because the error checks are macros implemented in a `do` ... `while (false)` loop. So, use `goto`. There is precedent with other instances of `OpenAL_ErrorCheck` in the code.
This may fix the issue where sound would occasionally randomly stop, requiring a pause or a screen change to get it back. This would be difficult to verify though.
Thanks to Coverity for flagging this situation!
Now that `snd_do_frame()` has been tightened up to specifically only adjust audio for the adjust-audio-volume sexp, the redundancy-avoiding code in `snd_set_volume()` is obsolete. So, set the sound volume immediately, even if it is a looping sound.
This is a two-for-one fix; the proper setting of volume fixes both #6504 and #6507.
Change `currentlyLoopingSoundInfos` and `currentlyLooping3dSoundInfos` from lists to maps. The data structure should keep track of the volumes currently, as opposed to historically, associated with each sound handle.
Since the map requires `util::ID` and its derivatives to be hashable, add `util::ID_Hash`.
Make some modifications to the adjust-audio-volume infrastructure:
1. Add an `aav_volume` array for ease of access to all three volume variables. Refactor `snd_adjust_audio_volume()` to use this array to avoid duplicating code.
2. Move `update_looping_sound_volumes()` to be handled in parallel with `audiostream_set_volume_all()`, and for the same reason: avoid setting the sound volume for every looping sound on every frame if the volume has not changed.
3. If the volume is to be adjusted immediately, apply the relevant changes without waiting for `snd_do_frame()` to be called on the next frame. Resolves#6291.
4. Fix some edge cases in `adjust_volume_on_frame()`.
This would crash because duplicate sounds were not being populated with the original entries. When snd_set_pos was called, the handle to the Sounds array would not be set, making our code think it was not loaded.
When game sounds were changed to allow named entries, it became possible for named entries to unexpectedly replace numbered entries. This was noticed most obviously in the ballistic rearm sound effect, which started using explosions rather than the standard rearm sound effects. This occurred because MV_Tiny and MV_Small were added into indexes 200 and 201.
To restore the original behavior, the code now prevents sound effects added via TBM from being placed into reserved indexes. The reserved indexes are instead assigned placeholders, which can subsequently be updated or left alone as the modder prefers.
This also makes the code a bit more robust including patching some sound validity checks in `gamesnd_game_sound_try_load` and `snd_load`.
When messages are distorted due to EMP effects, the voice volume should be controlled by the voice setting, not the effects setting. Fixes a bug noticed by @skdKitsune, a portion of which dates back to the original public source release.
Also, when volume is adjusted in `snd_set_volume`, make sure the correct voice volumes are used. Fixes a copy-paste bug from #5694.
* Create the ingame options game state
* Base working version of in-game options
* Cleanup + Optimization
* Localization pass
* more cleanup + documentation
* tooltips on option hover
* documentation and better inbounds check
* match case
* format strings instead of direct strings
* unused parameter
* address feedback
* localization id conflict with master
* Add this line back in
* pass the new option flags as well
* resolve xstr id conflict
Since event music soundtracks use the exact file extension specified (see #5567), the validity check should also use the exact file extension specified.
Also, move the validity check to after parsing has completed because extensions may be overridden.
Currently, menu music will trim the extension and look for both OGG and WAV files, but event music will use the exact extension specified. This is intended but could lead to unexpected results in mods, so display a warning for the modder.
These #include lines are needed for the changes introduced in #5492. Not sure why they weren't picked up by CI, or why they work in some compilers but not others.
If you pause the game, say something into the microphone, then unpause, it can abruptly perform an action based on voice recognition; this is probably counter to player expectations. This adds a `gameseq_get_state() != GS_STATE_GAME_PAUSED` check to the existing conditional.