PHYSFS_init is not guaranteed to succeed. Using PHYSFS functions after
PHYSFS_init fails is likely to fail badly. On Windows, failure may take
the form of a crash in ntdll. Avoid this by exiting gracefully.
Commit 88b5e616a9 ("Replace calls to
window_set_visible in DoPlayerDead() with stop/start_time()") switched
from hiding the game window to only stopping time, and that only if
hiding the window would have stopped time. In multiplayer, this allows
time to continue running. This introduced a crash if the player dies
during the mine countdown. When the player dies, the game checks if the
reactor has been destroyed. If so, the game immediately advances to the
next level. That advance will try to draw the game window if it is
visible. When the window is drawn, if time is not stopped, then game
logic runs. Some of that logic is not prepared to deal with the
inconsistent state present when a new level is only partially loaded.
That inconsistent state then causes a crash. Call stack:
#11 slew_frame () at similar/main/slew.cpp:152
#12 in d2x::object_move_one () at similar/main/object.cpp:1758
#13 in d2x::object_move_all () at similar/main/object.cpp:1956
#14 in d2x::GameProcessFrame () at similar/main/game.cpp:1848
#15 d2x::game_handler () at similar/main/game.cpp:1615
#16 in dcx::window_send_event () at common/include/window.h:116
#17 dcx::event_process () at common/arch/sdl/event.cpp:176
#18 in newmenu_do2 () at similar/main/newmenu.cpp:498
#19 in newmenu_do2<dcx::unused_newmenu_userdata_t> () at common/main/newmenu.h:184
#20 newmenu_do<dcx::unused_newmenu_userdata_t const> () at common/main/newmenu.h:190
#21 newmenu_do<1ul, dcx::unused_newmenu_userdata_t const> () at common/main/newmenu.h:196
#22 net_udp_wait_for_requests () at similar/main/net_udp.cpp:4563
#23 net_udp_level_sync () at similar/main/net_udp.cpp:4607
#24 in multi_level_sync () at similar/main/multi.cpp:3458
#25 in d2x::StartNewLevelSub () at similar/main/gameseq.cpp:1803
#26 in d2x::StartNewLevel () at similar/main/gameseq.cpp:2018
#27 in d2x::AdvanceLevel () at similar/main/gameseq.cpp:1648
#28 in d2x::DoPlayerDead () at similar/main/gameseq.cpp:1721
The root cause of this is the layering violation:
- Killing the player can have the side effect of advancing the level
- Advancing the level can have the side effect of calling multiplayer code while the level data is in an inconsistent state
- Calling multiplayer code can cause the event system to redraw the game
- Redrawing the game can cause game logic to run
Hack around this by restoring the logic that hides the game window, so
that the window is not redrawn and the game logic is not run. This does
not fix the layering problem, but prevents crashing affected users. To
avoid undoing the feature from the breaking commit, hide the window only
when advancing to a new level, rather than unconditionally. A player
advancing to a new level already lacks the move-at-cold-start capability
even on successfully escaping the mine, so no functionality is lost with
this change. Players who are dead and do not advance to a new level
retain that capability.
Fixes: 88b5e616a9 ("Replace calls to window_set_visible in DoPlayerDead() with stop/start_time()")
Reported-by: Ninjared <https://forum.dxx-rebirth.com/showthread.php?tid=1097>
- Raise the player limit to 8.
- Remove the logic that forces player counts up/down when switching
between cooperative and deathmatch game modes.
- Add heuristics to add start positions for the extra players, since
standard maps will not have the required number of starts.
`check_effect_blowup` should receive the `laser_info` of the weapon that
caused the blast. Previously, it was given the `laser_info` of the
parent of that weapon. The parent was not of type `OBJ_WEAPON`, so
passing its `laser_info` is meaningless.
Fixes: 9bd1ba7c47
clang warns that this interferes with copy elision. The generated code
is slightly worse after following clang's advice and removing this, but
this is not a hot path, so take the hit to silence clang instead of
complicating the source.
Fixes: d97afc2ad5 ("Retain directory structure in New Game dialog")
gcc-4.9 std::array::size() is `constexpr`, but gcc-4.9 refuses to
initialize a local `constexpr std::size_t` from the result of calling
`size()` on a `std::array`. Later gcc permit this. gcc-8 generates the
same code whether the variable is `constexpr std::size_t` or `const
std::size_t`, and the latter allows gcc-4.9 to build, so remove
`constexpr` and use plain `const`.
Reported-by: joolswills <https://github.com/dxx-rebirth/dxx-rebirth/issues/411>
Fixes: 91d6285751 ("Factor out shortening game/mission names")
gcc-4.9 shipped without support for std::is_trivially_move_assignable.
This is only needed in a sanity check, so preprocess it out when using a
gcc below gcc-5.
Reported-by: joolswills <https://github.com/dxx-rebirth/dxx-rebirth/issues/411>
Fixes: 57334255ac ("Simplify stuck object cleanup")
gcc permits this, but clang complains. Match the format specifier to
the type of the underlying temporary variable.
Fixes: a65068fed1 ("Move OGL RLE bitmap buffer to stack")
Add experimental support for using ADL MIDI instead of SDL for music
playback. Support for ADL MIDI contributed by Github user jpcima. This
feature is minimally supported by the core Rebirth team, but is included
as a courtesy so that users need not patch in support separately.
Suggested-by: jpcima <https://github.com/dxx-rebirth/dxx-rebirth/pull/408>
Add configuration file entries for number of chips, bank index, and
whether to use ADL MIDI. Currently, there is no GUI for this.
Interested users must enable it via direct configuration file editing.
A menu interface will come later.